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