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