| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_desktop.hxx" |
| |
| #include "dp_gui_updatedata.hxx" |
| |
| #include "sal/config.h" |
| #include "osl/file.hxx" |
| #include "osl/conditn.hxx" |
| #include "cppuhelper/exc_hlp.hxx" |
| #include "tools/resid.hxx" |
| #include "tools/resmgr.hxx" |
| #include "tools/solar.h" |
| #include "tools/string.hxx" |
| #include "vcl/dialog.hxx" |
| #include "vcl/msgbox.hxx" |
| #include "vcl/svapp.hxx" |
| #include "vos/mutex.hxx" |
| #include "vcl/dialog.hxx" |
| #include "cppuhelper/implbase3.hxx" |
| |
| #include "com/sun/star/beans/PropertyValue.hpp" |
| #include "com/sun/star/beans/NamedValue.hpp" |
| #include "com/sun/star/xml/dom/XElement.hpp" |
| #include "com/sun/star/xml/dom/XNode.hpp" |
| #include "com/sun/star/xml/dom/XNodeList.hpp" |
| #include "com/sun/star/ucb/NameClash.hpp" |
| #include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" |
| #include "com/sun/star/ucb/XCommandEnvironment.hpp" |
| #include "com/sun/star/ucb/XProgressHandler.hpp" |
| #include "com/sun/star/deployment/XExtensionManager.hpp" |
| #include "com/sun/star/deployment/ExtensionManager.hpp" |
| #include "com/sun/star/deployment/XUpdateInformationProvider.hpp" |
| #include "com/sun/star/deployment/DependencyException.hpp" |
| #include "com/sun/star/deployment/LicenseException.hpp" |
| #include "com/sun/star/deployment/VersionException.hpp" |
| #include "com/sun/star/deployment/ui/LicenseDialog.hpp" |
| #include "com/sun/star/task/XInteractionHandler.hpp" |
| #include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" |
| #include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" |
| #include "com/sun/star/task/XInteractionAbort.hpp" |
| #include "com/sun/star/task/XInteractionApprove.hpp" |
| |
| #include "dp_descriptioninfoset.hxx" |
| #include "dp_gui.hrc" |
| #include "dp_gui_updateinstalldialog.hxx" |
| #include "dp_gui_shared.hxx" |
| #include "dp_gui_updatedata.hxx" |
| #include "dp_ucb.h" |
| #include "dp_misc.h" |
| #include "dp_version.hxx" |
| #include "dp_gui_thread.hxx" |
| #include "dp_gui_extensioncmdqueue.hxx" |
| #include "ucbhelper/content.hxx" |
| #include "osl/mutex.hxx" |
| #include "vos/mutex.hxx" |
| #include "rtl/ref.hxx" |
| #include "com/sun/star/uno/Sequence.h" |
| #include "comphelper/anytostring.hxx" |
| #include "toolkit/helper/vclunohelper.hxx" |
| |
| #include <vector> |
| |
| class Window; |
| |
| namespace cssu = ::com::sun::star::uno; |
| namespace css = ::com::sun::star; |
| |
| using ::rtl::OUString; |
| |
| |
| namespace dp_gui { |
| |
| class UpdateInstallDialog::Thread: public dp_gui::Thread { |
| friend class UpdateCommandEnv; |
| public: |
| Thread(cssu::Reference< cssu::XComponentContext > ctx, |
| UpdateInstallDialog & dialog, std::vector< dp_gui::UpdateData > & aVecUpdateData); |
| |
| void stop(); |
| |
| |
| |
| private: |
| Thread(Thread &); // not defined |
| void operator =(Thread &); // not defined |
| |
| virtual ~Thread(); |
| |
| virtual void execute(); |
| void downloadExtensions(); |
| void download(::rtl::OUString const & aUrls, UpdateData & aUpdatData); |
| void installExtensions(); |
| void removeTempDownloads(); |
| |
| UpdateInstallDialog & m_dialog; |
| cssu::Reference< css::deployment::XUpdateInformationProvider > |
| m_updateInformation; |
| |
| // guarded by Application::GetSolarMutex(): |
| cssu::Reference< css::task::XAbortChannel > m_abort; |
| cssu::Reference< cssu::XComponentContext > m_xComponentContext; |
| std::vector< dp_gui::UpdateData > & m_aVecUpdateData; |
| ::rtl::Reference<UpdateCommandEnv> m_updateCmdEnv; |
| |
| //A folder which is created in the temp directory in which then the updates are downloaded |
| ::rtl::OUString m_sDownloadFolder; |
| |
| bool m_stop; |
| |
| }; |
| |
| class UpdateCommandEnv |
| : public ::cppu::WeakImplHelper3< css::ucb::XCommandEnvironment, |
| css::task::XInteractionHandler, |
| css::ucb::XProgressHandler > |
| { |
| friend class UpdateInstallDialog::Thread; |
| |
| UpdateInstallDialog & m_updateDialog; |
| ::rtl::Reference<UpdateInstallDialog::Thread> m_installThread; |
| cssu::Reference< cssu::XComponentContext > m_xContext; |
| |
| public: |
| virtual ~UpdateCommandEnv(); |
| UpdateCommandEnv( cssu::Reference< cssu::XComponentContext > const & xCtx, |
| UpdateInstallDialog & updateDialog, |
| ::rtl::Reference<UpdateInstallDialog::Thread>const & thread); |
| |
| // XCommandEnvironment |
| virtual cssu::Reference<css::task::XInteractionHandler > SAL_CALL |
| getInteractionHandler() throw (cssu::RuntimeException); |
| virtual cssu::Reference<css::ucb::XProgressHandler > |
| SAL_CALL getProgressHandler() throw (cssu::RuntimeException); |
| |
| // XInteractionHandler |
| virtual void SAL_CALL handle( |
| cssu::Reference<css::task::XInteractionRequest > const & xRequest ) |
| throw (cssu::RuntimeException); |
| |
| // XProgressHandler |
| virtual void SAL_CALL push( cssu::Any const & Status ) |
| throw (cssu::RuntimeException); |
| virtual void SAL_CALL update( cssu::Any const & Status ) |
| throw (cssu::RuntimeException); |
| virtual void SAL_CALL pop() throw (cssu::RuntimeException); |
| }; |
| |
| |
| UpdateInstallDialog::Thread::Thread( |
| cssu::Reference< cssu::XComponentContext> xCtx, |
| UpdateInstallDialog & dialog, |
| std::vector< dp_gui::UpdateData > & aVecUpdateData): |
| m_dialog(dialog), |
| m_xComponentContext(xCtx), |
| m_aVecUpdateData(aVecUpdateData), |
| m_updateCmdEnv(new UpdateCommandEnv(xCtx, m_dialog, this)), |
| m_stop(false) |
| {} |
| |
| void UpdateInstallDialog::Thread::stop() { |
| cssu::Reference< css::task::XAbortChannel > abort; |
| { |
| vos::OGuard g(Application::GetSolarMutex()); |
| abort = m_abort; |
| m_stop = true; |
| } |
| if (abort.is()) { |
| abort->sendAbort(); |
| } |
| } |
| |
| UpdateInstallDialog::Thread::~Thread() {} |
| |
| void UpdateInstallDialog::Thread::execute() |
| { |
| try { |
| downloadExtensions(); |
| installExtensions(); |
| } |
| catch (...) |
| { |
| } |
| |
| //clean up the temp directories |
| try { |
| removeTempDownloads(); |
| } catch( ... ) { |
| } |
| |
| { |
| //make sure m_dialog is still alive |
| ::vos::OGuard g(Application::GetSolarMutex()); |
| if (! m_stop) |
| m_dialog.updateDone(); |
| } |
| //UpdateCommandEnv keeps a reference to Thread and prevents destruction. Therefore remove it. |
| m_updateCmdEnv->m_installThread.clear(); |
| } |
| |
| |
| UpdateInstallDialog::UpdateInstallDialog( |
| Window * parent, |
| std::vector<dp_gui::UpdateData> & aVecUpdateData, |
| cssu::Reference< cssu::XComponentContext > const & xCtx): |
| ModalDialog( |
| parent, |
| DpGuiResId(RID_DLG_UPDATEINSTALL)), |
| |
| m_thread(new Thread(xCtx, *this, aVecUpdateData)), |
| m_xComponentContext(xCtx), |
| m_bError(false), |
| m_bNoEntry(true), |
| m_bActivated(false), |
| m_sInstalling(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_INSTALLING))), |
| m_sFinished(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_FINISHED))), |
| m_sNoErrors(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_NO_ERRORS))), |
| m_sErrorDownload(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_DOWNLOAD))), |
| m_sErrorInstallation(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_INSTALLATION))), |
| m_sErrorLicenseDeclined(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_LIC_DECLINED))), |
| m_sNoInstall(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_EXTENSION_NOINSTALL))), |
| m_sThisErrorOccurred(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_THIS_ERROR_OCCURRED))), |
| m_ft_action(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_DOWNLOADING)), |
| m_statusbar(this,DpGuiResId(RID_DLG_UPDATE_INSTALL_STATUSBAR)), |
| m_ft_extension_name(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_EXTENSION_NAME)), |
| m_ft_results(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_RESULTS)), |
| m_mle_info(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_INFO)), |
| m_line(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_LINE)), |
| m_help(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_HELP)), |
| m_ok(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_OK)), |
| m_cancel(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_ABORT)) |
| { |
| FreeResource(); |
| |
| m_xExtensionManager = css::deployment::ExtensionManager::get( xCtx ); |
| |
| m_cancel.SetClickHdl(LINK(this, UpdateInstallDialog, cancelHandler)); |
| m_mle_info.EnableCursor(sal_False); |
| if ( ! dp_misc::office_is_running()) |
| m_help.Disable(); |
| } |
| |
| UpdateInstallDialog::~UpdateInstallDialog() {} |
| |
| sal_Bool UpdateInstallDialog::Close() |
| { |
| m_thread->stop(); |
| return ModalDialog::Close(); |
| } |
| |
| short UpdateInstallDialog::Execute() |
| { |
| m_thread->launch(); |
| return ModalDialog::Execute(); |
| } |
| |
| |
| // make sure the solar mutex is locked before calling |
| void UpdateInstallDialog::updateDone() |
| { |
| if (!m_bError) |
| m_mle_info.InsertText(m_sNoErrors); |
| m_ok.Enable(); |
| m_ok.GrabFocus(); |
| m_cancel.Disable(); |
| } |
| // make sure the solar mutex is locked before calling |
| //sets an error message in the text area |
| void UpdateInstallDialog::setError(INSTALL_ERROR err, ::rtl::OUString const & sExtension, |
| OUString const & exceptionMessage) |
| { |
| String sError; |
| m_bError = true; |
| |
| switch (err) |
| { |
| case ERROR_DOWNLOAD: |
| sError = m_sErrorDownload; |
| break; |
| case ERROR_INSTALLATION: |
| sError = m_sErrorInstallation; |
| break; |
| case ERROR_LICENSE_DECLINED: |
| sError = m_sErrorLicenseDeclined; |
| break; |
| |
| default: |
| OSL_ASSERT(0); |
| } |
| |
| sError.SearchAndReplace(String(OUSTR("%NAME")), String(sExtension), 0); |
| //We want to have an empty line between the error messages. However, |
| //there shall be no empty line after the last entry. |
| if (m_bNoEntry) |
| m_bNoEntry = false; |
| else |
| m_mle_info.InsertText(OUSTR("\n")); |
| m_mle_info.InsertText(sError); |
| //Insert more information about the error |
| if (exceptionMessage.getLength()) |
| m_mle_info.InsertText(m_sThisErrorOccurred + exceptionMessage + OUSTR("\n")); |
| |
| m_mle_info.InsertText(m_sNoInstall); |
| m_mle_info.InsertText(OUSTR("\n")); |
| } |
| |
| void UpdateInstallDialog::setError(OUString const & exceptionMessage) |
| { |
| m_bError = true; |
| m_mle_info.InsertText(exceptionMessage + OUSTR("\n")); |
| } |
| |
| IMPL_LINK(UpdateInstallDialog, cancelHandler, void *, EMPTYARG) |
| { |
| m_thread->stop(); |
| EndDialog(RET_CANCEL); |
| return 0; |
| } |
| |
| //------------------------------------------------------------------------------------------------ |
| |
| void UpdateInstallDialog::Thread::downloadExtensions() |
| { |
| try |
| { |
| //create the download directory in the temp folder |
| OUString sTempDir; |
| if (::osl::FileBase::getTempDirURL(sTempDir) != ::osl::FileBase::E_None) |
| throw cssu::Exception(OUSTR("Could not get URL for the temp directory. No extensions will be installed."), 0); |
| |
| //create a unique name for the directory |
| OUString tempEntry, destFolder; |
| if (::osl::File::createTempFile(&sTempDir, 0, &tempEntry ) != ::osl::File::E_None) |
| throw cssu::Exception(OUSTR("Could not create a temporary file in ") + sTempDir + |
| OUSTR(". No extensions will be installed"), 0 ); |
| |
| tempEntry = tempEntry.copy( tempEntry.lastIndexOf( '/' ) + 1 ); |
| |
| destFolder = dp_misc::makeURL( sTempDir, tempEntry ); |
| destFolder += OUSTR("_"); |
| m_sDownloadFolder = destFolder; |
| try |
| { |
| dp_misc::create_folder(0, destFolder, m_updateCmdEnv.get(), true ); |
| } catch (cssu::Exception & e) |
| { |
| throw cssu::Exception(e.Message + OUSTR(" No extensions will be installed."), 0); |
| } |
| |
| |
| sal_uInt16 count = 0; |
| typedef std::vector<UpdateData>::iterator It; |
| for (It i = m_aVecUpdateData.begin(); i != m_aVecUpdateData.end(); i++) |
| { |
| UpdateData & curData = *i; |
| |
| if (!curData.aUpdateInfo.is() || curData.aUpdateSource.is()) |
| continue; |
| //We assume that m_aVecUpdateData contains only information about extensions which |
| //can be downloaded directly. |
| OSL_ASSERT(curData.sWebsiteURL.getLength() == 0); |
| |
| //update the name of the extension which is to be downloaded |
| { |
| ::vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| m_dialog.m_ft_extension_name.SetText(curData.aInstalledPackage->getDisplayName()); |
| sal_uInt16 prog = (sal::static_int_cast<sal_uInt16>(100) * ++count) / |
| sal::static_int_cast<sal_uInt16>(m_aVecUpdateData.size()); |
| m_dialog.m_statusbar.SetValue(prog); |
| } |
| dp_misc::DescriptionInfoset info(m_xComponentContext, curData.aUpdateInfo); |
| //remember occurring exceptions in case we need to print out error information |
| ::std::vector< ::std::pair<OUString, cssu::Exception> > vecExceptions; |
| cssu::Sequence<OUString> seqDownloadURLs = info.getUpdateDownloadUrls(); |
| OSL_ENSURE(seqDownloadURLs.getLength() > 0, "No download URL provided!"); |
| for (sal_Int32 j = 0; j < seqDownloadURLs.getLength(); j++) |
| { |
| try |
| { |
| OSL_ENSURE(seqDownloadURLs[j].getLength() > 0, "Download URL is empty!"); |
| download(seqDownloadURLs[j], curData); |
| if (curData.sLocalURL.getLength() > 0) |
| break; |
| } |
| catch ( cssu::Exception & e ) |
| { |
| vecExceptions.push_back( ::std::make_pair(seqDownloadURLs[j], e)); |
| //There can be several different errors, for example, the URL is wrong, webserver cannot be reached, |
| //name cannot be resolved. The UCB helper API does not specify different special exceptions for these |
| //cases. Therefore ignore and continue. |
| continue; |
| } |
| } |
| //update the progress and display download error |
| { |
| ::vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| if (curData.sLocalURL.getLength() == 0) |
| { |
| //Construct a string of all messages contained in the exceptions plus the respective download URLs |
| ::rtl::OUStringBuffer buf(256); |
| typedef ::std::vector< ::std::pair<OUString, cssu::Exception > >::const_iterator CIT; |
| for (CIT j = vecExceptions.begin(); j != vecExceptions.end(); j++) |
| { |
| if (j != vecExceptions.begin()) |
| buf.appendAscii("\n"); |
| buf.append(OUSTR("Could not download ")); |
| buf.append(j->first); |
| buf.appendAscii(". "); |
| buf.append(j->second.Message); |
| } |
| m_dialog.setError(UpdateInstallDialog::ERROR_DOWNLOAD, curData.aInstalledPackage->getDisplayName(), |
| buf.makeStringAndClear()); |
| } |
| } |
| |
| } |
| } |
| catch (cssu::Exception & e) |
| { |
| ::vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| m_dialog.setError(e.Message); |
| } |
| } |
| void UpdateInstallDialog::Thread::installExtensions() |
| { |
| //Update the fix text in the dialog to "Installing extensions..." |
| { |
| vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| m_dialog.m_ft_action.SetText(m_dialog.m_sInstalling); |
| m_dialog.m_statusbar.SetValue(0); |
| } |
| |
| sal_uInt16 count = 0; |
| typedef std::vector<UpdateData>::iterator It; |
| for (It i = m_aVecUpdateData.begin(); i != m_aVecUpdateData.end(); i++, count++) |
| { |
| //update the name of the extension which is to be installed |
| { |
| ::vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| //we only show progress after an extension has been installed. |
| if (count > 0) { |
| m_dialog.m_statusbar.SetValue( |
| (sal::static_int_cast<sal_uInt16>(100) * count) / |
| sal::static_int_cast<sal_uInt16>(m_aVecUpdateData.size())); |
| } |
| m_dialog.m_ft_extension_name.SetText(i->aInstalledPackage->getDisplayName()); |
| } |
| // TimeValue v = {1, 0}; |
| // osl::Thread::wait(v); |
| bool bError = false; |
| bool bLicenseDeclined = false; |
| cssu::Reference<css::deployment::XPackage> xExtension; |
| UpdateData & curData = *i; |
| cssu::Exception exc; |
| try |
| { |
| cssu::Reference< css::task::XAbortChannel > xAbortChannel( |
| curData.aInstalledPackage->createAbortChannel() ); |
| { |
| vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| m_abort = xAbortChannel; |
| } |
| if (!curData.aUpdateSource.is() && curData.sLocalURL.getLength()) |
| { |
| css::beans::NamedValue prop(OUSTR("EXTENSION_UPDATE"), css::uno::makeAny(OUSTR("1"))); |
| if (!curData.bIsShared) |
| xExtension = m_dialog.getExtensionManager()->addExtension( |
| curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(&prop, 1), |
| OUSTR("user"), xAbortChannel, m_updateCmdEnv.get()); |
| else |
| xExtension = m_dialog.getExtensionManager()->addExtension( |
| curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(&prop, 1), |
| OUSTR("shared"), xAbortChannel, m_updateCmdEnv.get()); |
| } |
| else if (curData.aUpdateSource.is()) |
| { |
| OSL_ASSERT(curData.aUpdateSource.is()); |
| //I am not sure if we should obtain the install properties and pass them into |
| //add extension. Currently it contains only "SUPPRESS_LICENSE". So it it could happen |
| //that a license is displayed when updating from the shared repository, although the |
| //shared extension was installed using "SUPPRESS_LICENSE". |
| css::beans::NamedValue prop(OUSTR("EXTENSION_UPDATE"), css::uno::makeAny(OUSTR("1"))); |
| if (!curData.bIsShared) |
| xExtension = m_dialog.getExtensionManager()->addExtension( |
| curData.aUpdateSource->getURL(), css::uno::Sequence<css::beans::NamedValue>(&prop, 1), |
| OUSTR("user"), xAbortChannel, m_updateCmdEnv.get()); |
| else |
| xExtension = m_dialog.getExtensionManager()->addExtension( |
| curData.aUpdateSource->getURL(), css::uno::Sequence<css::beans::NamedValue>(&prop, 1), |
| OUSTR("shared"), xAbortChannel, m_updateCmdEnv.get()); |
| } |
| } |
| catch (css::deployment::DeploymentException & de) |
| { |
| if (de.Cause.has<css::deployment::LicenseException>()) |
| { |
| bLicenseDeclined = true; |
| } |
| else |
| { |
| exc = de.Cause.get<cssu::Exception>(); |
| bError = true; |
| } |
| } |
| catch (cssu::Exception& e) |
| { |
| exc = e; |
| bError = true; |
| } |
| |
| if (bLicenseDeclined) |
| { |
| ::vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| m_dialog.setError(UpdateInstallDialog::ERROR_LICENSE_DECLINED, |
| curData.aInstalledPackage->getDisplayName(), OUString()); |
| } |
| else if (!xExtension.is() || bError) |
| { |
| ::vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| m_dialog.setError(UpdateInstallDialog::ERROR_INSTALLATION, |
| curData.aInstalledPackage->getDisplayName(), exc.Message); |
| } |
| } |
| { |
| vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| m_dialog.m_statusbar.SetValue(100); |
| m_dialog.m_ft_extension_name.SetText(OUString()); |
| m_dialog.m_ft_action.SetText(m_dialog.m_sFinished); |
| } |
| } |
| |
| void UpdateInstallDialog::Thread::removeTempDownloads() |
| { |
| if (m_sDownloadFolder.getLength()) |
| { |
| dp_misc::erase_path(m_sDownloadFolder, |
| cssu::Reference<css::ucb::XCommandEnvironment>(),false /* no throw: ignore errors */ ); |
| //remove also the temp file which we have used to create the unique name |
| OUString tempFile = m_sDownloadFolder.copy(0, m_sDownloadFolder.getLength() - 1); |
| dp_misc::erase_path(tempFile, cssu::Reference<css::ucb::XCommandEnvironment>(),false); |
| m_sDownloadFolder = OUString(); |
| } |
| } |
| |
| |
| void UpdateInstallDialog::Thread::download(OUString const & sDownloadURL, UpdateData & aUpdateData) |
| { |
| { |
| ::vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| } |
| |
| OSL_ASSERT(m_sDownloadFolder.getLength()); |
| OUString destFolder, tempEntry; |
| if (::osl::File::createTempFile( |
| &m_sDownloadFolder, |
| 0, &tempEntry ) != ::osl::File::E_None) |
| { |
| //ToDo feedback in window that download of this component failed |
| throw cssu::Exception(OUSTR("Could not create temporary file in folder ") + destFolder + OUSTR("."), 0); |
| } |
| tempEntry = tempEntry.copy( tempEntry.lastIndexOf( '/' ) + 1 ); |
| |
| destFolder = dp_misc::makeURL( m_sDownloadFolder, tempEntry ); |
| destFolder += OUSTR("_"); |
| |
| ::ucbhelper::Content destFolderContent; |
| dp_misc::create_folder( &destFolderContent, destFolder, m_updateCmdEnv.get() ); |
| |
| ::ucbhelper::Content sourceContent; |
| dp_misc::create_ucb_content( &sourceContent, sDownloadURL, m_updateCmdEnv.get() ); |
| |
| const OUString sTitle(sourceContent.getPropertyValue( |
| dp_misc::StrTitle::get() ).get<OUString>() ); |
| |
| if (destFolderContent.transferContent( |
| sourceContent, ::ucbhelper::InsertOperation_COPY, |
| sTitle, css::ucb::NameClash::OVERWRITE )) |
| { |
| //the user may have cancelled the dialog because downloading took to long |
| { |
| ::vos::OGuard g(Application::GetSolarMutex()); |
| if (m_stop) { |
| return; |
| } |
| //all errors should be handeld by the command environment. |
| aUpdateData.sLocalURL = destFolder + OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ) + sTitle; |
| } |
| } |
| } |
| |
| |
| // ------------------------------------------------------------------------------------------------------- |
| |
| UpdateCommandEnv::UpdateCommandEnv( cssu::Reference< cssu::XComponentContext > const & xCtx, |
| UpdateInstallDialog & updateDialog, |
| ::rtl::Reference<UpdateInstallDialog::Thread>const & thread) |
| : m_updateDialog( updateDialog ), |
| m_installThread(thread), |
| m_xContext(xCtx) |
| { |
| } |
| |
| UpdateCommandEnv::~UpdateCommandEnv() |
| { |
| } |
| |
| |
| // XCommandEnvironment |
| //______________________________________________________________________________ |
| cssu::Reference<css::task::XInteractionHandler> UpdateCommandEnv::getInteractionHandler() |
| throw (cssu::RuntimeException) |
| { |
| return this; |
| } |
| |
| //______________________________________________________________________________ |
| cssu::Reference<css::ucb::XProgressHandler> UpdateCommandEnv::getProgressHandler() |
| throw (cssu::RuntimeException) |
| { |
| return this; |
| } |
| |
| // XInteractionHandler |
| void UpdateCommandEnv::handle( |
| cssu::Reference< css::task::XInteractionRequest> const & xRequest ) |
| throw (cssu::RuntimeException) |
| { |
| cssu::Any request( xRequest->getRequest() ); |
| OSL_ASSERT( request.getValueTypeClass() == cssu::TypeClass_EXCEPTION ); |
| dp_misc::TRACE(OUSTR("[dp_gui_cmdenv.cxx] incoming request:\n") |
| + ::comphelper::anyToString(request) + OUSTR("\n\n")); |
| |
| css::deployment::VersionException verExc; |
| bool approve = false; |
| bool abort = false; |
| |
| if (request >>= verExc) |
| { //We must catch the version exception during the update, |
| //because otherwise the user would be confronted with the dialogs, asking |
| //them if they want to replace an already installed version of the same extension. |
| //During an update we assume that we always want to replace the old version with the |
| //new version. |
| approve = true; |
| } |
| |
| if (approve == false && abort == false) |
| { |
| //forward to interaction handler for main dialog. |
| handleInteractionRequest( m_xContext, xRequest ); |
| } |
| else |
| { |
| // select: |
| cssu::Sequence< cssu::Reference< css::task::XInteractionContinuation > > conts( |
| xRequest->getContinuations() ); |
| cssu::Reference< css::task::XInteractionContinuation > const * pConts = |
| conts.getConstArray(); |
| sal_Int32 len = conts.getLength(); |
| for ( sal_Int32 pos = 0; pos < len; ++pos ) |
| { |
| if (approve) { |
| cssu::Reference< css::task::XInteractionApprove > xInteractionApprove( |
| pConts[ pos ], cssu::UNO_QUERY ); |
| if (xInteractionApprove.is()) { |
| xInteractionApprove->select(); |
| // don't query again for ongoing continuations: |
| approve = false; |
| } |
| } |
| else if (abort) { |
| cssu::Reference< css::task::XInteractionAbort > xInteractionAbort( |
| pConts[ pos ], cssu::UNO_QUERY ); |
| if (xInteractionAbort.is()) { |
| xInteractionAbort->select(); |
| // don't query again for ongoing continuations: |
| abort = false; |
| } |
| } |
| } |
| } |
| } |
| |
| // XProgressHandler |
| void UpdateCommandEnv::push( cssu::Any const & /*Status*/ ) |
| throw (cssu::RuntimeException) |
| { |
| } |
| |
| |
| void UpdateCommandEnv::update( cssu::Any const & /*Status */) |
| throw (cssu::RuntimeException) |
| { |
| } |
| |
| void UpdateCommandEnv::pop() throw (cssu::RuntimeException) |
| { |
| } |
| |
| |
| } //end namespace dp_gui |