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 #include <cppuhelper/weak.hxx> 24 25 #include <embeddoc.hxx> 26 #include <docholder.hxx> 27 #include <intercept.hxx> 28 29 using namespace ::com::sun::star; 30 31 32 33 #define IUL 6 34 35 36 37 uno::Sequence< ::rtl::OUString > Interceptor::m_aInterceptedURL(IUL); 38 39 40 41 42 struct equalOUString 43 { 44 bool operator()( 45 const rtl::OUString& rKey1, 46 const rtl::OUString& rKey2 ) const 47 { 48 return !!( rKey1 == rKey2 ); 49 } 50 }; 51 52 53 struct hashOUString 54 { 55 size_t operator()( const rtl::OUString& rName ) const 56 { 57 return rName.hashCode(); 58 } 59 }; 60 61 62 63 class StatusChangeListenerContainer 64 : public ::cppu::OMultiTypeInterfaceContainerHelperVar< 65 rtl::OUString,hashOUString,equalOUString> 66 { 67 public: 68 StatusChangeListenerContainer( ::osl::Mutex& aMutex ) 69 : cppu::OMultiTypeInterfaceContainerHelperVar< 70 rtl::OUString,hashOUString,equalOUString>(aMutex) 71 { 72 } 73 }; 74 75 76 void SAL_CALL 77 Interceptor::addEventListener( 78 const uno::Reference<lang::XEventListener >& Listener ) 79 { 80 osl::MutexGuard aGuard( m_aMutex ); 81 82 if ( ! m_pDisposeEventListeners ) 83 m_pDisposeEventListeners = 84 new cppu::OInterfaceContainerHelper( m_aMutex ); 85 86 m_pDisposeEventListeners->addInterface( Listener ); 87 } 88 89 90 void SAL_CALL 91 Interceptor::removeEventListener( 92 const uno::Reference< lang::XEventListener >& Listener ) 93 { 94 osl::MutexGuard aGuard( m_aMutex ); 95 96 if ( m_pDisposeEventListeners ) 97 m_pDisposeEventListeners->removeInterface( Listener ); 98 } 99 100 101 void SAL_CALL Interceptor::dispose() 102 { 103 lang::EventObject aEvt; 104 aEvt.Source = static_cast< frame::XDispatch* >( this ); 105 106 osl::MutexGuard aGuard(m_aMutex); 107 108 if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) 109 m_pDisposeEventListeners->disposeAndClear( aEvt ); 110 111 if(m_pStatCL) 112 m_pStatCL->disposeAndClear( aEvt ); 113 114 m_xSlaveDispatchProvider = 0; 115 m_xMasterDispatchProvider = 0; 116 } 117 118 119 120 Interceptor::Interceptor( 121 const ::rtl::Reference< EmbeddedDocumentInstanceAccess_Impl >& xOleAccess, 122 DocumentHolder* pDocH, 123 sal_Bool bLink ) 124 : m_xOleAccess( xOleAccess ), 125 m_xDocHLocker( static_cast< ::cppu::OWeakObject* >( pDocH ) ), 126 m_pDocH(pDocH), 127 m_pStatCL(0), 128 m_pDisposeEventListeners(0), 129 m_bLink( bLink ) 130 { 131 m_aInterceptedURL[0] = rtl::OUString( 132 RTL_CONSTASCII_USTRINGPARAM(".uno:Save")); 133 m_aInterceptedURL[1] = rtl::OUString( 134 RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAll")); 135 m_aInterceptedURL[2] = rtl::OUString( 136 RTL_CONSTASCII_USTRINGPARAM(".uno:CloseDoc")); 137 m_aInterceptedURL[3] = rtl::OUString( 138 RTL_CONSTASCII_USTRINGPARAM(".uno:CloseWin")); 139 m_aInterceptedURL[4] = rtl::OUString( 140 RTL_CONSTASCII_USTRINGPARAM(".uno:CloseFrame")); 141 m_aInterceptedURL[5] = rtl::OUString( 142 RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAs")); 143 } 144 145 146 Interceptor::~Interceptor() 147 { 148 if( m_pDisposeEventListeners ) 149 delete m_pDisposeEventListeners; 150 151 if(m_pStatCL) 152 delete m_pStatCL; 153 154 DocumentHolder* pTmpDocH = NULL; 155 uno::Reference< uno::XInterface > xLock; 156 { 157 osl::MutexGuard aGuard(m_aMutex); 158 xLock = m_xDocHLocker.get(); 159 if ( xLock.is() ) 160 pTmpDocH = m_pDocH; 161 } 162 163 if ( pTmpDocH ) 164 pTmpDocH->ClearInterceptor(); 165 } 166 167 void Interceptor::DisconnectDocHolder() 168 { 169 osl::MutexGuard aGuard(m_aMutex); 170 m_xDocHLocker.clear(); 171 m_pDocH = NULL; 172 m_xOleAccess = NULL; 173 } 174 175 //XDispatch 176 void SAL_CALL 177 Interceptor::dispatch( 178 const util::URL& URL, 179 const uno::Sequence< 180 beans::PropertyValue >& Arguments ) 181 { 182 ::rtl::Reference< EmbeddedDocumentInstanceAccess_Impl > xOleAccess; 183 { 184 osl::MutexGuard aGuard(m_aMutex); 185 xOleAccess = m_xOleAccess; 186 } 187 188 if ( xOleAccess.is() ) 189 { 190 LockedEmbedDocument_Impl aDocLock = xOleAccess->GetEmbedDocument(); 191 if ( aDocLock.GetEmbedDocument() ) 192 { 193 if( !m_bLink && URL.Complete == m_aInterceptedURL[0]) 194 aDocLock.GetEmbedDocument()->SaveObject(); 195 else if(!m_bLink 196 && ( URL.Complete == m_aInterceptedURL[2] || 197 URL.Complete == m_aInterceptedURL[3] || 198 URL.Complete == m_aInterceptedURL[4] ) ) 199 aDocLock.GetEmbedDocument()->Close( 0 ); 200 else if ( URL.Complete == m_aInterceptedURL[5] ) 201 { 202 uno::Sequence< beans::PropertyValue > aNewArgs = Arguments; 203 sal_Int32 nInd = 0; 204 205 while( nInd < aNewArgs.getLength() ) 206 { 207 if ( aNewArgs[nInd].Name.equalsAscii( "SaveTo" ) ) 208 { 209 aNewArgs[nInd].Value <<= sal_True; 210 break; 211 } 212 nInd++; 213 } 214 215 if ( nInd == aNewArgs.getLength() ) 216 { 217 aNewArgs.realloc( nInd + 1 ); 218 aNewArgs[nInd].Name = ::rtl::OUString::createFromAscii( "SaveTo" ); 219 aNewArgs[nInd].Value <<= sal_True; 220 } 221 222 uno::Reference< frame::XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch( 223 URL, ::rtl::OUString::createFromAscii( "_self" ), 0 ); 224 if ( xDispatch.is() ) 225 xDispatch->dispatch( URL, aNewArgs ); 226 } 227 } 228 } 229 } 230 231 232 void Interceptor::generateFeatureStateEvent() 233 { 234 if( m_pStatCL ) 235 { 236 DocumentHolder* pTmpDocH = NULL; 237 uno::Reference< uno::XInterface > xLock; 238 { 239 osl::MutexGuard aGuard(m_aMutex); 240 xLock = m_xDocHLocker.get(); 241 if ( xLock.is() ) 242 pTmpDocH = m_pDocH; 243 } 244 245 ::rtl::OUString aTitle; 246 if ( pTmpDocH ) 247 aTitle = pTmpDocH->getTitle(); 248 249 for(int i = 0; i < IUL; ++i) 250 { 251 if( i == 1 || m_bLink && i != 5 ) 252 continue; 253 254 cppu::OInterfaceContainerHelper* pICH = 255 m_pStatCL->getContainer(m_aInterceptedURL[i]); 256 uno::Sequence<uno::Reference<uno::XInterface> > aSeq; 257 if(pICH) 258 aSeq = pICH->getElements(); 259 if(!aSeq.getLength()) 260 continue; 261 262 frame::FeatureStateEvent aStateEvent; 263 aStateEvent.IsEnabled = sal_True; 264 aStateEvent.Requery = sal_False; 265 if(i == 0) 266 { 267 268 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0]; 269 aStateEvent.FeatureDescriptor = rtl::OUString( 270 RTL_CONSTASCII_USTRINGPARAM("Update")); 271 aStateEvent.State <<= (rtl::OUString( 272 RTL_CONSTASCII_USTRINGPARAM("($1) ")) + 273 aTitle); 274 275 } 276 else if ( i == 5 ) 277 { 278 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5]; 279 aStateEvent.FeatureDescriptor = rtl::OUString( 280 RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo")); 281 aStateEvent.State <<= (rtl::OUString( 282 RTL_CONSTASCII_USTRINGPARAM("($3)"))); 283 } 284 else 285 { 286 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i]; 287 aStateEvent.FeatureDescriptor = rtl::OUString( 288 RTL_CONSTASCII_USTRINGPARAM("Close and Return")); 289 aStateEvent.State <<= (rtl::OUString( 290 RTL_CONSTASCII_USTRINGPARAM("($2) ")) + 291 aTitle); 292 293 } 294 295 for(sal_Int32 k = 0; k < aSeq.getLength(); ++k) 296 { 297 uno::Reference<frame::XStatusListener> 298 Control(aSeq[k],uno::UNO_QUERY); 299 if(Control.is()) 300 Control->statusChanged(aStateEvent); 301 302 } 303 } 304 } 305 } 306 307 308 void SAL_CALL 309 Interceptor::addStatusListener( 310 const uno::Reference< 311 frame::XStatusListener >& Control, 312 const util::URL& URL ) 313 { 314 if(!Control.is()) 315 return; 316 317 if( !m_bLink && URL.Complete == m_aInterceptedURL[0] ) 318 { // Save 319 DocumentHolder* pTmpDocH = NULL; 320 uno::Reference< uno::XInterface > xLock; 321 { 322 osl::MutexGuard aGuard(m_aMutex); 323 xLock = m_xDocHLocker.get(); 324 if ( xLock.is() ) 325 pTmpDocH = m_pDocH; 326 } 327 328 ::rtl::OUString aTitle; 329 if ( pTmpDocH ) 330 aTitle = pTmpDocH->getTitle(); 331 332 frame::FeatureStateEvent aStateEvent; 333 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0]; 334 aStateEvent.FeatureDescriptor = rtl::OUString( 335 RTL_CONSTASCII_USTRINGPARAM("Update")); 336 aStateEvent.IsEnabled = sal_True; 337 aStateEvent.Requery = sal_False; 338 aStateEvent.State <<= (rtl::OUString( 339 RTL_CONSTASCII_USTRINGPARAM("($1) ")) + 340 aTitle ); 341 Control->statusChanged(aStateEvent); 342 343 { 344 osl::MutexGuard aGuard(m_aMutex); 345 if(!m_pStatCL) 346 m_pStatCL = 347 new StatusChangeListenerContainer(m_aMutex); 348 } 349 350 m_pStatCL->addInterface(URL.Complete,Control); 351 return; 352 } 353 354 sal_Int32 i = 2; 355 if ( !m_bLink 356 && ( URL.Complete == m_aInterceptedURL[i] || 357 URL.Complete == m_aInterceptedURL[++i] || 358 URL.Complete == m_aInterceptedURL[++i] ) ) 359 { // Close and return 360 DocumentHolder* pTmpDocH = NULL; 361 uno::Reference< uno::XInterface > xLock; 362 { 363 osl::MutexGuard aGuard(m_aMutex); 364 xLock = m_xDocHLocker.get(); 365 if ( xLock.is() ) 366 pTmpDocH = m_pDocH; 367 } 368 369 ::rtl::OUString aTitle; 370 if ( pTmpDocH ) 371 aTitle = pTmpDocH->getTitle(); 372 373 frame::FeatureStateEvent aStateEvent; 374 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i]; 375 aStateEvent.FeatureDescriptor = rtl::OUString( 376 RTL_CONSTASCII_USTRINGPARAM("Close and Return")); 377 aStateEvent.IsEnabled = sal_True; 378 aStateEvent.Requery = sal_False; 379 aStateEvent.State <<= (rtl::OUString( 380 RTL_CONSTASCII_USTRINGPARAM("($2) ")) + 381 aTitle ); 382 Control->statusChanged(aStateEvent); 383 384 385 { 386 osl::MutexGuard aGuard(m_aMutex); 387 if(!m_pStatCL) 388 m_pStatCL = 389 new StatusChangeListenerContainer(m_aMutex); 390 } 391 392 m_pStatCL->addInterface(URL.Complete,Control); 393 return; 394 } 395 396 if(URL.Complete == m_aInterceptedURL[5]) 397 { // SaveAs 398 frame::FeatureStateEvent aStateEvent; 399 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5]; 400 aStateEvent.FeatureDescriptor = rtl::OUString( 401 RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo")); 402 aStateEvent.IsEnabled = sal_True; 403 aStateEvent.Requery = sal_False; 404 aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($3)"))); 405 Control->statusChanged(aStateEvent); 406 407 { 408 osl::MutexGuard aGuard(m_aMutex); 409 if(!m_pStatCL) 410 m_pStatCL = 411 new StatusChangeListenerContainer(m_aMutex); 412 } 413 414 m_pStatCL->addInterface(URL.Complete,Control); 415 return; 416 } 417 418 } 419 420 421 void SAL_CALL 422 Interceptor::removeStatusListener( 423 const uno::Reference< 424 frame::XStatusListener >& Control, 425 const util::URL& URL ) 426 { 427 if(!(Control.is() && m_pStatCL)) 428 return; 429 else { 430 m_pStatCL->removeInterface(URL.Complete,Control); 431 return; 432 } 433 } 434 435 436 //XInterceptorInfo 437 uno::Sequence< ::rtl::OUString > 438 SAL_CALL 439 Interceptor::getInterceptedURLs( ) 440 { 441 // now implemented as update 442 if ( m_bLink ) 443 { 444 uno::Sequence< ::rtl::OUString > aResult( 2 ); 445 aResult[0] = m_aInterceptedURL[1]; 446 aResult[1] = m_aInterceptedURL[5]; 447 448 return aResult; 449 } 450 451 return m_aInterceptedURL; 452 } 453 454 455 // XDispatchProvider 456 457 uno::Reference< frame::XDispatch > SAL_CALL 458 Interceptor::queryDispatch( 459 const util::URL& URL, 460 const ::rtl::OUString& TargetFrameName, 461 sal_Int32 SearchFlags ) 462 { 463 osl::MutexGuard aGuard(m_aMutex); 464 if( !m_bLink && URL.Complete == m_aInterceptedURL[0] ) 465 return (frame::XDispatch*)this; 466 else if(URL.Complete == m_aInterceptedURL[1]) 467 return (frame::XDispatch*)0 ; 468 else if( !m_bLink && URL.Complete == m_aInterceptedURL[2] ) 469 return (frame::XDispatch*)this; 470 else if( !m_bLink && URL.Complete == m_aInterceptedURL[3] ) 471 return (frame::XDispatch*)this; 472 else if( !m_bLink && URL.Complete == m_aInterceptedURL[4] ) 473 return (frame::XDispatch*)this; 474 else if(URL.Complete == m_aInterceptedURL[5]) 475 return (frame::XDispatch*)this; 476 else { 477 if(m_xSlaveDispatchProvider.is()) 478 return m_xSlaveDispatchProvider->queryDispatch( 479 URL,TargetFrameName,SearchFlags); 480 else 481 return uno::Reference<frame::XDispatch>(0); 482 } 483 } 484 485 uno::Sequence< uno::Reference< frame::XDispatch > > SAL_CALL 486 Interceptor::queryDispatches( 487 const uno::Sequence<frame::DispatchDescriptor >& Requests ) 488 { 489 uno::Sequence< uno::Reference< frame::XDispatch > > aRet; 490 osl::MutexGuard aGuard(m_aMutex); 491 if(m_xSlaveDispatchProvider.is()) 492 aRet = m_xSlaveDispatchProvider->queryDispatches(Requests); 493 else 494 aRet.realloc(Requests.getLength()); 495 496 for(sal_Int32 i = 0; i < Requests.getLength(); ++i) 497 if ( !m_bLink && m_aInterceptedURL[0] == Requests[i].FeatureURL.Complete ) 498 aRet[i] = (frame::XDispatch*) this; 499 else if(m_aInterceptedURL[1] == Requests[i].FeatureURL.Complete) 500 aRet[i] = (frame::XDispatch*) 0; 501 else if( !m_bLink && m_aInterceptedURL[2] == Requests[i].FeatureURL.Complete ) 502 aRet[i] = (frame::XDispatch*) this; 503 else if( !m_bLink && m_aInterceptedURL[3] == Requests[i].FeatureURL.Complete ) 504 aRet[i] = (frame::XDispatch*) this; 505 else if( !m_bLink && m_aInterceptedURL[4] == Requests[i].FeatureURL.Complete ) 506 aRet[i] = (frame::XDispatch*) this; 507 else if(m_aInterceptedURL[5] == Requests[i].FeatureURL.Complete) 508 aRet[i] = (frame::XDispatch*) this; 509 510 return aRet; 511 } 512 513 514 515 //XDispatchProviderInterceptor 516 517 uno::Reference< frame::XDispatchProvider > SAL_CALL 518 Interceptor::getSlaveDispatchProvider( ) 519 { 520 osl::MutexGuard aGuard(m_aMutex); 521 return m_xSlaveDispatchProvider; 522 } 523 524 void SAL_CALL 525 Interceptor::setSlaveDispatchProvider( 526 const uno::Reference< frame::XDispatchProvider >& NewDispatchProvider ) 527 { 528 osl::MutexGuard aGuard(m_aMutex); 529 m_xSlaveDispatchProvider = NewDispatchProvider; 530 } 531 532 533 uno::Reference< frame::XDispatchProvider > SAL_CALL 534 Interceptor::getMasterDispatchProvider( ) 535 { 536 osl::MutexGuard aGuard(m_aMutex); 537 return m_xMasterDispatchProvider; 538 } 539 540 541 void SAL_CALL 542 Interceptor::setMasterDispatchProvider( 543 const uno::Reference< frame::XDispatchProvider >& NewSupplier ) 544 { 545 osl::MutexGuard aGuard(m_aMutex); 546 m_xMasterDispatchProvider = NewSupplier; 547 } 548 549 // Fix strange warnings about some 550 // ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions. 551 // warning C4505: 'xxx' : unreferenced local function has been removed 552 #if defined(_MSC_VER) 553 #pragma warning(disable: 4505) 554 #endif 555