Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <loadenv/loadenv.hxx>
21 :
22 : #include <loadenv/targethelper.hxx>
23 : #include <framework/framelistanalyzer.hxx>
24 :
25 : #include <constant/containerquery.hxx>
26 : #include <interaction/quietinteraction.hxx>
27 : #include <threadhelp/writeguard.hxx>
28 : #include <threadhelp/readguard.hxx>
29 : #include <threadhelp/resetableguard.hxx>
30 : #include <properties.h>
31 : #include <protocols.h>
32 : #include <services.h>
33 : #include <comphelper/interaction.hxx>
34 : #include <framework/interaction.hxx>
35 : #include <comphelper/processfactory.hxx>
36 : #include <comphelper/configuration.hxx>
37 : #include "officecfg/Office/Common.hxx"
38 :
39 : #include <com/sun/star/task/ErrorCodeRequest.hpp>
40 : #include <com/sun/star/uno/RuntimeException.hpp>
41 : #include <com/sun/star/frame/DispatchResultState.hpp>
42 : #include <com/sun/star/frame/FrameSearchFlag.hpp>
43 : #include <com/sun/star/util/URLTransformer.hpp>
44 : #include <com/sun/star/util/XURLTransformer.hpp>
45 : #include <com/sun/star/ucb/UniversalContentBroker.hpp>
46 : #include <com/sun/star/util/XCloseable.hpp>
47 : #include <com/sun/star/lang/XComponent.hpp>
48 : #include <com/sun/star/lang/XServiceInfo.hpp>
49 : #include <com/sun/star/lang/DisposedException.hpp>
50 : #include <com/sun/star/awt/XWindow.hpp>
51 : #include <com/sun/star/awt/XWindow2.hpp>
52 : #include <com/sun/star/awt/XTopWindow.hpp>
53 : #include <com/sun/star/frame/Desktop.hpp>
54 : #include <com/sun/star/frame/XModel.hpp>
55 : #include <com/sun/star/frame/XFrameLoader.hpp>
56 : #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
57 : #include <com/sun/star/frame/XNotifyingDispatch.hpp>
58 : #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
59 : #include <com/sun/star/task/XStatusIndicator.hpp>
60 : #include <com/sun/star/util/XModifiable.hpp>
61 : #include <com/sun/star/frame/XDispatchProvider.hpp>
62 : #include <com/sun/star/document/XTypeDetection.hpp>
63 : #include <com/sun/star/document/XActionLockable.hpp>
64 : #include <com/sun/star/io/XInputStream.hpp>
65 : #include <com/sun/star/task/XInteractionHandler.hpp>
66 : #include <com/sun/star/container/XNameAccess.hpp>
67 : #include <com/sun/star/container/XContainerQuery.hpp>
68 : #include <com/sun/star/container/XEnumeration.hpp>
69 : #include <com/sun/star/document/MacroExecMode.hpp>
70 : #include <com/sun/star/document/UpdateDocMode.hpp>
71 :
72 : #include <vcl/window.hxx>
73 : #include <vcl/wrkwin.hxx>
74 : #include <vcl/syswin.hxx>
75 :
76 : #include <toolkit/unohlp.hxx>
77 : #include <unotools/moduleoptions.hxx>
78 : #include <svtools/sfxecode.hxx>
79 : #include <comphelper/processfactory.hxx>
80 : #include <unotools/ucbhelper.hxx>
81 : #include <comphelper/configurationhelper.hxx>
82 : #include <rtl/ustrbuf.hxx>
83 : #include <vcl/svapp.hxx>
84 :
85 : const char PROP_TYPES[] = "Types";
86 : const char PROP_NAME[] = "Name";
87 :
88 : namespace framework {
89 :
90 : using namespace com::sun::star;
91 :
92 :
93 0 : class LoadEnvListener : private ThreadHelpBase
94 : , public ::cppu::WeakImplHelper2< css::frame::XLoadEventListener ,
95 : css::frame::XDispatchResultListener >
96 : {
97 : private:
98 :
99 : bool m_bWaitingResult;
100 : LoadEnv* m_pLoadEnv;
101 :
102 : public:
103 :
104 : //_______________________________________
105 0 : LoadEnvListener(LoadEnv* pLoadEnv)
106 : : m_bWaitingResult(true)
107 0 : , m_pLoadEnv(pLoadEnv)
108 : {
109 0 : }
110 :
111 : //_______________________________________
112 : // frame.XLoadEventListener
113 : virtual void SAL_CALL loadFinished(const css::uno::Reference< css::frame::XFrameLoader >& xLoader)
114 : throw(css::uno::RuntimeException);
115 :
116 : virtual void SAL_CALL loadCancelled(const css::uno::Reference< css::frame::XFrameLoader >& xLoader)
117 : throw(css::uno::RuntimeException);
118 :
119 : //_______________________________________
120 : // frame.XDispatchResultListener
121 : virtual void SAL_CALL dispatchFinished(const css::frame::DispatchResultEvent& aEvent)
122 : throw(css::uno::RuntimeException);
123 :
124 : //_______________________________________
125 : // lang.XEventListener
126 : virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent)
127 : throw(css::uno::RuntimeException);
128 : };
129 :
130 :
131 241 : LoadEnv::LoadEnv(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
132 : throw(LoadEnvException, css::uno::RuntimeException)
133 : : ThreadHelpBase( )
134 : , m_xSMGR (xSMGR)
135 241 : , m_pQuietInteraction( 0 )
136 : {
137 241 : }
138 :
139 :
140 241 : LoadEnv::~LoadEnv()
141 : {
142 241 : }
143 :
144 :
145 241 : css::uno::Reference< css::lang::XComponent > LoadEnv::loadComponentFromURL(const css::uno::Reference< css::frame::XComponentLoader >& xLoader,
146 : const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
147 : const ::rtl::OUString& sURL ,
148 : const ::rtl::OUString& sTarget,
149 : sal_Int32 nFlags ,
150 : const css::uno::Sequence< css::beans::PropertyValue >& lArgs )
151 : throw(css::lang::IllegalArgumentException,
152 : css::io::IOException ,
153 : css::uno::RuntimeException )
154 : {
155 241 : css::uno::Reference< css::lang::XComponent > xComponent;
156 :
157 : try
158 : {
159 241 : LoadEnv aEnv(xSMGR);
160 :
161 : aEnv.initializeLoading(sURL,
162 : lArgs,
163 : css::uno::Reference< css::frame::XFrame >(xLoader, css::uno::UNO_QUERY),
164 : sTarget,
165 : nFlags,
166 241 : LoadEnv::E_NO_FEATURE);
167 241 : aEnv.startLoading();
168 241 : aEnv.waitWhileLoading(); // wait for ever!
169 :
170 241 : xComponent = aEnv.getTargetComponent();
171 : }
172 0 : catch(const LoadEnvException& ex)
173 : {
174 0 : switch(ex.m_nID)
175 : {
176 : case LoadEnvException::ID_INVALID_MEDIADESCRIPTOR:
177 : throw css::lang::IllegalArgumentException(
178 : ::rtl::OUString("Optional list of arguments seem to be corrupted."),
179 : xLoader,
180 0 : 4);
181 :
182 : case LoadEnvException::ID_UNSUPPORTED_CONTENT:
183 : {
184 0 : rtl::OUStringBuffer aMsg;
185 0 : aMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM("Unsupported URL <")).
186 0 : append(sURL).append('>');
187 :
188 0 : if (!ex.m_sMessage.isEmpty())
189 : {
190 0 : aMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM(": \"")).
191 : append(rtl::OStringToOUString(
192 0 : ex.m_sMessage, RTL_TEXTENCODING_UTF8)).
193 0 : appendAscii(RTL_CONSTASCII_STRINGPARAM("\""));
194 : }
195 :
196 : throw css::lang::IllegalArgumentException(aMsg.makeStringAndClear(),
197 0 : xLoader, 1);
198 : }
199 :
200 : default:
201 0 : xComponent.clear();
202 0 : break;
203 : }
204 : }
205 :
206 241 : return xComponent;
207 : }
208 :
209 : //-----------------------------------------------
210 241 : ::comphelper::MediaDescriptor impl_mergeMediaDescriptorWithMightExistingModelArgs(const css::uno::Sequence< css::beans::PropertyValue >& lOutsideDescriptor)
211 : {
212 241 : ::comphelper::MediaDescriptor lDescriptor(lOutsideDescriptor);
213 : css::uno::Reference< css::frame::XModel > xModel = lDescriptor.getUnpackedValueOrDefault(
214 241 : ::comphelper::MediaDescriptor::PROP_MODEL (),
215 482 : css::uno::Reference< css::frame::XModel > ());
216 241 : if (xModel.is ())
217 : {
218 4 : ::comphelper::MediaDescriptor lModelDescriptor(xModel->getArgs());
219 4 : ::comphelper::MediaDescriptor::iterator pIt = lModelDescriptor.find( ::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE() );
220 4 : if ( pIt != lModelDescriptor.end() )
221 4 : lDescriptor[::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()] = pIt->second;
222 : }
223 :
224 241 : return lDescriptor;
225 : }
226 :
227 :
228 241 : void LoadEnv::initializeLoading(const ::rtl::OUString& sURL ,
229 : const css::uno::Sequence< css::beans::PropertyValue >& lMediaDescriptor,
230 : const css::uno::Reference< css::frame::XFrame >& xBaseFrame ,
231 : const ::rtl::OUString& sTarget ,
232 : sal_Int32 nSearchFlags ,
233 : EFeature eFeature , // => use default ...
234 : EContentType eContentType ) // => use default ...
235 : {
236 : // SAFE -> ----------------------------------
237 241 : WriteGuard aWriteLock(m_aLock);
238 :
239 : // Handle still running processes!
240 241 : if (m_xAsynchronousJob.is())
241 0 : throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
242 :
243 : // take over all new parameters.
244 241 : m_xTargetFrame.clear();
245 241 : m_xBaseFrame = xBaseFrame ;
246 241 : m_lMediaDescriptor = impl_mergeMediaDescriptorWithMightExistingModelArgs(lMediaDescriptor);
247 241 : m_sTarget = sTarget ;
248 241 : m_nSearchFlags = nSearchFlags ;
249 241 : m_eFeature = eFeature ;
250 241 : m_eContentType = eContentType ;
251 241 : m_bCloseFrameOnError = sal_False ;
252 241 : m_bReactivateControllerOnError = sal_False ;
253 241 : m_bLoaded = sal_False ;
254 :
255 : // try to find out, if its really a content, which can be loaded or must be "handled"
256 : // We use a default value for this in-parameter. Then we have to start a complex check method
257 : // internally. But if this check was already done outside it can be supressed to perform
258 : // the load request. We take over the result then!
259 241 : if (m_eContentType == E_UNSUPPORTED_CONTENT)
260 : {
261 241 : m_eContentType = LoadEnv::classifyContent(sURL, lMediaDescriptor);
262 241 : if (m_eContentType == E_UNSUPPORTED_CONTENT)
263 0 : throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT);
264 : }
265 :
266 : // make URL part of the MediaDescriptor
267 : // It doesn't mater, if it is already an item of it.
268 : // It must be the same value ... so we can overwrite it :-)
269 241 : m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_URL()] <<= sURL;
270 :
271 : // parse it - because some following code require that
272 241 : m_aURL.Complete = sURL;
273 241 : css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(::comphelper::getComponentContext(m_xSMGR)));
274 241 : xParser->parseStrict(m_aURL);
275 :
276 : // BTW: Split URL and JumpMark ...
277 : // Because such mark is an explicit value of the media descriptor!
278 241 : if (!m_aURL.Mark.isEmpty())
279 0 : m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_JUMPMARK()] <<= m_aURL.Mark;
280 :
281 : // By the way: remove the old and deprecated value "FileName" from the descriptor!
282 241 : ::comphelper::MediaDescriptor::iterator pIt = m_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_FILENAME());
283 241 : if (pIt != m_lMediaDescriptor.end())
284 0 : m_lMediaDescriptor.erase(pIt);
285 :
286 : // patch the MediaDescriptor, so it fullfill the outside requirements
287 : // Means especially items like e.g. UI InteractionHandler, Status Indicator,
288 : // MacroExecutionMode etcpp.
289 :
290 : /*TODO progress is bound to a frame ... How can we set it here? */
291 :
292 : // UI mode
293 : const bool bUIMode =
294 : ( ( m_eFeature & E_WORK_WITH_UI ) == E_WORK_WITH_UI ) &&
295 241 : ( m_lMediaDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_HIDDEN() , sal_False ) == sal_False ) &&
296 241 : ( m_lMediaDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_PREVIEW(), sal_False ) == sal_False );
297 :
298 : initializeUIDefaults(
299 : m_xSMGR,
300 : m_lMediaDescriptor,
301 : bUIMode,
302 : &m_pQuietInteraction
303 241 : );
304 :
305 241 : aWriteLock.unlock();
306 : // <- SAFE ----------------------------------
307 241 : }
308 :
309 :
310 241 : void LoadEnv::initializeUIDefaults( const css::uno::Reference< css::lang::XMultiServiceFactory >& i_rSMGR,
311 : ::comphelper::MediaDescriptor& io_lMediaDescriptor, const bool i_bUIMode,
312 : QuietInteraction** o_ppQuietInteraction )
313 : {
314 241 : css::uno::Reference< css::task::XInteractionHandler > xInteractionHandler;
315 : sal_Int16 nMacroMode ;
316 : sal_Int16 nUpdateMode ;
317 :
318 241 : if ( i_bUIMode )
319 : {
320 0 : nMacroMode = css::document::MacroExecMode::USE_CONFIG;
321 0 : nUpdateMode = css::document::UpdateDocMode::ACCORDING_TO_CONFIG;
322 : try
323 : {
324 0 : xInteractionHandler = css::uno::Reference< css::task::XInteractionHandler >(i_rSMGR->createInstance(IMPLEMENTATIONNAME_UIINTERACTIONHANDLER), css::uno::UNO_QUERY);
325 : }
326 0 : catch(const css::uno::RuntimeException&) {throw;}
327 0 : catch(const css::uno::Exception& ) { }
328 : }
329 : // hidden mode
330 : else
331 : {
332 241 : nMacroMode = css::document::MacroExecMode::NEVER_EXECUTE;
333 241 : nUpdateMode = css::document::UpdateDocMode::NO_UPDATE;
334 241 : QuietInteraction* pQuietInteraction = new QuietInteraction();
335 241 : xInteractionHandler = css::uno::Reference< css::task::XInteractionHandler >(static_cast< css::task::XInteractionHandler* >(pQuietInteraction), css::uno::UNO_QUERY);
336 241 : if ( o_ppQuietInteraction != NULL )
337 : {
338 241 : *o_ppQuietInteraction = pQuietInteraction;
339 241 : (*o_ppQuietInteraction)->acquire();
340 : }
341 : }
342 :
343 1446 : if (
344 241 : (xInteractionHandler.is() ) &&
345 964 : (io_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()) == io_lMediaDescriptor.end())
346 : )
347 : {
348 241 : io_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()] <<= xInteractionHandler;
349 : }
350 :
351 241 : if (io_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()) == io_lMediaDescriptor.end())
352 0 : io_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()] <<= nMacroMode;
353 :
354 241 : if (io_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_UPDATEDOCMODE()) == io_lMediaDescriptor.end())
355 241 : io_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_UPDATEDOCMODE()] <<= nUpdateMode;
356 241 : }
357 :
358 :
359 241 : void LoadEnv::startLoading()
360 : {
361 : // SAFE ->
362 241 : ReadGuard aReadLock(m_aLock);
363 :
364 : // Handle still running processes!
365 241 : if (m_xAsynchronousJob.is())
366 0 : throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
367 :
368 : // content can not be loaded or handled
369 : // check "classifyContent()" failed before ...
370 241 : if (m_eContentType == E_UNSUPPORTED_CONTENT)
371 0 : throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT);
372 :
373 : // <- SAFE
374 241 : aReadLock.unlock();
375 :
376 : // detect its type/filter etcpp.
377 : // These information will be available by the
378 : // used descriptor member afterwards and is needed
379 : // for all following operations!
380 : // Note: An exception will be thrown, in case operation was not successfully ...
381 241 : if (m_eContentType != E_CAN_BE_SET)/* Attention: special feature to set existing component on a frame must ignore type detection! */
382 237 : impl_detectTypeAndFilter();
383 :
384 : // start loading the content ...
385 : // Attention: Dont check m_eContentType deeper then UNSUPPORTED/SUPPORTED!
386 : // Because it was made in th easiest way ... may a flat detection was made only.
387 : // And such simple detection can fail some times .-)
388 : // Use another strategy here. Try it and let it run into the case "loading not possible".
389 241 : sal_Bool bStarted = sal_False;
390 241 : if (
391 : ((m_eFeature & E_ALLOW_CONTENTHANDLER) == E_ALLOW_CONTENTHANDLER) &&
392 : (m_eContentType != E_CAN_BE_SET ) /* Attention: special feature to set existing component on a frame must ignore type detection! */
393 : )
394 : {
395 0 : bStarted = impl_handleContent();
396 : }
397 :
398 241 : if (!bStarted)
399 241 : bStarted = impl_loadContent();
400 :
401 : // not started => general error
402 : // We can't say - what was the reason for.
403 241 : if (!bStarted)
404 0 : throw LoadEnvException(LoadEnvException::ID_GENERAL_ERROR);
405 241 : }
406 :
407 : /*-----------------------------------------------
408 : TODO
409 : First draft does not implement timeout using [ms].
410 : Current implementation counts yield calls only ...
411 : -----------------------------------------------*/
412 241 : sal_Bool LoadEnv::waitWhileLoading(sal_uInt32 nTimeout)
413 : {
414 : // Because its not a good idea to block the main thread
415 : // (and we can't be sure that we are currently not used inside the
416 : // main thread!), we can't use conditions here really. We must yield
417 : // in an intellegent manner :-)
418 :
419 241 : sal_Int32 nTime = nTimeout;
420 0 : while(true)
421 : {
422 : // SAFE -> ------------------------------
423 241 : ReadGuard aReadLock1(m_aLock);
424 241 : if (!m_xAsynchronousJob.is())
425 : break;
426 0 : aReadLock1.unlock();
427 : // <- SAFE ------------------------------
428 :
429 0 : Application::Yield();
430 :
431 : // forever!
432 0 : if (nTimeout==0)
433 0 : continue;
434 :
435 : // timed out?
436 0 : --nTime;
437 0 : if (nTime<1)
438 : break;
439 241 : }
440 :
441 : // SAFE -> ----------------------------------
442 241 : ReadGuard aReadLock2(m_aLock);
443 241 : return !m_xAsynchronousJob.is();
444 : // <- SAFE ----------------------------------
445 : }
446 :
447 241 : css::uno::Reference< css::lang::XComponent > LoadEnv::getTargetComponent() const
448 : {
449 : // SAFE ->
450 241 : ReadGuard aReadLock(m_aLock);
451 :
452 241 : if (!m_xTargetFrame.is())
453 0 : return css::uno::Reference< css::lang::XComponent >();
454 :
455 241 : css::uno::Reference< css::frame::XController > xController = m_xTargetFrame->getController();
456 241 : if (!xController.is())
457 0 : return css::uno::Reference< css::lang::XComponent >(m_xTargetFrame->getComponentWindow(), css::uno::UNO_QUERY);
458 :
459 241 : css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
460 241 : if (!xModel.is())
461 0 : return css::uno::Reference< css::lang::XComponent >(xController, css::uno::UNO_QUERY);
462 :
463 241 : return css::uno::Reference< css::lang::XComponent >(xModel, css::uno::UNO_QUERY);
464 : // <- SAFE
465 : }
466 :
467 :
468 0 : void SAL_CALL LoadEnvListener::loadFinished(const css::uno::Reference< css::frame::XFrameLoader >&)
469 : throw(css::uno::RuntimeException)
470 : {
471 : // SAFE -> ----------------------------------
472 0 : WriteGuard aWriteLock(m_aLock);
473 :
474 0 : if (m_bWaitingResult)
475 0 : m_pLoadEnv->impl_setResult(sal_True);
476 0 : m_bWaitingResult = false;
477 :
478 0 : aWriteLock.unlock();
479 : // <- SAFE ----------------------------------
480 0 : }
481 :
482 :
483 0 : void SAL_CALL LoadEnvListener::loadCancelled(const css::uno::Reference< css::frame::XFrameLoader >&)
484 : throw(css::uno::RuntimeException)
485 : {
486 : // SAFE -> ----------------------------------
487 0 : WriteGuard aWriteLock(m_aLock);
488 :
489 0 : if (m_bWaitingResult)
490 0 : m_pLoadEnv->impl_setResult(sal_False);
491 0 : m_bWaitingResult = false;
492 :
493 0 : aWriteLock.unlock();
494 : // <- SAFE ----------------------------------
495 0 : }
496 :
497 :
498 0 : void SAL_CALL LoadEnvListener::dispatchFinished(const css::frame::DispatchResultEvent& aEvent)
499 : throw(css::uno::RuntimeException)
500 : {
501 : // SAFE -> ----------------------------------
502 0 : WriteGuard aWriteLock(m_aLock);
503 :
504 0 : if (!m_bWaitingResult)
505 0 : return;
506 :
507 0 : switch(aEvent.State)
508 : {
509 : case css::frame::DispatchResultState::FAILURE :
510 0 : m_pLoadEnv->impl_setResult(sal_False);
511 0 : break;
512 :
513 : case css::frame::DispatchResultState::SUCCESS :
514 0 : m_pLoadEnv->impl_setResult(sal_False);
515 0 : break;
516 :
517 : case css::frame::DispatchResultState::DONTKNOW :
518 0 : m_pLoadEnv->impl_setResult(sal_False);
519 0 : break;
520 : }
521 0 : m_bWaitingResult = false;
522 :
523 0 : aWriteLock.unlock();
524 : // <- SAFE ----------------------------------
525 : }
526 :
527 :
528 0 : void SAL_CALL LoadEnvListener::disposing(const css::lang::EventObject&)
529 : throw(css::uno::RuntimeException)
530 : {
531 : // SAFE -> ----------------------------------
532 0 : WriteGuard aWriteLock(m_aLock);
533 :
534 0 : if (m_bWaitingResult)
535 0 : m_pLoadEnv->impl_setResult(sal_False);
536 0 : m_bWaitingResult = false;
537 :
538 0 : aWriteLock.unlock();
539 : // <- SAFE ----------------------------------
540 0 : }
541 :
542 :
543 241 : void LoadEnv::impl_setResult(sal_Bool bResult)
544 : {
545 : // SAFE -> ----------------------------------
546 241 : WriteGuard aWriteLock(m_aLock);
547 :
548 241 : m_bLoaded = bResult;
549 :
550 241 : impl_reactForLoadingState();
551 :
552 : // clearing of this reference will unblock waitWhileLoading()!
553 : // So we must be sure, that loading process was really finished.
554 : // => do it as last operation of this method ...
555 241 : m_xAsynchronousJob.clear();
556 :
557 241 : aWriteLock.unlock();
558 : // <- SAFE ----------------------------------
559 241 : }
560 :
561 : /*-----------------------------------------------
562 : TODO: Is it a good idea to change Sequence<>
563 : parameter to stl-adapter?
564 : -----------------------------------------------*/
565 2601 : LoadEnv::EContentType LoadEnv::classifyContent(const ::rtl::OUString& sURL ,
566 : const css::uno::Sequence< css::beans::PropertyValue >& lMediaDescriptor)
567 : {
568 : //-------------------------------------------
569 : // (i) Filter some special well known URL protocols,
570 : // which can not be handled or loaded in general.
571 : // Of course an empty URL must be ignored here too.
572 : // Note: These URL schemata are fix and well known ...
573 : // But there can be some additional ones, which was not
574 : // defined at implementation time of this class :-(
575 : // So we have to make sure, that the following code
576 : // can detect such protocol schemata too :-)
577 :
578 18207 : if(
579 2601 : (sURL.isEmpty() ) ||
580 2601 : (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_UNO )) ||
581 2601 : (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_SLOT )) ||
582 2601 : (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_MACRO )) ||
583 2601 : (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_SERVICE)) ||
584 2601 : (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_MAILTO )) ||
585 2601 : (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_NEWS ))
586 : )
587 : {
588 0 : return E_UNSUPPORTED_CONTENT;
589 : }
590 :
591 : //-------------------------------------------
592 : // (ii) Some special URLs indicates a given input stream,
593 : // a full featured document model directly or
594 : // specify a request for opening an empty document.
595 : // Such contents are loadable in general.
596 : // But we have to check, if the media descriptor contains
597 : // all needed resources. If they are missing - the following
598 : // load request will fail.
599 :
600 : /* Attention: The following code can't work on such special URLs!
601 : It should not break the office .. but it make no sense
602 : to start expensive object creations and complex search
603 : algorithm if its clear, that such URLs must be handled
604 : in a special way .-)
605 : */
606 :
607 : // creation of new documents
608 2601 : if (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_PRIVATE_FACTORY))
609 0 : return E_CAN_BE_LOADED;
610 :
611 : // using of an existing input stream
612 2601 : ::comphelper::MediaDescriptor stlMediaDescriptor(lMediaDescriptor);
613 2601 : ::comphelper::MediaDescriptor::const_iterator pIt;
614 2601 : if (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_PRIVATE_STREAM))
615 : {
616 0 : pIt = stlMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_INPUTSTREAM());
617 0 : css::uno::Reference< css::io::XInputStream > xStream;
618 0 : if (pIt != stlMediaDescriptor.end())
619 0 : pIt->second >>= xStream;
620 0 : if (xStream.is())
621 0 : return E_CAN_BE_LOADED;
622 : LOG_WARNING("LoadEnv::classifyContent()", "loading from stream with right URL but invalid stream detected")
623 0 : return E_UNSUPPORTED_CONTENT;
624 : }
625 :
626 : // using of a full featured document
627 2601 : if (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_PRIVATE_OBJECT))
628 : {
629 4 : pIt = stlMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_MODEL());
630 4 : css::uno::Reference< css::frame::XModel > xModel;
631 4 : if (pIt != stlMediaDescriptor.end())
632 4 : pIt->second >>= xModel;
633 4 : if (xModel.is())
634 4 : return E_CAN_BE_SET;
635 : LOG_WARNING("LoadEnv::classifyContent()", "loading with object with right URL but invalid object detected")
636 0 : return E_UNSUPPORTED_CONTENT;
637 : }
638 :
639 : // following operatons can work on an internal type name only :-(
640 2597 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
641 2597 : css::uno::Reference< css::document::XTypeDetection > xDetect(xSMGR->createInstance(SERVICENAME_TYPEDETECTION), css::uno::UNO_QUERY);
642 :
643 2597 : ::rtl::OUString sType = xDetect->queryTypeByURL(sURL);
644 :
645 2597 : css::uno::Sequence< css::beans::NamedValue > lQuery(1) ;
646 2597 : css::uno::Reference< css::container::XContainerQuery > xContainer ;
647 2597 : css::uno::Reference< css::container::XEnumeration > xSet ;
648 2597 : css::uno::Sequence< ::rtl::OUString > lTypesReg(1);
649 :
650 :
651 : //-------------------------------------------
652 : // (iii) If a FrameLoader service (or at least
653 : // a Filter) can be found, which supports
654 : // this URL - it must be a loadable content.
655 : // Because both items are registered for types
656 : // its enough to check for frame loaders only.
657 : // Mos of our filters are handled by our global
658 : // default loader. But there exist some specialized
659 : // loader, which does not work on top of filters!
660 : // So its not enough to search on the filter configuration.
661 : // Further its not enough to search for types!
662 : // Because there exist some types, which are referenced by
663 : // other objects ... but not by filters nor frame loaders!
664 :
665 2597 : rtl::OUString sPROP_TYPES(PROP_TYPES);
666 :
667 2597 : lTypesReg[0] = sType;
668 2597 : lQuery[0].Name = sPROP_TYPES;
669 2597 : lQuery[0].Value <<= lTypesReg;
670 :
671 2597 : xContainer = css::uno::Reference< css::container::XContainerQuery >(xSMGR->createInstance(SERVICENAME_FRAMELOADERFACTORY), css::uno::UNO_QUERY);
672 2597 : xSet = xContainer->createSubSetEnumerationByProperties(lQuery);
673 : // at least one registered frame loader is enough!
674 2597 : if (xSet->hasMoreElements())
675 182 : return E_CAN_BE_LOADED;
676 :
677 : //-------------------------------------------
678 : // (iv) Some URL protocols are supported by special services.
679 : // E.g. ContentHandler.
680 : // Such contents can be handled ... but not loaded.
681 :
682 2415 : lTypesReg[0] = sType;
683 2415 : lQuery[0].Name = sPROP_TYPES;
684 2415 : lQuery[0].Value <<= lTypesReg;
685 :
686 2415 : xContainer = css::uno::Reference< css::container::XContainerQuery >(xSMGR->createInstance(SERVICENAME_CONTENTHANDLERFACTORY), css::uno::UNO_QUERY);
687 2415 : xSet = xContainer->createSubSetEnumerationByProperties(lQuery);
688 : // at least one registered content handler is enough!
689 2415 : if (xSet->hasMoreElements())
690 0 : return E_CAN_BE_HANDLED;
691 :
692 : //-------------------------------------------
693 : // (v) Last but not least the UCB is used inside office to
694 : // load contents. He has a special configuration to know
695 : // which URL schemata can be used inside office.
696 2415 : css::uno::Reference< css::ucb::XUniversalContentBroker > xUCB(css::ucb::UniversalContentBroker::create(comphelper::getComponentContext(xSMGR)));
697 2415 : if (xUCB->queryContentProvider(sURL).is())
698 55 : return E_CAN_BE_LOADED;
699 :
700 : //-------------------------------------------
701 : // (TODO) At this point, we have no idea .-)
702 : // But it seems to be better, to break all
703 : // further requests for this URL. Otherwhise
704 : // we can run into some trouble.
705 2360 : return E_UNSUPPORTED_CONTENT;
706 : }
707 :
708 : namespace {
709 :
710 : #if 0
711 : // TODO: We will reinstate this function later, so don't remove this!
712 : bool queryOrcusTypeAndFilter(const uno::Sequence<beans::PropertyValue>&, OUString&, OUString&)
713 : {
714 : return false;
715 : }
716 : #else
717 237 : bool queryOrcusTypeAndFilter(const uno::Sequence<beans::PropertyValue>& rDescriptor, OUString& rType, OUString& rFilter)
718 : {
719 : // depending on the experimental mode
720 237 : uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
721 237 : if (!xContext.is() || !officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
722 : {
723 237 : return false;
724 : }
725 :
726 0 : OUString aURL;
727 0 : sal_Int32 nSize = rDescriptor.getLength();
728 0 : for (sal_Int32 i = 0; i < nSize; ++i)
729 : {
730 0 : const beans::PropertyValue& rProp = rDescriptor[i];
731 0 : if (rProp.Name == "URL")
732 : {
733 0 : rProp.Value >>= aURL;
734 0 : break;
735 : }
736 : }
737 :
738 0 : if (aURL.isEmpty() || aURL.copy(0,8).equalsIgnoreAsciiCase("private:"))
739 0 : return false;
740 :
741 0 : if(aURL.endsWith(".gnumeric"))
742 : {
743 0 : rType = "generic_Text";
744 0 : rFilter = "orcus-gnumeric";
745 0 : return true;
746 : }
747 : #if 0
748 : else if (aURL.endsWith(".csv"))
749 : {
750 : // Use .csv as the first test file type.
751 : rType = "generic_Text";
752 : rFilter = "orcus-test-filter";
753 : return true;
754 : }
755 : #endif
756 :
757 0 : return false;
758 : }
759 : #endif
760 :
761 : }
762 :
763 237 : void LoadEnv::impl_detectTypeAndFilter()
764 : throw(LoadEnvException, css::uno::RuntimeException)
765 : {
766 237 : static ::rtl::OUString TYPEPROP_PREFERREDFILTER("PreferredFilter");
767 237 : static ::rtl::OUString FILTERPROP_FLAGS ("Flags");
768 : static sal_Int32 FILTERFLAG_TEMPLATEPATH = 16;
769 :
770 : // SAFE ->
771 237 : ReadGuard aReadLock(m_aLock);
772 :
773 : // Attention: Because our stl media descriptor is a copy of an uno sequence
774 : // we can't use as an in/out parameter here. Copy it before and dont forget to
775 : // update structure afterwards again!
776 237 : css::uno::Sequence< css::beans::PropertyValue > lDescriptor = m_lMediaDescriptor.getAsConstPropertyValueList();
777 237 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
778 :
779 237 : aReadLock.unlock();
780 : // <- SAFE
781 :
782 237 : rtl::OUString sType, sFilter;
783 :
784 237 : if (queryOrcusTypeAndFilter(lDescriptor, sType, sFilter) && !sType.isEmpty() && !sFilter.isEmpty())
785 : {
786 : // Orcus type detected. Skip the normal type detection process.
787 0 : m_lMediaDescriptor << lDescriptor;
788 0 : m_lMediaDescriptor[comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sType;
789 0 : m_lMediaDescriptor[comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
790 0 : m_lMediaDescriptor[comphelper::MediaDescriptor::PROP_FILTERPROVIDER()] <<= OUString("orcus");
791 237 : return;
792 : }
793 :
794 237 : css::uno::Reference< css::document::XTypeDetection > xDetect(xSMGR->createInstance(SERVICENAME_TYPEDETECTION), css::uno::UNO_QUERY);
795 237 : if (xDetect.is())
796 237 : sType = xDetect->queryTypeByDescriptor(lDescriptor, sal_True); /*TODO should deep detection be able for enable/disable it from outside? */
797 :
798 : // no valid content -> loading not possible
799 237 : if (sType.isEmpty())
800 0 : throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT);
801 :
802 : // SAFE ->
803 237 : WriteGuard aWriteLock(m_aLock);
804 :
805 : // detection was successfully => update the descriptor member of this class
806 237 : m_lMediaDescriptor << lDescriptor;
807 237 : m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sType;
808 : // Is there an already detected (may be preselected) filter?
809 : // see below ...
810 237 : sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME(), ::rtl::OUString());
811 :
812 237 : aWriteLock.unlock();
813 : // <- SAFE
814 :
815 : // But the type isnt enough. For loading sometimes we need more informations.
816 : // E.g. for our "_default" feature, where we recylce any frame which contains
817 : // and "Untitled" document, we must know if the new document is based on a template!
818 : // But this information is available as a filter property only.
819 : // => We must try(!) to detect the right filter for this load request.
820 : // On the other side ... if no filter is available .. ignore it.
821 : // Then the type information must be enough.
822 237 : if (sFilter.isEmpty())
823 : {
824 : // no -> try to find a preferred filter for the detected type.
825 : // Dont forget to updatet he media descriptor.
826 0 : css::uno::Reference< css::container::XNameAccess > xTypeCont(xDetect, css::uno::UNO_QUERY_THROW);
827 : try
828 : {
829 0 : ::comphelper::SequenceAsHashMap lTypeProps(xTypeCont->getByName(sType));
830 0 : sFilter = lTypeProps.getUnpackedValueOrDefault(TYPEPROP_PREFERREDFILTER, ::rtl::OUString());
831 0 : if (!sFilter.isEmpty())
832 : {
833 : // SAFE ->
834 0 : aWriteLock.lock();
835 0 : m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
836 0 : aWriteLock.unlock();
837 : // <- SAFE
838 0 : }
839 : }
840 0 : catch(const css::container::NoSuchElementException&)
841 0 : {}
842 : }
843 :
844 : // check if the filter (if one exists) points to a template format filter.
845 : // Then we have to add the property "AsTemplate".
846 : // We need this information to decide afterwards if we can use a "recycle frame"
847 : // for target "_default" or has to create a new one everytimes.
848 : // On the other side we have to supress that, if this property already exists
849 : // and should trigger a special handling. Then the outside calli of this method here,
850 : // has to know, what he is doing .-)
851 :
852 237 : sal_Bool bIsOwnTemplate = sal_False;
853 237 : if (!sFilter.isEmpty())
854 : {
855 237 : css::uno::Reference< css::container::XNameAccess > xFilterCont(xSMGR->createInstance(SERVICENAME_FILTERFACTORY), css::uno::UNO_QUERY_THROW);
856 : try
857 : {
858 237 : ::comphelper::SequenceAsHashMap lFilterProps(xFilterCont->getByName(sFilter));
859 237 : sal_Int32 nFlags = lFilterProps.getUnpackedValueOrDefault(FILTERPROP_FLAGS, (sal_Int32)0);
860 237 : bIsOwnTemplate = ((nFlags & FILTERFLAG_TEMPLATEPATH) == FILTERFLAG_TEMPLATEPATH);
861 : }
862 0 : catch(const css::container::NoSuchElementException&)
863 237 : {}
864 : }
865 237 : if (bIsOwnTemplate)
866 : {
867 : // SAFE ->
868 1 : aWriteLock.lock();
869 : // Dont overwrite external decisions! See comments before ...
870 1 : ::comphelper::MediaDescriptor::const_iterator pAsTemplateItem = m_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_ASTEMPLATE());
871 1 : if (pAsTemplateItem == m_lMediaDescriptor.end())
872 1 : m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_ASTEMPLATE()] <<= sal_True;
873 1 : aWriteLock.unlock();
874 : // <- SAFE
875 237 : }
876 : }
877 :
878 :
879 0 : sal_Bool LoadEnv::impl_handleContent()
880 : throw(LoadEnvException, css::uno::RuntimeException)
881 : {
882 : // SAFE -> -----------------------------------
883 0 : ReadGuard aReadLock(m_aLock);
884 :
885 : // the type must exist inside the descriptor ... otherwhise this class is implemented wrong :-)
886 0 : ::rtl::OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), ::rtl::OUString());
887 0 : if (sType.isEmpty())
888 0 : throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
889 :
890 : // convert media descriptor and URL to right format for later interface call!
891 0 : css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
892 0 : m_lMediaDescriptor >> lDescriptor;
893 0 : css::util::URL aURL = m_aURL;
894 :
895 : // get neccessary container to query for a handler object
896 0 : css::uno::Reference< css::lang::XMultiServiceFactory > xFactory(m_xSMGR->createInstance(SERVICENAME_CONTENTHANDLERFACTORY), css::uno::UNO_QUERY);
897 0 : css::uno::Reference< css::container::XContainerQuery > xQuery (xFactory , css::uno::UNO_QUERY);
898 :
899 0 : aReadLock.unlock();
900 : // <- SAFE -----------------------------------
901 :
902 : // query
903 0 : css::uno::Sequence< ::rtl::OUString > lTypeReg(1);
904 0 : lTypeReg[0] = sType;
905 :
906 0 : css::uno::Sequence< css::beans::NamedValue > lQuery(1);
907 0 : lQuery[0].Name = rtl::OUString(PROP_TYPES);
908 0 : lQuery[0].Value <<= lTypeReg;
909 :
910 0 : ::rtl::OUString sPROP_NAME(PROP_NAME);
911 :
912 0 : css::uno::Reference< css::container::XEnumeration > xSet = xQuery->createSubSetEnumerationByProperties(lQuery);
913 0 : while(xSet->hasMoreElements())
914 : {
915 0 : ::comphelper::SequenceAsHashMap lProps (xSet->nextElement());
916 0 : ::rtl::OUString sHandler = lProps.getUnpackedValueOrDefault(sPROP_NAME, ::rtl::OUString());
917 :
918 0 : css::uno::Reference< css::frame::XNotifyingDispatch > xHandler;
919 : try
920 : {
921 0 : xHandler = css::uno::Reference< css::frame::XNotifyingDispatch >(xFactory->createInstance(sHandler), css::uno::UNO_QUERY);
922 0 : if (!xHandler.is())
923 0 : continue;
924 : }
925 0 : catch(const css::uno::RuntimeException&)
926 0 : { throw; }
927 0 : catch(const css::uno::Exception&)
928 0 : { continue; }
929 :
930 : // SAFE -> -----------------------------------
931 0 : WriteGuard aWriteLock(m_aLock);
932 0 : m_xAsynchronousJob = xHandler;
933 0 : LoadEnvListener* pListener = new LoadEnvListener(this);
934 0 : aWriteLock.unlock();
935 : // <- SAFE -----------------------------------
936 :
937 0 : css::uno::Reference< css::frame::XDispatchResultListener > xListener(static_cast< css::frame::XDispatchResultListener* >(pListener), css::uno::UNO_QUERY);
938 0 : xHandler->dispatchWithNotification(aURL, lDescriptor, xListener);
939 :
940 0 : return sal_True;
941 0 : }
942 :
943 0 : return sal_False;
944 : }
945 :
946 : //-----------------------------------------------
947 236 : sal_Bool LoadEnv::impl_furtherDocsAllowed()
948 : {
949 : // SAFE ->
950 236 : ReadGuard aReadLock(m_aLock);
951 236 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
952 236 : aReadLock.unlock();
953 : // <- SAFE
954 :
955 236 : sal_Bool bAllowed = sal_True;
956 :
957 : try
958 : {
959 : css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey(
960 : comphelper::getComponentContext(xSMGR),
961 : ::rtl::OUString("org.openoffice.Office.Common/"),
962 : ::rtl::OUString("Misc"),
963 : ::rtl::OUString("MaxOpenDocuments"),
964 236 : ::comphelper::ConfigurationHelper::E_READONLY);
965 :
966 : // NIL means: count of allowed documents = infinite !
967 : // => return sal_True
968 236 : if ( ! aVal.hasValue())
969 236 : bAllowed = sal_True;
970 : else
971 : {
972 0 : sal_Int32 nMaxOpenDocuments = 0;
973 0 : aVal >>= nMaxOpenDocuments;
974 :
975 : css::uno::Reference< css::frame::XFramesSupplier > xDesktop(
976 : css::frame::Desktop::create( comphelper::getComponentContext(xSMGR)),
977 0 : css::uno::UNO_QUERY_THROW);
978 :
979 : FrameListAnalyzer aAnalyzer(xDesktop,
980 : css::uno::Reference< css::frame::XFrame >(),
981 : FrameListAnalyzer::E_HELP |
982 : FrameListAnalyzer::E_BACKINGCOMPONENT |
983 0 : FrameListAnalyzer::E_HIDDEN);
984 :
985 0 : sal_Int32 nOpenDocuments = aAnalyzer.m_lOtherVisibleFrames.getLength();
986 0 : bAllowed = (nOpenDocuments < nMaxOpenDocuments);
987 236 : }
988 : }
989 0 : catch(const css::uno::Exception&)
990 0 : { bAllowed = sal_True; } // !! internal errors are no reason to disturb the office from opening documents .-)
991 :
992 236 : if ( ! bAllowed )
993 : {
994 : // SAFE ->
995 0 : aReadLock.lock();
996 : css::uno::Reference< css::task::XInteractionHandler > xInteraction = m_lMediaDescriptor.getUnpackedValueOrDefault(
997 0 : ::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER(),
998 0 : css::uno::Reference< css::task::XInteractionHandler >());
999 0 : aReadLock.unlock();
1000 : // <- SAFE
1001 :
1002 0 : if (xInteraction.is())
1003 : {
1004 0 : css::uno::Any aInteraction;
1005 0 : css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations(2);
1006 :
1007 0 : comphelper::OInteractionAbort* pAbort = new comphelper::OInteractionAbort();
1008 0 : comphelper::OInteractionApprove* pApprove = new comphelper::OInteractionApprove();
1009 :
1010 0 : lContinuations[0] = css::uno::Reference< css::task::XInteractionContinuation >(
1011 0 : static_cast< css::task::XInteractionContinuation* >(pAbort),
1012 0 : css::uno::UNO_QUERY_THROW);
1013 0 : lContinuations[1] = css::uno::Reference< css::task::XInteractionContinuation >(
1014 0 : static_cast< css::task::XInteractionContinuation* >(pApprove),
1015 0 : css::uno::UNO_QUERY_THROW);
1016 :
1017 0 : css::task::ErrorCodeRequest aErrorCode;
1018 0 : aErrorCode.ErrCode = ERRCODE_SFX_NOMOREDOCUMENTSALLOWED;
1019 0 : aInteraction <<= aErrorCode;
1020 0 : xInteraction->handle( InteractionRequest::CreateRequest(aInteraction, lContinuations) );
1021 0 : }
1022 : }
1023 :
1024 236 : return bAllowed;
1025 : }
1026 :
1027 : //-----------------------------------------------
1028 241 : sal_Bool LoadEnv::impl_loadContent()
1029 : throw(LoadEnvException, css::uno::RuntimeException)
1030 : {
1031 : // SAFE -> -----------------------------------
1032 241 : WriteGuard aWriteLock(m_aLock);
1033 :
1034 : // search or create right target frame
1035 241 : ::rtl::OUString sTarget = m_sTarget;
1036 241 : if (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::E_DEFAULT))
1037 : {
1038 237 : m_xTargetFrame = impl_searchAlreadyLoaded();
1039 237 : if (m_xTargetFrame.is())
1040 : {
1041 1 : impl_setResult(sal_True);
1042 1 : return sal_True;
1043 : }
1044 236 : m_xTargetFrame = impl_searchRecycleTarget();
1045 : }
1046 :
1047 240 : if (! m_xTargetFrame.is())
1048 : {
1049 480 : if (
1050 240 : (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::E_BLANK )) ||
1051 240 : (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::E_DEFAULT))
1052 : )
1053 : {
1054 236 : if (! impl_furtherDocsAllowed())
1055 0 : return sal_False;
1056 236 : m_xTargetFrame = m_xBaseFrame->findFrame(SPECIALTARGET_BLANK, 0);
1057 236 : m_bCloseFrameOnError = m_xTargetFrame.is();
1058 : }
1059 : else
1060 : {
1061 4 : sal_Int32 nFlags = m_nSearchFlags & ~css::frame::FrameSearchFlag::CREATE;
1062 4 : m_xTargetFrame = m_xBaseFrame->findFrame(sTarget, nFlags);
1063 4 : if (! m_xTargetFrame.is())
1064 : {
1065 0 : if (! impl_furtherDocsAllowed())
1066 0 : return sal_False;
1067 0 : m_xTargetFrame = m_xBaseFrame->findFrame(SPECIALTARGET_BLANK, 0);
1068 0 : m_bCloseFrameOnError = m_xTargetFrame.is();
1069 : }
1070 : }
1071 : }
1072 :
1073 : // If we couldn't find a valid frame or the frame has no container window
1074 : // we have to throw an exception.
1075 1200 : if (
1076 240 : ( ! m_xTargetFrame.is() ) ||
1077 720 : ( ! m_xTargetFrame->getContainerWindow().is() )
1078 : )
1079 0 : throw LoadEnvException(LoadEnvException::ID_NO_TARGET_FOUND);
1080 :
1081 240 : css::uno::Reference< css::frame::XFrame > xTargetFrame = m_xTargetFrame;
1082 :
1083 : // Now we have a valid frame ... and type detection was already done.
1084 : // We should apply the module dependend window position and size to the
1085 : // frame window.
1086 240 : impl_applyPersistentWindowState(xTargetFrame->getContainerWindow());
1087 :
1088 : // Don't forget to lock task for following load process. Otherwise it could die
1089 : // during this operation runs by terminating the office or closing this task via api.
1090 : // If we set this lock "close()" will return false and closing will be broken.
1091 : // Attention: Don't forget to reset this lock again after finishing operation.
1092 : // Otherwise task AND office couldn't die!!!
1093 : // This includes gracefully handling of Exceptions (Runtime!) too ...
1094 : // Thats why we use a specialized guard, which will reset the lock
1095 : // if it will be run out of scope.
1096 :
1097 : // Note further: ignore if this internal guard already contains a resource.
1098 : // Might impl_searchRecylcTarget() set it before. But incase this impl-method wasnt used
1099 : // and the target frame was new created ... this lock here must be set!
1100 240 : css::uno::Reference< css::document::XActionLockable > xTargetLock(xTargetFrame, css::uno::UNO_QUERY);
1101 240 : m_aTargetLock.setResource(xTargetLock);
1102 :
1103 : // Add status indicator to descriptor. Loader can show an progresses then.
1104 : // But don't do it, if loading should be hidden or preview is used ...!
1105 : // So we prevent our code against wrong using. Why?
1106 : // It could be, that using of this progress could make trouble. e.g. He make window visible ...
1107 : // but shouldn't do that. But if no indicator is available ... nobody has a chance to do that!
1108 240 : sal_Bool bHidden = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN() , sal_False );
1109 240 : sal_Bool bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_MINIMIZED() , sal_False );
1110 240 : sal_Bool bPreview = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_PREVIEW() , sal_False );
1111 240 : css::uno::Reference< css::task::XStatusIndicator > xProgress = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), css::uno::Reference< css::task::XStatusIndicator >());
1112 :
1113 240 : if (!bHidden && !bMinimized && !bPreview && !xProgress.is())
1114 : {
1115 : // Note: its an optional interface!
1116 236 : css::uno::Reference< css::task::XStatusIndicatorFactory > xProgressFactory(xTargetFrame, css::uno::UNO_QUERY);
1117 236 : if (xProgressFactory.is())
1118 : {
1119 236 : xProgress = xProgressFactory->createStatusIndicator();
1120 236 : if (xProgress.is())
1121 236 : m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_STATUSINDICATOR()] <<= xProgress;
1122 236 : }
1123 : }
1124 :
1125 : // convert media descriptor and URL to right format for later interface call!
1126 240 : css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
1127 240 : m_lMediaDescriptor >> lDescriptor;
1128 240 : ::rtl::OUString sURL = m_aURL.Complete;
1129 :
1130 : // try to locate any interested frame loader
1131 240 : css::uno::Reference< css::uno::XInterface > xLoader = impl_searchLoader();
1132 240 : css::uno::Reference< css::frame::XFrameLoader > xAsyncLoader(xLoader, css::uno::UNO_QUERY);
1133 240 : css::uno::Reference< css::frame::XSynchronousFrameLoader > xSyncLoader (xLoader, css::uno::UNO_QUERY);
1134 :
1135 240 : if (xAsyncLoader.is())
1136 : {
1137 : // SAFE -> -----------------------------------
1138 0 : aWriteLock.lock();
1139 0 : m_xAsynchronousJob = xAsyncLoader;
1140 0 : LoadEnvListener* pListener = new LoadEnvListener(this);
1141 0 : aWriteLock.unlock();
1142 : // <- SAFE -----------------------------------
1143 :
1144 0 : css::uno::Reference< css::frame::XLoadEventListener > xListener(static_cast< css::frame::XLoadEventListener* >(pListener), css::uno::UNO_QUERY);
1145 0 : xAsyncLoader->load(xTargetFrame, sURL, lDescriptor, xListener);
1146 :
1147 0 : return sal_True;
1148 : }
1149 240 : else if (xSyncLoader.is())
1150 : {
1151 240 : sal_Bool bResult = xSyncLoader->load(lDescriptor, xTargetFrame);
1152 : // react for the result here, so the outside waiting
1153 : // code can ask for it later.
1154 240 : impl_setResult(bResult);
1155 : // But the return value indicates a valid started(!) operation.
1156 : // And thats true everxtimes, we reach this line :-)
1157 240 : return sal_True;
1158 : }
1159 :
1160 0 : aWriteLock.unlock();
1161 : // <- SAFE
1162 :
1163 0 : return sal_False;
1164 : }
1165 :
1166 :
1167 240 : css::uno::Reference< css::uno::XInterface > LoadEnv::impl_searchLoader()
1168 : {
1169 : // SAFE -> -----------------------------------
1170 240 : ReadGuard aReadLock(m_aLock);
1171 :
1172 : // special mode to set an existing component on this frame
1173 : // In such case the laoder is fix. It must be the SFX based implementation,
1174 : // which can create a view on top of such xModel components :-)
1175 240 : if (m_eContentType == E_CAN_BE_SET)
1176 : {
1177 : try
1178 : {
1179 4 : return m_xSMGR->createInstance(IMPLEMENTATIONNAME_GENERICFRAMELOADER);
1180 : }
1181 0 : catch(const css::uno::RuntimeException&)
1182 0 : { throw; }
1183 0 : catch(const css::uno::Exception&)
1184 : {}
1185 0 : throw LoadEnvException(LoadEnvException::ID_INVALID_ENVIRONMENT);
1186 : }
1187 :
1188 : // Otherwhise ...
1189 : // We need this type information to locate an registered frame loader
1190 : // Without such information we can't work!
1191 236 : ::rtl::OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), ::rtl::OUString());
1192 236 : if (sType.isEmpty())
1193 0 : throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
1194 :
1195 : // try to locate any interested frame loader
1196 236 : css::uno::Reference< css::lang::XMultiServiceFactory > xLoaderFactory(m_xSMGR->createInstance(SERVICENAME_FRAMELOADERFACTORY), css::uno::UNO_QUERY);
1197 236 : css::uno::Reference< css::container::XContainerQuery > xQuery (xLoaderFactory , css::uno::UNO_QUERY);
1198 :
1199 236 : aReadLock.unlock();
1200 : // <- SAFE -----------------------------------
1201 :
1202 236 : css::uno::Sequence< ::rtl::OUString > lTypesReg(1);
1203 236 : lTypesReg[0] = sType;
1204 :
1205 236 : css::uno::Sequence< css::beans::NamedValue > lQuery(1);
1206 236 : lQuery[0].Name = rtl::OUString(PROP_TYPES);
1207 236 : lQuery[0].Value <<= lTypesReg;
1208 :
1209 236 : ::rtl::OUString sPROP_NAME(PROP_NAME);
1210 :
1211 236 : css::uno::Reference< css::container::XEnumeration > xSet = xQuery->createSubSetEnumerationByProperties(lQuery);
1212 472 : while(xSet->hasMoreElements())
1213 : {
1214 : // try everyone ...
1215 : // Ignore any loader, which makes trouble :-)
1216 236 : ::comphelper::SequenceAsHashMap lLoaderProps(xSet->nextElement());
1217 236 : ::rtl::OUString sLoader = lLoaderProps.getUnpackedValueOrDefault(sPROP_NAME, ::rtl::OUString());
1218 236 : css::uno::Reference< css::uno::XInterface > xLoader ;
1219 : try
1220 : {
1221 236 : xLoader = xLoaderFactory->createInstance(sLoader);
1222 236 : if (xLoader.is())
1223 236 : return xLoader;
1224 : }
1225 0 : catch(const css::uno::RuntimeException&)
1226 0 : { throw; }
1227 0 : catch(const css::uno::Exception&)
1228 0 : { continue; }
1229 236 : }
1230 :
1231 0 : return css::uno::Reference< css::uno::XInterface >();
1232 : }
1233 :
1234 :
1235 0 : void LoadEnv::impl_jumpToMark(const css::uno::Reference< css::frame::XFrame >& xFrame,
1236 : const css::util::URL& aURL )
1237 : {
1238 0 : if (aURL.Mark.isEmpty())
1239 : return;
1240 :
1241 0 : css::uno::Reference< css::frame::XDispatchProvider > xProvider(xFrame, css::uno::UNO_QUERY);
1242 0 : if (! xProvider.is())
1243 : return;
1244 :
1245 : // SAFE ->
1246 0 : ReadGuard aReadLock(m_aLock);
1247 0 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1248 0 : aReadLock.unlock();
1249 : // <- SAFE
1250 :
1251 0 : css::util::URL aCmd;
1252 0 : aCmd.Complete = ::rtl::OUString(".uno:JumpToMark");
1253 :
1254 0 : css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(::comphelper::getComponentContext(m_xSMGR)));
1255 0 : xParser->parseStrict(aCmd);
1256 :
1257 0 : css::uno::Reference< css::frame::XDispatch > xDispatcher = xProvider->queryDispatch(aCmd, SPECIALTARGET_SELF, 0);
1258 0 : if (! xDispatcher.is())
1259 : return;
1260 :
1261 0 : ::comphelper::SequenceAsHashMap lArgs;
1262 0 : lArgs[::rtl::OUString("Bookmark")] <<= aURL.Mark;
1263 0 : xDispatcher->dispatch(aCmd, lArgs.getAsConstPropertyValueList());
1264 : }
1265 :
1266 :
1267 237 : css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchAlreadyLoaded()
1268 : throw(LoadEnvException, css::uno::RuntimeException)
1269 : {
1270 : // SAFE ->
1271 237 : ReadGuard aReadLock(m_aLock);
1272 :
1273 : // such search is allowed for special requests only ...
1274 : // or better its not allowed for some requests in general :-)
1275 1657 : if (
1276 237 : ( ! TargetHelper::matchSpecialTarget(m_sTarget, TargetHelper::E_DEFAULT) ) ||
1277 711 : (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_ASTEMPLATE() , sal_False) == sal_True) ||
1278 : // (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN() , sal_False) == sal_True) ||
1279 709 : (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_OPENNEWVIEW(), sal_False) == sal_True)
1280 : )
1281 : {
1282 1 : return css::uno::Reference< css::frame::XFrame >();
1283 : }
1284 :
1285 : // check URL
1286 : // May its not useful to start expensive document search, if it
1287 : // can fail only .. because we load from a stream or model directly!
1288 472 : if (
1289 236 : (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_STREAM )) ||
1290 236 : (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_OBJECT ))
1291 : /*TODO should be private:factory here tested too? */
1292 : )
1293 : {
1294 0 : return css::uno::Reference< css::frame::XFrame >();
1295 : }
1296 :
1297 : // otherwhise - iterate through the tasks of the desktop container
1298 : // to find out, which of them might contains the requested document
1299 236 : css::uno::Reference< css::frame::XDesktop2 > xSupplier = css::frame::Desktop::create( comphelper::getComponentContext(m_xSMGR) );
1300 236 : css::uno::Reference< css::container::XIndexAccess > xTaskList(xSupplier->getFrames() , css::uno::UNO_QUERY);
1301 :
1302 236 : if (!xTaskList.is())
1303 0 : return css::uno::Reference< css::frame::XFrame >(); // task list can be empty!
1304 :
1305 : // Note: To detect if a document was alrady loaded before
1306 : // we check URLs here only. But might the existing and the required
1307 : // document has different versions! Then its URLs are the same ...
1308 236 : sal_Int16 nNewVersion = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_VERSION(), (sal_Int16)(-1));
1309 :
1310 : // will be used to save the first hidden frame referring the searched model
1311 : // Normally we are interested on visible frames ... but if there is no such visible
1312 : // frame we referr to any hidden frame also (but as fallback only).
1313 236 : css::uno::Reference< css::frame::XFrame > xHiddenTask;
1314 236 : css::uno::Reference< css::frame::XFrame > xTask;
1315 :
1316 236 : sal_Int32 count = xTaskList->getCount();
1317 4887 : for (sal_Int32 i=0; i<count; ++i)
1318 : {
1319 : try
1320 : {
1321 : // locate model of task
1322 : // Note: Without a model there is no chance to decide if
1323 : // this task contains the searched document or not!
1324 4652 : xTaskList->getByIndex(i) >>= xTask;
1325 4652 : if (!xTask.is())
1326 0 : continue;
1327 :
1328 4652 : css::uno::Reference< css::frame::XController > xController = xTask->getController();
1329 4652 : if (!xController.is())
1330 : {
1331 0 : xTask.clear ();
1332 0 : continue;
1333 : }
1334 :
1335 4652 : css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
1336 4652 : if (!xModel.is())
1337 : {
1338 0 : xTask.clear ();
1339 0 : continue;
1340 : }
1341 :
1342 : // don't check the complete URL here.
1343 : // use its main part - ignore optional jumpmarks!
1344 4652 : const ::rtl::OUString sURL = xModel->getURL();
1345 4652 : if (!::utl::UCBContentHelper::EqualURLs( m_aURL.Main, sURL ))
1346 : {
1347 4651 : xTask.clear ();
1348 4651 : continue;
1349 : }
1350 :
1351 : // get the original load arguments from the current document
1352 : // and decide if its really the same then the one will be.
1353 : // It must be visible and must use the same file revision ...
1354 : // or must not have any file revision set (-1 == -1!)
1355 1 : ::comphelper::MediaDescriptor lOldDocDescriptor(xModel->getArgs());
1356 :
1357 1 : if (lOldDocDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_VERSION(), (sal_Int32)(-1)) != nNewVersion)
1358 : {
1359 0 : xTask.clear ();
1360 0 : continue;
1361 : }
1362 :
1363 : // Hidden frames are special.
1364 : // They will be used as "last chance" if there is no visible frame pointing to the same model.
1365 : // Safe the result but continue with current loop might be looking for other visible frames.
1366 1 : ::sal_Bool bIsHidden = lOldDocDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False);
1367 1 : if (
1368 : ( bIsHidden ) &&
1369 0 : ( ! xHiddenTask.is())
1370 : )
1371 : {
1372 0 : xHiddenTask = xTask;
1373 0 : xTask.clear ();
1374 0 : continue;
1375 : }
1376 :
1377 : // We found a visible task pointing to the right model ...
1378 : // Break search.
1379 1 : break;
1380 : }
1381 0 : catch(const css::uno::RuntimeException&)
1382 0 : { throw; }
1383 0 : catch(const css::uno::Exception&)
1384 0 : { continue; }
1385 : }
1386 :
1387 236 : css::uno::Reference< css::frame::XFrame > xResult;
1388 236 : if (xTask.is())
1389 1 : xResult = xTask;
1390 235 : else if (xHiddenTask.is())
1391 0 : xResult = xHiddenTask;
1392 :
1393 236 : if (xResult.is())
1394 : {
1395 : // Now we are sure, that this task includes the searched document.
1396 : // It's time to activate it. As special feature we try to jump internally
1397 : // if an optional jumpmark is given too.
1398 1 : if (!m_aURL.Mark.isEmpty())
1399 0 : impl_jumpToMark(xResult, m_aURL);
1400 :
1401 : // bring it to front and make sure it's visible...
1402 1 : impl_makeFrameWindowVisible(xResult->getContainerWindow(), sal_True);
1403 : }
1404 :
1405 236 : aReadLock.unlock();
1406 : // <- SAFE
1407 :
1408 236 : return xResult;
1409 : }
1410 :
1411 :
1412 0 : sal_Bool LoadEnv::impl_isFrameAlreadyUsedForLoading(const css::uno::Reference< css::frame::XFrame >& xFrame) const
1413 : {
1414 0 : css::uno::Reference< css::document::XActionLockable > xLock(xFrame, css::uno::UNO_QUERY);
1415 :
1416 : // ? no lock interface ?
1417 : // Might its an external written frame implementation :-(
1418 : // Allowing using of it ... but it can fail if its not synchronized with our processes !
1419 0 : if (!xLock.is())
1420 0 : return sal_False;
1421 :
1422 : // Otherwise we have to look for any other existing lock.
1423 0 : return xLock->isActionLocked();
1424 : }
1425 :
1426 :
1427 236 : css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchRecycleTarget()
1428 : throw(LoadEnvException, css::uno::RuntimeException)
1429 : {
1430 : // SAFE -> ..................................
1431 236 : ReadGuard aReadLock(m_aLock);
1432 :
1433 : // The special backing mode frame will be recycled by definition!
1434 : // It doesn't matter if somehwere whish to create a new view
1435 : // or open a new untitled document ...
1436 : // The only exception form that - hidden frames!
1437 236 : if (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False) == sal_True)
1438 0 : return css::uno::Reference< css::frame::XFrame >();
1439 :
1440 236 : css::uno::Reference< css::frame::XFramesSupplier > xSupplier( css::frame::Desktop::create( comphelper::getComponentContext(m_xSMGR) ), css::uno::UNO_QUERY);
1441 236 : FrameListAnalyzer aTasksAnalyzer(xSupplier, css::uno::Reference< css::frame::XFrame >(), FrameListAnalyzer::E_BACKINGCOMPONENT);
1442 236 : if (aTasksAnalyzer.m_xBackingComponent.is())
1443 : {
1444 0 : if (!impl_isFrameAlreadyUsedForLoading(aTasksAnalyzer.m_xBackingComponent))
1445 : {
1446 : // bring it to front ...
1447 0 : impl_makeFrameWindowVisible(aTasksAnalyzer.m_xBackingComponent->getContainerWindow(), sal_True);
1448 0 : return aTasksAnalyzer.m_xBackingComponent;
1449 : }
1450 : }
1451 :
1452 : // These states indicates a wish for creation of a new view in general.
1453 1414 : if (
1454 708 : (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_ASTEMPLATE() , sal_False) == sal_True) ||
1455 706 : (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_OPENNEWVIEW(), sal_False) == sal_True)
1456 : )
1457 : {
1458 1 : return css::uno::Reference< css::frame::XFrame >();
1459 : }
1460 :
1461 : // On the other side some special URLs will open a new frame everytimes (expecting
1462 : // they can use the backing-mode frame!)
1463 705 : if (
1464 235 : (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_FACTORY )) ||
1465 235 : (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_STREAM )) ||
1466 235 : (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_OBJECT ))
1467 : )
1468 : {
1469 0 : return css::uno::Reference< css::frame::XFrame >();
1470 : }
1471 :
1472 : // No backing frame! No special URL => recycle active task - if possible.
1473 : // Means - if it does not already contains a modified document, or
1474 : // use another office module.
1475 235 : css::uno::Reference< css::frame::XFrame > xTask = xSupplier->getActiveFrame();
1476 :
1477 : // not a real error - but might a focus problem!
1478 235 : if (!xTask.is())
1479 134 : return css::uno::Reference< css::frame::XFrame >();
1480 :
1481 : // not a real error - may its a view only
1482 101 : css::uno::Reference< css::frame::XController > xController = xTask->getController();
1483 101 : if (!xController.is())
1484 0 : return css::uno::Reference< css::frame::XFrame >();
1485 :
1486 : // not a real error - may its a db component instead of a full feartured office document
1487 101 : css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
1488 101 : if (!xModel.is())
1489 0 : return css::uno::Reference< css::frame::XFrame >();
1490 :
1491 : // get some more informations ...
1492 :
1493 : // A valid set URL means: there is already a location for this document.
1494 : // => it was saved there or opened from there. Such Documents can not be used here.
1495 : // We search for empty document ... created by a private:factory/ URL!
1496 101 : if (xModel->getURL().getLength()>0)
1497 100 : return css::uno::Reference< css::frame::XFrame >();
1498 :
1499 : // The old document must be unmodified ...
1500 1 : css::uno::Reference< css::util::XModifiable > xModified(xModel, css::uno::UNO_QUERY);
1501 1 : if (xModified->isModified())
1502 1 : return css::uno::Reference< css::frame::XFrame >();
1503 :
1504 0 : Window* pWindow = VCLUnoHelper::GetWindow(xTask->getContainerWindow());
1505 0 : if (pWindow && pWindow->IsInModalMode())
1506 0 : return css::uno::Reference< css::frame::XFrame >();
1507 :
1508 : // find out the application type of this document
1509 : // We can recycle only documents, which uses the same application
1510 : // then the new one.
1511 0 : SvtModuleOptions::EFactory eOldApp = SvtModuleOptions::ClassifyFactoryByModel(xModel);
1512 0 : SvtModuleOptions::EFactory eNewApp = SvtModuleOptions::ClassifyFactoryByURL (m_aURL.Complete, m_lMediaDescriptor.getAsConstPropertyValueList());
1513 :
1514 0 : aReadLock.unlock();
1515 : // <- SAFE ..................................
1516 :
1517 0 : if (eOldApp != eNewApp)
1518 0 : return css::uno::Reference< css::frame::XFrame >();
1519 :
1520 : // OK this task seams to be useable for recycling
1521 : // But we should mark it as such - means set an action lock.
1522 : // Otherwhise it would be used more then ones or will be destroyed
1523 : // by a close() or terminate() request.
1524 : // But if such lock already exist ... it means this task is used for
1525 : // any other operation already. Don't use it then.
1526 0 : if (impl_isFrameAlreadyUsedForLoading(xTask))
1527 0 : return css::uno::Reference< css::frame::XFrame >();
1528 :
1529 : // OK - there is a valid target frame.
1530 : // But may be it contains already a document.
1531 : // Then we have to ask it, if it allows recylcing of this frame .-)
1532 0 : sal_Bool bReactivateOldControllerOnError = sal_False;
1533 0 : css::uno::Reference< css::frame::XController > xOldDoc = xTask->getController();
1534 0 : if (xOldDoc.is())
1535 : {
1536 0 : bReactivateOldControllerOnError = xOldDoc->suspend(sal_True);
1537 0 : if (! bReactivateOldControllerOnError)
1538 0 : return css::uno::Reference< css::frame::XFrame >();
1539 : }
1540 :
1541 : // SAFE -> ..................................
1542 0 : WriteGuard aWriteLock(m_aLock);
1543 :
1544 0 : css::uno::Reference< css::document::XActionLockable > xLock(xTask, css::uno::UNO_QUERY);
1545 0 : if (!m_aTargetLock.setResource(xLock))
1546 0 : return css::uno::Reference< css::frame::XFrame >();
1547 :
1548 0 : m_bReactivateControllerOnError = bReactivateOldControllerOnError;
1549 0 : aWriteLock.unlock();
1550 : // <- SAFE ..................................
1551 :
1552 : // bring it to front ...
1553 0 : impl_makeFrameWindowVisible(xTask->getContainerWindow(), sal_True);
1554 :
1555 0 : return xTask;
1556 : }
1557 :
1558 :
1559 241 : void LoadEnv::impl_reactForLoadingState()
1560 : throw(LoadEnvException, css::uno::RuntimeException)
1561 : {
1562 : /*TODO reset action locks */
1563 :
1564 : // SAFE -> ----------------------------------
1565 241 : ReadGuard aReadLock(m_aLock);
1566 :
1567 241 : if (m_bLoaded)
1568 : {
1569 : // Bring the new loaded document to front (if allowed!).
1570 : // Note: We show new created frames here only.
1571 : // We dont hide already visible frames here ...
1572 241 : css::uno::Reference< css::awt::XWindow > xWindow = m_xTargetFrame->getContainerWindow();
1573 241 : sal_Bool bHidden = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False);
1574 241 : sal_Bool bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_MINIMIZED(), sal_False);
1575 :
1576 241 : if (bMinimized)
1577 : {
1578 0 : SolarMutexGuard aSolarGuard;
1579 0 : Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
1580 : // check for system window is neccessary to guarantee correct pointer cast!
1581 0 : if (pWindow && pWindow->IsSystemWindow())
1582 0 : ((WorkWindow*)pWindow)->Minimize();
1583 : }
1584 241 : else if (!bHidden)
1585 : {
1586 : // show frame ... if it's not still visible ...
1587 : // But do nothing if it's already visible!
1588 237 : impl_makeFrameWindowVisible(xWindow, sal_False);
1589 : }
1590 :
1591 : // Note: Only if an existing property "FrameName" is given by this media descriptor,
1592 : // it should be used. Otherwhise we should do nothing. May be the outside code has already
1593 : // set a frame name on the target!
1594 241 : ::comphelper::MediaDescriptor::const_iterator pFrameName = m_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_FRAMENAME());
1595 241 : if (pFrameName != m_lMediaDescriptor.end())
1596 : {
1597 0 : ::rtl::OUString sFrameName;
1598 0 : pFrameName->second >>= sFrameName;
1599 : // Check the name again. e.g. "_default" isnt allowed.
1600 : // On the other side "_beamer" is a valid name :-)
1601 0 : if (TargetHelper::isValidNameForFrame(sFrameName))
1602 0 : m_xTargetFrame->setName(sFrameName);
1603 241 : }
1604 : }
1605 0 : else if (m_bReactivateControllerOnError)
1606 : {
1607 : // Try to reactivate the old document (if any exists!)
1608 0 : css::uno::Reference< css::frame::XController > xOldDoc = m_xTargetFrame->getController();
1609 : // clear does not depend from reactivation state of a might existing old document!
1610 : // We must make sure, that a might following getTargetComponent() call does not return
1611 : // the old document!
1612 0 : m_xTargetFrame.clear();
1613 0 : if (xOldDoc.is())
1614 : {
1615 0 : sal_Bool bReactivated = xOldDoc->suspend(sal_False);
1616 0 : if (!bReactivated)
1617 0 : throw LoadEnvException(LoadEnvException::ID_COULD_NOT_REACTIVATE_CONTROLLER);
1618 0 : m_bReactivateControllerOnError = sal_False;
1619 0 : }
1620 : }
1621 0 : else if (m_bCloseFrameOnError)
1622 : {
1623 : // close empty frames
1624 0 : css::uno::Reference< css::util::XCloseable > xCloseable (m_xTargetFrame, css::uno::UNO_QUERY);
1625 0 : css::uno::Reference< css::lang::XComponent > xDisposable(m_xTargetFrame, css::uno::UNO_QUERY);
1626 :
1627 : try
1628 : {
1629 0 : if (xCloseable.is())
1630 0 : xCloseable->close(sal_True);
1631 : else
1632 0 : if (xDisposable.is())
1633 0 : xDisposable->dispose();
1634 : }
1635 0 : catch(const css::util::CloseVetoException&)
1636 : {}
1637 0 : catch(const css::lang::DisposedException&)
1638 : {}
1639 0 : m_xTargetFrame.clear();
1640 : }
1641 :
1642 : // This max force an implicit closing of our target frame ...
1643 : // e.g. in case close(sal_True) was called before and the frame
1644 : // kill itself if our external use-lock is released here!
1645 : // Thats why we releas this lock AFTER ALL OPERATIONS on this frame
1646 : // are finished. The frame itslef must handle then
1647 : // this situation gracefully.
1648 241 : m_aTargetLock.freeResource();
1649 :
1650 : // Last but not least :-)
1651 : // We have to clear the current media descriptor.
1652 : // Otherwhise it hold a might existing stream open!
1653 241 : m_lMediaDescriptor.clear();
1654 :
1655 241 : css::uno::Any aRequest;
1656 241 : bool bThrow = false;
1657 241 : if ( !m_bLoaded && m_pQuietInteraction && m_pQuietInteraction->wasUsed() )
1658 : {
1659 0 : aRequest = m_pQuietInteraction->getRequest();
1660 0 : m_pQuietInteraction->release();
1661 0 : m_pQuietInteraction = 0;
1662 0 : bThrow = true;
1663 : }
1664 :
1665 241 : aReadLock.unlock();
1666 :
1667 241 : if (bThrow)
1668 : {
1669 0 : if ( aRequest.isExtractableTo( ::cppu::UnoType< css::uno::Exception >::get() ) )
1670 0 : throw LoadEnvException( LoadEnvException::ID_GENERAL_ERROR, aRequest );
1671 241 : }
1672 :
1673 : // <- SAFE ----------------------------------
1674 241 : }
1675 :
1676 :
1677 238 : void LoadEnv::impl_makeFrameWindowVisible(const css::uno::Reference< css::awt::XWindow >& xWindow ,
1678 : sal_Bool bForceToFront)
1679 : {
1680 : // SAFE -> ----------------------------------
1681 238 : ReadGuard aReadLock(m_aLock);
1682 238 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR( m_xSMGR.get(), css::uno::UNO_QUERY );
1683 238 : aReadLock.unlock();
1684 : // <- SAFE ----------------------------------
1685 :
1686 238 : SolarMutexGuard aSolarGuard;
1687 238 : Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
1688 238 : if ( pWindow )
1689 : {
1690 : bool const preview( m_lMediaDescriptor.getUnpackedValueOrDefault(
1691 238 : ::comphelper::MediaDescriptor::PROP_PREVIEW(), sal_False) );
1692 :
1693 238 : bool bForceFrontAndFocus(false);
1694 238 : if ( !preview )
1695 : {
1696 : css::uno::Any const a =
1697 : ::comphelper::ConfigurationHelper::readDirectKey(
1698 : comphelper::getComponentContext(xSMGR),
1699 : ::rtl::OUString("org.openoffice.Office.Common/View"),
1700 : ::rtl::OUString("NewDocumentHandling"),
1701 : ::rtl::OUString("ForceFocusAndToFront"),
1702 238 : ::comphelper::ConfigurationHelper::E_READONLY);
1703 238 : a >>= bForceFrontAndFocus;
1704 : }
1705 :
1706 238 : if( pWindow->IsVisible() && (bForceFrontAndFocus || bForceToFront) )
1707 144 : pWindow->ToTop();
1708 : else
1709 94 : pWindow->Show(sal_True, (bForceFrontAndFocus || bForceToFront) ? SHOW_FOREGROUNDTASK : 0 );
1710 238 : }
1711 238 : }
1712 :
1713 :
1714 240 : void LoadEnv::impl_applyPersistentWindowState(const css::uno::Reference< css::awt::XWindow >& xWindow)
1715 : {
1716 240 : static ::rtl::OUString PACKAGE_SETUP_MODULES("/org.openoffice.Setup/Office/Factories");
1717 :
1718 : // no window -> action not possible
1719 240 : if (!xWindow.is())
1720 : return;
1721 :
1722 : // window already visible -> do nothing! If we use a "recycle frame" for loading ...
1723 : // the current position and size must be used.
1724 240 : css::uno::Reference< css::awt::XWindow2 > xVisibleCheck(xWindow, css::uno::UNO_QUERY);
1725 480 : if (
1726 240 : (xVisibleCheck.is() ) &&
1727 240 : (xVisibleCheck->isVisible())
1728 : )
1729 : return;
1730 :
1731 : // SOLAR SAFE ->
1732 240 : SolarMutexClearableGuard aSolarGuard1;
1733 :
1734 240 : Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
1735 240 : if (!pWindow)
1736 : return;
1737 :
1738 240 : sal_Bool bSystemWindow = pWindow->IsSystemWindow();
1739 240 : sal_Bool bWorkWindow = (pWindow->GetType() == WINDOW_WORKWINDOW);
1740 :
1741 240 : if (!bSystemWindow && !bWorkWindow)
1742 : return;
1743 :
1744 : // dont overwrite this special state!
1745 240 : WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
1746 240 : if (pWorkWindow->IsMinimized())
1747 : return;
1748 :
1749 240 : aSolarGuard1.clear();
1750 : // <- SOLAR SAFE
1751 :
1752 : // SAFE ->
1753 240 : ReadGuard aReadLock(m_aLock);
1754 :
1755 : // no filter -> no module -> no persistent window state
1756 : ::rtl::OUString sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(
1757 240 : ::comphelper::MediaDescriptor::PROP_FILTERNAME(),
1758 480 : ::rtl::OUString());
1759 240 : if (sFilter.isEmpty())
1760 : return;
1761 :
1762 236 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1763 :
1764 236 : aReadLock.unlock();
1765 : // <- SAFE
1766 :
1767 : try
1768 : {
1769 : // retrieve the module name from the filter configuration
1770 : css::uno::Reference< css::container::XNameAccess > xFilterCfg(
1771 236 : xSMGR->createInstance(SERVICENAME_FILTERFACTORY),
1772 236 : css::uno::UNO_QUERY_THROW);
1773 236 : ::comphelper::SequenceAsHashMap lProps (xFilterCfg->getByName(sFilter));
1774 236 : ::rtl::OUString sModule = lProps.getUnpackedValueOrDefault(FILTER_PROPNAME_DOCUMENTSERVICE, ::rtl::OUString());
1775 :
1776 : // get access to the configuration of this office module
1777 : css::uno::Reference< css::container::XNameAccess > xModuleCfg(::comphelper::ConfigurationHelper::openConfig(
1778 : comphelper::getComponentContext(xSMGR),
1779 : PACKAGE_SETUP_MODULES,
1780 : ::comphelper::ConfigurationHelper::E_READONLY),
1781 236 : css::uno::UNO_QUERY_THROW);
1782 :
1783 : // read window state from the configuration
1784 : // and apply it on the window.
1785 : // Do nothing, if no configuration entry exists!
1786 236 : ::rtl::OUString sWindowState ;
1787 236 : ::comphelper::ConfigurationHelper::readRelativeKey(xModuleCfg, sModule, OFFICEFACTORY_PROPNAME_WINDOWATTRIBUTES) >>= sWindowState;
1788 236 : if (!sWindowState.isEmpty())
1789 : {
1790 : // SOLAR SAFE ->
1791 107 : SolarMutexGuard aSolarGuard;
1792 :
1793 : // We have to retrieve the window pointer again. Because nobody can guarantee
1794 : // that the XWindow was not disposed inbetween .-)
1795 : // But if we get a valid pointer we can be sure, that it's the system window pointer
1796 : // we already checked and used before. Because nobody recylce the same uno reference for
1797 : // a new internal c++ implementation ... hopefully .-))
1798 107 : Window* pWindowCheck = VCLUnoHelper::GetWindow(xWindow);
1799 107 : if (! pWindowCheck)
1800 : return;
1801 :
1802 107 : SystemWindow* pSystemWindow = (SystemWindow*)pWindowCheck;
1803 107 : pSystemWindow->SetWindowState(rtl::OUStringToOString(sWindowState,RTL_TEXTENCODING_UTF8));
1804 : // <- SOLAR SAFE
1805 236 : }
1806 : }
1807 0 : catch(const css::uno::RuntimeException&)
1808 0 : { throw; }
1809 0 : catch(const css::uno::Exception&)
1810 236 : {}
1811 : }
1812 :
1813 : } // namespace framework
1814 :
1815 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|