@threadsafeyes
*/
css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL DispatchProvider::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptions )
{ // Create return list - which must have the same size as the given descriptor. // It's not allowed to pack it!
sal_Int32 nCount = lDescriptions.getLength();
css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount ); auto lDispatcherRange = asNonConstRange(lDispatcher); // Step over all descriptors and try to get a dispatcher for it. for( sal_Int32 i=0; i<nCount; ++i )
{
lDispatcherRange[i] = queryDispatch( lDescriptions[i].FeatureURL ,
lDescriptions[i].FrameName ,
lDescriptions[i].SearchFlags );
}
// ignore wrong requests which are not supported if (
(sTargetFrameName==SPECIALTARGET_PARENT ) || // We have no parent by definition
(sTargetFrameName==SPECIALTARGET_BEAMER ) // Beamer frames are allowed as children of tasks only - // and they exist more than once. We have no idea which of our sub tasks is the right one
)
{ return nullptr;
}
// I) First handle special cases which are not suited for using findFrame()
// I.I) "_blank" // It's not the right place to create a new task here - because we are queried for a dispatch object // only, which can handle such request. Such a dispatcher should create the required task on demand. // Normally the functionality for "_blank" is provided by findFrame(), but that would create it directly // here. That's why we must "intercept" here.
if (sTargetFrameName==SPECIALTARGET_BLANK)
{ if (implts_isLoadableContent(aURL))
xDispatcher = implts_getOrCreateDispatchHelper( E_BLANKDISPATCHER, xDesktop );
}
// I.II) "_default" // This is a combination of searching an empty task for recycling or creating a new one.
if (isStartModuleDispatch(aURL))
xDispatcher = implts_getOrCreateDispatchHelper( E_STARTMODULEDISPATCHER, xDesktop );
}
// I.III) "_self", "", "_top" // The desktop can't load any document, but it can handle some special protocols like "uno", "slot" ... // Why is "top" handled here as well? Because the desktop is the topmost frame. Normally it's superfluous // to use this target, but we can handle it in the same manner as "_self".
// I.IV) no further special targets exist // Now we have to search for the right target frame by calling findFrame(), but should provide our code // against the creation of a new task if no frame could be found. // As mentioned earlier, it's allowed for dispatch() only.
// try to find any existing target and ask it for its dispatcher
css::uno::Reference< css::frame::XFrame > xFoundFrame = xDesktop->findFrame(sTargetFrameName, nRightFlags); if (xFoundFrame.is())
{
css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFoundFrame, css::uno::UNO_QUERY );
xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_SELF,0);
} // If it couldn't be found, but creation was allowed, // use a special dispatcher for creation or forwarding to the browser elseif (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
xDispatcher = implts_getOrCreateDispatchHelper( E_CREATEDISPATCHER, xDesktop, sTargetFrameName, nSearchFlags );
}
// 0) Some URLs are dispatched in a generic way (e.g. by the menu) using the default target "". // But they are specified to use their own fixed target. Detect such URLs here and use the correct target.
// I) First handle special cases which are not suited for using findFrame()
// I.I) "_blank", "_default" // It's not the right place to create a new task here. Only the desktop can do that. // Normally the functionality for "_blank" is provided by findFrame(), but that would create it directly // here. That's why we must "intercept" here.
if (
(sTargetFrameName==SPECIALTARGET_BLANK ) ||
(sTargetFrameName==SPECIALTARGET_DEFAULT)
)
{
css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY ); if (xParent.is())
xDispatcher = xParent->queryDispatch(aURL, sTargetFrameName, 0); // it's a special target - ignore search flags
}
// I.II) "_beamer" // Special sub frame of a top frame only. Search or create it. It's currently a little bit hacky. // Only the sfx (meaning the controller) can create it.
elseif (sTargetFrameName==SPECIALTARGET_BEAMER)
{
css::uno::Reference< css::frame::XDispatchProvider > xBeamer( xFrame->findFrame( SPECIALTARGET_BEAMER, css::frame::FrameSearchFlag::CHILDREN | css::frame::FrameSearchFlag::SELF ), css::uno::UNO_QUERY ); if (xBeamer.is())
{
xDispatcher = xBeamer->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
} else
{
css::uno::Reference< css::frame::XDispatchProvider > xController( xFrame->getController(), css::uno::UNO_QUERY ); if (xController.is()) // Force using of a special target, but use original search flags. // The caller may or may not use the CREATE flag!
xDispatcher = xController->queryDispatch(aURL, SPECIALTARGET_BEAMER, nSearchFlags);
}
}
// I.IV) "_parent" // Our parent frame (if it exists) should handle this URL.
elseif (sTargetFrameName==SPECIALTARGET_PARENT)
{
css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY ); if (xParent.is()) // SELF => we must address the parent directly, and not its parent or any other parent!
xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
}
// I.V) "_top" // This request must be forwarded to any parent frame, until we reach a top frame. // If no parent exists, the frame itself can be handled.
elseif (sTargetFrameName==SPECIALTARGET_TOP)
{ if (xFrame->isTop())
{ // If we are this top frame itself (meaning our owner frame), // we should call ourselves recursively with a better target "_self". // So we can share the same code! (see reaction for "_self" inside this method too.)
xDispatcher = queryDispatch(aURL,SPECIALTARGET_SELF,0);
} else
{
css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY ); // Normally if isTop() returned sal_False, the parent frame MUST(!) exist, // but it seems to be better to check that here to avoid an access violation. if (xParent.is())
xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_TOP, 0);
}
}
// I.VI) "_self", "" // Our owner frame should handle this URL. But we can't do it for all of them. // So we ask the internal set controller first. If it disagrees we try to find a registered // protocol handler. If this failed as well, we check for loadable content and in case of true // we load it into the frame by returning a specialized dispatch object.
elseif (
(sTargetFrameName==SPECIALTARGET_SELF) ||
(sTargetFrameName.isEmpty())
)
{ // There is a hardcoded interception for special URLs. if ( aURL.Complete == ".uno:CloseDoc" || aURL.Complete == ".uno:CloseWin" )
{
css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY ); // In case the frame is not a top one, is not based on system window and has a parent, // the parent frame should be queried for the correct dispatcher. // See i93473 if (
!WindowHelper::isTopWindow(xFrame->getContainerWindow()) &&
!VCLUnoHelper::GetWindow(xFrame->getContainerWindow())->IsSystemWindow() &&
xParent.is()
)
xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_SELF, 0); else
xDispatcher = implts_getOrCreateDispatchHelper( E_CLOSEDISPATCHER, xFrame );
} elseif ( aURL.Complete == ".uno:CloseFrame" )
xDispatcher = implts_getOrCreateDispatchHelper( E_CLOSEDISPATCHER, xFrame );
if ( ! xDispatcher.is())
{ // Ask our controller for its opinion on these dispatched URLs, // because some URLs are internal and can be handled faster by SFX - which usually is the current controller! // But in case of e.g. the bibliography not all queries will be handled successfully here.
css::uno::Reference< css::frame::XDispatchProvider > xController( xFrame->getController(), css::uno::UNO_QUERY ); if (xController.is())
xDispatcher = xController->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
}
// If the controller doesn't feel like dispatching these URLs, we must find an appropriate dispatcher. // Search for any registered protocol handlers first. if (!xDispatcher.is())
xDispatcher = implts_searchProtocolHandler(aURL);
// Not for controller - not for protocol handler. // It should be a loadable content, maybe a file. Check it. // This check is necessary for finding out, if // support for some protocols isn't installed by the user. // If a protocol is not available, we suppress the creation of our dispatcher. // The result will be clear. It can't handle it, but will try. if (
( ! xDispatcher.is() ) &&
( implts_isLoadableContent(aURL) )
)
{
xDispatcher = implts_getOrCreateDispatchHelper( E_SELFDISPATCHER, xFrame );
}
}
// I.VII) No further special handlings exist. // Now we have to search for the right target frame by calling findFrame(), but should provide our code // against the creation of a new task if no frame could be found. // As mentioned earlier, it's allowed for dispatch() only.
// try to find any existing target and ask it for its dispatcher
css::uno::Reference< css::frame::XFrame > xFoundFrame = xFrame->findFrame(sTargetFrameName, nRightFlags); if (xFoundFrame.is())
{ // Attention: Found target is our own owner frame! // Don't ask it for its dispatcher. We know it already - it's our dispatch helper. // Otherwise we can start a neverending recursive call. Why? // Our owner frame was called somewhere, it called some interceptor objects and maybe this dispatch provider // is called. If we use queryDispatch() on our owner frame again, we start this call stack again and again. if (xFoundFrame==xFrame)
xDispatcher = implts_getOrCreateDispatchHelper( E_SELFDISPATCHER, xFrame ); else
{
css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFoundFrame, css::uno::UNO_QUERY );
xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_SELF,0);
}
} else // If it couldn't be found, but creation was allowed // forward request to the desktop. // Note: The given target name must be used to set the name on a new created task! // Don't forward the request by changing it to a special one e.g _blank. // Use the CREATE flag only to prevent call against further searches. // We already know it: the target must be created new. if (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
{
css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY ); if (xParent.is())
xDispatcher = xParent->queryDispatch(aURL, sTargetFrameName, css::frame::FrameSearchFlag::CREATE);
}
}
// This member itself is threadsafe and lives if we live - we don't need any mutex here. if (framework::HandlerCache::search(aURL,&aHandler))
{
css::uno::Reference< css::frame::XDispatchProvider > xHandler;
{
SolarMutexGuard g;
// create it bool bInitialize = true; try
{ // Only create the protocol handler instance once, the creation is expensive. auto it = m_aProtocolHandlers.find(aHandler.m_sUNOName); if (it == m_aProtocolHandlers.end())
{
xHandler.set(
css::uno::Reference<css::lang::XMultiServiceFactory>(m_xContext->getServiceManager(), css::uno::UNO_QUERY_THROW)
->createInstance(aHandler.m_sUNOName),
css::uno::UNO_QUERY);
// Check if the handler explicitly requested to avoid caching.
css::uno::Reference<css::util::XCacheInfo> xCacheInfo(xHandler, css::uno::UNO_QUERY); if (!xCacheInfo.is() || xCacheInfo->isCachingAllowed())
{
m_aProtocolHandlers.emplace(aHandler.m_sUNOName, xHandler);
}
} else
{
xHandler = it->second;
bInitialize = false;
}
} catch(const css::uno::Exception&) {}
// check if initialization is necessary
css::uno::Reference< css::lang::XInitialization > xInit( xHandler, css::uno::UNO_QUERY ); if (xInit.is() && bInitialize)
{
css::uno::Reference< css::frame::XFrame > xOwner( m_xFrame.get(), css::uno::UNO_QUERY );
SAL_WARN_IF(!xOwner.is(), "fwk", "DispatchProvider::implts_searchProtocolHandler(): Couldn't get reference to my owner frame. So I can't set may needed context information for this protocol handler."); if (xOwner.is())
{ try
{ // but do it only, if all context information is OK
css::uno::Sequence< css::uno::Any > lContext{ css::uno::Any(xOwner) };
xInit->initialize(lContext);
} catch(const css::uno::Exception&) {}
}
}
}
// ask for its (sub)dispatcher for the given URL if (xHandler.is())
xDispatcher = xHandler->queryDispatch(aURL,SPECIALTARGET_SELF,0);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.