Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / extensions / unpacked_installer.cc
blob56d5197e4d692ce3943fabfbfe4712519c132f04
1 // Copyright (c) 2013 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/unpacked_installer.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "chrome/browser/extensions/extension_error_reporter.h"
15 #include "chrome/browser/extensions/extension_install_prompt.h"
16 #include "chrome/browser/extensions/extension_install_ui.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/permissions_updater.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/extensions/api/plugins/plugins_handler.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "extensions/browser/extension_prefs.h"
24 #include "extensions/browser/extension_registry.h"
25 #include "extensions/common/extension.h"
26 #include "extensions/common/extension_l10n_util.h"
27 #include "extensions/common/file_util.h"
28 #include "extensions/common/id_util.h"
29 #include "extensions/common/manifest.h"
30 #include "sync/api/string_ordinal.h"
32 using content::BrowserThread;
33 using extensions::Extension;
35 namespace {
37 const char kUnpackedExtensionsBlacklistedError[] =
38 "Loading of unpacked extensions is disabled by the administrator.";
40 // Manages an ExtensionInstallPrompt for a particular extension.
41 class SimpleExtensionLoadPrompt : public ExtensionInstallPrompt::Delegate {
42 public:
43 SimpleExtensionLoadPrompt(const Extension* extension,
44 Profile* profile,
45 const base::Closure& callback);
46 virtual ~SimpleExtensionLoadPrompt();
48 void ShowPrompt();
50 // ExtensionInstallUI::Delegate
51 virtual void InstallUIProceed() OVERRIDE;
52 virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
54 private:
55 scoped_ptr<ExtensionInstallPrompt> install_ui_;
56 scoped_refptr<const Extension> extension_;
57 base::Closure callback_;
60 SimpleExtensionLoadPrompt::SimpleExtensionLoadPrompt(
61 const Extension* extension,
62 Profile* profile,
63 const base::Closure& callback)
64 : install_ui_(ExtensionInstallUI::CreateInstallPromptWithProfile(
65 profile)),
66 extension_(extension),
67 callback_(callback) {
70 SimpleExtensionLoadPrompt::~SimpleExtensionLoadPrompt() {
73 void SimpleExtensionLoadPrompt::ShowPrompt() {
74 std::string confirm = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
75 switches::kAppsGalleryInstallAutoConfirmForTests);
76 if (confirm == "accept") {
77 InstallUIProceed();
78 return;
80 if (confirm == "cancel") {
81 InstallUIAbort(false);
82 return;
85 install_ui_->ConfirmInstall(
86 this,
87 extension_.get(),
88 ExtensionInstallPrompt::GetDefaultShowDialogCallback());
91 void SimpleExtensionLoadPrompt::InstallUIProceed() {
92 callback_.Run();
93 delete this;
96 void SimpleExtensionLoadPrompt::InstallUIAbort(bool user_initiated) {
97 delete this;
100 } // namespace
102 namespace extensions {
104 // static
105 scoped_refptr<UnpackedInstaller> UnpackedInstaller::Create(
106 ExtensionService* extension_service) {
107 DCHECK(extension_service);
108 return scoped_refptr<UnpackedInstaller>(
109 new UnpackedInstaller(extension_service));
112 UnpackedInstaller::UnpackedInstaller(ExtensionService* extension_service)
113 : service_weak_(extension_service->AsWeakPtr()),
114 prompt_for_plugins_(true),
115 require_modern_manifest_version_(true),
116 be_noisy_on_failure_(true),
117 installer_(extension_service->profile()) {
118 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
121 UnpackedInstaller::~UnpackedInstaller() {
122 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
123 BrowserThread::CurrentlyOn(BrowserThread::FILE));
126 void UnpackedInstaller::Load(const base::FilePath& path_in) {
127 DCHECK(extension_path_.empty());
128 extension_path_ = path_in;
129 BrowserThread::PostTask(
130 BrowserThread::FILE,
131 FROM_HERE,
132 base::Bind(&UnpackedInstaller::GetAbsolutePath, this));
135 bool UnpackedInstaller::LoadFromCommandLine(const base::FilePath& path_in,
136 std::string* extension_id) {
137 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
138 DCHECK(extension_path_.empty());
140 if (!service_weak_.get())
141 return false;
142 // Load extensions from the command line synchronously to avoid a race
143 // between extension loading and loading an URL from the command line.
144 base::ThreadRestrictions::ScopedAllowIO allow_io;
146 extension_path_ = base::MakeAbsoluteFilePath(path_in);
148 if (!IsLoadingUnpackedAllowed()) {
149 ReportExtensionLoadError(kUnpackedExtensionsBlacklistedError);
150 return false;
153 std::string error;
154 installer_.set_extension(
155 file_util::LoadExtension(
156 extension_path_, Manifest::COMMAND_LINE, GetFlags(), &error).get());
158 if (!installer_.extension().get() ||
159 !extension_l10n_util::ValidateExtensionLocales(
160 extension_path_,
161 installer_.extension()->manifest()->value(),
162 &error)) {
163 ReportExtensionLoadError(error);
164 return false;
167 ShowInstallPrompt();
169 *extension_id = installer_.extension()->id();
170 return true;
173 void UnpackedInstaller::ShowInstallPrompt() {
174 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
175 if (!service_weak_.get())
176 return;
178 const ExtensionSet& disabled_extensions =
179 ExtensionRegistry::Get(service_weak_->profile())->disabled_extensions();
180 if (service_weak_->show_extensions_prompts() && prompt_for_plugins_ &&
181 PluginInfo::HasPlugins(installer_.extension().get()) &&
182 !disabled_extensions.Contains(installer_.extension()->id())) {
183 SimpleExtensionLoadPrompt* prompt = new SimpleExtensionLoadPrompt(
184 installer_.extension().get(),
185 installer_.profile(),
186 base::Bind(&UnpackedInstaller::CallCheckRequirements, this));
187 prompt->ShowPrompt();
188 return;
190 CallCheckRequirements();
193 void UnpackedInstaller::CallCheckRequirements() {
194 installer_.CheckRequirements(
195 base::Bind(&UnpackedInstaller::OnRequirementsChecked, this));
198 void UnpackedInstaller::OnRequirementsChecked(
199 std::vector<std::string> requirement_errors) {
200 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
202 if (!requirement_errors.empty()) {
203 ReportExtensionLoadError(JoinString(requirement_errors, ' '));
204 return;
207 ConfirmInstall();
210 int UnpackedInstaller::GetFlags() {
211 std::string id = id_util::GenerateIdForPath(extension_path_);
212 bool allow_file_access =
213 Manifest::ShouldAlwaysAllowFileAccess(Manifest::UNPACKED);
214 ExtensionPrefs* prefs = ExtensionPrefs::Get(service_weak_->profile());
215 if (prefs->HasAllowFileAccessSetting(id))
216 allow_file_access = prefs->AllowFileAccess(id);
218 int result = Extension::FOLLOW_SYMLINKS_ANYWHERE;
219 if (allow_file_access)
220 result |= Extension::ALLOW_FILE_ACCESS;
221 if (require_modern_manifest_version_)
222 result |= Extension::REQUIRE_MODERN_MANIFEST_VERSION;
224 return result;
227 bool UnpackedInstaller::IsLoadingUnpackedAllowed() const {
228 if (!service_weak_.get())
229 return true;
230 // If there is a "*" in the extension blacklist, then no extensions should be
231 // allowed at all (except explicitly whitelisted extensions).
232 ExtensionPrefs* prefs = ExtensionPrefs::Get(service_weak_->profile());
233 return !prefs->ExtensionsBlacklistedByDefault();
236 void UnpackedInstaller::GetAbsolutePath() {
237 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
239 extension_path_ = base::MakeAbsoluteFilePath(extension_path_);
241 std::string error;
242 if (!file_util::CheckForIllegalFilenames(extension_path_, &error)) {
243 BrowserThread::PostTask(
244 BrowserThread::UI,
245 FROM_HERE,
246 base::Bind(&UnpackedInstaller::ReportExtensionLoadError, this, error));
247 return;
249 BrowserThread::PostTask(
250 BrowserThread::UI, FROM_HERE,
251 base::Bind(&UnpackedInstaller::CheckExtensionFileAccess, this));
254 void UnpackedInstaller::CheckExtensionFileAccess() {
255 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
256 if (!service_weak_.get())
257 return;
259 if (!IsLoadingUnpackedAllowed()) {
260 ReportExtensionLoadError(kUnpackedExtensionsBlacklistedError);
261 return;
264 BrowserThread::PostTask(
265 BrowserThread::FILE,
266 FROM_HERE,
267 base::Bind(&UnpackedInstaller::LoadWithFileAccess, this, GetFlags()));
270 void UnpackedInstaller::LoadWithFileAccess(int flags) {
271 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
273 std::string error;
274 installer_.set_extension(
275 file_util::LoadExtension(
276 extension_path_, Manifest::UNPACKED, flags, &error).get());
278 if (!installer_.extension().get() ||
279 !extension_l10n_util::ValidateExtensionLocales(
280 extension_path_,
281 installer_.extension()->manifest()->value(),
282 &error)) {
283 BrowserThread::PostTask(
284 BrowserThread::UI,
285 FROM_HERE,
286 base::Bind(&UnpackedInstaller::ReportExtensionLoadError, this, error));
287 return;
290 BrowserThread::PostTask(
291 BrowserThread::UI,
292 FROM_HERE,
293 base::Bind(&UnpackedInstaller::ShowInstallPrompt, this));
296 void UnpackedInstaller::ReportExtensionLoadError(const std::string &error) {
297 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
298 if (!on_failure_callback_.is_null())
299 on_failure_callback_.Run(extension_path_, error);
301 if (service_weak_.get()) {
302 ExtensionErrorReporter::GetInstance()->ReportLoadError(
303 extension_path_,
304 error,
305 service_weak_->profile(),
306 be_noisy_on_failure_);
310 void UnpackedInstaller::ConfirmInstall() {
311 DCHECK_CURRENTLY_ON(BrowserThread::UI);
312 base::string16 error = installer_.CheckManagementPolicy();
313 if (!error.empty()) {
314 ReportExtensionLoadError(base::UTF16ToUTF8(error));
315 return;
318 PermissionsUpdater perms_updater(service_weak_->profile());
319 perms_updater.GrantActivePermissions(installer_.extension().get());
321 service_weak_->OnExtensionInstalled(
322 installer_.extension().get(),
323 syncer::StringOrdinal(),
324 false /* no requirement errors */,
325 NOT_BLACKLISTED,
326 false /* don't wait for idle */);
329 } // namespace extensions