1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_desktop.hxx"
30 
31 #include "dp_gui_shared.hxx"
32 #include "dp_gui.h"
33 #include "dp_gui_theextmgr.hxx"
34 #include "cppuhelper/implbase2.hxx"
35 #include "cppuhelper/implementationentry.hxx"
36 #include "unotools/configmgr.hxx"
37 #include "comphelper/servicedecl.hxx"
38 #include "comphelper/unwrapargs.hxx"
39 #include <i18npool/mslangid.hxx>
40 #include "vcl/svapp.hxx"
41 #include "vcl/msgbox.hxx"
42 #include "com/sun/star/lang/XServiceInfo.hpp"
43 #include "com/sun/star/task/XJobExecutor.hpp"
44 #include "com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp"
45 
46 #include "boost/bind.hpp"
47 #include "license_dialog.hxx"
48 #include "dp_gui_dialog2.hxx"
49 #include "dp_gui_extensioncmdqueue.hxx"
50 
51 using namespace ::dp_misc;
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::uno;
54 
55 using ::rtl::OUString;
56 
57 namespace css = ::com::sun::star;
58 namespace dp_gui {
59 
60 //==============================================================================
61 class MyApp : public Application, private boost::noncopyable
62 {
63 public:
64     MyApp();
65     virtual ~MyApp();
66 
67     // Application
68     virtual void Main();
69 };
70 
71 //______________________________________________________________________________
72 MyApp::~MyApp()
73 {
74 }
75 
76 //______________________________________________________________________________
77 MyApp::MyApp()
78 {
79 }
80 
81 //______________________________________________________________________________
82 void MyApp::Main()
83 {
84 }
85 
86 //##############################################################################
87 
88 namespace
89 {
90     struct ProductName
91         : public rtl::Static< String, ProductName > {};
92     struct Version
93         : public rtl::Static< String, Version > {};
94     struct AboutBoxVersion
95         : public rtl::Static< String, AboutBoxVersion > {};
96     struct OOOVendor
97         : public rtl::Static< String, OOOVendor > {};
98     struct Extension
99         : public rtl::Static< String, Extension > {};
100 }
101 
102 void ReplaceProductNameHookProc( String& rStr )
103 {
104     static int nAll = 0, nPro = 0;
105 
106     nAll++;
107     if ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND )
108     {
109         String &rProductName = ProductName::get();
110         String &rVersion = Version::get();
111         String &rAboutBoxVersion = AboutBoxVersion::get();
112         String &rExtension = Extension::get();
113         String &rOOOVendor = OOOVendor::get();
114 
115         if ( !rProductName.Len() )
116         {
117             rtl::OUString aTmp;
118             Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME );
119             aRet >>= aTmp;
120             rProductName = aTmp;
121 
122             aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTVERSION );
123             aRet >>= aTmp;
124             rVersion = aTmp;
125 
126             aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::ABOUTBOXPRODUCTVERSION );
127             aRet >>= aTmp;
128             rAboutBoxVersion = aTmp;
129 
130             aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::OOOVENDOR );
131             aRet >>= aTmp;
132             rOOOVendor = aTmp;
133 
134             if ( !rExtension.Len() )
135             {
136                 aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTEXTENSION );
137                 aRet >>= aTmp;
138                 rExtension = aTmp;
139             }
140         }
141 
142         nPro++;
143         rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", rProductName );
144         rStr.SearchAndReplaceAllAscii( "%PRODUCTVERSION", rVersion );
145         rStr.SearchAndReplaceAllAscii( "%ABOUTBOXPRODUCTVERSION", rAboutBoxVersion );
146         rStr.SearchAndReplaceAllAscii( "%OOOVENDOR", rOOOVendor );
147         rStr.SearchAndReplaceAllAscii( "%PRODUCTEXTENSION", rExtension );
148     }
149 }
150 
151 //==============================================================================
152 class ServiceImpl
153     : public ::cppu::WeakImplHelper2<ui::dialogs::XAsynchronousExecutableDialog,
154                                      task::XJobExecutor>
155 {
156     Reference<XComponentContext> const m_xComponentContext;
157     boost::optional< Reference<awt::XWindow> > /* const */ m_parent;
158     boost::optional<OUString> /* const */ m_view;
159     /* if true then this service is running in an unopkg process and not in an office process */
160     boost::optional<sal_Bool> /* const */ m_unopkg;
161 	boost::optional<OUString> m_extensionURL;
162     OUString m_initialTitle;
163     bool m_bShowUpdateOnly;
164 
165 public:
166     ServiceImpl( Sequence<Any> const & args,
167                  Reference<XComponentContext> const & xComponentContext );
168 
169     // XAsynchronousExecutableDialog
170     virtual void SAL_CALL setDialogTitle( OUString const & aTitle )
171         throw (RuntimeException);
172     virtual void SAL_CALL startExecuteModal(
173         Reference< ui::dialogs::XDialogClosedListener > const & xListener )
174         throw (RuntimeException);
175 
176     // XJobExecutor
177     virtual void SAL_CALL trigger( OUString const & event )
178         throw (RuntimeException);
179 };
180 
181 //______________________________________________________________________________
182 ServiceImpl::ServiceImpl( Sequence<Any> const& args,
183                           Reference<XComponentContext> const& xComponentContext)
184     : m_xComponentContext(xComponentContext),
185       m_bShowUpdateOnly( false )
186 {
187 	try {
188 		comphelper::unwrapArgs( args, m_parent, m_view, m_unopkg );
189 		return;
190 	} catch (css::lang::IllegalArgumentException & ) {
191 	}
192 	try {
193 		comphelper::unwrapArgs( args, m_extensionURL);
194 	} catch (css::lang::IllegalArgumentException & ) {
195 	}
196 
197     ResHookProc pProc = ResMgr::GetReadStringHook();
198     if ( !pProc )
199         ResMgr::SetReadStringHook( ReplaceProductNameHookProc );
200 }
201 
202 // XAsynchronousExecutableDialog
203 //______________________________________________________________________________
204 void ServiceImpl::setDialogTitle( OUString const & title )
205     throw (RuntimeException)
206 {
207     if ( dp_gui::TheExtensionManager::s_ExtMgr.is() )
208     {
209         const ::vos::OGuard guard( Application::GetSolarMutex() );
210         ::rtl::Reference< ::dp_gui::TheExtensionManager > dialog(
211             ::dp_gui::TheExtensionManager::get( m_xComponentContext,
212                                                 m_parent ? *m_parent : Reference<awt::XWindow>(),
213                                                 m_extensionURL ? *m_extensionURL : OUString() ) );
214         dialog->SetText( title );
215     }
216     else
217         m_initialTitle = title;
218 }
219 
220 //______________________________________________________________________________
221 void ServiceImpl::startExecuteModal(
222     Reference< ui::dialogs::XDialogClosedListener > const & xListener )
223     throw (RuntimeException)
224 {
225     bool bCloseDialog = true;  // only used if m_bShowUpdateOnly is true
226     ::std::auto_ptr<Application> app;
227     //ToDo: synchronize access to s_dialog !!!
228     if (! dp_gui::TheExtensionManager::s_ExtMgr.is())
229     {
230         const bool bAppUp = (GetpApp() != 0);
231         bool bOfficePipePresent;
232         try {
233             bOfficePipePresent = dp_misc::office_is_running();
234         }
235         catch (Exception & exc) {
236             if (bAppUp) {
237                 const vos::OGuard guard( Application::GetSolarMutex() );
238                 std::auto_ptr<ErrorBox> box(
239                     new ErrorBox( Application::GetActiveTopWindow(),
240                                   WB_OK, exc.Message ) );
241                 box->Execute();
242             }
243             throw;
244         }
245 
246         if (! bOfficePipePresent) {
247             OSL_ASSERT( ! bAppUp );
248             app.reset( new MyApp );
249             if (! InitVCL( Reference<lang::XMultiServiceFactory>(
250                                m_xComponentContext->getServiceManager(),
251                                UNO_QUERY_THROW ) ))
252                 throw RuntimeException( OUSTR("Cannot initialize VCL!"),
253                                         static_cast<OWeakObject *>(this) );
254             AllSettings as = app->GetSettings();
255             OUString slang;
256             if (! (::utl::ConfigManager::GetDirectConfigProperty(
257                        ::utl::ConfigManager::LOCALE ) >>= slang))
258                 throw RuntimeException( OUSTR("Cannot determine language!"),
259                                         static_cast<OWeakObject *>(this) );
260             as.SetUILanguage( MsLangId::convertIsoStringToLanguage( slang ) );
261             app->SetSettings( as );
262             String sTitle = ::utl::ConfigManager::GetDirectConfigProperty(
263                                 ::utl::ConfigManager::PRODUCTNAME).get<OUString>()
264                                 + String(static_cast<sal_Unicode>(' '))
265                                 + ::utl::ConfigManager::GetDirectConfigProperty(
266                                     ::utl::ConfigManager::PRODUCTVERSION).get<OUString>();
267             app->SetDisplayName(sTitle);
268             ExtensionCmdQueue::syncRepositories( m_xComponentContext );
269         }
270     }
271     else
272     {
273         // When m_bShowUpdateOnly is set, we are inside the office and the user clicked
274         // the update notification icon in the menu bar. We must not close the extensions
275         // dialog after displaying the update dialog when it has been visible before
276         if ( m_bShowUpdateOnly )
277             bCloseDialog = ! dp_gui::TheExtensionManager::s_ExtMgr->isVisible();
278     }
279 
280     {
281         const ::vos::OGuard guard( Application::GetSolarMutex() );
282         ::rtl::Reference< ::dp_gui::TheExtensionManager > myExtMgr(
283             ::dp_gui::TheExtensionManager::get(
284                 m_xComponentContext,
285                 m_parent ? *m_parent : Reference<awt::XWindow>(),
286                 m_extensionURL ? *m_extensionURL : OUString() ) );
287         myExtMgr->createDialog( false );
288         if (m_initialTitle.getLength() > 0) {
289             myExtMgr->SetText( m_initialTitle );
290             m_initialTitle = OUString();
291         }
292         if ( m_bShowUpdateOnly )
293         {
294             myExtMgr->checkUpdates( true, !bCloseDialog );
295             if ( bCloseDialog )
296                 myExtMgr->Close();
297             else
298                 myExtMgr->ToTop( TOTOP_RESTOREWHENMIN );
299         }
300         else
301         {
302             myExtMgr->Show();
303             myExtMgr->ToTop( TOTOP_RESTOREWHENMIN );
304         }
305     }
306 
307     if (app.get() != 0) {
308         Application::Execute();
309         DeInitVCL();
310     }
311 
312     if (xListener.is())
313         xListener->dialogClosed(
314             ui::dialogs::DialogClosedEvent(
315                 static_cast< ::cppu::OWeakObject * >(this),
316                 sal_Int16(0)) );
317 }
318 
319 // XJobExecutor
320 //______________________________________________________________________________
321 void ServiceImpl::trigger( OUString const &rEvent ) throw (RuntimeException)
322 {
323     if ( rEvent == OUSTR("SHOW_UPDATE_DIALOG") )
324         m_bShowUpdateOnly = true;
325     else
326         m_bShowUpdateOnly = false;
327 
328     startExecuteModal( Reference< ui::dialogs::XDialogClosedListener >() );
329 }
330 
331 namespace sdecl = comphelper::service_decl;
332 sdecl::class_<ServiceImpl, sdecl::with_args<true> > serviceSI;
333 sdecl::ServiceDecl const serviceDecl(
334     serviceSI,
335     "com.sun.star.comp.deployment.ui.PackageManagerDialog",
336     "com.sun.star.deployment.ui.PackageManagerDialog" );
337 
338 sdecl::class_<LicenseDialog, sdecl::with_args<true> > licenseSI;
339 sdecl::ServiceDecl const licenseDecl(
340     licenseSI,
341     "com.sun.star.comp.deployment.ui.LicenseDialog",
342     "com.sun.star.deployment.ui.LicenseDialog" );
343 
344 sdecl::class_<UpdateRequiredDialogService, sdecl::with_args<true> > updateSI;
345 sdecl::ServiceDecl const updateDecl(
346     updateSI,
347     "com.sun.star.comp.deployment.ui.UpdateRequiredDialog",
348     "com.sun.star.deployment.ui.UpdateRequiredDialog" );
349 } // namespace dp_gui
350 
351 extern "C" {
352 
353 void SAL_CALL component_getImplementationEnvironment(
354     const sal_Char ** ppEnvTypeName, uno_Environment ** )
355 {
356     *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
357 }
358 
359 void * SAL_CALL component_getFactory(
360     sal_Char const * pImplName,
361     lang::XMultiServiceFactory * pServiceManager,
362     registry::XRegistryKey * pRegistryKey )
363 {
364     return component_getFactoryHelper(
365         pImplName, pServiceManager, pRegistryKey, dp_gui::serviceDecl, dp_gui::licenseDecl, dp_gui::updateDecl );
366 }
367 
368 } // extern "C"
369