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