Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : //_______________________________________________
31 : : // include own header
32 : : #include <jobs/helponstartup.hxx>
33 : : #include <threadhelp/resetableguard.hxx>
34 : : #include <loadenv/targethelper.hxx>
35 : : #include <services.h>
36 : :
37 : : //_______________________________________________
38 : : // include others
39 : : #include <comphelper/configurationhelper.hxx>
40 : : #include <comphelper/sequenceashashmap.hxx>
41 : : #include <unotools/configmgr.hxx>
42 : : #include <vcl/svapp.hxx>
43 : : #include <vcl/help.hxx>
44 : : #include <rtl/ustrbuf.hxx>
45 : :
46 : : //_______________________________________________
47 : : // include interfaces
48 : : #include <com/sun/star/frame/FrameSearchFlag.hpp>
49 : : #include <com/sun/star/frame/XFramesSupplier.hpp>
50 : : #include <com/sun/star/frame/XDesktop.hpp>
51 : :
52 : :
53 : : namespace framework{
54 : :
55 : :
56 : : // path to module config
57 : 0 : static ::rtl::OUString CFG_PACKAGE_MODULES ("/org.openoffice.Setup/Office/Factories");
58 : 0 : static ::rtl::OUString CFG_PACKAGE_SETUP ("/org.openoffice.Setup");
59 : 0 : static ::rtl::OUString CFG_PACKAGE_COMMON ("/org.openoffice.Office.Common");
60 : 0 : static ::rtl::OUString CFG_PATH_L10N ("L10N");
61 : 0 : static ::rtl::OUString CFG_PATH_HELP ("Help");
62 : 0 : static ::rtl::OUString CFG_KEY_LOCALE ("ooLocale");
63 : 0 : static ::rtl::OUString CFG_KEY_HELPSYSTEM ("System");
64 : :
65 : : // props of job environment
66 : 0 : static ::rtl::OUString PROP_ENVIRONMENT ("Environment");
67 : 0 : static ::rtl::OUString PROP_JOBCONFIG ("JobConfig");
68 : 0 : static ::rtl::OUString PROP_ENVTYPE ("EnvType");
69 : 0 : static ::rtl::OUString PROP_MODEL ("Model");
70 : :
71 : : // props of module config
72 : 0 : static ::rtl::OUString PROP_HELP_BASEURL ("ooSetupFactoryHelpBaseURL");
73 : 0 : static ::rtl::OUString PROP_AUTOMATIC_HELP ("ooSetupFactoryHelpOnOpen");
74 : :
75 : : // special value of job environment
76 : 0 : static ::rtl::OUString ENVTYPE_DOCUMENTEVENT ("DOCUMENTEVENT");
77 : :
78 : : //-----------------------------------------------
79 : :
80 : 0 : DEFINE_XSERVICEINFO_MULTISERVICE(HelpOnStartup ,
81 : : ::cppu::OWeakObject ,
82 : : SERVICENAME_JOB ,
83 : : IMPLEMENTATIONNAME_HELPONSTARTUP)
84 : :
85 : 0 : DEFINE_INIT_SERVICE(HelpOnStartup,
86 : : {
87 : : /* Attention
88 : : I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
89 : : to create a new instance of this class by our own supported service factory.
90 : : see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
91 : : */
92 : : // create some needed uno services and cache it
93 : : m_xModuleManager = css::uno::Reference< css::frame::XModuleManager >(
94 : : m_xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
95 : : css::uno::UNO_QUERY_THROW);
96 : :
97 : : m_xDesktop = css::uno::Reference< css::frame::XFrame >(
98 : : m_xSMGR->createInstance(SERVICENAME_DESKTOP),
99 : : css::uno::UNO_QUERY_THROW);
100 : :
101 : : m_xConfig = css::uno::Reference< css::container::XNameAccess >(
102 : : ::comphelper::ConfigurationHelper::openConfig(
103 : : m_xSMGR,
104 : : CFG_PACKAGE_MODULES,
105 : : ::comphelper::ConfigurationHelper::E_READONLY),
106 : : css::uno::UNO_QUERY_THROW);
107 : :
108 : : // ask for office locale
109 : : ::comphelper::ConfigurationHelper::readDirectKey(
110 : : m_xSMGR,
111 : : CFG_PACKAGE_SETUP,
112 : : CFG_PATH_L10N,
113 : : CFG_KEY_LOCALE,
114 : : ::comphelper::ConfigurationHelper::E_READONLY) >>= m_sLocale;
115 : :
116 : : // detect system
117 : : ::comphelper::ConfigurationHelper::readDirectKey(
118 : : m_xSMGR,
119 : : CFG_PACKAGE_COMMON,
120 : : CFG_PATH_HELP,
121 : : CFG_KEY_HELPSYSTEM,
122 : : ::comphelper::ConfigurationHelper::E_READONLY) >>= m_sSystem;
123 : :
124 : : // Start listening for disposing events of these services,
125 : : // so we can react e.g. for an office shutdown
126 : : css::uno::Reference< css::lang::XComponent > xComponent;
127 : : xComponent = css::uno::Reference< css::lang::XComponent >(m_xModuleManager, css::uno::UNO_QUERY);
128 : : if (xComponent.is())
129 : : xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
130 : : xComponent = css::uno::Reference< css::lang::XComponent >(m_xDesktop, css::uno::UNO_QUERY);
131 : : if (xComponent.is())
132 : : xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
133 : : xComponent = css::uno::Reference< css::lang::XComponent >(m_xConfig, css::uno::UNO_QUERY);
134 : : if (xComponent.is())
135 : : xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
136 : : }
137 : : )
138 : :
139 : : //-----------------------------------------------
140 : 0 : HelpOnStartup::HelpOnStartup(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
141 : : : ThreadHelpBase( )
142 : 0 : , m_xSMGR (xSMGR)
143 : : {
144 : 0 : }
145 : :
146 : : //-----------------------------------------------
147 : 0 : HelpOnStartup::~HelpOnStartup()
148 : : {
149 : 0 : }
150 : :
151 : : //-----------------------------------------------
152 : : // css.task.XJob
153 : 0 : css::uno::Any SAL_CALL HelpOnStartup::execute(const css::uno::Sequence< css::beans::NamedValue >& lArguments)
154 : : throw(css::lang::IllegalArgumentException,
155 : : css::uno::Exception ,
156 : : css::uno::RuntimeException )
157 : : {
158 : : // Analyze the given arguments; try to locate a model there and
159 : : // classify it's used application module.
160 : 0 : ::rtl::OUString sModule = its_getModuleIdFromEnv(lArguments);
161 : :
162 : : // Attention: We are bound to events for openeing any document inside the office.
163 : : // That includes e.g. the help module itself. But we have to do nothing then!
164 : 0 : if (sModule.isEmpty())
165 : 0 : return css::uno::Any();
166 : :
167 : : // check current state of the help module
168 : : // a) help isnt open => show default page for the detected module
169 : : // b) help shows any other default page(!) => show default page for the detected module
170 : : // c) help shows any other content => do nothing (user travelled to any other content and leaved the set of default pages)
171 : 0 : ::rtl::OUString sCurrentHelpURL = its_getCurrentHelpURL();
172 : 0 : sal_Bool bCurrentHelpURLIsAnyDefaultURL = its_isHelpUrlADefaultOne(sCurrentHelpURL);
173 : 0 : sal_Bool bShowIt = sal_False;
174 : :
175 : : // a)
176 : 0 : if (sCurrentHelpURL.isEmpty())
177 : 0 : bShowIt = sal_True;
178 : : else
179 : : // b)
180 : 0 : if (bCurrentHelpURLIsAnyDefaultURL)
181 : 0 : bShowIt = sal_True;
182 : :
183 : 0 : if (bShowIt)
184 : : {
185 : : // retrieve the help URL for the detected application module
186 : 0 : ::rtl::OUString sModuleDependendHelpURL = its_checkIfHelpEnabledAndGetURL(sModule);
187 : 0 : if (!sModuleDependendHelpURL.isEmpty())
188 : : {
189 : : // Show this help page.
190 : : // Note: The help window brings itself to front ...
191 : 0 : Help* pHelp = Application::GetHelp();
192 : 0 : if (pHelp)
193 : 0 : pHelp->Start(sModuleDependendHelpURL, 0);
194 : 0 : }
195 : : }
196 : :
197 : 0 : return css::uno::Any();
198 : : }
199 : :
200 : : //-----------------------------------------------
201 : 0 : void SAL_CALL HelpOnStartup::disposing(const css::lang::EventObject& aEvent)
202 : : throw(css::uno::RuntimeException)
203 : : {
204 : : // SAFE ->
205 : 0 : ResetableGuard aLock(m_aLock);
206 : :
207 : 0 : if (aEvent.Source == m_xModuleManager)
208 : 0 : m_xModuleManager.clear();
209 : : else
210 : 0 : if (aEvent.Source == m_xDesktop)
211 : 0 : m_xDesktop.clear();
212 : : else
213 : 0 : if (aEvent.Source == m_xConfig)
214 : 0 : m_xConfig.clear();
215 : :
216 : 0 : aLock.unlock();
217 : : // <- SAFE
218 : 0 : }
219 : :
220 : : //-----------------------------------------------
221 : 0 : ::rtl::OUString HelpOnStartup::its_getModuleIdFromEnv(const css::uno::Sequence< css::beans::NamedValue >& lArguments)
222 : : {
223 : 0 : ::comphelper::SequenceAsHashMap lArgs (lArguments);
224 : 0 : ::comphelper::SequenceAsHashMap lEnvironment = lArgs.getUnpackedValueOrDefault(PROP_ENVIRONMENT, css::uno::Sequence< css::beans::NamedValue >());
225 : 0 : ::comphelper::SequenceAsHashMap lJobConfig = lArgs.getUnpackedValueOrDefault(PROP_JOBCONFIG , css::uno::Sequence< css::beans::NamedValue >());
226 : :
227 : : // check for right environment.
228 : : // If its not a DocumentEvent, which triggered this job,
229 : : // we cant work correctly! => return immediatly and do nothing
230 : 0 : ::rtl::OUString sEnvType = lEnvironment.getUnpackedValueOrDefault(PROP_ENVTYPE, ::rtl::OUString());
231 : 0 : if (!sEnvType.equals(ENVTYPE_DOCUMENTEVENT))
232 : 0 : return ::rtl::OUString();
233 : :
234 : 0 : css::uno::Reference< css::frame::XModel > xDoc = lEnvironment.getUnpackedValueOrDefault(PROP_MODEL, css::uno::Reference< css::frame::XModel >());
235 : 0 : if (!xDoc.is())
236 : 0 : return ::rtl::OUString();
237 : :
238 : : // be sure that we work on top level documents only, which are registered
239 : : // on the desktop instance. Ignore e.g. life previews, which are top frames too ...
240 : : // but not registered at this global desktop instance.
241 : 0 : css::uno::Reference< css::frame::XDesktop > xDesktopCheck;
242 : 0 : css::uno::Reference< css::frame::XFrame > xFrame ;
243 : 0 : css::uno::Reference< css::frame::XController > xController = xDoc->getCurrentController();
244 : 0 : if (xController.is())
245 : 0 : xFrame = xController->getFrame();
246 : 0 : if (xFrame.is() && xFrame->isTop())
247 : 0 : xDesktopCheck = css::uno::Reference< css::frame::XDesktop >(xFrame->getCreator(), css::uno::UNO_QUERY);
248 : 0 : if (!xDesktopCheck.is())
249 : 0 : return ::rtl::OUString();
250 : :
251 : : // OK - now we are sure this document is a top level document.
252 : : // Classify it.
253 : : // SAFE ->
254 : 0 : ResetableGuard aLock(m_aLock);
255 : 0 : css::uno::Reference< css::frame::XModuleManager > xModuleManager = m_xModuleManager;
256 : 0 : aLock.unlock();
257 : : // <- SAFE
258 : :
259 : 0 : if (!xModuleManager.is())
260 : 0 : return ::rtl::OUString();
261 : :
262 : 0 : ::rtl::OUString sModuleId;
263 : : try
264 : : {
265 : 0 : sModuleId = xModuleManager->identify(xDoc);
266 : : }
267 : 0 : catch(const css::uno::RuntimeException&)
268 : 0 : { throw; }
269 : 0 : catch(const css::uno::Exception&)
270 : 0 : { sModuleId = ::rtl::OUString(); }
271 : :
272 : 0 : return sModuleId;
273 : : }
274 : :
275 : : //-----------------------------------------------
276 : 0 : ::rtl::OUString HelpOnStartup::its_getCurrentHelpURL()
277 : : {
278 : : // SAFE ->
279 : 0 : ResetableGuard aLock(m_aLock);
280 : 0 : css::uno::Reference< css::frame::XFrame > xDesktop = m_xDesktop;
281 : 0 : aLock.unlock();
282 : : // <- SAFE
283 : :
284 : 0 : if (!xDesktop.is())
285 : 0 : return ::rtl::OUString();
286 : :
287 : 0 : css::uno::Reference< css::frame::XFrame > xHelp = xDesktop->findFrame(SPECIALTARGET_HELPTASK, css::frame::FrameSearchFlag::CHILDREN);
288 : 0 : if (!xHelp.is())
289 : 0 : return ::rtl::OUString();
290 : :
291 : 0 : ::rtl::OUString sCurrentHelpURL;
292 : : try
293 : : {
294 : 0 : css::uno::Reference< css::frame::XFramesSupplier > xHelpRoot (xHelp , css::uno::UNO_QUERY_THROW);
295 : 0 : css::uno::Reference< css::container::XIndexAccess > xHelpChildren(xHelpRoot->getFrames(), css::uno::UNO_QUERY_THROW);
296 : :
297 : 0 : css::uno::Reference< css::frame::XFrame > xHelpChild ;
298 : 0 : css::uno::Reference< css::frame::XController > xHelpView ;
299 : 0 : css::uno::Reference< css::frame::XModel > xHelpContent;
300 : :
301 : 0 : xHelpChildren->getByIndex(0) >>= xHelpChild;
302 : 0 : if (xHelpChild.is())
303 : 0 : xHelpView = xHelpChild->getController();
304 : 0 : if (xHelpView.is())
305 : 0 : xHelpContent = xHelpView->getModel();
306 : 0 : if (xHelpContent.is())
307 : 0 : sCurrentHelpURL = xHelpContent->getURL();
308 : : }
309 : 0 : catch(const css::uno::RuntimeException&)
310 : 0 : { throw; }
311 : 0 : catch(const css::uno::Exception&)
312 : 0 : { sCurrentHelpURL = ::rtl::OUString(); }
313 : :
314 : 0 : return sCurrentHelpURL;
315 : : }
316 : :
317 : : //-----------------------------------------------
318 : 0 : ::sal_Bool HelpOnStartup::its_isHelpUrlADefaultOne(const ::rtl::OUString& sHelpURL)
319 : : {
320 : 0 : if (sHelpURL.isEmpty())
321 : 0 : return sal_False;
322 : :
323 : : // SAFE ->
324 : 0 : ResetableGuard aLock(m_aLock);
325 : 0 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR (m_xSMGR, css::uno::UNO_QUERY_THROW);
326 : 0 : css::uno::Reference< css::container::XNameAccess > xConfig = m_xConfig;
327 : 0 : ::rtl::OUString sLocale = m_sLocale;
328 : 0 : ::rtl::OUString sSystem = m_sSystem;
329 : 0 : aLock.unlock();
330 : : // <- SAFE
331 : :
332 : 0 : if (!xConfig.is())
333 : 0 : return sal_False;
334 : :
335 : : // check given help url against all default ones
336 : 0 : const css::uno::Sequence< ::rtl::OUString > lModules = xConfig->getElementNames();
337 : 0 : const ::rtl::OUString* pModules = lModules.getConstArray();
338 : 0 : ::sal_Int32 c = lModules.getLength();
339 : 0 : ::sal_Int32 i = 0;
340 : :
341 : 0 : for (i=0; i<c; ++i)
342 : : {
343 : : try
344 : : {
345 : 0 : css::uno::Reference< css::container::XNameAccess > xModuleConfig;
346 : 0 : xConfig->getByName(pModules[i]) >>= xModuleConfig;
347 : 0 : if (!xModuleConfig.is())
348 : 0 : continue;
349 : :
350 : 0 : ::rtl::OUString sHelpBaseURL;
351 : 0 : xModuleConfig->getByName(PROP_HELP_BASEURL) >>= sHelpBaseURL;
352 : 0 : ::rtl::OUString sHelpURLForModule = HelpOnStartup::ist_createHelpURL(sHelpBaseURL, sLocale, sSystem);
353 : 0 : if (sHelpURL.equals(sHelpURLForModule))
354 : 0 : return sal_True;
355 : : }
356 : 0 : catch(const css::uno::RuntimeException&)
357 : 0 : { throw; }
358 : 0 : catch(const css::uno::Exception&)
359 : : {}
360 : : }
361 : :
362 : 0 : return sal_False;
363 : : }
364 : :
365 : : //-----------------------------------------------
366 : 0 : ::rtl::OUString HelpOnStartup::its_checkIfHelpEnabledAndGetURL(const ::rtl::OUString& sModule)
367 : : {
368 : : // SAFE ->
369 : 0 : ResetableGuard aLock(m_aLock);
370 : 0 : css::uno::Reference< css::container::XNameAccess > xConfig = m_xConfig;
371 : 0 : ::rtl::OUString sLocale = m_sLocale;
372 : 0 : ::rtl::OUString sSystem = m_sSystem;
373 : 0 : aLock.unlock();
374 : : // <- SAFE
375 : :
376 : 0 : ::rtl::OUString sHelpURL;
377 : :
378 : : try
379 : : {
380 : 0 : css::uno::Reference< css::container::XNameAccess > xModuleConfig;
381 : 0 : if (xConfig.is())
382 : 0 : xConfig->getByName(sModule) >>= xModuleConfig;
383 : :
384 : 0 : sal_Bool bHelpEnabled = sal_False;
385 : 0 : if (xModuleConfig.is())
386 : 0 : xModuleConfig->getByName(PROP_AUTOMATIC_HELP) >>= bHelpEnabled;
387 : :
388 : 0 : if (bHelpEnabled)
389 : : {
390 : 0 : ::rtl::OUString sHelpBaseURL;
391 : 0 : xModuleConfig->getByName(PROP_HELP_BASEURL) >>= sHelpBaseURL;
392 : 0 : sHelpURL = HelpOnStartup::ist_createHelpURL(sHelpBaseURL, sLocale, sSystem);
393 : 0 : }
394 : : }
395 : 0 : catch(const css::uno::RuntimeException&)
396 : 0 : { throw; }
397 : 0 : catch(const css::uno::Exception&)
398 : 0 : { sHelpURL = ::rtl::OUString(); }
399 : :
400 : 0 : return sHelpURL;
401 : : }
402 : :
403 : : //-----------------------------------------------
404 : 0 : ::rtl::OUString HelpOnStartup::ist_createHelpURL(const ::rtl::OUString& sBaseURL,
405 : : const ::rtl::OUString& sLocale ,
406 : : const ::rtl::OUString& sSystem )
407 : : {
408 : 0 : ::rtl::OUStringBuffer sHelpURL(256);
409 : 0 : sHelpURL.append (sBaseURL );
410 : 0 : sHelpURL.appendAscii("?Language=");
411 : 0 : sHelpURL.append (sLocale );
412 : 0 : sHelpURL.appendAscii("&System=" );
413 : 0 : sHelpURL.append (sSystem );
414 : :
415 : 0 : return sHelpURL.makeStringAndClear();
416 : : }
417 : :
418 : 0 : } // namespace framework
419 : :
420 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|