2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file job_widget_install.cpp
18 * @author Radoslaw Wicik r.wicik@samsung.com
19 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
21 * @brief Implementation file for main installer task
23 #include <dpl/noncopyable.h>
24 #include <dpl/abstract_waitable_input_adapter.h>
25 #include <dpl/abstract_waitable_output_adapter.h>
26 #include <dpl/zip_input.h>
27 #include <dpl/scoped_ptr.h>
28 #include <dpl/binary_queue.h>
30 #include <dpl/assert.h>
31 #include <dpl/sstream.h>
32 #include "root_parser.h"
33 #include "widget_parser.h"
34 #include "parser_runner.h"
35 #include <widget_install/job_widget_install.h>
36 #include <widget_install/task_unzip.h>
37 #include <widget_install/task_certify.h>
38 #include <widget_install/task_widget_config.h>
39 #include <widget_install/task_db_update.h>
40 #include <widget_install/task_ace_check.h>
41 #include <widget_install/task_smack.h>
42 #include <widget_install/task_desktop_file.h>
43 #include <widget_install/task_private_storage.h>
44 #include <widget_install/task_prepare_files.h>
45 #include <widget_install/widget_install_errors.h>
46 #include <widget_install/widget_install_context.h>
48 #include <dpl/wrt-dao-rw/widget_dao.h> //TODO remove
49 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
50 #include <dpl/wrt-dao-rw/global_dao.h> // TODO remove
52 #include <dpl/localization/w3c_file_localization.h>
53 #include <libiriwrapper.h>
55 using namespace WrtDB;
57 namespace // anonymous
59 const char * const CONFIG_XML = "config.xml";
61 class InstallerTaskFail :
62 public DPL::TaskDecl<InstallerTaskFail>
70 ThrowMsg(Jobs::WidgetInstall::Exceptions::Deferred,
71 "Widget installation or update deferred!");
73 ThrowMsg(Jobs::WidgetInstall::Exceptions::NotAllowed,
74 "Widget installation or update not allowed!");
79 InstallerTaskFail(bool deferred) :
80 DPL::TaskDecl<InstallerTaskFail>(this),
83 AddStep(&InstallerTaskFail::StepFail);
86 } // namespace anonymous
89 namespace WidgetInstall {
90 JobWidgetInstall::JobWidgetInstall(std::string const &widgetPath,
91 const WidgetInstallationStruct &installerStruct) :
93 JobContextBase<WidgetInstallationStruct>(installerStruct),
94 m_exceptionCaught(Exceptions::Success)
96 // Configure installation
97 ConfigureResult result = ConfigureInstallation(widgetPath, false);
99 if (result == ConfigureResult::Ok) {
100 LogInfo("Configure installation succeeded");
102 // Create installation tasks
103 AddTask(new TaskUnzip(m_installerContext));
104 AddTask(new TaskWidgetConfig(m_installerContext));
105 AddTask(new TaskCertify(m_installerContext));
106 AddTask(new TaskDbUpdate(m_installerContext));
107 // TODO: Update progress information for this task
109 AddTask(new TaskAceCheck(m_installerContext));
110 //This is sort of quick solution, because ACE verdicts are based upon
111 //data from DAO (DB). So AceCheck for now has to be AFTER DbUpdate
113 AddTask(new TaskSmack(m_installerContext));
115 AddTask(new TaskDesktopFile(m_installerContext));
116 AddTask(new TaskPrivateStorage(m_installerContext));
117 } else if (result == ConfigureResult::Deferred) {
118 // Installation is deferred
119 LogInfo("Configure installation deferred");
121 AddTask(new InstallerTaskFail(true));
122 } else if (result == ConfigureResult::Failed) {
123 // Installation is not allowed to proceed due to widget update policy
124 LogWarning("Configure installation failed!");
126 AddTask(new InstallerTaskFail(false));
128 Assert(false && "Invalid configure result!");
132 JobWidgetInstall::JobWidgetInstall(
133 std::string const & widgetUrl,
134 std::string const & iconPath,
135 const WidgetInstallationStruct &installerStruct) :
137 JobContextBase<WidgetInstallationStruct>(installerStruct),
138 m_exceptionCaught(Exceptions::Success)
140 // Configure installation
141 ConfigureResult result = ConfigureInstallation(widgetUrl, true);
143 if (result == ConfigureResult::Ok) {
144 LogInfo("Configure installation succeeded");
147 LibIri::Wrapper iri(widgetUrl.c_str());
148 if (!iri.Validate()) {
149 ThrowMsg(Exceptions::InvalidWidgetUrl,
150 "Web app url must be a valid iri/uri/url");
153 m_installerContext.widgetConfig.configInfo.startFile =
154 DPL::FromUTF8String(widgetUrl);
156 m_installerContext.iconPath = iconPath;
158 // Create installation tasks
159 AddTask(new TaskPrepareFiles(m_installerContext));
160 AddTask(new TaskWidgetConfig(m_installerContext));
161 AddTask(new TaskCertify(m_installerContext));
162 AddTask(new TaskDbUpdate(m_installerContext));
163 // TODO: Update progress information for this task
165 AddTask(new TaskAceCheck(m_installerContext));
166 //This is sort of quick solution, because ACE verdicts are based upon
167 //data from DAO (DB). So AceCheck for now has to be AFTER DbUpdate
169 AddTask(new TaskSmack(m_installerContext));
171 AddTask(new TaskDesktopFile(m_installerContext));
172 AddTask(new TaskPrivateStorage(m_installerContext));
173 } else if (result == ConfigureResult::Deferred) {
174 // Installation is deferred
175 LogInfo("Configure installation deferred");
177 AddTask(new InstallerTaskFail(true));
178 } else if (result == ConfigureResult::Failed) {
179 // Installation is not allowed to proceed due to widget update policy
180 LogWarning("Configure installation failed!");
182 AddTask(new InstallerTaskFail(false));
184 Assert(false && "Invalid configure result!");
188 DPL::Optional<WidgetHandle> JobWidgetInstall::getNewWidgetHandle() const
190 return m_installerContext.widgetHandle;
193 JobWidgetInstall::ConfigureResult JobWidgetInstall::ConfigureInstallation(
194 const std::string &widgetSource, bool fromBrowser)
196 // Detect widget update
197 WidgetUpdateInfo update = detectWidgetUpdate(widgetSource, fromBrowser);
200 "Widget install/update: incoming guid = '" <<
201 update.incomingGUID << "'");
203 "Widget install/update: incoming version = '" <<
204 update.incomingVersion << "'");
207 WidgetUpdateMode::Type updateTypeCheckBit;
209 if (update.existingWidgetInfo.isExist == false) {
210 LogInfo("Widget info does not exist");
211 updateTypeCheckBit = WidgetUpdateMode::NotInstalled;
213 LogInfo("Widget info exists. Handle: " <<
214 update.existingWidgetInfo.existingHandle);
216 DPL::OStringStream pkgName;
217 DPL::OptionalString pkgname =
218 WidgetDAOReadOnly(update.existingWidgetInfo.existingHandle).getPkgname();
220 if(pkgname.IsNull()) {
221 LogInfo("But widget package name doesn't exist");
222 return ConfigureResult::Failed;
225 LogInfo("Widget model exists. Package name: " << pkgName);
226 if (aul_app_is_running(DPL::ToUTF8String(*pkgname).c_str())) {
227 // Must be deferred when update in progress
228 if (m_jobStruct.updateMode == WidgetUpdateMode::PolicyWac) {
230 "Widget is already running. Policy is update according to WAC");
231 LogInfo("Installation deferred: " << widgetSource);
233 GlobalDAO::AddDefferedWidgetPackageInstallation(
234 DPL::FromUTF8String(widgetSource));
236 return ConfigureResult::Deferred;
239 "Widget is already running. Policy is not update according to WAC");
240 LogInfo("Installation aborted: " << widgetSource);
242 return ConfigureResult::Failed;
246 OptionalWidgetVersion existingVersion;
247 existingVersion = update.existingWidgetInfo.existingVersion;
248 OptionalWidgetVersion incomingVersion = update.incomingVersion;
250 updateTypeCheckBit = CalcWidgetUpdatePolicy(existingVersion,
255 bool canProceed = (m_jobStruct.updateMode & updateTypeCheckBit) > 0;
257 LogInfo("Whether widget policy allow proceed: " << canProceed);
259 // Init installer context
260 m_installerContext.widgetSource = widgetSource;
261 m_installerContext.tempWidgetPath = std::string();
262 m_installerContext.widgetConfig = WidgetRegisterInfo();
263 m_installerContext.installStep = InstallerContext::INSTALL_START;
264 m_installerContext.job = this;
265 m_installerContext.existingWidgetInfo = update.existingWidgetInfo;
266 m_installerContext.widgetConfig.shareHref = std::string();
269 return canProceed ? ConfigureResult::Ok : ConfigureResult::Failed;
272 WidgetUpdateMode::Type JobWidgetInstall::CalcWidgetUpdatePolicy(
273 const OptionalWidgetVersion &existingVersion,
274 const OptionalWidgetVersion &incomingVersion) const
276 // Widget is installed, check versions
277 if (!existingVersion && !incomingVersion) {
278 return WidgetUpdateMode::ExistingVersionEqual;
279 } else if (!existingVersion && !!incomingVersion) {
280 return WidgetUpdateMode::ExistingVersionNewer;
281 } else if (!!existingVersion && !incomingVersion) {
282 return WidgetUpdateMode::ExistingVersionOlder;
284 LogInfo("Existing widget: version = '" << *existingVersion << "'");
286 if (!existingVersion->IsWac() && !incomingVersion->IsWac()) {
287 return WidgetUpdateMode::BothVersionsNotStd;
288 } else if (!existingVersion->IsWac()) {
289 return WidgetUpdateMode::ExistingVersionNotStd;
290 } else if (!incomingVersion->IsWac()) {
291 return WidgetUpdateMode::IncomingVersionNotStd;
293 // Both versions are WAC-comparable. Do compare.
294 if (*incomingVersion == *existingVersion) {
295 return WidgetUpdateMode::ExistingVersionEqual;
296 } else if (*incomingVersion > *existingVersion) {
297 return WidgetUpdateMode::ExistingVersionOlder;
299 return WidgetUpdateMode::ExistingVersionNewer;
305 WidgetUpdateInfo JobWidgetInstall::detectWidgetUpdate(
306 const std::string &widgetSource, bool fromBrowser)
308 LogInfo("Checking up widget package for config.xml...");
312 DPL::OptionalString widgetGUID;
313 OptionalWidgetVersion widgetVersion;
315 widgetGUID = DPL::FromUTF8String(widgetSource);
319 DPL::ScopedPtr<DPL::ZipInput> zipFile(
320 new DPL::ZipInput(widgetSource));
322 // Open config.xml file
323 DPL::ScopedPtr<DPL::ZipInput::File> configFile(
324 zipFile->OpenFile(CONFIG_XML));
327 DPL::BinaryQueue buffer;
328 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.Get());
329 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
330 DPL::Copy(&inputAdapter, &outputAdapter);
334 ConfigParserData configInfo;
336 parser.Parse(&buffer,
338 new RootParser<WidgetParser>(configInfo,
339 DPL::FromUTF32String(
343 widgetGUID = configInfo.widget_id;
345 if (widgetGUID.IsNull()) {
346 LogDebug("Installed widget has no GUID");
347 return WidgetUpdateInfo();
350 LogDebug("Installed widget GUID: " << *widgetGUID);
352 // Locate widget ID with this GUID
353 // Incoming widget version
354 if (!configInfo.version.IsNull()) {
356 DPL::Optional<WidgetVersion>(
357 WidgetVersion(*configInfo.version));
363 // Search widget handle by GUID
364 WidgetDAO dao(widgetGUID);
365 return WidgetUpdateInfo(
368 WidgetUpdateInfo::ExistingWidgetInfo(
369 dao.getHandle(), dao.getVersion()));
371 Catch(WidgetDAOReadOnly::Exception::WidgetNotExist){
372 // GUID isn't installed
373 return WidgetUpdateInfo(
376 WidgetUpdateInfo::ExistingWidgetInfo());
379 Catch(DPL::ZipInput::Exception::OpenFailed)
381 LogDebug("Failed to open widget package");
382 return WidgetUpdateInfo();
384 Catch(DPL::ZipInput::Exception::OpenFileFailed)
386 LogDebug("Failed to open config.xml file");
387 return WidgetUpdateInfo();
389 Catch(DPL::CopyFailed)
391 LogDebug("Failed to extract config.xml file");
392 return WidgetUpdateInfo();
394 Catch(ElementParser::Exception::ParseError)
396 LogDebug("Failed to parse config.xml file");
397 return WidgetUpdateInfo();
401 void JobWidgetInstall::SendProgress()
403 if (GetProgressFlag() != false) {
404 if (getInstallerStruct().progressCallback != NULL) {
406 LogDebug("Call widget install progressCallbak");
407 getInstallerStruct().progressCallback(getInstallerStruct().userParam,
408 GetProgressPercent(),GetProgressDescription());
413 void JobWidgetInstall::SendFinishedSuccess()
416 JobWidgetInstall::displayWidgetInfo();
418 DPL::Optional<WidgetHandle> handle = getNewWidgetHandle();
419 const WidgetHandle INVALID_WIDGET_HANDLE = 0;
421 LogDebug("Call widget install successfinishedCallback");
422 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
423 !!handle ? *handle : INVALID_WIDGET_HANDLE, Exceptions::Success);
426 void JobWidgetInstall::SendFinishedFailure()
428 LogError("Error in installation step: " << m_exceptionCaught);
429 LogError("Message: " << m_exceptionMessage);
430 DPL::Optional<WidgetHandle> handle = getNewWidgetHandle();
431 const WidgetHandle INVALID_WIDGET_HANDLE = 0;
433 LogDebug("Call widget install failure finishedCallback");
434 getInstallerStruct().finishedCallback(getInstallerStruct().userParam,
435 !!handle ? *handle : INVALID_WIDGET_HANDLE, m_exceptionCaught);
438 void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e)
440 m_exceptionCaught = static_cast<Exceptions::Type>(e.getParam());
441 m_exceptionMessage = e.GetMessage();
444 void JobWidgetInstall::displayWidgetInfo()
446 DPL::Optional<WidgetHandle> handle = getNewWidgetHandle();
449 WidgetDAOReadOnly dao(*handle);
451 std::ostringstream out;
452 WidgetLocalizedInfo localizedInfo =
453 W3CFileLocalization::getLocalizedInfo(*handle);
456 "===================================== INSTALLED WIDGET INFO ========="\
457 "============================";
458 out << std::endl << "Name: " << localizedInfo.name;
459 WidgetSize size = dao.getPreferredSize();
460 out << std::endl << "Width: " << size.width;
461 out << std::endl << "Height: " << size.height;
462 out << std::endl << "Start File: " <<
463 W3CFileLocalization::getStartFile(*handle);
464 out << std::endl << "Version: " << dao.getVersion();
465 out << std::endl << "Licence: " <<
466 localizedInfo.license;
467 out << std::endl << "Licence Href: " <<
468 localizedInfo.licenseHref;
469 out << std::endl << "Description: " <<
470 localizedInfo.description;
471 out << std::endl << "Widget Id: " << dao.getGUID();
472 out << std::endl << "Widget recognized: " << dao.isRecognized();
473 out << std::endl << "Widget wac signed: " << dao.isWacSigned();
474 out << std::endl << "Widget distributor signed: " <<
475 dao.isDistributorSigned();
476 out << std::endl << "Widget trusted: " << dao.isTrusted();
478 OptionalWidgetIcon icon = W3CFileLocalization::getIcon(*handle);
479 DPL::OptionalString iconSrc =
480 !!icon ? icon->src : DPL::OptionalString::Null;
481 out << std::endl << "Icon: " << iconSrc;
483 out << std::endl << "Preferences:";
485 PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList();
488 out << std::endl << " Key: " <<
490 out << std::endl << " Readonly: " <<
495 out << std::endl << "Features:";
497 WidgetFeatureSet list = dao.getFeaturesList();
500 out << std::endl << " Name: " << it->name;
501 out << std::endl << " Required: " << it->required;
502 out << std::endl << " Params:";
511 } //namespace WidgetInstall