1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: helponstartup.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 //_______________________________________________
36 #include <jobs/helponstartup.hxx>
37 #include <threadhelp/resetableguard.hxx>
38 #include <loadenv/targethelper.hxx>
41 //_______________________________________________
43 #include <comphelper/configurationhelper.hxx>
44 #include <comphelper/sequenceashashmap.hxx>
45 #include <unotools/configmgr.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/help.hxx>
48 #include <rtl/ustrbuf.hxx>
50 //_______________________________________________
52 #include <com/sun/star/frame/FrameSearchFlag.hpp>
53 #include <com/sun/star/frame/XFramesSupplier.hpp>
54 #include <com/sun/star/frame/XDesktop.hpp>
56 //_______________________________________________
61 //_______________________________________________
64 // path to module config
65 static ::rtl::OUString CFG_PACKAGE_MODULES
= ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Office/Factories");
66 static ::rtl::OUString CFG_PACKAGE_SETUP
= ::rtl::OUString::createFromAscii("/org.openoffice.Setup" );
67 static ::rtl::OUString CFG_PACKAGE_COMMON
= ::rtl::OUString::createFromAscii("/org.openoffice.Office.Common" );
68 static ::rtl::OUString CFG_PATH_L10N
= ::rtl::OUString::createFromAscii("L10N" );
69 static ::rtl::OUString CFG_PATH_HELP
= ::rtl::OUString::createFromAscii("Help" );
70 static ::rtl::OUString CFG_KEY_LOCALE
= ::rtl::OUString::createFromAscii("ooLocale" );
71 static ::rtl::OUString CFG_KEY_HELPSYSTEM
= ::rtl::OUString::createFromAscii("System" );
73 // props of job environment
74 static ::rtl::OUString PROP_ENVIRONMENT
= ::rtl::OUString::createFromAscii("Environment" );
75 static ::rtl::OUString PROP_JOBCONFIG
= ::rtl::OUString::createFromAscii("JobConfig" );
76 static ::rtl::OUString PROP_ENVTYPE
= ::rtl::OUString::createFromAscii("EnvType" );
77 static ::rtl::OUString PROP_MODEL
= ::rtl::OUString::createFromAscii("Model" );
79 // props of module config
80 static ::rtl::OUString PROP_HELP_BASEURL
= ::rtl::OUString::createFromAscii("ooSetupFactoryHelpBaseURL" );
81 static ::rtl::OUString PROP_AUTOMATIC_HELP
= ::rtl::OUString::createFromAscii("ooSetupFactoryHelpOnOpen" );
83 // special value of job environment
84 static ::rtl::OUString ENVTYPE_DOCUMENTEVENT
= ::rtl::OUString::createFromAscii("DOCUMENTEVENT" );
86 //-----------------------------------------------
88 DEFINE_XSERVICEINFO_MULTISERVICE(HelpOnStartup
,
91 IMPLEMENTATIONNAME_HELPONSTARTUP
)
93 DEFINE_INIT_SERVICE(HelpOnStartup
,
96 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
97 to create a new instance of this class by our own supported service factory.
98 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
100 // create some needed uno services and cache it
101 m_xModuleManager
= css::uno::Reference
< css::frame::XModuleManager
>(
102 m_xSMGR
->createInstance(SERVICENAME_MODULEMANAGER
),
103 css::uno::UNO_QUERY_THROW
);
105 m_xDesktop
= css::uno::Reference
< css::frame::XFrame
>(
106 m_xSMGR
->createInstance(SERVICENAME_DESKTOP
),
107 css::uno::UNO_QUERY_THROW
);
109 m_xConfig
= css::uno::Reference
< css::container::XNameAccess
>(
110 ::comphelper::ConfigurationHelper::openConfig(
113 ::comphelper::ConfigurationHelper::E_READONLY
),
114 css::uno::UNO_QUERY_THROW
);
116 // ask for office locale
117 ::comphelper::ConfigurationHelper::readDirectKey(
122 ::comphelper::ConfigurationHelper::E_READONLY
) >>= m_sLocale
;
125 ::comphelper::ConfigurationHelper::readDirectKey(
130 ::comphelper::ConfigurationHelper::E_READONLY
) >>= m_sSystem
;
132 // Start listening for disposing events of these services,
133 // so we can react e.g. for an office shutdown
134 css::uno::Reference
< css::lang::XComponent
> xComponent
;
135 xComponent
= css::uno::Reference
< css::lang::XComponent
>(m_xModuleManager
, css::uno::UNO_QUERY
);
137 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
138 xComponent
= css::uno::Reference
< css::lang::XComponent
>(m_xDesktop
, css::uno::UNO_QUERY
);
140 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
141 xComponent
= css::uno::Reference
< css::lang::XComponent
>(m_xConfig
, css::uno::UNO_QUERY
);
143 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
147 //-----------------------------------------------
148 HelpOnStartup::HelpOnStartup(const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
154 //-----------------------------------------------
155 HelpOnStartup::~HelpOnStartup()
159 //-----------------------------------------------
161 css::uno::Any SAL_CALL
HelpOnStartup::execute(const css::uno::Sequence
< css::beans::NamedValue
>& lArguments
)
162 throw(css::lang::IllegalArgumentException
,
163 css::uno::Exception
,
164 css::uno::RuntimeException
)
166 // Analyze the given arguments; try to locate a model there and
167 // classify it's used application module.
168 ::rtl::OUString sModule
= its_getModuleIdFromEnv(lArguments
);
170 // Attention: We are bound to events for openeing any document inside the office.
171 // That includes e.g. the help module itself. But we have to do nothing then!
172 if (!sModule
.getLength())
173 return css::uno::Any();
175 // check current state of the help module
176 // a) help isnt open => show default page for the detected module
177 // b) help shows any other default page(!) => show default page for the detected module
178 // c) help shows any other content => do nothing (user travelled to any other content and leaved the set of default pages)
179 ::rtl::OUString sCurrentHelpURL
= its_getCurrentHelpURL();
180 sal_Bool bCurrentHelpURLIsAnyDefaultURL
= its_isHelpUrlADefaultOne(sCurrentHelpURL
);
181 sal_Bool bShowIt
= sal_False
;
184 if (!sCurrentHelpURL
.getLength())
188 if (bCurrentHelpURLIsAnyDefaultURL
)
193 // retrieve the help URL for the detected application module
194 ::rtl::OUString sModuleDependendHelpURL
= its_checkIfHelpEnabledAndGetURL(sModule
);
195 if (sModuleDependendHelpURL
.getLength())
197 // Show this help page.
198 // Note: The help window brings itself to front ...
199 Help
* pHelp
= Application::GetHelp();
201 pHelp
->Start(sModuleDependendHelpURL
, 0);
205 return css::uno::Any();
208 //-----------------------------------------------
209 void SAL_CALL
HelpOnStartup::disposing(const css::lang::EventObject
& aEvent
)
210 throw(css::uno::RuntimeException
)
213 ResetableGuard
aLock(m_aLock
);
215 if (aEvent
.Source
== m_xModuleManager
)
216 m_xModuleManager
.clear();
218 if (aEvent
.Source
== m_xDesktop
)
221 if (aEvent
.Source
== m_xConfig
)
228 //-----------------------------------------------
229 ::rtl::OUString
HelpOnStartup::its_getModuleIdFromEnv(const css::uno::Sequence
< css::beans::NamedValue
>& lArguments
)
231 ::comphelper::SequenceAsHashMap
lArgs (lArguments
);
232 ::comphelper::SequenceAsHashMap lEnvironment
= lArgs
.getUnpackedValueOrDefault(PROP_ENVIRONMENT
, css::uno::Sequence
< css::beans::NamedValue
>());
233 ::comphelper::SequenceAsHashMap lJobConfig
= lArgs
.getUnpackedValueOrDefault(PROP_JOBCONFIG
, css::uno::Sequence
< css::beans::NamedValue
>());
235 // check for right environment.
236 // If its not a DocumentEvent, which triggered this job,
237 // we cant work correctly! => return immediatly and do nothing
238 ::rtl::OUString sEnvType
= lEnvironment
.getUnpackedValueOrDefault(PROP_ENVTYPE
, ::rtl::OUString());
239 if (!sEnvType
.equals(ENVTYPE_DOCUMENTEVENT
))
240 return ::rtl::OUString();
242 css::uno::Reference
< css::frame::XModel
> xDoc
= lEnvironment
.getUnpackedValueOrDefault(PROP_MODEL
, css::uno::Reference
< css::frame::XModel
>());
244 return ::rtl::OUString();
246 // be sure that we work on top level documents only, which are registered
247 // on the desktop instance. Ignore e.g. life previews, which are top frames too ...
248 // but not registered at this global desktop instance.
249 css::uno::Reference
< css::frame::XDesktop
> xDesktopCheck
;
250 css::uno::Reference
< css::frame::XFrame
> xFrame
;
251 css::uno::Reference
< css::frame::XController
> xController
= xDoc
->getCurrentController();
252 if (xController
.is())
253 xFrame
= xController
->getFrame();
254 if (xFrame
.is() && xFrame
->isTop())
255 xDesktopCheck
= css::uno::Reference
< css::frame::XDesktop
>(xFrame
->getCreator(), css::uno::UNO_QUERY
);
256 if (!xDesktopCheck
.is())
257 return ::rtl::OUString();
259 // OK - now we are sure this document is a top level document.
262 ResetableGuard
aLock(m_aLock
);
263 css::uno::Reference
< css::frame::XModuleManager
> xModuleManager
= m_xModuleManager
;
267 if (!xModuleManager
.is())
268 return ::rtl::OUString();
270 ::rtl::OUString sModuleId
;
273 sModuleId
= xModuleManager
->identify(xDoc
);
275 catch(const css::uno::RuntimeException
& exRun
)
277 catch(const css::uno::Exception
&)
278 { sModuleId
= ::rtl::OUString(); }
283 //-----------------------------------------------
284 ::rtl::OUString
HelpOnStartup::its_getCurrentHelpURL()
287 ResetableGuard
aLock(m_aLock
);
288 css::uno::Reference
< css::frame::XFrame
> xDesktop
= m_xDesktop
;
293 return ::rtl::OUString();
295 css::uno::Reference
< css::frame::XFrame
> xHelp
= xDesktop
->findFrame(SPECIALTARGET_HELPTASK
, css::frame::FrameSearchFlag::CHILDREN
);
297 return ::rtl::OUString();
299 ::rtl::OUString sCurrentHelpURL
;
302 css::uno::Reference
< css::frame::XFramesSupplier
> xHelpRoot (xHelp
, css::uno::UNO_QUERY_THROW
);
303 css::uno::Reference
< css::container::XIndexAccess
> xHelpChilds(xHelpRoot
->getFrames(), css::uno::UNO_QUERY_THROW
);
305 css::uno::Reference
< css::frame::XFrame
> xHelpChild
;
306 css::uno::Reference
< css::frame::XController
> xHelpView
;
307 css::uno::Reference
< css::frame::XModel
> xHelpContent
;
309 xHelpChilds
->getByIndex(0) >>= xHelpChild
;
311 xHelpView
= xHelpChild
->getController();
313 xHelpContent
= xHelpView
->getModel();
314 if (xHelpContent
.is())
315 sCurrentHelpURL
= xHelpContent
->getURL();
317 catch(css::uno::RuntimeException
& exRun
)
319 catch(css::uno::Exception
&)
320 { sCurrentHelpURL
= ::rtl::OUString(); }
322 return sCurrentHelpURL
;
325 //-----------------------------------------------
326 ::sal_Bool
HelpOnStartup::its_isHelpUrlADefaultOne(const ::rtl::OUString
& sHelpURL
)
328 if (!sHelpURL
.getLength())
332 ResetableGuard
aLock(m_aLock
);
333 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR (m_xSMGR
, css::uno::UNO_QUERY_THROW
);
334 css::uno::Reference
< css::container::XNameAccess
> xConfig
= m_xConfig
;
335 ::rtl::OUString sLocale
= m_sLocale
;
336 ::rtl::OUString sSystem
= m_sSystem
;
343 // check given help url against all default ones
344 const css::uno::Sequence
< ::rtl::OUString
> lModules
= xConfig
->getElementNames();
345 const ::rtl::OUString
* pModules
= lModules
.getConstArray();
346 ::sal_Int32 c
= lModules
.getLength();
353 css::uno::Reference
< css::container::XNameAccess
> xModuleConfig
;
354 xConfig
->getByName(pModules
[i
]) >>= xModuleConfig
;
355 if (!xModuleConfig
.is())
358 ::rtl::OUString sHelpBaseURL
;
359 xModuleConfig
->getByName(PROP_HELP_BASEURL
) >>= sHelpBaseURL
;
360 ::rtl::OUString sHelpURLForModule
= HelpOnStartup::ist_createHelpURL(sHelpBaseURL
, sLocale
, sSystem
);
361 if (sHelpURL
.equals(sHelpURLForModule
))
364 catch(const css::uno::RuntimeException
& exRun
)
366 catch(const css::uno::Exception
&)
373 //-----------------------------------------------
374 ::rtl::OUString
HelpOnStartup::its_checkIfHelpEnabledAndGetURL(const ::rtl::OUString
& sModule
)
377 ResetableGuard
aLock(m_aLock
);
378 css::uno::Reference
< css::container::XNameAccess
> xConfig
= m_xConfig
;
379 ::rtl::OUString sLocale
= m_sLocale
;
380 ::rtl::OUString sSystem
= m_sSystem
;
384 ::rtl::OUString sHelpURL
;
388 css::uno::Reference
< css::container::XNameAccess
> xModuleConfig
;
390 xConfig
->getByName(sModule
) >>= xModuleConfig
;
392 sal_Bool bHelpEnabled
= sal_False
;
393 if (xModuleConfig
.is())
394 xModuleConfig
->getByName(PROP_AUTOMATIC_HELP
) >>= bHelpEnabled
;
398 ::rtl::OUString sHelpBaseURL
;
399 xModuleConfig
->getByName(PROP_HELP_BASEURL
) >>= sHelpBaseURL
;
400 sHelpURL
= HelpOnStartup::ist_createHelpURL(sHelpBaseURL
, sLocale
, sSystem
);
403 catch(const css::uno::RuntimeException
& exRun
)
405 catch(const css::uno::Exception
&)
406 { sHelpURL
= ::rtl::OUString(); }
411 //-----------------------------------------------
412 ::rtl::OUString
HelpOnStartup::ist_createHelpURL(const ::rtl::OUString
& sBaseURL
,
413 const ::rtl::OUString
& sLocale
,
414 const ::rtl::OUString
& sSystem
)
416 ::rtl::OUStringBuffer
sHelpURL(256);
417 sHelpURL
.append (sBaseURL
);
418 sHelpURL
.appendAscii("?Language=");
419 sHelpURL
.append (sLocale
);
420 sHelpURL
.appendAscii("&System=" );
421 sHelpURL
.append (sSystem
);
423 return sHelpURL
.makeStringAndClear();
426 } // namespace framework