Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1377)

Side by Side Diff: chrome/browser/extensions/crx_installer.cc

Issue 160311: Pull CrxInstaller out of ExtensionsService. (Closed)
Patch Set: Fix leak of SandboxedExtensionUnpacker Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2009 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.
4
5 #include "chrome/browser/extensions/crx_installer.h"
6
7 #include "app/l10n_util.h"
8 #include "base/file_util.h"
9 #include "base/scoped_temp_dir.h"
10 #include "base/string_util.h"
11 #include "base/task.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/extensions/extension_file_util.h"
14 #include "chrome/common/extensions/extension_error_reporter.h"
15 #include "grit/chromium_strings.h"
16
17 #if defined(OS_WIN)
18 #include "app/win_util.h"
19 #elif defined(OS_MACOSX)
20 #include "base/scoped_cftyperef.h"
21 #include "base/sys_string_conversions.h"
22 #include <CoreFoundation/CFUserNotification.h>
23 #endif
24
25 CrxInstaller::CrxInstaller(const FilePath& crx_path,
26 const FilePath& install_directory,
27 Extension::Location install_source,
28 const std::string& expected_id,
29 bool extensions_enabled,
30 bool is_from_gallery,
31 bool show_prompts,
32 bool delete_crx,
33 MessageLoop* file_loop,
34 ExtensionsService* frontend)
35 : crx_path_(crx_path),
36 install_directory_(install_directory),
37 install_source_(install_source),
38 expected_id_(expected_id),
39 extensions_enabled_(extensions_enabled),
40 is_from_gallery_(is_from_gallery),
41 show_prompts_(show_prompts),
42 file_loop_(file_loop),
43 ui_loop_(MessageLoop::current()) {
44
45 // Note: this is a refptr so that we keep the frontend alive long enough to
46 // get our response.
47 frontend_ = frontend;
48 unpacker_ = new SandboxedExtensionUnpacker(
49 crx_path, g_browser_process->resource_dispatcher_host(), this);
50
51 file_loop->PostTask(FROM_HERE, NewRunnableMethod(unpacker_,
52 &SandboxedExtensionUnpacker::Start));
53 }
54
55 void CrxInstaller::OnUnpackFailure(const std::string& error_message) {
56 ReportFailureFromFileThread(error_message);
57 }
58
59 void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir,
60 const FilePath& extension_dir,
61 Extension* extension) {
62 // Note: We take ownership of |extension| and |temp_dir|.
63 extension_.reset(extension);
64 temp_dir_ = temp_dir;
65
66 // temp_dir_deleter is stack allocated instead of a member of CrxInstaller, so
67 // that delete always happens on the file thread.
68 ScopedTempDir temp_dir_deleter;
69 temp_dir_deleter.Set(temp_dir);
70
71 // The unpack dir we don't have to delete explicity since it is a child of
72 // the temp dir.
73 unpacked_extension_root_ = extension_dir;
74 DCHECK(file_util::ContainsPath(temp_dir_, unpacked_extension_root_));
75
76 // If we were supposed to delete the source file, we can do that now.
77 if (delete_crx_)
78 file_util::Delete(crx_path_, false); // non-recursive
79
80 // Determine whether to allow installation. We always allow themes and
81 // external installs.
82 if (!extensions_enabled_ && !extension->IsTheme() &&
83 !Extension::IsExternalLocation(install_source_)) {
84 ReportFailureFromFileThread("Extensions are not enabled.");
85 return;
86 }
87
88 // Make sure the expected id matches.
89 // TODO(aa): Also support expected version?
90 if (!expected_id_.empty() && expected_id_ != extension->id()) {
91 ReportFailureFromFileThread(
92 StringPrintf("ID in new extension manifest (%s) does not match "
93 "expected id (%s)",
94 extension->id().c_str(),
95 expected_id_.c_str()));
96 return;
97 }
98
99 // Show the confirm UI if necessary.
100 // NOTE: We also special case themes to not have a dialog, because we show
101 // a special infobar UI for them instead.
102 if (show_prompts_ && !extension->IsTheme()) {
103 if (!ConfirmInstall())
104 return; // error reported by ConfirmInstall()
105 }
106
107 CompleteInstall();
108 }
109
110 bool CrxInstaller::ConfirmInstall() {
111 #if defined(OS_WIN)
112 if (win_util::MessageBox(GetForegroundWindow(),
113 L"Are you sure you want to install this extension?\n\n"
114 L"You should only install extensions from sources you trust.",
115 l10n_util::GetString(IDS_PRODUCT_NAME).c_str(),
116 MB_OKCANCEL) != IDOK) {
117 ReportFailureFromFileThread("User did not allow extension to be "
118 "installed.");
119 return false;
120 }
121 #elif defined(OS_MACOSX)
122 // Using CoreFoundation to do this dialog is unimaginably lame but will do
123 // until the UI is redone.
124 scoped_cftyperef<CFStringRef> product_name(
125 base::SysWideToCFStringRef(l10n_util::GetString(IDS_PRODUCT_NAME)));
126 CFOptionFlags response;
127 if (kCFUserNotificationAlternateResponse == CFUserNotificationDisplayAlert(
128 0, kCFUserNotificationCautionAlertLevel, NULL, NULL, NULL,
129 product_name,
130 CFSTR("Are you sure you want to install this extension?\n\n"
131 "This is a temporary message and it will be removed when "
132 "extensions UI is finalized."),
133 NULL, CFSTR("Cancel"), NULL, &response);
134 ReportFailureFromFileThread("User did not allow extension to be "
135 "installed.");
136 return false;
137 }
138 #endif // OS_*
139
140 return true;
141 }
142
143 void CrxInstaller::CompleteInstall() {
144 FilePath version_dir;
145 Extension::InstallType install_type = Extension::INSTALL_ERROR;
146 std::string error_msg;
147 if (!extension_file_util::InstallExtension(unpacked_extension_root_,
148 install_directory_,
149 extension_->id(),
150 extension_->VersionString(),
151 &version_dir,
152 &install_type, &error_msg)) {
153 ReportFailureFromFileThread(error_msg);
154 return;
155 }
156
157 if (install_type == Extension::DOWNGRADE) {
158 ReportFailureFromFileThread("Attempted to downgrade extension.");
159 return;
160 }
161
162 extension_->set_path(version_dir);
163 extension_->set_location(install_source_);
164
165 if (install_type == Extension::REINSTALL) {
166 // We use this as a signal to switch themes.
167 ReportOverinstallFromFileThread();
168 return;
169 }
170
171 ReportSuccessFromFileThread();
172 }
173
174 void CrxInstaller::ReportFailureFromFileThread(const std::string& error) {
175 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
176 &CrxInstaller::ReportFailureFromUIThread, error));
177 }
178
179 void CrxInstaller::ReportFailureFromUIThread(const std::string& error) {
180 ExtensionErrorReporter::GetInstance()->ReportError(error, show_prompts_);
181 }
182
183 void CrxInstaller::ReportOverinstallFromFileThread() {
184 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(frontend_.get(),
185 &ExtensionsService::OnExtensionOverinstallAttempted, extension_->id()));
186 }
187
188 void CrxInstaller::ReportSuccessFromFileThread() {
189 // Tell the frontend about the installation and hand off ownership of
190 // extension_ to it.
191 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(frontend_.get(),
192 &ExtensionsService::OnExtensionInstalled, extension_.release()));
193 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/crx_installer.h ('k') | chrome/browser/extensions/extension_updater.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698