blob: 892f55654f9266d20615ad2b6d742a53a70352c7 [file] [log] [blame]
[email protected]098fa7a2013-03-08 22:11:171// Copyright (c) 2013 The Chromium Authors. All rights reserved.
[email protected]d8c8f25f2011-11-02 18:18:012// 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/unpacked_installer.h"
6
7#include "base/bind.h"
8#include "base/callback.h"
thestig18dfb7a52014-08-26 10:44:049#include "base/files/file_util.h"
dgozmand741d25d2017-03-23 00:35:3410#include "base/memory/ptr_util.h"
michaelpga8ea0372017-04-06 20:41:3511#include "base/strings/string16.h"
[email protected]46acbf12013-06-10 18:43:4212#include "base/strings/string_util.h"
michaelpga8ea0372017-04-06 20:41:3513#include "base/strings/utf_string_conversions.h"
Istiaque Ahmed81ff01e2017-08-09 16:00:5914#include "base/task_scheduler/post_task.h"
[email protected]bebe1d02012-08-02 20:17:0915#include "base/threading/thread_restrictions.h"
[email protected]1f0722442014-05-01 17:26:0216#include "chrome/browser/extensions/extension_error_reporter.h"
[email protected]c82da8c42012-06-08 19:49:1117#include "chrome/browser/extensions/extension_install_prompt.h"
binjin1569c9b2014-09-05 13:33:1818#include "chrome/browser/extensions/extension_management.h"
[email protected]d8c8f25f2011-11-02 18:18:0119#include "chrome/browser/extensions/extension_service.h"
[email protected]0d904312012-01-25 23:00:1620#include "chrome/browser/extensions/permissions_updater.h"
[email protected]284ffac2014-02-12 01:08:5821#include "chrome/browser/profiles/profile.h"
pkotwicza57a1f322014-10-21 00:24:3022#include "chrome/browser/ui/extensions/extension_install_ui_factory.h"
[email protected]fdd28372014-08-21 02:27:2623#include "components/crx_file/id_util.h"
skym71603842016-10-10 18:17:3124#include "components/sync/model/string_ordinal.h"
[email protected]79a60642012-10-20 21:03:1825#include "content/public/browser/browser_thread.h"
Istiaque Ahmed81ff01e2017-08-09 16:00:5926#include "extensions/browser/extension_file_task_runner.h"
[email protected]489db0842014-01-22 18:20:0327#include "extensions/browser/extension_prefs.h"
[email protected]284ffac2014-02-12 01:08:5828#include "extensions/browser/extension_registry.h"
pkotwicza57a1f322014-10-21 00:24:3029#include "extensions/browser/install/extension_install_ui.h"
[email protected]4a1d9c0d2014-06-13 12:50:1130#include "extensions/browser/install_flag.h"
michaelpg6a4874f2017-04-13 20:41:3331#include "extensions/browser/policy_check.h"
32#include "extensions/browser/preload_check_group.h"
33#include "extensions/browser/requirements_checker.h"
[email protected]e4452d32013-11-15 23:07:4134#include "extensions/common/extension.h"
[email protected]6668e5d2014-04-08 23:32:5235#include "extensions/common/extension_l10n_util.h"
[email protected]85df9d12014-04-15 17:02:1436#include "extensions/common/file_util.h"
[email protected]d42c11152013-08-22 19:36:3237#include "extensions/common/manifest.h"
michaelpga8ea0372017-04-06 20:41:3538#include "extensions/common/manifest_handlers/plugins_handler.h"
elijahtaylore343b542014-10-03 19:48:1939#include "extensions/common/manifest_handlers/shared_module_info.h"
rdevlin.cronine2d0fd02015-09-24 22:35:4940#include "extensions/common/permissions/permissions_data.h"
[email protected]d8c8f25f2011-11-02 18:18:0141
[email protected]545ab7a2011-11-03 14:54:2142using content::BrowserThread;
[email protected]1c321ee2012-05-21 03:02:3443using extensions::Extension;
elijahtaylore343b542014-10-03 19:48:1944using extensions::SharedModuleInfo;
[email protected]545ab7a2011-11-03 14:54:2145
[email protected]d8c8f25f2011-11-02 18:18:0146namespace {
47
[email protected]8e7b2cf42012-04-18 14:26:5848const char kUnpackedExtensionsBlacklistedError[] =
49 "Loading of unpacked extensions is disabled by the administrator.";
50
elijahtaylorc93f75472014-10-15 18:42:2551const char kImportMinVersionNewer[] =
52 "'import' version requested is newer than what is installed.";
53const char kImportMissing[] = "'import' extension is not installed.";
54const char kImportNotSharedModule[] = "'import' is not a shared module.";
55
[email protected]c82da8c42012-06-08 19:49:1156// Manages an ExtensionInstallPrompt for a particular extension.
rdevlin.cronin41593052016-01-08 01:40:1257class SimpleExtensionLoadPrompt {
[email protected]d8c8f25f2011-11-02 18:18:0158 public:
[email protected]849749d2013-05-06 17:30:4559 SimpleExtensionLoadPrompt(const Extension* extension,
60 Profile* profile,
61 const base::Closure& callback);
[email protected]d8c8f25f2011-11-02 18:18:0162
63 void ShowPrompt();
64
[email protected]d8c8f25f2011-11-02 18:18:0165 private:
rdevlin.cronin41593052016-01-08 01:40:1266 ~SimpleExtensionLoadPrompt(); // Manages its own lifetime.
67
68 void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
69
dchengc963c7142016-04-08 03:55:2270 std::unique_ptr<ExtensionInstallPrompt> install_ui_;
[email protected]d8c8f25f2011-11-02 18:18:0171 scoped_refptr<const Extension> extension_;
[email protected]849749d2013-05-06 17:30:4572 base::Closure callback_;
rdevlin.cronin41593052016-01-08 01:40:1273
74 DISALLOW_COPY_AND_ASSIGN(SimpleExtensionLoadPrompt);
[email protected]d8c8f25f2011-11-02 18:18:0175};
76
77SimpleExtensionLoadPrompt::SimpleExtensionLoadPrompt(
[email protected]849749d2013-05-06 17:30:4578 const Extension* extension,
[email protected]d8c8f25f2011-11-02 18:18:0179 Profile* profile,
[email protected]849749d2013-05-06 17:30:4580 const base::Closure& callback)
pkotwicza57a1f322014-10-21 00:24:3081 : extension_(extension), callback_(callback) {
dchengc963c7142016-04-08 03:55:2282 std::unique_ptr<extensions::ExtensionInstallUI> ui(
pkotwicza57a1f322014-10-21 00:24:3083 extensions::CreateExtensionInstallUI(profile));
84 install_ui_.reset(new ExtensionInstallPrompt(
pkotwicz2175c622014-10-22 19:56:2885 profile, ui->GetDefaultInstallDialogParent()));
[email protected]d8c8f25f2011-11-02 18:18:0186}
87
88SimpleExtensionLoadPrompt::~SimpleExtensionLoadPrompt() {
89}
90
91void SimpleExtensionLoadPrompt::ShowPrompt() {
rdevlin.croninbe6e8cf2016-02-08 19:28:0692 // Unretained() is safe because this object manages its own lifetime.
93 install_ui_->ShowDialog(
94 base::Bind(&SimpleExtensionLoadPrompt::OnInstallPromptDone,
95 base::Unretained(this)),
96 extension_.get(), nullptr,
97 ExtensionInstallPrompt::GetDefaultShowDialogCallback());
[email protected]d8c8f25f2011-11-02 18:18:0198}
99
rdevlin.cronin41593052016-01-08 01:40:12100void SimpleExtensionLoadPrompt::OnInstallPromptDone(
101 ExtensionInstallPrompt::Result result) {
102 if (result == ExtensionInstallPrompt::Result::ACCEPTED)
103 callback_.Run();
[email protected]d8c8f25f2011-11-02 18:18:01104 delete this;
105}
106
107} // namespace
108
109namespace extensions {
110
111// static
112scoped_refptr<UnpackedInstaller> UnpackedInstaller::Create(
113 ExtensionService* extension_service) {
[email protected]3a7fbc242013-12-19 17:43:37114 DCHECK(extension_service);
[email protected]d8c8f25f2011-11-02 18:18:01115 return scoped_refptr<UnpackedInstaller>(
116 new UnpackedInstaller(extension_service));
117}
118
119UnpackedInstaller::UnpackedInstaller(ExtensionService* extension_service)
120 : service_weak_(extension_service->AsWeakPtr()),
dgozmand741d25d2017-03-23 00:35:34121 profile_(extension_service->profile()),
[email protected]b7462f32012-09-02 15:18:12122 prompt_for_plugins_(true),
[email protected]9d02fa12013-02-19 05:12:57123 require_modern_manifest_version_(true),
dgozmand741d25d2017-03-23 00:35:34124 be_noisy_on_failure_(true) {
yoz416ae9f2015-02-24 19:40:41125 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]d8c8f25f2011-11-02 18:18:01126}
127
128UnpackedInstaller::~UnpackedInstaller() {
[email protected]d8c8f25f2011-11-02 18:18:01129}
130
[email protected]650b2d52013-02-10 03:41:45131void UnpackedInstaller::Load(const base::FilePath& path_in) {
[email protected]98270432012-09-11 20:51:24132 DCHECK(extension_path_.empty());
[email protected]d8c8f25f2011-11-02 18:18:01133 extension_path_ = path_in;
Istiaque Ahmed81ff01e2017-08-09 16:00:59134 GetExtensionFileTaskRunner()->PostTask(
135 FROM_HERE, base::BindOnce(&UnpackedInstaller::GetAbsolutePath, this));
[email protected]d8c8f25f2011-11-02 18:18:01136}
137
[email protected]2a69b942013-05-31 09:37:53138bool UnpackedInstaller::LoadFromCommandLine(const base::FilePath& path_in,
proberge80a37f32016-08-04 19:44:55139 std::string* extension_id,
140 bool only_allow_apps) {
yoz416ae9f2015-02-24 19:40:41141 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]98270432012-09-11 20:51:24142 DCHECK(extension_path_.empty());
143
[email protected]e8dad9b2013-06-04 04:43:45144 if (!service_weak_.get())
[email protected]2a69b942013-05-31 09:37:53145 return false;
[email protected]d8c8f25f2011-11-02 18:18:01146 // Load extensions from the command line synchronously to avoid a race
147 // between extension loading and loading an URL from the command line.
148 base::ThreadRestrictions::ScopedAllowIO allow_io;
149
[email protected]15476932013-04-12 05:17:15150 extension_path_ = base::MakeAbsoluteFilePath(path_in);
[email protected]d8c8f25f2011-11-02 18:18:01151
[email protected]8e7b2cf42012-04-18 14:26:58152 if (!IsLoadingUnpackedAllowed()) {
153 ReportExtensionLoadError(kUnpackedExtensionsBlacklistedError);
[email protected]2a69b942013-05-31 09:37:53154 return false;
[email protected]8e7b2cf42012-04-18 14:26:58155 }
156
[email protected]d8c8f25f2011-11-02 18:18:01157 std::string error;
dgozmand741d25d2017-03-23 00:35:34158 extension_ = file_util::LoadExtension(extension_path_, Manifest::COMMAND_LINE,
159 GetFlags(), &error);
[email protected]d8c8f25f2011-11-02 18:18:01160
probergeac2a4b62016-08-29 16:16:09161 if (!extension() ||
162 !extension_l10n_util::ValidateExtensionLocales(
163 extension_path_, extension()->manifest()->value(), &error)) {
164 ReportExtensionLoadError(error);
165 return false;
166 }
167
proberge80a37f32016-08-04 19:44:55168 if (only_allow_apps && !extension()->is_platform_app()) {
169#if defined(GOOGLE_CHROME_BUILD)
170 // Avoid crashing for users with hijacked shortcuts.
171 return true;
172#else
173 // Defined here to avoid unused variable errors in official builds.
174 const char extension_instead_of_app_error[] =
175 "App loading flags cannot be used to load extensions. Please use "
176 "--load-extension instead.";
177 ReportExtensionLoadError(extension_instead_of_app_error);
178 return false;
179#endif
180 }
181
rdevlin.cronine2d0fd02015-09-24 22:35:49182 extension()->permissions_data()->BindToCurrentThread();
rdevlin.croninf173cbc42014-09-24 18:03:32183 PermissionsUpdater(
184 service_weak_->profile(), PermissionsUpdater::INIT_FLAG_TRANSIENT)
185 .InitializePermissions(extension());
[email protected]849749d2013-05-06 17:30:45186 ShowInstallPrompt();
[email protected]2a69b942013-05-31 09:37:53187
[email protected]253fc2bb2014-07-10 04:21:18188 *extension_id = extension()->id();
[email protected]2a69b942013-05-31 09:37:53189 return true;
[email protected]98270432012-09-11 20:51:24190}
191
[email protected]849749d2013-05-06 17:30:45192void UnpackedInstaller::ShowInstallPrompt() {
yoz416ae9f2015-02-24 19:40:41193 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]e8dad9b2013-06-04 04:43:45194 if (!service_weak_.get())
[email protected]849749d2013-05-06 17:30:45195 return;
196
[email protected]284ffac2014-02-12 01:08:58197 const ExtensionSet& disabled_extensions =
198 ExtensionRegistry::Get(service_weak_->profile())->disabled_extensions();
rdevlin.cronin726ab492017-01-30 21:36:07199 if (prompt_for_plugins_ &&
[email protected]253fc2bb2014-07-10 04:21:18200 PluginInfo::HasPlugins(extension()) &&
201 !disabled_extensions.Contains(extension()->id())) {
[email protected]849749d2013-05-06 17:30:45202 SimpleExtensionLoadPrompt* prompt = new SimpleExtensionLoadPrompt(
dgozmand741d25d2017-03-23 00:35:34203 extension(), profile_,
[email protected]253fc2bb2014-07-10 04:21:18204 base::Bind(&UnpackedInstaller::StartInstallChecks, this));
[email protected]849749d2013-05-06 17:30:45205 prompt->ShowPrompt();
206 return;
207 }
[email protected]253fc2bb2014-07-10 04:21:18208 StartInstallChecks();
[email protected]849749d2013-05-06 17:30:45209}
210
[email protected]253fc2bb2014-07-10 04:21:18211void UnpackedInstaller::StartInstallChecks() {
elijahtaylorc93f75472014-10-15 18:42:25212 // TODO(crbug.com/421128): Enable these checks all the time. The reason
213 // they are disabled for extensions loaded from the command-line is that
214 // installing unpacked extensions is asynchronous, but there can be
215 // dependencies between the extensions loaded by the command line.
216 if (extension()->manifest()->location() != Manifest::COMMAND_LINE) {
217 ExtensionService* service = service_weak_.get();
218 if (!service || service->browser_terminating())
219 return;
220
221 // TODO(crbug.com/420147): Move this code to a utility class to avoid
222 // duplication of SharedModuleService::CheckImports code.
223 if (SharedModuleInfo::ImportsModules(extension())) {
224 const std::vector<SharedModuleInfo::ImportInfo>& imports =
225 SharedModuleInfo::GetImports(extension());
226 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
227 for (i = imports.begin(); i != imports.end(); ++i) {
pwnallcbd73192016-08-22 18:59:17228 base::Version version_required(i->minimum_version);
elijahtaylorc93f75472014-10-15 18:42:25229 const Extension* imported_module =
230 service->GetExtensionById(i->extension_id, true);
231 if (!imported_module) {
232 ReportExtensionLoadError(kImportMissing);
233 return;
234 } else if (imported_module &&
235 !SharedModuleInfo::IsSharedModule(imported_module)) {
236 ReportExtensionLoadError(kImportNotSharedModule);
237 return;
238 } else if (imported_module && (version_required.IsValid() &&
239 imported_module->version()->CompareTo(
240 version_required) < 0)) {
241 ReportExtensionLoadError(kImportMinVersionNewer);
242 return;
243 }
244 }
245 }
246 }
247
michaelpg6a4874f2017-04-13 20:41:33248 policy_check_ = base::MakeUnique<PolicyCheck>(profile_, extension_);
249 requirements_check_ = base::MakeUnique<RequirementsChecker>(extension_);
250
251 check_group_ = base::MakeUnique<PreloadCheckGroup>();
252 check_group_->set_stop_on_first_error(true);
253
254 check_group_->AddCheck(policy_check_.get());
255 check_group_->AddCheck(requirements_check_.get());
256 check_group_->Start(
257 base::BindOnce(&UnpackedInstaller::OnInstallChecksComplete, this));
[email protected]98270432012-09-11 20:51:24258}
259
michaelpg6a4874f2017-04-13 20:41:33260void UnpackedInstaller::OnInstallChecksComplete(PreloadCheck::Errors errors) {
yoz416ae9f2015-02-24 19:40:41261 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]98270432012-09-11 20:51:24262
michaelpg6a4874f2017-04-13 20:41:33263 if (errors.empty()) {
264 InstallExtension();
[email protected]253fc2bb2014-07-10 04:21:18265 return;
266 }
267
michaelpg6a4874f2017-04-13 20:41:33268 base::string16 error_message;
269 if (errors.count(PreloadCheck::DISALLOWED_BY_POLICY))
270 error_message = policy_check_->GetErrorMessage();
271 else
272 error_message = requirements_check_->GetErrorMessage();
273
274 DCHECK(!error_message.empty());
275 ReportExtensionLoadError(base::UTF16ToUTF8(error_message));
[email protected]d8c8f25f2011-11-02 18:18:01276}
277
[email protected]b7462f32012-09-02 15:18:12278int UnpackedInstaller::GetFlags() {
[email protected]fdd28372014-08-21 02:27:26279 std::string id = crx_file::id_util::GenerateIdForPath(extension_path_);
[email protected]b7462f32012-09-02 15:18:12280 bool allow_file_access =
[email protected]12075d12013-02-27 05:38:05281 Manifest::ShouldAlwaysAllowFileAccess(Manifest::UNPACKED);
[email protected]7c82539c2014-02-19 06:09:17282 ExtensionPrefs* prefs = ExtensionPrefs::Get(service_weak_->profile());
[email protected]849749d2013-05-06 17:30:45283 if (prefs->HasAllowFileAccessSetting(id))
284 allow_file_access = prefs->AllowFileAccess(id);
[email protected]b7462f32012-09-02 15:18:12285
286 int result = Extension::FOLLOW_SYMLINKS_ANYWHERE;
287 if (allow_file_access)
288 result |= Extension::ALLOW_FILE_ACCESS;
289 if (require_modern_manifest_version_)
290 result |= Extension::REQUIRE_MODERN_MANIFEST_VERSION;
291
292 return result;
293}
294
[email protected]8e7b2cf42012-04-18 14:26:58295bool UnpackedInstaller::IsLoadingUnpackedAllowed() const {
[email protected]e8dad9b2013-06-04 04:43:45296 if (!service_weak_.get())
[email protected]8e7b2cf42012-04-18 14:26:58297 return true;
298 // If there is a "*" in the extension blacklist, then no extensions should be
299 // allowed at all (except explicitly whitelisted extensions).
binjin1569c9b2014-09-05 13:33:18300 return !ExtensionManagementFactory::GetForBrowserContext(
301 service_weak_->profile())->BlacklistedByDefault();
[email protected]8e7b2cf42012-04-18 14:26:58302}
303
[email protected]d8c8f25f2011-11-02 18:18:01304void UnpackedInstaller::GetAbsolutePath() {
Istiaque Ahmed81ff01e2017-08-09 16:00:59305 base::ThreadRestrictions::AssertIOAllowed();
[email protected]d8c8f25f2011-11-02 18:18:01306
[email protected]15476932013-04-12 05:17:15307 extension_path_ = base::MakeAbsoluteFilePath(extension_path_);
[email protected]d8c8f25f2011-11-02 18:18:01308
[email protected]5ccca8ad2013-08-19 22:35:34309 std::string error;
[email protected]85df9d12014-04-15 17:02:14310 if (!file_util::CheckForIllegalFilenames(extension_path_, &error)) {
[email protected]5ccca8ad2013-08-19 22:35:34311 BrowserThread::PostTask(
tzik8d880ee2017-04-20 19:46:24312 BrowserThread::UI, FROM_HERE,
313 base::BindOnce(&UnpackedInstaller::ReportExtensionLoadError, this,
314 error));
[email protected]5ccca8ad2013-08-19 22:35:34315 return;
316 }
[email protected]849749d2013-05-06 17:30:45317 BrowserThread::PostTask(
318 BrowserThread::UI, FROM_HERE,
tzik8d880ee2017-04-20 19:46:24319 base::BindOnce(&UnpackedInstaller::CheckExtensionFileAccess, this));
[email protected]d8c8f25f2011-11-02 18:18:01320}
321
322void UnpackedInstaller::CheckExtensionFileAccess() {
yoz416ae9f2015-02-24 19:40:41323 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]e8dad9b2013-06-04 04:43:45324 if (!service_weak_.get())
[email protected]8e7b2cf42012-04-18 14:26:58325 return;
326
327 if (!IsLoadingUnpackedAllowed()) {
328 ReportExtensionLoadError(kUnpackedExtensionsBlacklistedError);
329 return;
330 }
331
Istiaque Ahmed81ff01e2017-08-09 16:00:59332 GetExtensionFileTaskRunner()->PostTask(
333 FROM_HERE,
tzik8d880ee2017-04-20 19:46:24334 base::BindOnce(&UnpackedInstaller::LoadWithFileAccess, this, GetFlags()));
[email protected]d8c8f25f2011-11-02 18:18:01335}
336
[email protected]b7462f32012-09-02 15:18:12337void UnpackedInstaller::LoadWithFileAccess(int flags) {
Istiaque Ahmed81ff01e2017-08-09 16:00:59338 base::ThreadRestrictions::AssertIOAllowed();
[email protected]b7462f32012-09-02 15:18:12339
[email protected]d8c8f25f2011-11-02 18:18:01340 std::string error;
dgozmand741d25d2017-03-23 00:35:34341 extension_ = file_util::LoadExtension(extension_path_, Manifest::UNPACKED,
342 flags, &error);
[email protected]d8c8f25f2011-11-02 18:18:01343
[email protected]253fc2bb2014-07-10 04:21:18344 if (!extension() ||
[email protected]557c7bd2013-09-18 21:51:25345 !extension_l10n_util::ValidateExtensionLocales(
[email protected]253fc2bb2014-07-10 04:21:18346 extension_path_, extension()->manifest()->value(), &error)) {
[email protected]849749d2013-05-06 17:30:45347 BrowserThread::PostTask(
tzik8d880ee2017-04-20 19:46:24348 BrowserThread::UI, FROM_HERE,
349 base::BindOnce(&UnpackedInstaller::ReportExtensionLoadError, this,
350 error));
[email protected]d8c8f25f2011-11-02 18:18:01351 return;
352 }
353
[email protected]849749d2013-05-06 17:30:45354 BrowserThread::PostTask(
tzik8d880ee2017-04-20 19:46:24355 BrowserThread::UI, FROM_HERE,
356 base::BindOnce(&UnpackedInstaller::ShowInstallPrompt, this));
[email protected]d8c8f25f2011-11-02 18:18:01357}
358
359void UnpackedInstaller::ReportExtensionLoadError(const std::string &error) {
yoz416ae9f2015-02-24 19:40:41360 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]500c7bb2014-04-26 22:44:33361
[email protected]1f0722442014-05-01 17:26:02362 if (service_weak_.get()) {
363 ExtensionErrorReporter::GetInstance()->ReportLoadError(
364 extension_path_,
365 error,
366 service_weak_->profile(),
367 be_noisy_on_failure_);
368 }
rdevlin.croninf6ea63a2015-03-04 17:51:04369
370 if (!callback_.is_null()) {
371 callback_.Run(nullptr, extension_path_, error);
372 callback_.Reset();
373 }
[email protected]d8c8f25f2011-11-02 18:18:01374}
375
[email protected]253fc2bb2014-07-10 04:21:18376void UnpackedInstaller::InstallExtension() {
[email protected]54ee8192014-03-29 17:37:24377 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]0d904312012-01-25 23:00:16378
asargent1e46c512016-09-16 00:46:09379 if (!service_weak_.get()) {
380 callback_.Reset();
381 return;
382 }
383
[email protected]0d904312012-01-25 23:00:16384 PermissionsUpdater perms_updater(service_weak_->profile());
gpdavis.chromium48f08c42014-09-18 22:09:34385 perms_updater.InitializePermissions(extension());
[email protected]253fc2bb2014-07-10 04:21:18386 perms_updater.GrantActivePermissions(extension());
[email protected]9d02fa12013-02-19 05:12:57387
[email protected]253fc2bb2014-07-10 04:21:18388 service_weak_->OnExtensionInstalled(
389 extension(), syncer::StringOrdinal(), kInstallFlagInstallImmediately);
rdevlin.croninf6ea63a2015-03-04 17:51:04390
391 if (!callback_.is_null()) {
392 callback_.Run(extension(), extension_path_, std::string());
393 callback_.Reset();
394 }
[email protected]d8c8f25f2011-11-02 18:18:01395}
396
397} // namespace extensions