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