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 //_______________________________________________
33 #include <jobs/helponstartup.hxx>
34 #include <threadhelp/resetableguard.hxx>
35 #include <loadenv/targethelper.hxx>
38 //_______________________________________________
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 //_______________________________________________
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 //_______________________________________________
58 //_______________________________________________
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
,
88 IMPLEMENTATIONNAME_HELPONSTARTUP
)
90 DEFINE_INIT_SERVICE(HelpOnStartup
,
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(
110 ::comphelper::ConfigurationHelper::E_READONLY
),
111 css::uno::UNO_QUERY_THROW
);
113 // ask for office locale
114 ::comphelper::ConfigurationHelper::readDirectKey(
119 ::comphelper::ConfigurationHelper::E_READONLY
) >>= m_sLocale
;
122 ::comphelper::ConfigurationHelper::readDirectKey(
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
);
134 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
135 xComponent
= css::uno::Reference
< css::lang::XComponent
>(m_xDesktop
, css::uno::UNO_QUERY
);
137 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
138 xComponent
= css::uno::Reference
< css::lang::XComponent
>(m_xConfig
, css::uno::UNO_QUERY
);
140 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
144 //-----------------------------------------------
145 HelpOnStartup::HelpOnStartup(const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
151 //-----------------------------------------------
152 HelpOnStartup::~HelpOnStartup()
156 //-----------------------------------------------
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
;
181 if (!sCurrentHelpURL
.getLength())
185 if (bCurrentHelpURLIsAnyDefaultURL
)
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();
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
)
210 ResetableGuard
aLock(m_aLock
);
212 if (aEvent
.Source
== m_xModuleManager
)
213 m_xModuleManager
.clear();
215 if (aEvent
.Source
== m_xDesktop
)
218 if (aEvent
.Source
== m_xConfig
)
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
>());
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.
259 ResetableGuard
aLock(m_aLock
);
260 css::uno::Reference
< css::frame::XModuleManager
> xModuleManager
= m_xModuleManager
;
264 if (!xModuleManager
.is())
265 return ::rtl::OUString();
267 ::rtl::OUString sModuleId
;
270 sModuleId
= xModuleManager
->identify(xDoc
);
272 catch(const css::uno::RuntimeException
& exRun
)
274 catch(const css::uno::Exception
&)
275 { sModuleId
= ::rtl::OUString(); }
280 //-----------------------------------------------
281 ::rtl::OUString
HelpOnStartup::its_getCurrentHelpURL()
284 ResetableGuard
aLock(m_aLock
);
285 css::uno::Reference
< css::frame::XFrame
> xDesktop
= m_xDesktop
;
290 return ::rtl::OUString();
292 css::uno::Reference
< css::frame::XFrame
> xHelp
= xDesktop
->findFrame(SPECIALTARGET_HELPTASK
, css::frame::FrameSearchFlag::CHILDREN
);
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
;
308 xHelpView
= xHelpChild
->getController();
310 xHelpContent
= xHelpView
->getModel();
311 if (xHelpContent
.is())
312 sCurrentHelpURL
= xHelpContent
->getURL();
314 catch(css::uno::RuntimeException
& 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())
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
;
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();
350 css::uno::Reference
< css::container::XNameAccess
> xModuleConfig
;
351 xConfig
->getByName(pModules
[i
]) >>= xModuleConfig
;
352 if (!xModuleConfig
.is())
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
))
361 catch(const css::uno::RuntimeException
& exRun
)
363 catch(const css::uno::Exception
&)
370 //-----------------------------------------------
371 ::rtl::OUString
HelpOnStartup::its_checkIfHelpEnabledAndGetURL(const ::rtl::OUString
& sModule
)
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
;
381 ::rtl::OUString sHelpURL
;
385 css::uno::Reference
< css::container::XNameAccess
> xModuleConfig
;
387 xConfig
->getByName(sModule
) >>= xModuleConfig
;
389 sal_Bool bHelpEnabled
= sal_False
;
390 if (xModuleConfig
.is())
391 xModuleConfig
->getByName(PROP_AUTOMATIC_HELP
) >>= 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
)
402 catch(const css::uno::Exception
&)
403 { sHelpURL
= ::rtl::OUString(); }
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