1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26
27 //_________________________________________________________________________________________________________________
28 // my own includes
29 //_________________________________________________________________________________________________________________
30
31 #include <stdio.h>
32 #include <dispatch/dispatchprovider.hxx>
33 #include <loadenv/loadenv.hxx>
34 #include <dispatch/loaddispatcher.hxx>
35 #include <dispatch/closedispatcher.hxx>
36 #include <dispatch/menudispatcher.hxx>
37 #include <dispatch/helpagentdispatcher.hxx>
38 #include <dispatch/startmoduledispatcher.hxx>
39
40 #include <pattern/window.hxx>
41 #include <threadhelp/transactionguard.hxx>
42 #include <threadhelp/readguard.hxx>
43 #include <threadhelp/writeguard.hxx>
44 #include <dispatchcommands.h>
45 #include <protocols.h>
46 #include <services.h>
47 #include <targets.h>
48 #include <general.h>
49
50 //_________________________________________________________________________________________________________________
51 // interface includes
52 //_________________________________________________________________________________________________________________
53 #include <com/sun/star/frame/FrameSearchFlag.hpp>
54 #include <com/sun/star/uno/Exception.hpp>
55 #include <com/sun/star/ucb/XContentProviderManager.hpp>
56 #include <com/sun/star/document/XTypeDetection.hpp>
57 #include <com/sun/star/lang/XInitialization.hpp>
58
59 //_________________________________________________________________________________________________________________
60 // includes of other projects
61 //_________________________________________________________________________________________________________________
62 #include <osl/diagnose.h>
63 #include <rtl/string.h>
64 #include <rtl/ustring.hxx>
65 #include <vcl/svapp.hxx>
66 #include <rtl/ustrbuf.hxx>
67 //_________________________________________________________________________________________________________________
68 // namespace
69 //_________________________________________________________________________________________________________________
70
71 namespace framework{
72
73 //_________________________________________________________________________________________________________________
74 // non exported const
75 //_________________________________________________________________________________________________________________
76
77 //_________________________________________________________________________________________________________________
78 // non exported definitions
79 //_________________________________________________________________________________________________________________
80
81 //_________________________________________________________________________________________________________________
82 // declarations
83 //_________________________________________________________________________________________________________________
84
85 //*****************************************************************************************************************
86 // XInterface, XTypeProvider
87 //*****************************************************************************************************************
DEFINE_XINTERFACE_2(DispatchProvider,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::frame::XDispatchProvider))88 DEFINE_XINTERFACE_2( DispatchProvider ,
89 OWeakObject ,
90 DIRECT_INTERFACE(css::lang::XTypeProvider ),
91 DIRECT_INTERFACE(css::frame::XDispatchProvider)
92 )
93
94 DEFINE_XTYPEPROVIDER_2( DispatchProvider ,
95 css::lang::XTypeProvider ,
96 css::frame::XDispatchProvider
97 )
98
99 //_________________________________________________________________________________________________________________
100
101 /**
102 @short standard ctor/dtor
103 @descr These initialize a new instance of tihs class with needed informations for work.
104 We hold a weakreference to our owner frame which start dispatches at us.
105 We can't use a normal reference because he hold a reference of us too ...
106 nobody can die so ...!
107
108 @seealso using at owner
109
110 @param xFactory
111 reference to servicemanager to create new services.
112 @param xFrame
113 reference to our owner frame.
114
115 @modified 17.05.2002 10:07, as96863
116 */
117 DispatchProvider::DispatchProvider( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory ,
118 const css::uno::Reference< css::frame::XFrame >& xFrame )
119 // Init baseclasses first
120 : ThreadHelpBase( &Application::GetSolarMutex() )
121 , OWeakObject ( )
122 // Init member
123 , m_xFactory ( xFactory )
124 , m_xFrame ( xFrame )
125 {
126 }
127
128 //_________________________________________________________________________________________________________________
129
130 /**
131 @short protected(!) dtor for deinitializing
132 @descr We made it protected to prevent using of us as base class instead as a member.
133
134 @modified 17.05.2002 10:05, as96863
135 */
~DispatchProvider()136 DispatchProvider::~DispatchProvider()
137 {
138 }
139
140 //_________________________________________________________________________________________________________________
141
142 /**
143 @interface XDispatchProvider
144 @short search a dispatcher for given URL
145 @descr If no interceptor is set on owner, we search for right frame and dispatch URL to it.
146 If no frame was found, we do nothing.
147 But we doesn't do it directly here. We detect the type of our owner frame and calls
148 specialized queryDispatch() helper dependen from that. Because a Desktop handle some
149 requests in another way then a normal frame.
150
151 @param aURL
152 URL to dispatch.
153 @param sTargetFrameName
154 name of searched frame.
155 @param nSearchFlags
156 flags for searching.
157 @return A reference to a dispatch object for this URL (if someone was found!).
158
159 @threadsafe yes
160 @modified 17.05.2002 10:59, as96863
161 */
queryDispatch(const css::util::URL & aURL,const::rtl::OUString & sTargetFrameName,sal_Int32 nSearchFlags)162 css::uno::Reference< css::frame::XDispatch > SAL_CALL DispatchProvider::queryDispatch( const css::util::URL& aURL ,
163 const ::rtl::OUString& sTargetFrameName ,
164 sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException )
165 {
166 css::uno::Reference< css::frame::XDispatch > xDispatcher;
167
168 /* SAFE { */
169 ReadGuard aReadLock( m_aLock );
170 css::uno::Reference< css::frame::XFrame > xOwner( m_xFrame.get(), css::uno::UNO_QUERY );
171 aReadLock.unlock();
172 /* } SAFE */
173
174 css::uno::Reference< css::frame::XDesktop > xDesktopCheck( xOwner, css::uno::UNO_QUERY );
175
176 if (xDesktopCheck.is())
177 xDispatcher = implts_queryDesktopDispatch(xOwner, aURL, sTargetFrameName, nSearchFlags);
178 else
179 xDispatcher = implts_queryFrameDispatch(xOwner, aURL, sTargetFrameName, nSearchFlags);
180
181 return xDispatcher;
182 }
183
184 //_________________________________________________________________________________________________________________
185
186 /**
187 @interface XDispatchProvider
188 @short do the same like queryDispatch() ... but handle multiple dispatches at the same time
189 @descr It's an optimism. User give us a list of queries ... and we return a list of dispatcher.
190 If one of given queries couldn't be solved to a real existing dispatcher ...
191 we return a list with empty references in it! Order of both lists will be retained!
192
193 @seealso method queryDispatch()
194
195 @param lDescriptions
196 a list of all dispatch parameters for multiple requests
197 @return A reference a list of dispatch objects for these URLs - may with some <NULL/> values inside.
198
199 @threadsafe yes
200 @modified 17.05.2002 09:55, as96863
201 */
queryDispatches(const css::uno::Sequence<css::frame::DispatchDescriptor> & lDescriptions)202 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL DispatchProvider::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptions ) throw( css::uno::RuntimeException )
203 {
204 // Create return list - which must have same size then the given descriptor
205 // It's not allowed to pack it!
206 sal_Int32 nCount = lDescriptions.getLength();
207 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
208
209 // Step over all descriptors and try to get any dispatcher for it.
210 for( sal_Int32 i=0; i<nCount; ++i )
211 {
212 lDispatcher[i] = queryDispatch( lDescriptions[i].FeatureURL ,
213 lDescriptions[i].FrameName ,
214 lDescriptions[i].SearchFlags );
215 }
216
217 return lDispatcher;
218 }
219
220 //_________________________________________________________________________________________________________________
221
lcl_isStartModuleDispatch(const css::util::URL & aURL)222 ::sal_Bool lcl_isStartModuleDispatch (const css::util::URL& aURL)
223 {
224 return (aURL.Complete.equals(CMD_UNO_SHOWSTARTMODULE));
225 }
226
227 //_________________________________________________________________________________________________________________
228
229 /**
230 @short helper for queryDispatch()
231 @descr Every member of the frame tree (frame, desktop) must handle such request
232 in another way. So we implement different specialized metods for every one.
233
234 @threadsafe yes
235 @modified 20.08.2003 08:32, as96863
236 */
implts_queryDesktopDispatch(const css::uno::Reference<css::frame::XFrame> xDesktop,const css::util::URL & aURL,const::rtl::OUString & sTargetFrameName,sal_Int32 nSearchFlags)237 css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_queryDesktopDispatch( const css::uno::Reference< css::frame::XFrame > xDesktop ,
238 const css::util::URL& aURL ,
239 const ::rtl::OUString& sTargetFrameName ,
240 sal_Int32 nSearchFlags )
241 {
242 css::uno::Reference< css::frame::XDispatch > xDispatcher;
243
244 // ignore wrong requests which are not supported
245 if (
246 (sTargetFrameName==SPECIALTARGET_MENUBAR ) || // valid for frame dispatches - not for desktop
247 (sTargetFrameName==SPECIALTARGET_HELPAGENT) || // valid for frame dispatches - not for desktop
248 (sTargetFrameName==SPECIALTARGET_PARENT ) || // we have no parent by definition
249 (sTargetFrameName==SPECIALTARGET_BEAMER ) // beamer frames are allowed as child of tasks only -
250 // and they exist more then ones. We have no idea which our sub tasks is the right one
251 )
252 {
253 return NULL;
254 }
255
256 //-----------------------------------------------------------------------------------------------------
257 // I) handle special cases which not right for using findFrame() first
258 //-----------------------------------------------------------------------------------------------------
259
260 //-----------------------------------------------------------------------------------------------------
261 // I.I) "_blank"
262 // It's not the right place to create a new task here - because we are queried for a dispatch object
263 // only, which can handle such request. Such dispatcher should create the required task on demand.
264 // Normaly the functionality for "_blank" is provided by findFrame() - but that would create it directly
265 // here. Thats why we must "intercept" here.
266 //-----------------------------------------------------------------------------------------------------
267 if (sTargetFrameName==SPECIALTARGET_BLANK)
268 {
269 if (implts_isLoadableContent(aURL))
270 xDispatcher = implts_getOrCreateDispatchHelper( E_BLANKDISPATCHER, xDesktop );
271 }
272
273 //-----------------------------------------------------------------------------------------------------
274 // I.II) "_default"
275 // This is a combination of search an empty task for recycling - or create a new one.
276 //-----------------------------------------------------------------------------------------------------
277 else
278 if (sTargetFrameName==SPECIALTARGET_DEFAULT)
279 {
280 if (implts_isLoadableContent(aURL))
281 xDispatcher = implts_getOrCreateDispatchHelper( E_DEFAULTDISPATCHER, xDesktop );
282
283 if (lcl_isStartModuleDispatch(aURL))
284 xDispatcher = implts_getOrCreateDispatchHelper( E_STARTMODULEDISPATCHER, xDesktop );
285 }
286
287 //-----------------------------------------------------------------------------------------------------
288 // I.III) "_self", "", "_top"
289 // The desktop can't load any document - but he can handle some special protocols like "uno", "slot" ...
290 // Why is "top" here handled too? Because the desktop is the topest frame. Normaly it's superflous
291 // to use this target - but we can handle it in the same manner then "_self".
292 //-----------------------------------------------------------------------------------------------------
293 else
294 if (
295 (sTargetFrameName==SPECIALTARGET_SELF) ||
296 (sTargetFrameName==SPECIALTARGET_TOP ) ||
297 (sTargetFrameName.getLength()<1 )
298 )
299 {
300 xDispatcher = implts_searchProtocolHandler(aURL);
301 }
302
303 //-----------------------------------------------------------------------------------------------------
304 // I.IV) no further special targets exist
305 // Now we have to search for the right target frame by calling findFrame() - but should provide our code
306 // against creation of a new task if no frame could be found.
307 // I said it b efore - it's allowed for dispatch() only.
308 //-----------------------------------------------------------------------------------------------------
309 else
310 {
311 sal_Int32 nRightFlags = nSearchFlags;
312 nRightFlags &= ~css::frame::FrameSearchFlag::CREATE;
313
314 // try to find any existing target and ask him for his dispatcher
315 css::uno::Reference< css::frame::XFrame > xFoundFrame = xDesktop->findFrame(sTargetFrameName, nRightFlags);
316 if (xFoundFrame.is())
317 {
318 css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFoundFrame, css::uno::UNO_QUERY );
319 xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_SELF,0);
320 }
321 else
322 // if it couldn't be found - but creation was allowed
323 // use special dispatcher for creatio or froward it to the browser
324 if (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
325 xDispatcher = implts_getOrCreateDispatchHelper( E_CREATEDISPATCHER, xDesktop, sTargetFrameName, nSearchFlags );
326 }
327
328 return xDispatcher;
329 }
330
331 //_________________________________________________________________________________________________________________
332
implts_queryFrameDispatch(const css::uno::Reference<css::frame::XFrame> xFrame,const css::util::URL & aURL,const::rtl::OUString & sTargetFrameName,sal_Int32 nSearchFlags)333 css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_queryFrameDispatch( const css::uno::Reference< css::frame::XFrame > xFrame ,
334 const css::util::URL& aURL ,
335 const ::rtl::OUString& sTargetFrameName ,
336 sal_Int32 nSearchFlags )
337 {
338 css::uno::Reference< css::frame::XDispatch > xDispatcher;
339
340 //-----------------------------------------------------------------------------------------------------
341 // 0) Some URLs are dispatched in a generic way (e.g. by the menu) using the default target "".
342 // But they are specified to use her own fix target. Detect such URLs here and use the correct target.
343 //-----------------------------------------------------------------------------------------------------
344
345 ::rtl::OUString sTargetName = sTargetFrameName;
346
347 //-----------------------------------------------------------------------------------------------------
348 // I) handle special cases which not right for using findFrame() first
349 //-----------------------------------------------------------------------------------------------------
350
351 //-----------------------------------------------------------------------------------------------------
352 // I.I) "_blank", "_default"
353 // It's not the right place to create a new task here. Only the desktop can do that.
354 // Normaly the functionality for "_blank" is provided by findFrame() - but that would create it directly
355 // here. Thats why we must "intercept" here.
356 //-----------------------------------------------------------------------------------------------------
357 if (
358 (sTargetName==SPECIALTARGET_BLANK ) ||
359 (sTargetName==SPECIALTARGET_DEFAULT)
360 )
361 {
362 css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
363 if (xParent.is())
364 xDispatcher = xParent->queryDispatch(aURL, sTargetName, 0); // its a special target - ignore search flags
365 }
366
367 //-----------------------------------------------------------------------------------------------------
368 // I.II) "_menubar"
369 // Special mode on frame or task to receive the local menu. Not supported by findFrame()
370 //-----------------------------------------------------------------------------------------------------
371 else
372 if (sTargetName==SPECIALTARGET_MENUBAR)
373 {
374 xDispatcher = implts_getOrCreateDispatchHelper( E_MENUDISPATCHER, xFrame );
375 }
376
377 //-----------------------------------------------------------------------------------------------------
378 // I.III) "_helpagent"
379 // Special mode on frame or task to start the help agent.
380 // It's defined for top level frames only.
381 //-----------------------------------------------------------------------------------------------------
382 else
383 if (sTargetName==SPECIALTARGET_HELPAGENT)
384 {
385 if (WindowHelper::isTopWindow(xFrame->getContainerWindow()))
386 xDispatcher = implts_getOrCreateDispatchHelper( E_HELPAGENTDISPATCHER, xFrame );
387 else
388 {
389 // Don''t use findFrame() here - because it's not possible to find
390 // a top lebel frame without knowing his name. And a frame with name
391 // "" can't be realy searched! That's why forward query to any parent
392 // explicitly.
393 css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFrame->getCreator(), css::uno::UNO_QUERY );
394 if (xProvider.is())
395 xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_HELPAGENT,0);
396 }
397 }
398
399 //-----------------------------------------------------------------------------------------------------
400 // I.IV) "_helpagent"
401 // Special sub frame of a top frame only. Search or create it. ... OK it's currently a little bit HACKI.
402 // Only the sfx (means the controller) can create it it.
403 //-----------------------------------------------------------------------------------------------------
404 else
405 if (sTargetName==SPECIALTARGET_BEAMER)
406 {
407 css::uno::Reference< css::frame::XDispatchProvider > xBeamer( xFrame->findFrame( SPECIALTARGET_BEAMER, css::frame::FrameSearchFlag::CHILDREN | css::frame::FrameSearchFlag::SELF ), css::uno::UNO_QUERY );
408 if (xBeamer.is())
409 {
410 xDispatcher = xBeamer->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
411 }
412 else
413 {
414 css::uno::Reference< css::frame::XDispatchProvider > xController( xFrame->getController(), css::uno::UNO_QUERY );
415 if (xController.is())
416 // force using of special target - but use original search flags
417 // May the caller used the CREATE flag or not!
418 xDispatcher = xController->queryDispatch(aURL, SPECIALTARGET_BEAMER, nSearchFlags);
419 }
420 }
421
422 //-----------------------------------------------------------------------------------------------------
423 // I.V) "_parent"
424 // Our parent frame (if it exist) should handle this URL.
425 //-----------------------------------------------------------------------------------------------------
426 else
427 if (sTargetName==SPECIALTARGET_PARENT)
428 {
429 css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
430 if (xParent.is())
431 // SELF => we must adress the parent directly... and not his parent or any other parent!
432 xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
433 }
434
435 //-----------------------------------------------------------------------------------------------------
436 // I.VI) "_top"
437 // This request must be forwarded to any parent frame, till we reach a top frame.
438 // If no parent exist, we can handle itself.
439 //-----------------------------------------------------------------------------------------------------
440 else
441 if (sTargetName==SPECIALTARGET_TOP)
442 {
443 if (xFrame->isTop())
444 {
445 // If we are this top frame itself (means our owner frame)
446 // we should call ourself recursiv with a better target "_self".
447 // So we can share the same code! (see reaction for "_self" inside this method too.)
448 xDispatcher = this->queryDispatch(aURL,SPECIALTARGET_SELF,0);
449 }
450 else
451 {
452 css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
453 // Normaly if isTop() returned sal_False ... the parent frame MUST(!) exist ...
454 // But it seams to be better to check that here to prevent us against an access violation.
455 if (xParent.is())
456 xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_TOP, 0);
457 }
458 }
459
460 //-----------------------------------------------------------------------------------------------------
461 // I.VII) "_self", ""
462 // Our owner frame should handle this URL. But we can't do it for all of them.
463 // So we ask the internal setted controller first. If he disagree we try to find a registered
464 // protocol handler. If this failed too - we check for a loadable content and in case of true
465 // we load it into the frame by returning specilized dispatch object.
466 //-----------------------------------------------------------------------------------------------------
467 else
468 if (
469 (sTargetName==SPECIALTARGET_SELF) ||
470 (sTargetName.getLength()<1 )
471 )
472 {
473 // There exist a hard coded interception for special URLs.
474 if (
475 (aURL.Complete.equalsAscii(".uno:CloseDoc" )) ||
476 (aURL.Complete.equalsAscii(".uno:CloseWin" ))
477 )
478 {
479 css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
480 // In case the frame is not a top one, is not based on system window and has a parent,
481 // the parent frame should to be queried for the correct dispatcher.
482 // See i93473
483 if (
484 !WindowHelper::isTopWindow(xFrame->getContainerWindow()) &&
485 !VCLUnoHelper::GetWindow(xFrame->getContainerWindow())->IsSystemWindow() &&
486 xParent.is()
487 )
488 xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
489 else
490 xDispatcher = implts_getOrCreateDispatchHelper( E_CLOSEDISPATCHER, xFrame );
491 }
492 else if (aURL.Complete.equalsAscii(".uno:CloseFrame"))
493 xDispatcher = implts_getOrCreateDispatchHelper( E_CLOSEDISPATCHER, xFrame );
494
495 if ( ! xDispatcher.is())
496 {
497 // Ask our controller for his agreement for these dispatched URL ...
498 // because some URLs are internal and can be handled faster by SFX - which most is the current controller!
499 // But in case of e.g. the bibliography not all queries will be handled successfully here.
500 css::uno::Reference< css::frame::XDispatchProvider > xController( xFrame->getController(), css::uno::UNO_QUERY );
501 if (xController.is())
502 xDispatcher = xController->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
503 }
504
505 // If controller has no fun to dispatch these URL - we must search another right dispatcher.
506 // Search for any registered protocol handler first.
507 if (!xDispatcher.is())
508 xDispatcher = implts_searchProtocolHandler(aURL);
509
510 // Not for controller - not for protocol handler
511 // It should be a loadable content - may be a file. Check it ...
512 // This check is neccessary to found out, that
513 // support for some protocols isn't installed by user. May be
514 // "ftp" isn't available. So we suppress creation of our self dispatcher.
515 // The result will be clear. He can't handle it - but he would try it.
516 if (
517 ( ! xDispatcher.is() ) &&
518 ( implts_isLoadableContent(aURL) )
519 )
520 {
521 xDispatcher = implts_getOrCreateDispatchHelper( E_SELFDISPATCHER, xFrame );
522 }
523 }
524
525 //-----------------------------------------------------------------------------------------------------
526 // I.VI) no further special handlings exist
527 // Now we have to search for the right target frame by calling findFrame() - but should provide our code
528 // against creation of a new task if no frame could be found.
529 // I said it before - it's allowed for dispatch() only.
530 //-----------------------------------------------------------------------------------------------------
531 else
532 {
533 sal_Int32 nRightFlags = nSearchFlags;
534 nRightFlags &= ~css::frame::FrameSearchFlag::CREATE;
535
536 // try to find any existing target and ask him for his dispatcher
537 css::uno::Reference< css::frame::XFrame > xFoundFrame = xFrame->findFrame(sTargetName, nRightFlags);
538 if (xFoundFrame.is())
539 {
540 // Attention: Found target is our own owner frame!
541 // Don't ask him for his dispatcher. We know it already - it's our self dispatch helper.
542 // Otherwhise we can start a never ending recursiv call. Why?
543 // Somewere called our owner frame - he called some interceptor objects - and may by this dispatch provider
544 // is called. If wa use queryDispatch() on our owner frame again - we start this call stack again ... and again.
545 if (xFoundFrame==xFrame)
546 xDispatcher = implts_getOrCreateDispatchHelper( E_SELFDISPATCHER, xFrame );
547 else
548 {
549 css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFoundFrame, css::uno::UNO_QUERY );
550 xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_SELF,0);
551 }
552 }
553 else
554 // if it couldn't be found - but creation was allowed
555 // forward request to the desktop.
556 // Note: The given target name must be used to set the name on new created task!
557 // Don't forward request by changing it to a special one e.g _blank.
558 // Use the CREATE flag only to prevent call against further searches.
559 // We already know it - the target must be created new.
560 if (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
561 {
562 css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
563 if (xParent.is())
564 xDispatcher = xParent->queryDispatch(aURL, sTargetName, css::frame::FrameSearchFlag::CREATE);
565 }
566 }
567
568 return xDispatcher;
569 }
570
571 //_________________________________________________________________________________________________________________
572
573 /**
574 @short search for a registered protocol handler and ask him for a dispatch object
575 @descr Wes earch a suitable handler inside our cfg package org.openoffice.Office.ProtocolHandler.
576 If we found anyone, we create and initialize it. Initialize means: we set our owner frame on it
577 as context information. He can use it or leave it. Of course - we are aware of handler implementations,
578 which doesn't support initialization. It's an optional feature.
579
580 @param aURL
581 the dispatch URL for which may a handler is registered
582
583 @return A dispatch object if a handler was found and agree with the given URL or <NULL/> otherwhise.
584
585 @threadsafe yes
586 @modified 05.09.2002 13:43, as96863
587 */
implts_searchProtocolHandler(const css::util::URL & aURL)588 css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_searchProtocolHandler( const css::util::URL& aURL )
589 {
590 css::uno::Reference< css::frame::XDispatch > xDispatcher;
591 ProtocolHandler aHandler ;
592
593 // This member is threadsafe by himself and lives if we live - we doesn't need any mutex here.
594 if (m_aProtocolHandlerCache.search(aURL,&aHandler))
595 {
596 /* SAFE { */
597 ReadGuard aReadLock( m_aLock );
598
599 // create it
600 css::uno::Reference< css::frame::XDispatchProvider > xHandler;
601 try
602 {
603 xHandler = css::uno::Reference< css::frame::XDispatchProvider >(
604 m_xFactory->createInstance(aHandler.m_sUNOName),
605 css::uno::UNO_QUERY);
606 }
607 catch(css::uno::Exception&) {}
608
609 // look if initialization is neccessary
610 css::uno::Reference< css::lang::XInitialization > xInit( xHandler, css::uno::UNO_QUERY );
611 if (xInit.is())
612 {
613 css::uno::Reference< css::frame::XFrame > xOwner( m_xFrame.get(), css::uno::UNO_QUERY );
614 LOG_ASSERT(xOwner.is(), "DispatchProvider::implts_searchProtocolHandler()\nCouldn't get reference to my owner frame. So I can't set may needed context information for this protocol handler.")
615 if (xOwner.is())
616 {
617 try
618 {
619 // but do it only, if all context informations are OK
620 css::uno::Sequence< css::uno::Any > lContext(1);
621 lContext[0] <<= xOwner;
622 xInit->initialize(lContext);
623 }
624 catch(css::uno::Exception&) {}
625 }
626 }
627
628 aReadLock.unlock();
629 /* } SAFE */
630
631 // ask for his (sub)dispatcher for the given URL
632 if (xHandler.is())
633 xDispatcher = xHandler->queryDispatch(aURL,SPECIALTARGET_SELF,0);
634 }
635
636 return xDispatcher;
637 }
638
639 //_________________________________________________________________________________________________________________
640
641 /**
642 @short get or create new dispatch helper
643 @descr Sometimes we need some helper implementations to support dispatching of special URLs or commands.
644 But it's not a good idea to hold these services for the whole life time of this provider instance.
645 We should create it on demand ...
646 Thats why we implement this method. It return an already existing helper or create a new one otherwise.
647
648 @attention The parameter sTarget and nSearchFlags are defaulted to "" and 0!
649 Please use it only, if you can be shure, that the realy given by the outside calli!
650 Mostly it depends from the parameter eHelper is they are required or not.
651
652 @param eHelper
653 specify the requested dispatch helper
654 @param xOwner
655 the target of possible dispatch() call on created dispatch helper
656 @param sTarget
657 the target parameter of the original queryDispatch() request
658 @param nSearchFlags
659 the flags parameter of the original queryDispatch() request
660 @return A reference to a dispatch helper.
661
662 @threadsafe yes
663 @modified 20.08.2003 10:22, as96863
664 */
implts_getOrCreateDispatchHelper(EDispatchHelper eHelper,const css::uno::Reference<css::frame::XFrame> & xOwner,const::rtl::OUString & sTarget,sal_Int32 nSearchFlags)665 css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_getOrCreateDispatchHelper( EDispatchHelper eHelper ,
666 const css::uno::Reference< css::frame::XFrame >& xOwner ,
667 const ::rtl::OUString& sTarget ,
668 sal_Int32 nSearchFlags)
669 {
670 css::uno::Reference< css::frame::XDispatch > xDispatchHelper;
671
672 /* SAFE { */
673 ReadGuard aReadLock( m_aLock );
674 css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
675 aReadLock.unlock();
676 /* } SAFE */
677
678 switch (eHelper)
679 {
680 case E_MENUDISPATCHER :
681 {
682 // Attention: Such menue dispatcher must be a singleton for this frame - means our owner frame.
683 // Otherwhise he can make some trouble.
684 /* SAFE { */
685 WriteGuard aWriteLock( m_aLock );
686 if ( ! m_xMenuDispatcher.is() )
687 {
688 MenuDispatcher* pDispatcher = new MenuDispatcher( xFactory, xOwner );
689 m_xMenuDispatcher = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
690 }
691 xDispatchHelper = m_xMenuDispatcher;
692 aWriteLock.unlock();
693 /* } SAFE */
694 }
695 break;
696
697 case E_HELPAGENTDISPATCHER :
698 {
699 // Attention: It's not a good idea to create this help agent twice for the same frame (window)
700 // May it will be shown twice too - and user activate the first one. Then he get the corresponding
701 // help window ... but there exist another help agent window on bottom side of the frame window.
702 // It's superflous. Create it on demand - but hold it alive till this provider dies.
703 /* SAFE { */
704 WriteGuard aWriteLock( m_aLock );
705 if ( ! m_xHelpAgentDispatcher.is() )
706 {
707 HelpAgentDispatcher* pDispatcher = new HelpAgentDispatcher( xOwner );
708 m_xHelpAgentDispatcher = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
709 }
710 xDispatchHelper = m_xHelpAgentDispatcher;
711 aWriteLock.unlock();
712 /* } SAFE */
713 }
714 break;
715
716 case E_CREATEDISPATCHER :
717 {
718 LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, sTarget, nSearchFlags);
719 xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
720 }
721 break;
722
723 case E_BLANKDISPATCHER :
724 {
725 css::uno::Reference< css::frame::XFrame > xDesktop( xOwner, css::uno::UNO_QUERY );
726 if (xDesktop.is())
727 {
728 LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_BLANK, 0);
729 xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
730 }
731 }
732 break;
733
734 case E_DEFAULTDISPATCHER :
735 {
736 css::uno::Reference< css::frame::XFrame > xDesktop( xOwner, css::uno::UNO_QUERY );
737 if (xDesktop.is())
738 {
739 LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_DEFAULT, 0);
740 xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
741 }
742 }
743 break;
744
745 case E_SELFDISPATCHER :
746 {
747 LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_SELF, 0);
748 xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
749 }
750 break;
751
752 case E_CLOSEDISPATCHER :
753 {
754 CloseDispatcher* pDispatcher = new CloseDispatcher( xFactory, xOwner, sTarget );
755 xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
756 }
757 break;
758
759 case E_STARTMODULEDISPATCHER :
760 {
761 StartModuleDispatcher* pDispatcher = new StartModuleDispatcher( xFactory, xOwner, sTarget );
762 xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
763 }
764 break;
765 }
766
767 return xDispatchHelper;
768 }
769
770 //_________________________________________________________________________________________________________________
771
772 /**
773 @short check URL for support by our used loader or handler
774 @descr If we must return our own dispatch helper implementations (self, blank, create dispatcher!)
775 we should be shure, that URL describe any loadable content. Otherwise slot/uno URLs
776 will be detected ... but there exist nothing for ral loading into a target frame!
777
778 @param aURL
779 URL which should be "detected"
780 @return <TRUE/> if somewhere could handle that - <FALSE/> otherwise.
781
782 @threadsafe yes
783 @modified 17.05.2002 09:47, as96863
784 */
implts_isLoadableContent(const css::util::URL & aURL)785 sal_Bool DispatchProvider::implts_isLoadableContent( const css::util::URL& aURL )
786 {
787 LoadEnv::EContentType eType = LoadEnv::classifyContent(aURL.Complete, css::uno::Sequence< css::beans::PropertyValue >());
788 return ( eType == LoadEnv::E_CAN_BE_LOADED );
789 }
790
791 } // namespace framework
792