1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/startup_helper.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "chrome/common/extensions/chrome_extensions_client.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "extensions/browser/sandboxed_unpacker.h"
20 #include "extensions/common/extension.h"
22 using content::BrowserThread
;
24 namespace extensions
{
28 void PrintPackExtensionMessage(const std::string
& message
) {
34 StartupHelper::StartupHelper() : pack_job_succeeded_(false) {
35 ExtensionsClient::Set(ChromeExtensionsClient::GetInstance());
38 void StartupHelper::OnPackSuccess(
39 const base::FilePath
& crx_path
,
40 const base::FilePath
& output_private_key_path
) {
41 pack_job_succeeded_
= true;
42 PrintPackExtensionMessage(
44 PackExtensionJob::StandardSuccessMessage(crx_path
,
45 output_private_key_path
)));
48 void StartupHelper::OnPackFailure(const std::string
& error_message
,
49 ExtensionCreator::ErrorType type
) {
50 PrintPackExtensionMessage(error_message
);
53 bool StartupHelper::PackExtension(const base::CommandLine
& cmd_line
) {
54 if (!cmd_line
.HasSwitch(switches::kPackExtension
))
58 base::FilePath src_dir
=
59 cmd_line
.GetSwitchValuePath(switches::kPackExtension
);
60 base::FilePath private_key_path
;
61 if (cmd_line
.HasSwitch(switches::kPackExtensionKey
)) {
62 private_key_path
= cmd_line
.GetSwitchValuePath(switches::kPackExtensionKey
);
65 // Launch a job to perform the packing on the file thread. Ignore warnings
66 // from the packing process. (e.g. Overwrite any existing crx file.)
67 pack_job_
= new PackExtensionJob(this, src_dir
, private_key_path
,
68 ExtensionCreator::kOverwriteCRX
);
69 pack_job_
->set_asynchronous(false);
72 return pack_job_succeeded_
;
77 class ValidateCrxHelper
: public SandboxedUnpackerClient
{
79 ValidateCrxHelper(const CRXFileInfo
& file
,
80 const base::FilePath
& temp_dir
,
81 base::RunLoop
* run_loop
)
88 bool finished() { return finished_
; }
89 bool success() { return success_
; }
90 const base::string16
& error() { return error_
; }
93 BrowserThread::PostTask(BrowserThread::FILE,
95 base::Bind(&ValidateCrxHelper::StartOnFileThread
,
100 ~ValidateCrxHelper() override
{}
102 void OnUnpackSuccess(const base::FilePath
& temp_dir
,
103 const base::FilePath
& extension_root
,
104 const base::DictionaryValue
* original_manifest
,
105 const Extension
* extension
,
106 const SkBitmap
& install_icon
) override
{
109 BrowserThread::PostTask(BrowserThread::UI
,
111 base::Bind(&ValidateCrxHelper::FinishOnUIThread
,
115 void OnUnpackFailure(const CrxInstallError
& error
) override
{
118 error_
= error
.message();
119 BrowserThread::PostTask(BrowserThread::UI
,
121 base::Bind(&ValidateCrxHelper::FinishOnUIThread
,
125 void FinishOnUIThread() {
126 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
127 if (run_loop_
->running())
131 void StartOnFileThread() {
132 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
133 scoped_refptr
<base::SingleThreadTaskRunner
> file_task_runner
=
134 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE);
136 scoped_refptr
<SandboxedUnpacker
> unpacker(new SandboxedUnpacker(
137 Manifest::INTERNAL
, 0, /* no special creation flags */
138 temp_dir_
, file_task_runner
.get(), this));
139 unpacker
->StartWithCrx(crx_file_
);
142 // The file being validated.
143 const CRXFileInfo
& crx_file_
;
145 // The temporary directory where the sandboxed unpacker will do work.
146 const base::FilePath
& temp_dir_
;
148 // Unowned pointer to a runloop, so our consumer can wait for us to finish.
149 base::RunLoop
* run_loop_
;
151 // Whether we're finished unpacking;
154 // Whether the unpacking was successful.
157 // If the unpacking wasn't successful, this contains an error message.
158 base::string16 error_
;
163 bool StartupHelper::ValidateCrx(const base::CommandLine
& cmd_line
,
164 std::string
* error
) {
166 base::FilePath path
= cmd_line
.GetSwitchValuePath(switches::kValidateCrx
);
168 *error
= base::StringPrintf("Empty path passed for %s",
169 switches::kValidateCrx
);
172 base::ScopedTempDir temp_dir
;
174 if (!temp_dir
.CreateUniqueTempDir()) {
175 *error
= std::string("Failed to create temp dir");
179 base::RunLoop run_loop
;
180 CRXFileInfo
file(path
);
181 scoped_refptr
<ValidateCrxHelper
> helper(
182 new ValidateCrxHelper(file
, temp_dir
.path(), &run_loop
));
184 if (!helper
->finished())
187 bool success
= helper
->success();
189 *error
= base::UTF16ToUTF8(helper
->error());
193 StartupHelper::~StartupHelper() {
195 pack_job_
->ClearClient();
198 } // namespace extensions