merged tag ooo/OOO330_m14
[LibreOffice.git] / framework / source / jobs / helponstartup.cxx
blob93ea64e94cb4893a81ad2e23c75b968f517748aa
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
31 //_______________________________________________
32 // include own header
33 #include <jobs/helponstartup.hxx>
34 #include <threadhelp/resetableguard.hxx>
35 #include <loadenv/targethelper.hxx>
36 #include <services.h>
38 //_______________________________________________
39 // include others
40 #include <comphelper/configurationhelper.hxx>
41 #include <comphelper/sequenceashashmap.hxx>
42 #include <unotools/configmgr.hxx>
43 #include <vcl/svapp.hxx>
44 #include <vcl/help.hxx>
45 #include <rtl/ustrbuf.hxx>
47 //_______________________________________________
48 // include interfaces
49 #include <com/sun/star/frame/FrameSearchFlag.hpp>
50 #include <com/sun/star/frame/XFramesSupplier.hpp>
51 #include <com/sun/star/frame/XDesktop.hpp>
53 //_______________________________________________
54 // namespace
56 namespace framework{
58 //_______________________________________________
59 // definitions
61 // path to module config
62 static ::rtl::OUString CFG_PACKAGE_MODULES = ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Office/Factories");
63 static ::rtl::OUString CFG_PACKAGE_SETUP = ::rtl::OUString::createFromAscii("/org.openoffice.Setup" );
64 static ::rtl::OUString CFG_PACKAGE_COMMON = ::rtl::OUString::createFromAscii("/org.openoffice.Office.Common" );
65 static ::rtl::OUString CFG_PATH_L10N = ::rtl::OUString::createFromAscii("L10N" );
66 static ::rtl::OUString CFG_PATH_HELP = ::rtl::OUString::createFromAscii("Help" );
67 static ::rtl::OUString CFG_KEY_LOCALE = ::rtl::OUString::createFromAscii("ooLocale" );
68 static ::rtl::OUString CFG_KEY_HELPSYSTEM = ::rtl::OUString::createFromAscii("System" );
70 // props of job environment
71 static ::rtl::OUString PROP_ENVIRONMENT = ::rtl::OUString::createFromAscii("Environment" );
72 static ::rtl::OUString PROP_JOBCONFIG = ::rtl::OUString::createFromAscii("JobConfig" );
73 static ::rtl::OUString PROP_ENVTYPE = ::rtl::OUString::createFromAscii("EnvType" );
74 static ::rtl::OUString PROP_MODEL = ::rtl::OUString::createFromAscii("Model" );
76 // props of module config
77 static ::rtl::OUString PROP_HELP_BASEURL = ::rtl::OUString::createFromAscii("ooSetupFactoryHelpBaseURL" );
78 static ::rtl::OUString PROP_AUTOMATIC_HELP = ::rtl::OUString::createFromAscii("ooSetupFactoryHelpOnOpen" );
80 // special value of job environment
81 static ::rtl::OUString ENVTYPE_DOCUMENTEVENT = ::rtl::OUString::createFromAscii("DOCUMENTEVENT" );
83 //-----------------------------------------------
85 DEFINE_XSERVICEINFO_MULTISERVICE(HelpOnStartup ,
86 ::cppu::OWeakObject ,
87 SERVICENAME_JOB ,
88 IMPLEMENTATIONNAME_HELPONSTARTUP)
90 DEFINE_INIT_SERVICE(HelpOnStartup,
92 /* Attention
93 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
94 to create a new instance of this class by our own supported service factory.
95 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
97 // create some needed uno services and cache it
98 m_xModuleManager = css::uno::Reference< css::frame::XModuleManager >(
99 m_xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
100 css::uno::UNO_QUERY_THROW);
102 m_xDesktop = css::uno::Reference< css::frame::XFrame >(
103 m_xSMGR->createInstance(SERVICENAME_DESKTOP),
104 css::uno::UNO_QUERY_THROW);
106 m_xConfig = css::uno::Reference< css::container::XNameAccess >(
107 ::comphelper::ConfigurationHelper::openConfig(
108 m_xSMGR,
109 CFG_PACKAGE_MODULES,
110 ::comphelper::ConfigurationHelper::E_READONLY),
111 css::uno::UNO_QUERY_THROW);
113 // ask for office locale
114 ::comphelper::ConfigurationHelper::readDirectKey(
115 m_xSMGR,
116 CFG_PACKAGE_SETUP,
117 CFG_PATH_L10N,
118 CFG_KEY_LOCALE,
119 ::comphelper::ConfigurationHelper::E_READONLY) >>= m_sLocale;
121 // detect system
122 ::comphelper::ConfigurationHelper::readDirectKey(
123 m_xSMGR,
124 CFG_PACKAGE_COMMON,
125 CFG_PATH_HELP,
126 CFG_KEY_HELPSYSTEM,
127 ::comphelper::ConfigurationHelper::E_READONLY) >>= m_sSystem;
129 // Start listening for disposing events of these services,
130 // so we can react e.g. for an office shutdown
131 css::uno::Reference< css::lang::XComponent > xComponent;
132 xComponent = css::uno::Reference< css::lang::XComponent >(m_xModuleManager, css::uno::UNO_QUERY);
133 if (xComponent.is())
134 xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
135 xComponent = css::uno::Reference< css::lang::XComponent >(m_xDesktop, css::uno::UNO_QUERY);
136 if (xComponent.is())
137 xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
138 xComponent = css::uno::Reference< css::lang::XComponent >(m_xConfig, css::uno::UNO_QUERY);
139 if (xComponent.is())
140 xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
144 //-----------------------------------------------
145 HelpOnStartup::HelpOnStartup(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
146 : ThreadHelpBase( )
147 , m_xSMGR (xSMGR)
151 //-----------------------------------------------
152 HelpOnStartup::~HelpOnStartup()
156 //-----------------------------------------------
157 // css.task.XJob
158 css::uno::Any SAL_CALL HelpOnStartup::execute(const css::uno::Sequence< css::beans::NamedValue >& lArguments)
159 throw(css::lang::IllegalArgumentException,
160 css::uno::Exception ,
161 css::uno::RuntimeException )
163 // Analyze the given arguments; try to locate a model there and
164 // classify it's used application module.
165 ::rtl::OUString sModule = its_getModuleIdFromEnv(lArguments);
167 // Attention: We are bound to events for openeing any document inside the office.
168 // That includes e.g. the help module itself. But we have to do nothing then!
169 if (!sModule.getLength())
170 return css::uno::Any();
172 // check current state of the help module
173 // a) help isnt open => show default page for the detected module
174 // b) help shows any other default page(!) => show default page for the detected module
175 // c) help shows any other content => do nothing (user travelled to any other content and leaved the set of default pages)
176 ::rtl::OUString sCurrentHelpURL = its_getCurrentHelpURL();
177 sal_Bool bCurrentHelpURLIsAnyDefaultURL = its_isHelpUrlADefaultOne(sCurrentHelpURL);
178 sal_Bool bShowIt = sal_False;
180 // a)
181 if (!sCurrentHelpURL.getLength())
182 bShowIt = sal_True;
183 else
184 // b)
185 if (bCurrentHelpURLIsAnyDefaultURL)
186 bShowIt = sal_True;
188 if (bShowIt)
190 // retrieve the help URL for the detected application module
191 ::rtl::OUString sModuleDependendHelpURL = its_checkIfHelpEnabledAndGetURL(sModule);
192 if (sModuleDependendHelpURL.getLength())
194 // Show this help page.
195 // Note: The help window brings itself to front ...
196 Help* pHelp = Application::GetHelp();
197 if (pHelp)
198 pHelp->Start(sModuleDependendHelpURL, 0);
202 return css::uno::Any();
205 //-----------------------------------------------
206 void SAL_CALL HelpOnStartup::disposing(const css::lang::EventObject& aEvent)
207 throw(css::uno::RuntimeException)
209 // SAFE ->
210 ResetableGuard aLock(m_aLock);
212 if (aEvent.Source == m_xModuleManager)
213 m_xModuleManager.clear();
214 else
215 if (aEvent.Source == m_xDesktop)
216 m_xDesktop.clear();
217 else
218 if (aEvent.Source == m_xConfig)
219 m_xConfig.clear();
221 aLock.unlock();
222 // <- SAFE
225 //-----------------------------------------------
226 ::rtl::OUString HelpOnStartup::its_getModuleIdFromEnv(const css::uno::Sequence< css::beans::NamedValue >& lArguments)
228 ::comphelper::SequenceAsHashMap lArgs (lArguments);
229 ::comphelper::SequenceAsHashMap lEnvironment = lArgs.getUnpackedValueOrDefault(PROP_ENVIRONMENT, css::uno::Sequence< css::beans::NamedValue >());
230 ::comphelper::SequenceAsHashMap lJobConfig = lArgs.getUnpackedValueOrDefault(PROP_JOBCONFIG , css::uno::Sequence< css::beans::NamedValue >());
232 // check for right environment.
233 // If its not a DocumentEvent, which triggered this job,
234 // we cant work correctly! => return immediatly and do nothing
235 ::rtl::OUString sEnvType = lEnvironment.getUnpackedValueOrDefault(PROP_ENVTYPE, ::rtl::OUString());
236 if (!sEnvType.equals(ENVTYPE_DOCUMENTEVENT))
237 return ::rtl::OUString();
239 css::uno::Reference< css::frame::XModel > xDoc = lEnvironment.getUnpackedValueOrDefault(PROP_MODEL, css::uno::Reference< css::frame::XModel >());
240 if (!xDoc.is())
241 return ::rtl::OUString();
243 // be sure that we work on top level documents only, which are registered
244 // on the desktop instance. Ignore e.g. life previews, which are top frames too ...
245 // but not registered at this global desktop instance.
246 css::uno::Reference< css::frame::XDesktop > xDesktopCheck;
247 css::uno::Reference< css::frame::XFrame > xFrame ;
248 css::uno::Reference< css::frame::XController > xController = xDoc->getCurrentController();
249 if (xController.is())
250 xFrame = xController->getFrame();
251 if (xFrame.is() && xFrame->isTop())
252 xDesktopCheck = css::uno::Reference< css::frame::XDesktop >(xFrame->getCreator(), css::uno::UNO_QUERY);
253 if (!xDesktopCheck.is())
254 return ::rtl::OUString();
256 // OK - now we are sure this document is a top level document.
257 // Classify it.
258 // SAFE ->
259 ResetableGuard aLock(m_aLock);
260 css::uno::Reference< css::frame::XModuleManager > xModuleManager = m_xModuleManager;
261 aLock.unlock();
262 // <- SAFE
264 if (!xModuleManager.is())
265 return ::rtl::OUString();
267 ::rtl::OUString sModuleId;
270 sModuleId = xModuleManager->identify(xDoc);
272 catch(const css::uno::RuntimeException& exRun)
273 { throw exRun; }
274 catch(const css::uno::Exception&)
275 { sModuleId = ::rtl::OUString(); }
277 return sModuleId;
280 //-----------------------------------------------
281 ::rtl::OUString HelpOnStartup::its_getCurrentHelpURL()
283 // SAFE ->
284 ResetableGuard aLock(m_aLock);
285 css::uno::Reference< css::frame::XFrame > xDesktop = m_xDesktop;
286 aLock.unlock();
287 // <- SAFE
289 if (!xDesktop.is())
290 return ::rtl::OUString();
292 css::uno::Reference< css::frame::XFrame > xHelp = xDesktop->findFrame(SPECIALTARGET_HELPTASK, css::frame::FrameSearchFlag::CHILDREN);
293 if (!xHelp.is())
294 return ::rtl::OUString();
296 ::rtl::OUString sCurrentHelpURL;
299 css::uno::Reference< css::frame::XFramesSupplier > xHelpRoot (xHelp , css::uno::UNO_QUERY_THROW);
300 css::uno::Reference< css::container::XIndexAccess > xHelpChilds(xHelpRoot->getFrames(), css::uno::UNO_QUERY_THROW);
302 css::uno::Reference< css::frame::XFrame > xHelpChild ;
303 css::uno::Reference< css::frame::XController > xHelpView ;
304 css::uno::Reference< css::frame::XModel > xHelpContent;
306 xHelpChilds->getByIndex(0) >>= xHelpChild;
307 if (xHelpChild.is())
308 xHelpView = xHelpChild->getController();
309 if (xHelpView.is())
310 xHelpContent = xHelpView->getModel();
311 if (xHelpContent.is())
312 sCurrentHelpURL = xHelpContent->getURL();
314 catch(css::uno::RuntimeException& exRun)
315 { throw exRun; }
316 catch(css::uno::Exception&)
317 { sCurrentHelpURL = ::rtl::OUString(); }
319 return sCurrentHelpURL;
322 //-----------------------------------------------
323 ::sal_Bool HelpOnStartup::its_isHelpUrlADefaultOne(const ::rtl::OUString& sHelpURL)
325 if (!sHelpURL.getLength())
326 return sal_False;
328 // SAFE ->
329 ResetableGuard aLock(m_aLock);
330 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR (m_xSMGR, css::uno::UNO_QUERY_THROW);
331 css::uno::Reference< css::container::XNameAccess > xConfig = m_xConfig;
332 ::rtl::OUString sLocale = m_sLocale;
333 ::rtl::OUString sSystem = m_sSystem;
334 aLock.unlock();
335 // <- SAFE
337 if (!xConfig.is())
338 return sal_False;
340 // check given help url against all default ones
341 const css::uno::Sequence< ::rtl::OUString > lModules = xConfig->getElementNames();
342 const ::rtl::OUString* pModules = lModules.getConstArray();
343 ::sal_Int32 c = lModules.getLength();
344 ::sal_Int32 i = 0;
346 for (i=0; i<c; ++i)
350 css::uno::Reference< css::container::XNameAccess > xModuleConfig;
351 xConfig->getByName(pModules[i]) >>= xModuleConfig;
352 if (!xModuleConfig.is())
353 continue;
355 ::rtl::OUString sHelpBaseURL;
356 xModuleConfig->getByName(PROP_HELP_BASEURL) >>= sHelpBaseURL;
357 ::rtl::OUString sHelpURLForModule = HelpOnStartup::ist_createHelpURL(sHelpBaseURL, sLocale, sSystem);
358 if (sHelpURL.equals(sHelpURLForModule))
359 return sal_True;
361 catch(const css::uno::RuntimeException& exRun)
362 { throw exRun; }
363 catch(const css::uno::Exception&)
367 return sal_False;
370 //-----------------------------------------------
371 ::rtl::OUString HelpOnStartup::its_checkIfHelpEnabledAndGetURL(const ::rtl::OUString& sModule)
373 // SAFE ->
374 ResetableGuard aLock(m_aLock);
375 css::uno::Reference< css::container::XNameAccess > xConfig = m_xConfig;
376 ::rtl::OUString sLocale = m_sLocale;
377 ::rtl::OUString sSystem = m_sSystem;
378 aLock.unlock();
379 // <- SAFE
381 ::rtl::OUString sHelpURL;
385 css::uno::Reference< css::container::XNameAccess > xModuleConfig;
386 if (xConfig.is())
387 xConfig->getByName(sModule) >>= xModuleConfig;
389 sal_Bool bHelpEnabled = sal_False;
390 if (xModuleConfig.is())
391 xModuleConfig->getByName(PROP_AUTOMATIC_HELP) >>= bHelpEnabled;
393 if (bHelpEnabled)
395 ::rtl::OUString sHelpBaseURL;
396 xModuleConfig->getByName(PROP_HELP_BASEURL) >>= sHelpBaseURL;
397 sHelpURL = HelpOnStartup::ist_createHelpURL(sHelpBaseURL, sLocale, sSystem);
400 catch(const css::uno::RuntimeException& exRun)
401 { throw exRun; }
402 catch(const css::uno::Exception&)
403 { sHelpURL = ::rtl::OUString(); }
405 return sHelpURL;
408 //-----------------------------------------------
409 ::rtl::OUString HelpOnStartup::ist_createHelpURL(const ::rtl::OUString& sBaseURL,
410 const ::rtl::OUString& sLocale ,
411 const ::rtl::OUString& sSystem )
413 ::rtl::OUStringBuffer sHelpURL(256);
414 sHelpURL.append (sBaseURL );
415 sHelpURL.appendAscii("?Language=");
416 sHelpURL.append (sLocale );
417 sHelpURL.appendAscii("&System=" );
418 sHelpURL.append (sSystem );
420 return sHelpURL.makeStringAndClear();
423 } // namespace framework