15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/startup_helper.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind_helpers.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/file_path.h" 11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/run_loop.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/extensions/sandboxed_unpacker.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/webstore_startup_installer.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 21ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/common/extensions/chrome_extensions_client.h" 2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN) 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window.h" 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window_registry.h" 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/extension_registry.h" 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/extension_util.h" 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using content::BrowserThread; 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)namespace extensions { 3834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintPackExtensionMessage(const std::string& message) { 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << message; 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// On Windows, the jumplist action for installing an ephemeral app has to use 4634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)// the --install-ephemeral-app-from-webstore command line arg to initiate an 4734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)// install. 4834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)scoped_refptr<WebstoreStandaloneInstaller> CreateEphemeralAppInstaller( 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Profile* profile, 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& app_id, 5134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) WebstoreStandaloneInstaller::Callback callback) { 5234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) scoped_refptr<WebstoreStandaloneInstaller> installer; 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN) 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExtensionRegistry* registry = ExtensionRegistry::Get(profile); 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(registry); 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!registry->GetExtensionById(app_id, ExtensionRegistry::EVERYTHING) || 5834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) !util::IsEphemeralApp(app_id, profile)) { 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return installer; 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) AppWindowRegistry* app_window_registry = AppWindowRegistry::Get(profile); 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(app_window_registry); 6434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) AppWindow* app_window = 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) app_window_registry->GetCurrentAppWindowForApp(app_id); 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!app_window) 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return installer; 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) installer = new WebstoreInstallWithPrompt( 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) app_id, profile, app_window->GetNativeWindow(), callback); 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return installer; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StartupHelper::StartupHelper() : pack_job_succeeded_(false) { 79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ExtensionsClient::Set(ChromeExtensionsClient::GetInstance()); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupHelper::OnPackSuccess( 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& crx_path, 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& output_private_key_path) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pack_job_succeeded_ = true; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintPackExtensionMessage( 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF16ToUTF8( 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PackExtensionJob::StandardSuccessMessage(crx_path, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_private_key_path))); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StartupHelper::OnPackFailure(const std::string& error_message, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionCreator::ErrorType type) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintPackExtensionMessage(error_message); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StartupHelper::PackExtension(const CommandLine& cmd_line) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cmd_line.HasSwitch(switches::kPackExtension)) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Input Paths. 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath src_dir = 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cmd_line.GetSwitchValuePath(switches::kPackExtension); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath private_key_path; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_line.HasSwitch(switches::kPackExtensionKey)) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private_key_path = cmd_line.GetSwitchValuePath(switches::kPackExtensionKey); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launch a job to perform the packing on the file thread. Ignore warnings 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the packing process. (e.g. Overwrite any existing crx file.) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pack_job_ = new PackExtensionJob(this, src_dir, private_key_path, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionCreator::kOverwriteCRX); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pack_job_->set_asynchronous(false); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pack_job_->Start(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pack_job_succeeded_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ValidateCrxHelper : public SandboxedUnpackerClient { 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ValidateCrxHelper(const base::FilePath& crx_file, 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& temp_dir, 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::RunLoop* run_loop) 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : crx_file_(crx_file), temp_dir_(temp_dir), run_loop_(run_loop), 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) finished_(false), success_(false) {} 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool finished() { return finished_; } 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool success() { return success_; } 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& error() { return error_; } 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Start() { 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ValidateCrxHelper::StartOnFileThread, 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this)); 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~ValidateCrxHelper() {} 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void OnUnpackSuccess(const base::FilePath& temp_dir, 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& extension_root, 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::DictionaryValue* original_manifest, 1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const Extension* extension, 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const SkBitmap& install_icon) OVERRIDE { 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) finished_ = true; 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) success_ = true; 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ValidateCrxHelper::FinishOnUIThread, 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this)); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual void OnUnpackFailure(const base::string16& error) OVERRIDE { 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) finished_ = true; 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) success_ = false; 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) error_ = error; 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ValidateCrxHelper::FinishOnUIThread, 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this)); 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void FinishOnUIThread() { 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (run_loop_->running()) 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) run_loop_->Quit(); 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void StartOnFileThread() { 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<base::MessageLoopProxy> file_thread_proxy = 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE); 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<SandboxedUnpacker> unpacker( 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new SandboxedUnpacker(crx_file_, 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Manifest::INTERNAL, 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, /* no special creation flags */ 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) temp_dir_, 182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) file_thread_proxy.get(), 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this)); 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unpacker->Start(); 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The file being validated. 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& crx_file_; 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The temporary directory where the sandboxed unpacker will do work. 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& temp_dir_; 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Unowned pointer to a runloop, so our consumer can wait for us to finish. 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::RunLoop* run_loop_; 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Whether we're finished unpacking; 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool finished_; 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Whether the unpacking was successful. 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool success_; 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If the unpacking wasn't successful, this contains an error message. 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 error_; 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool StartupHelper::ValidateCrx(const CommandLine& cmd_line, 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string* error) { 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK(error); 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath path = cmd_line.GetSwitchValuePath(switches::kValidateCrx); 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (path.empty()) { 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = base::StringPrintf("Empty path passed for %s", 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switches::kValidateCrx); 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ScopedTempDir temp_dir; 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!temp_dir.CreateUniqueTempDir()) { 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = std::string("Failed to create temp dir"); 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::RunLoop run_loop; 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<ValidateCrxHelper> helper( 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new ValidateCrxHelper(path, temp_dir.path(), &run_loop)); 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) helper->Start(); 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!helper->finished()) 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) run_loop.Run(); 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool success = helper->success(); 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!success) 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::UTF16ToUTF8(helper->error()); 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return success; 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AppInstallHelper { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A callback for when the install process is done. 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef base::Callback<void()> DoneCallback; 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppInstallHelper(); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~AppInstallHelper(); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success() { return success_; } 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& error() { return error_; } 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void BeginInstall(Profile* profile, 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& id, 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool show_prompt, 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoneCallback callback); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebstoreStandaloneInstaller::Callback Callback(); 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void OnAppInstallComplete(bool success, 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& error, 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) webstore_install::Result result); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoneCallback done_callback_; 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These hold on to the result of the app install when it is complete. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success_; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error_; 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<WebstoreStandaloneInstaller> installer_; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppInstallHelper::AppInstallHelper() : success_(false) {} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppInstallHelper::~AppInstallHelper() {} 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebstoreStandaloneInstaller::Callback AppInstallHelper::Callback() { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::Bind(&AppInstallHelper::OnAppInstallComplete, 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this)); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppInstallHelper::BeginInstall( 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile, 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& id, 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool show_prompt, 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoneCallback done_callback) { 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) done_callback_ = done_callback; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebstoreStandaloneInstaller::Callback callback = 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&AppInstallHelper::OnAppInstallComplete, 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this)); 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) installer_ = CreateEphemeralAppInstaller(profile, id, callback); 28934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (installer_.get()) { 29034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) installer_->BeginInstall(); 29134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } else { 29234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) error_ = "Not a supported ephemeral app installation."; 29334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) done_callback_.Run(); 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppInstallHelper::OnAppInstallComplete(bool success, 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& error, 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) webstore_install::Result result) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success_ = success; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_= error; 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) done_callback_.Run(); 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)bool StartupHelper::InstallEphemeralApp(const CommandLine& cmd_line, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile) { 30934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) std::string id = 31034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) cmd_line.GetSwitchValueASCII(switches::kInstallEphemeralAppFromWebstore); 31103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!crx_file::id_util::IdIsValid(id)) { 31234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) LOG(ERROR) << "Invalid id for " 31334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) << switches::kInstallEphemeralAppFromWebstore << " : '" << id << "'"; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppInstallHelper helper; 318a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::RunLoop run_loop; 319a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch helper.BeginInstall(profile, id, true, run_loop.QuitClosure()); 320a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch run_loop.Run(); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!helper.success()) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "InstallFromWebstore failed with error: " << helper.error(); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return helper.success(); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StartupHelper::~StartupHelper() { 328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (pack_job_.get()) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pack_job_->ClearClient(); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 333