1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ucb.hxx"
26
27 /**************************************************************************
28 TODO
29 **************************************************************************
30
31 *************************************************************************/
32
33 #include "osl/diagnose.h"
34 #include "rtl/ref.hxx"
35 #include "cppuhelper/weak.hxx"
36
37 #include "comphelper/namedvaluecollection.hxx"
38 #include "comphelper/documentinfo.hxx"
39
40 #include "com/sun/star/awt/XTopWindow.hpp"
41 #include "com/sun/star/beans/XPropertySet.hpp"
42 #include "com/sun/star/container/XEnumerationAccess.hpp"
43 #include "com/sun/star/document/XStorageBasedDocument.hpp"
44 #include "com/sun/star/frame/XStorable.hpp"
45 #include "com/sun/star/lang/DisposedException.hpp"
46 #include "com/sun/star/util/XCloseBroadcaster.hpp"
47
48 #include "tdoc_docmgr.hxx"
49
50 using namespace com::sun::star;
51 using namespace tdoc_ucp;
52 using ::comphelper::DocumentInfo;
53
54 //=========================================================================
55 //=========================================================================
56 //
57 // OfficeDocumentsCloseListener Implementation.
58 //
59 //=========================================================================
60 //=========================================================================
61
62 //=========================================================================
63 //
64 // util::XCloseListener
65 //
66 //=========================================================================
67
68 // virtual
queryClosing(const lang::EventObject &,sal_Bool)69 void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::queryClosing(
70 const lang::EventObject& /*Source*/, sal_Bool /*GetsOwnership*/ )
71 throw ( util::CloseVetoException,
72 uno::RuntimeException )
73 {
74 }
75
76 //=========================================================================
notifyClosing(const lang::EventObject & Source)77 void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::notifyClosing(
78 const lang::EventObject& Source )
79 throw ( uno::RuntimeException )
80 {
81 document::EventObject aDocEvent;
82 aDocEvent.Source = Source.Source;
83 aDocEvent.EventName = rtl::OUString(
84 RTL_CONSTASCII_USTRINGPARAM( "OfficeDocumentsListener::notifyClosing" ) );
85 m_pManager->notifyEvent( aDocEvent );
86 }
87
88 //=========================================================================
89 //
90 // lang::XEventListener (base of util::XCloseListener)
91 //
92 //=========================================================================
93
94 // virtual
disposing(const lang::EventObject &)95 void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::disposing(
96 const lang::EventObject& /*Source*/ )
97 throw ( uno::RuntimeException )
98 {
99 }
100
101 //=========================================================================
102 //=========================================================================
103 //
104 // OfficeDocumentsManager Implementation.
105 //
106 //=========================================================================
107 //=========================================================================
108
OfficeDocumentsManager(const uno::Reference<lang::XMultiServiceFactory> & xSMgr,OfficeDocumentsEventListener * pDocEventListener)109 OfficeDocumentsManager::OfficeDocumentsManager(
110 const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
111 OfficeDocumentsEventListener * pDocEventListener )
112 : m_xSMgr( xSMgr ),
113 m_xDocEvtNotifier( createDocumentEventNotifier( xSMgr ) ),
114 m_pDocEventListener( pDocEventListener ),
115 m_xDocCloseListener( new OfficeDocumentsCloseListener( this ) )
116 {
117 if ( m_xDocEvtNotifier.is() )
118 {
119 // Order is important (multithreaded environment)
120 m_xDocEvtNotifier->addEventListener( this );
121 buildDocumentsList();
122 }
123 }
124
125 //=========================================================================
126 // virtual
~OfficeDocumentsManager()127 OfficeDocumentsManager::~OfficeDocumentsManager()
128 {
129 //OSL_ENSURE( m_aDocs.empty(), "document list not empty!" );
130 // no need to assert this: Normal shutdown of OOo could already trigger it, since the order in which
131 // objects are actually released/destroyed upon shutdown is not defined. And when we arrive *here*,
132 // OOo *is* shutting down currently, since we're held by the TDOC provider, which is disposed
133 // upon shutdown.
134 }
135
136 //=========================================================================
destroy()137 void OfficeDocumentsManager::destroy()
138 {
139 if ( m_xDocEvtNotifier.is() )
140 m_xDocEvtNotifier->removeEventListener( this );
141 }
142
143 //=========================================================================
144 static rtl::OUString
getDocumentId(const uno::Reference<uno::XInterface> & xDoc)145 getDocumentId( const uno::Reference< uno::XInterface > & xDoc )
146 {
147 rtl::OUString aId;
148
149 // Try to get the UID directly from the document.
150 uno::Reference< beans::XPropertySet > xPropSet( xDoc, uno::UNO_QUERY );
151 if ( xPropSet.is() )
152 {
153 try
154 {
155 uno::Any aValue = xPropSet->getPropertyValue(
156 rtl::OUString(
157 RTL_CONSTASCII_USTRINGPARAM( "RuntimeUID" ) ) );
158 aValue >>= aId;
159 }
160 catch ( beans::UnknownPropertyException const & )
161 {
162 // Not actually an error. Property is optional.
163 }
164 catch ( lang::WrappedTargetException const & )
165 {
166 OSL_ENSURE( false, "Caught WrappedTargetException!" );
167 }
168 }
169
170 if ( aId.getLength() == 0 )
171 {
172 // fallback: generate UID from document's this pointer.
173 // normalize the interface pointer first. Else, calls with different
174 // interfaces to the same object (say, XFoo and XBar) will produce
175 // different IDs
176 uno::Reference< uno::XInterface > xNormalizedIFace( xDoc, uno::UNO_QUERY );
177 sal_Int64 nId = reinterpret_cast< sal_Int64 >( xNormalizedIFace.get() );
178 aId = rtl::OUString::valueOf( nId );
179 }
180
181 OSL_ENSURE( aId.getLength() > 0, "getDocumentId - Empty id!" );
182 return aId;
183 }
184
185 //=========================================================================
186 //
187 // document::XEventListener
188 //
189 //=========================================================================
190
191 // virtual
notifyEvent(const document::EventObject & Event)192 void SAL_CALL OfficeDocumentsManager::notifyEvent(
193 const document::EventObject & Event )
194 throw ( uno::RuntimeException )
195 {
196 /*
197 Events documentation: OOo Developer's Guide / Writing UNO Components / Jobs
198 */
199
200 if ( Event.EventName.equalsAsciiL(
201 RTL_CONSTASCII_STRINGPARAM( "OnLoadFinished" ) ) // document loaded
202 || Event.EventName.equalsAsciiL(
203 RTL_CONSTASCII_STRINGPARAM( "OnCreate" ) ) ) // document created
204 {
205 if ( isOfficeDocument( Event.Source ) )
206 {
207 osl::MutexGuard aGuard( m_aMtx );
208
209 uno::Reference< frame::XModel >
210 xModel( Event.Source, uno::UNO_QUERY );
211 OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
212
213 DocumentList::const_iterator it = m_aDocs.begin();
214 while ( it != m_aDocs.end() )
215 {
216 if ( (*it).second.xModel == xModel )
217 {
218 // already known.
219 break;
220 }
221 ++it;
222 }
223
224 if ( it == m_aDocs.end() )
225 {
226 // new document
227
228 uno::Reference< document::XStorageBasedDocument >
229 xDoc( Event.Source, uno::UNO_QUERY );
230 OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" );
231
232 uno::Reference< embed::XStorage > xStorage
233 = xDoc->getDocumentStorage();
234 OSL_ENSURE( xStorage.is(), "Got no document storage!" );
235
236 rtl:: OUString aDocId = getDocumentId( Event.Source );
237 rtl:: OUString aTitle = DocumentInfo::getDocumentTitle(
238 uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
239
240 m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel );
241
242 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
243 Event.Source, uno::UNO_QUERY );
244 OSL_ENSURE( xCloseBroadcaster.is(),
245 "OnLoadFinished/OnCreate event: got no close broadcaster!" );
246
247 if ( xCloseBroadcaster.is() )
248 xCloseBroadcaster->addCloseListener( m_xDocCloseListener );
249
250 // Propagate document closure.
251 OSL_ENSURE( m_pDocEventListener,
252 "OnLoadFinished/OnCreate event: no owner for insert event propagation!" );
253
254 if ( m_pDocEventListener )
255 m_pDocEventListener->notifyDocumentOpened( aDocId );
256 }
257 }
258 }
259 else if ( Event.EventName.equalsAsciiL(
260 RTL_CONSTASCII_STRINGPARAM( "OfficeDocumentsListener::notifyClosing" ) ) )
261 {
262 if ( isOfficeDocument( Event.Source ) )
263 {
264 // Document has been closed (unloaded)
265
266 // #163732# - Official event "OnUnload" does not work here. Event
267 // gets fired to early. Other OnUnload listeners called after this
268 // listener may still need TDOC access to the document. Remove the
269 // document from TDOC docs list on XCloseListener::notifyClosing.
270 // See OfficeDocumentsManager::OfficeDocumentsListener::notifyClosing.
271
272 osl::MutexGuard aGuard( m_aMtx );
273
274 uno::Reference< frame::XModel >
275 xModel( Event.Source, uno::UNO_QUERY );
276 OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
277
278 DocumentList::iterator it = m_aDocs.begin();
279 while ( it != m_aDocs.end() )
280 {
281 if ( (*it).second.xModel == xModel )
282 {
283 // Propagate document closure.
284 OSL_ENSURE( m_pDocEventListener,
285 "OnUnload event: no owner for close event propagation!" );
286
287 if ( m_pDocEventListener )
288 {
289 rtl::OUString aDocId( (*it).first );
290 m_pDocEventListener->notifyDocumentClosed( aDocId );
291 }
292 break;
293 }
294 ++it;
295 }
296
297 OSL_ENSURE( it != m_aDocs.end(),
298 "OnUnload event notified for unknown document!" );
299
300 if ( it != m_aDocs.end() )
301 {
302 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
303 Event.Source, uno::UNO_QUERY );
304 OSL_ENSURE( xCloseBroadcaster.is(),
305 "OnUnload event: got no XCloseBroadcaster from XModel" );
306
307 if ( xCloseBroadcaster.is() )
308 xCloseBroadcaster->removeCloseListener( m_xDocCloseListener );
309
310 m_aDocs.erase( it );
311 }
312 }
313 }
314 else if ( Event.EventName.equalsAsciiL(
315 RTL_CONSTASCII_STRINGPARAM( "OnSaveDone" ) ) )
316 {
317 if ( isOfficeDocument( Event.Source ) )
318 {
319 osl::MutexGuard aGuard( m_aMtx );
320
321 uno::Reference< frame::XModel >
322 xModel( Event.Source, uno::UNO_QUERY );
323 OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
324
325 DocumentList::iterator it = m_aDocs.begin();
326 while ( it != m_aDocs.end() )
327 {
328 if ( (*it).second.xModel == xModel )
329 {
330 // Storage gets exchanged while saving.
331 uno::Reference< document::XStorageBasedDocument >
332 xDoc( Event.Source, uno::UNO_QUERY );
333 OSL_ENSURE( xDoc.is(),
334 "Got no document::XStorageBasedDocument!" );
335
336 uno::Reference< embed::XStorage > xStorage
337 = xDoc->getDocumentStorage();
338 OSL_ENSURE( xStorage.is(), "Got no document storage!" );
339
340 (*it).second.xStorage = xStorage;
341 break;
342 }
343 ++it;
344 }
345
346 OSL_ENSURE( it != m_aDocs.end(),
347 "OnSaveDone event notified for unknown document!" );
348 }
349 }
350 else if ( Event.EventName.equalsAsciiL(
351 RTL_CONSTASCII_STRINGPARAM( "OnSaveAsDone" ) ) )
352 {
353 if ( isOfficeDocument( Event.Source ) )
354 {
355 osl::MutexGuard aGuard( m_aMtx );
356
357 uno::Reference< frame::XModel >
358 xModel( Event.Source, uno::UNO_QUERY );
359 OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
360
361 DocumentList::iterator it = m_aDocs.begin();
362 while ( it != m_aDocs.end() )
363 {
364 if ( (*it).second.xModel == xModel )
365 {
366 // Storage gets exchanged while saving.
367 uno::Reference< document::XStorageBasedDocument >
368 xDoc( Event.Source, uno::UNO_QUERY );
369 OSL_ENSURE( xDoc.is(),
370 "Got no document::XStorageBasedDocument!" );
371
372 uno::Reference< embed::XStorage > xStorage
373 = xDoc->getDocumentStorage();
374 OSL_ENSURE( xStorage.is(), "Got no document storage!" );
375
376 (*it).second.xStorage = xStorage;
377
378 // Adjust title.
379 (*it).second.aTitle = DocumentInfo::getDocumentTitle( xModel );
380 break;
381 }
382 ++it;
383 }
384
385 OSL_ENSURE( it != m_aDocs.end(),
386 "OnSaveAsDone event notified for unknown document!" );
387 }
388 }
389 else if ( Event.EventName.equalsAsciiL(
390 RTL_CONSTASCII_STRINGPARAM( "OnTitleChanged" ) ) )
391 {
392 if ( isOfficeDocument( Event.Source ) )
393 {
394 osl::MutexGuard aGuard( m_aMtx );
395
396 uno::Reference< frame::XModel >
397 xModel( Event.Source, uno::UNO_QUERY );
398 OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
399
400 DocumentList::iterator it = m_aDocs.begin();
401 while ( it != m_aDocs.end() )
402 {
403 if ( (*it).second.xModel == xModel )
404 {
405 // Adjust title.
406 rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( xModel );
407 (*it).second.aTitle = aTitle;
408
409 // Adjust storage.
410 uno::Reference< document::XStorageBasedDocument >
411 xDoc( Event.Source, uno::UNO_QUERY );
412 OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" );
413
414 uno::Reference< embed::XStorage > xStorage
415 = xDoc->getDocumentStorage();
416 OSL_ENSURE( xDoc.is(), "Got no document storage!" );
417
418 rtl:: OUString aDocId = getDocumentId( Event.Source );
419
420 m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel );
421 break;
422 }
423 ++it;
424 }
425
426 // OSL_ENSURE( it != m_aDocs.end(),
427 // "TitleChanged event notified for unknown document!" );
428 // TODO: re-enable this assertion. It has been disabled for now, since it breaks the assertion-free smoketest,
429 // and the fix is more difficult than what can be done now.
430 // The problem is that at the moment, when you close a SFX-based document via API, it will first
431 // fire the notifyClosing event, which will make the OfficeDocumentsManager remove the doc from its list.
432 // Then, it will notify an OnTitleChanged, then an OnUnload. Documents closed via call the notifyClosing
433 // *after* OnUnload and all other On* events.
434 // In agreement with MBA, the implementation for SfxBaseModel::Close should be changed to also send notifyClosing
435 // as last event. When this happens, the assertion here must be enabled, again.
436 // There is no bug for this, yet - IZ is currently down due to the Kenai migration.
437 // 2011-02-23 / frank.schoenheit@sun.com
438 }
439 }
440 }
441
442 //=========================================================================
443 //
444 // lang::XEventListener (base of document::XEventListener)
445 //
446 //=========================================================================
447
448 // virtual
disposing(const lang::EventObject &)449 void SAL_CALL OfficeDocumentsManager::disposing(
450 const lang::EventObject& /*Source*/ )
451 throw ( uno::RuntimeException )
452 {
453 }
454
455 //=========================================================================
456 //
457 // Non-interface.
458 //
459 //=========================================================================
460
461 // static
462 uno::Reference< document::XEventBroadcaster >
createDocumentEventNotifier(const uno::Reference<lang::XMultiServiceFactory> & rXSMgr)463 OfficeDocumentsManager::createDocumentEventNotifier(
464 const uno::Reference< lang::XMultiServiceFactory >& rXSMgr )
465 {
466 uno::Reference< uno::XInterface > xIfc;
467 try
468 {
469 xIfc = rXSMgr->createInstance(
470 rtl::OUString(
471 RTL_CONSTASCII_USTRINGPARAM(
472 "com.sun.star.frame.GlobalEventBroadcaster" ) ) );
473 }
474 catch ( uno::Exception const & )
475 {
476 // handled below.
477 }
478
479 OSL_ENSURE(
480 xIfc.is(),
481 "Could not instanciate com.sun.star.frame.GlobalEventBroadcaster" );
482
483 if ( xIfc.is() )
484 {
485 uno::Reference< document::XEventBroadcaster > xBC(
486 xIfc, uno::UNO_QUERY );
487
488 OSL_ENSURE(
489 xBC.is(),
490 "com.sun.star.frame.GlobalEventBroadcaster does not implement "
491 "interface com.sun.star.document.XEventBroadcaster!" );
492
493 return xBC;
494 }
495 else
496 return uno::Reference< document::XEventBroadcaster >();
497 }
498
499 //=========================================================================
buildDocumentsList()500 void OfficeDocumentsManager::buildDocumentsList()
501 {
502 OSL_ENSURE( m_xDocEvtNotifier.is(),
503 "OfficeDocumentsManager::buildDocumentsList - "
504 "No document event notifier!" );
505
506 uno::Reference< container::XEnumerationAccess > xEnumAccess(
507 m_xDocEvtNotifier, uno::UNO_QUERY_THROW );
508
509 uno::Reference< container::XEnumeration > xEnum
510 = xEnumAccess->createEnumeration();
511
512 osl::MutexGuard aGuard( m_aMtx );
513
514 while ( xEnum->hasMoreElements() )
515 {
516 uno::Any aValue = xEnum->nextElement();
517 // container::NoSuchElementException
518 // lang::WrappedTargetException
519
520 try
521 {
522 uno::Reference< frame::XModel > xModel;
523 aValue >>= xModel;
524
525 if ( xModel.is() )
526 {
527 if ( isOfficeDocument( xModel ) )
528 {
529 DocumentList::const_iterator it = m_aDocs.begin();
530 while ( it != m_aDocs.end() )
531 {
532 if ( (*it).second.xModel == xModel )
533 {
534 // already known.
535 break;
536 }
537 ++it;
538 }
539
540 if ( it == m_aDocs.end() )
541 {
542 // new document
543 rtl::OUString aDocId = getDocumentId( xModel );
544 rtl::OUString aTitle = DocumentInfo::getDocumentTitle( xModel );
545
546 uno::Reference< document::XStorageBasedDocument >
547 xDoc( xModel, uno::UNO_QUERY );
548 OSL_ENSURE( xDoc.is(),
549 "Got no document::XStorageBasedDocument!" );
550
551 uno::Reference< embed::XStorage > xStorage
552 = xDoc->getDocumentStorage();
553 OSL_ENSURE( xDoc.is(), "Got no document storage!" );
554
555 m_aDocs[ aDocId ]
556 = StorageInfo( aTitle, xStorage, xModel );
557
558 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
559 xModel, uno::UNO_QUERY );
560 OSL_ENSURE( xCloseBroadcaster.is(),
561 "buildDocumentsList: got no close broadcaster!" );
562
563 if ( xCloseBroadcaster.is() )
564 xCloseBroadcaster->addCloseListener( m_xDocCloseListener );
565 }
566 }
567 }
568 }
569 catch ( lang::DisposedException const & )
570 {
571 // Note: Due to race conditions the XEnumeration can
572 // contains docs that already have been closed
573 }
574 }
575 }
576
577 //=========================================================================
578 uno::Reference< embed::XStorage >
queryStorage(const rtl::OUString & rDocId)579 OfficeDocumentsManager::queryStorage( const rtl::OUString & rDocId )
580 {
581 osl::MutexGuard aGuard( m_aMtx );
582
583 DocumentList::const_iterator it = m_aDocs.find( rDocId );
584 if ( it == m_aDocs.end() )
585 return uno::Reference< embed::XStorage >();
586
587 return (*it).second.xStorage;
588 }
589
590 //=========================================================================
queryDocumentId(const uno::Reference<frame::XModel> & xModel)591 rtl::OUString OfficeDocumentsManager::queryDocumentId(
592 const uno::Reference< frame::XModel > & xModel )
593 {
594 return getDocumentId( xModel );
595 }
596
597 //=========================================================================
598 uno::Reference< frame::XModel >
queryDocumentModel(const rtl::OUString & rDocId)599 OfficeDocumentsManager::queryDocumentModel( const rtl::OUString & rDocId )
600 {
601 osl::MutexGuard aGuard( m_aMtx );
602
603 DocumentList::const_iterator it = m_aDocs.find( rDocId );
604 if ( it == m_aDocs.end() )
605 return uno::Reference< frame::XModel >();
606
607 return (*it).second.xModel;
608 }
609
610 //=========================================================================
queryDocuments()611 uno::Sequence< rtl::OUString > OfficeDocumentsManager::queryDocuments()
612 {
613 osl::MutexGuard aGuard( m_aMtx );
614
615 uno::Sequence< rtl::OUString > aRet( m_aDocs.size() );
616 sal_Int32 nPos = 0;
617
618 DocumentList::const_iterator it = m_aDocs.begin();
619 while ( it != m_aDocs.end() )
620 {
621 aRet[ nPos ] = (*it).first;
622 ++it;
623 ++nPos;
624 }
625 return aRet;
626 }
627
628 //=========================================================================
629 rtl::OUString
queryStorageTitle(const rtl::OUString & rDocId)630 OfficeDocumentsManager::queryStorageTitle( const rtl::OUString & rDocId )
631 {
632 osl::MutexGuard aGuard( m_aMtx );
633
634 DocumentList::const_iterator it = m_aDocs.find( rDocId );
635 if ( it == m_aDocs.end() )
636 return rtl::OUString();
637
638 return (*it).second.aTitle;
639 }
640
641 //=========================================================================
isDocumentPreview(const uno::Reference<frame::XModel> & xModel)642 bool OfficeDocumentsManager::isDocumentPreview(
643 const uno::Reference< frame::XModel > & xModel )
644 {
645 if ( !xModel.is() )
646 return false;
647
648 ::comphelper::NamedValueCollection aArgs(
649 xModel->getArgs() );
650 sal_Bool bIsPreview = aArgs.getOrDefault( "Preview", sal_False );
651 return bIsPreview;
652 }
653
654 //=========================================================================
isHelpDocument(const uno::Reference<frame::XModel> & xModel)655 bool OfficeDocumentsManager::isHelpDocument(
656 const uno::Reference< frame::XModel > & xModel )
657 {
658 if ( !xModel.is() )
659 return false;
660
661 ::rtl::OUString sURL( xModel->getURL() );
662 if ( sURL.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.help://" ) ) )
663 return true;
664
665 return false;
666 }
667
668 //=========================================================================
isWithoutOrInTopLevelFrame(const uno::Reference<frame::XModel> & xModel)669 bool OfficeDocumentsManager::isWithoutOrInTopLevelFrame(
670 const uno::Reference< frame::XModel > & xModel )
671 {
672 if ( !xModel.is() )
673 return false;
674
675 uno::Reference< frame::XController > xController
676 = xModel->getCurrentController();
677 if ( xController.is() )
678 {
679 uno::Reference< frame::XFrame > xFrame
680 = xController->getFrame();
681 if ( xFrame.is() )
682 {
683 // don't use XFrame::isTop here. This nowadays excludes
684 // "sub documents" such as forms embedded in database documents
685 uno::Reference< awt::XTopWindow > xFrameContainer(
686 xFrame->getContainerWindow(), uno::UNO_QUERY );
687 if ( !xFrameContainer.is() )
688 return false;
689 }
690 }
691
692 return true;
693 }
694
695 //=========================================================================
isBasicIDE(const uno::Reference<frame::XModel> & xModel)696 bool OfficeDocumentsManager::isBasicIDE(
697 const uno::Reference< frame::XModel > & xModel )
698 {
699 if ( !m_xModuleMgr.is() )
700 {
701 osl::MutexGuard aGuard( m_aMtx );
702 if ( !m_xModuleMgr.is() )
703 {
704 try
705 {
706 m_xModuleMgr
707 = uno::Reference<
708 frame::XModuleManager >(
709 m_xSMgr->createInstance(
710 rtl::OUString(
711 RTL_CONSTASCII_USTRINGPARAM(
712 "com.sun.star.frame.ModuleManager" ) ) ),
713 uno::UNO_QUERY );
714 }
715 catch ( uno::Exception const & )
716 {
717 // handled below.
718 }
719
720 OSL_ENSURE( m_xModuleMgr .is(),
721 "Could not instanciate ModuleManager service!" );
722 }
723 }
724
725 if ( m_xModuleMgr.is() )
726 {
727 rtl::OUString aModule;
728 try
729 {
730 aModule = m_xModuleMgr->identify( xModel );
731 }
732 catch ( lang::IllegalArgumentException const & )
733 {
734 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
735 }
736 catch ( frame::UnknownModuleException const & )
737 {
738 OSL_ENSURE( false, "Caught UnknownModuleException!" );
739 }
740
741 if ( aModule.getLength() > 0 )
742 {
743 // Filter unwanted items, that are no real documents.
744 if ( aModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(
745 "com.sun.star.script.BasicIDE" ) ) )
746 {
747 return true;
748 }
749 }
750 }
751
752 return false;
753 }
754
755 //=========================================================================
isOfficeDocument(const uno::Reference<uno::XInterface> & xDoc)756 bool OfficeDocumentsManager::isOfficeDocument(
757 const uno::Reference< uno::XInterface > & xDoc )
758 {
759 uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY );
760 uno::Reference< document::XStorageBasedDocument >
761 xStorageBasedDoc( xModel, uno::UNO_QUERY );
762 if ( !xStorageBasedDoc.is() )
763 return false;
764
765 if ( !isWithoutOrInTopLevelFrame( xModel ) )
766 return false;
767
768 if ( isDocumentPreview( xModel ) )
769 return false;
770
771 if ( isHelpDocument( xModel ) )
772 return false;
773
774 if ( isBasicIDE( xModel ) )
775 return false;
776
777 return true;
778 }
779