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

Side by Side Diff: chrome/browser/extensions/api/management/management_api.cc

Issue 696543002: Move the chrome.management API to extensions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month 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) 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.
4
5 #include "chrome/browser/extensions/api/management/management_api.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/json/json_writer.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/memory/linked_ptr.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/metrics/histogram.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "chrome/browser/extensions/api/management/management_api_constants.h"
22 #include "chrome/browser/extensions/extension_service.h"
23 #include "chrome/browser/extensions/extension_ui_util.h"
24 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
25 #include "chrome/browser/extensions/extension_util.h"
26 #include "chrome/browser/extensions/launch_util.h"
27 #include "chrome/browser/favicon/favicon_service_factory.h"
28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/browser/ui/browser_dialogs.h"
30 #include "chrome/browser/ui/browser_finder.h"
31 #include "chrome/browser/ui/browser_window.h"
32 #include "chrome/browser/ui/extensions/application_launch.h"
33 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
34 #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
35 #include "chrome/common/extensions/api/management.h"
36 #include "chrome/common/extensions/chrome_utility_extensions_messages.h"
37 #include "chrome/common/extensions/extension_constants.h"
38 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
39 #include "content/public/browser/utility_process_host.h"
40 #include "content/public/browser/utility_process_host_client.h"
41 #include "extensions/browser/event_router.h"
42 #include "extensions/browser/extension_prefs.h"
43 #include "extensions/browser/extension_registry.h"
44 #include "extensions/browser/extension_system.h"
45 #include "extensions/browser/management_policy.h"
46 #include "extensions/browser/uninstall_reason.h"
47 #include "extensions/common/constants.h"
48 #include "extensions/common/error_utils.h"
49 #include "extensions/common/extension.h"
50 #include "extensions/common/extension_icon_set.h"
51 #include "extensions/common/manifest_handlers/icons_handler.h"
52 #include "extensions/common/manifest_handlers/offline_enabled_info.h"
53 #include "extensions/common/manifest_handlers/options_page_info.h"
54 #include "extensions/common/manifest_url_handlers.h"
55 #include "extensions/common/permissions/permission_set.h"
56 #include "extensions/common/permissions/permissions_data.h"
57 #include "extensions/common/url_pattern.h"
58
59 using base::IntToString;
60 using content::BrowserThread;
61 using content::UtilityProcessHost;
62 using content::UtilityProcessHostClient;
63
64 namespace keys = extension_management_api_constants;
65
66 namespace extensions {
67
68 namespace management = api::management;
69
70 namespace {
71
72 typedef std::vector<linked_ptr<management::ExtensionInfo> > ExtensionInfoList;
73 typedef std::vector<linked_ptr<management::IconInfo> > IconInfoList;
74
75 enum AutoConfirmForTest {
76 DO_NOT_SKIP = 0,
77 PROCEED,
78 ABORT
79 };
80
81 AutoConfirmForTest auto_confirm_for_test = DO_NOT_SKIP;
82
83 std::vector<std::string> CreateWarningsList(const Extension* extension) {
84 std::vector<std::string> warnings_list;
85 PermissionMessages warnings =
86 extension->permissions_data()->GetPermissionMessages();
87 for (PermissionMessages::const_iterator iter = warnings.begin();
88 iter != warnings.end(); ++iter) {
89 warnings_list.push_back(base::UTF16ToUTF8(iter->message()));
90 }
91
92 return warnings_list;
93 }
94
95 std::vector<management::LaunchType> GetAvailableLaunchTypes(
96 const Extension& extension) {
97 std::vector<management::LaunchType> launch_type_list;
98 if (extension.is_platform_app()) {
99 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW);
100 return launch_type_list;
101 }
102
103 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB);
104
105 #if !defined(OS_MACOSX)
106 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW);
107 #endif
108
109 if (!util::IsStreamlinedHostedAppsEnabled()) {
110 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB);
111 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_FULL_SCREEN);
112 }
113 return launch_type_list;
114 }
115
116 scoped_ptr<management::ExtensionInfo> CreateExtensionInfo(
117 const Extension& extension,
118 ExtensionSystem* system) {
119 scoped_ptr<management::ExtensionInfo> info(new management::ExtensionInfo());
120 ExtensionService* service = system->extension_service();
121
122 info->id = extension.id();
123 info->name = extension.name();
124 info->short_name = extension.short_name();
125 info->enabled = service->IsExtensionEnabled(info->id);
126 info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&extension);
127 info->version = extension.VersionString();
128 info->description = extension.description();
129 info->options_url = OptionsPageInfo::GetOptionsPage(&extension).spec();
130 info->homepage_url.reset(new std::string(
131 ManifestURL::GetHomepageURL(&extension).spec()));
132 info->may_disable = system->management_policy()->
133 UserMayModifySettings(&extension, NULL);
134 info->is_app = extension.is_app();
135 if (info->is_app) {
136 if (extension.is_legacy_packaged_app())
137 info->type = management::ExtensionInfo::TYPE_LEGACY_PACKAGED_APP;
138 else if (extension.is_hosted_app())
139 info->type = management::ExtensionInfo::TYPE_HOSTED_APP;
140 else
141 info->type = management::ExtensionInfo::TYPE_PACKAGED_APP;
142 } else if (extension.is_theme()) {
143 info->type = management::ExtensionInfo::TYPE_THEME;
144 } else {
145 info->type = management::ExtensionInfo::TYPE_EXTENSION;
146 }
147
148 if (info->enabled) {
149 info->disabled_reason = management::ExtensionInfo::DISABLED_REASON_NONE;
150 } else {
151 ExtensionPrefs* prefs = ExtensionPrefs::Get(service->profile());
152 if (prefs->DidExtensionEscalatePermissions(extension.id())) {
153 info->disabled_reason =
154 management::ExtensionInfo::DISABLED_REASON_PERMISSIONS_INCREASE;
155 } else {
156 info->disabled_reason =
157 management::ExtensionInfo::DISABLED_REASON_UNKNOWN;
158 }
159 }
160
161 if (!ManifestURL::GetUpdateURL(&extension).is_empty()) {
162 info->update_url.reset(new std::string(
163 ManifestURL::GetUpdateURL(&extension).spec()));
164 }
165
166 if (extension.is_app()) {
167 info->app_launch_url.reset(new std::string(
168 AppLaunchInfo::GetFullLaunchURL(&extension).spec()));
169 }
170
171 const ExtensionIconSet::IconMap& icons =
172 IconsInfo::GetIcons(&extension).map();
173 if (!icons.empty()) {
174 info->icons.reset(new IconInfoList());
175 ExtensionIconSet::IconMap::const_iterator icon_iter;
176 for (icon_iter = icons.begin(); icon_iter != icons.end(); ++icon_iter) {
177 management::IconInfo* icon_info = new management::IconInfo();
178 icon_info->size = icon_iter->first;
179 GURL url = ExtensionIconSource::GetIconURL(
180 &extension, icon_info->size, ExtensionIconSet::MATCH_EXACTLY, false,
181 NULL);
182 icon_info->url = url.spec();
183 info->icons->push_back(make_linked_ptr<management::IconInfo>(icon_info));
184 }
185 }
186
187 const std::set<std::string> perms =
188 extension.permissions_data()->active_permissions()->GetAPIsAsStrings();
189 if (!perms.empty()) {
190 std::set<std::string>::const_iterator perms_iter;
191 for (perms_iter = perms.begin(); perms_iter != perms.end(); ++perms_iter)
192 info->permissions.push_back(*perms_iter);
193 }
194
195 if (!extension.is_hosted_app()) {
196 // Skip host permissions for hosted apps.
197 const URLPatternSet host_perms =
198 extension.permissions_data()->active_permissions()->explicit_hosts();
199 if (!host_perms.is_empty()) {
200 for (URLPatternSet::const_iterator iter = host_perms.begin();
201 iter != host_perms.end(); ++iter) {
202 info->host_permissions.push_back(iter->GetAsString());
203 }
204 }
205 }
206
207 switch (extension.location()) {
208 case Manifest::INTERNAL:
209 info->install_type = management::ExtensionInfo::INSTALL_TYPE_NORMAL;
210 break;
211 case Manifest::UNPACKED:
212 case Manifest::COMMAND_LINE:
213 info->install_type = management::ExtensionInfo::INSTALL_TYPE_DEVELOPMENT;
214 break;
215 case Manifest::EXTERNAL_PREF:
216 case Manifest::EXTERNAL_REGISTRY:
217 case Manifest::EXTERNAL_PREF_DOWNLOAD:
218 info->install_type = management::ExtensionInfo::INSTALL_TYPE_SIDELOAD;
219 break;
220 case Manifest::EXTERNAL_POLICY:
221 case Manifest::EXTERNAL_POLICY_DOWNLOAD:
222 info->install_type = management::ExtensionInfo::INSTALL_TYPE_ADMIN;
223 break;
224 case Manifest::NUM_LOCATIONS:
225 NOTREACHED();
226 case Manifest::INVALID_LOCATION:
227 case Manifest::COMPONENT:
228 case Manifest::EXTERNAL_COMPONENT:
229 info->install_type = management::ExtensionInfo::INSTALL_TYPE_OTHER;
230 break;
231 }
232
233 info->launch_type = management::LAUNCH_TYPE_NONE;
234 if (extension.is_app()) {
235 LaunchType launch_type;
236 if (extension.is_platform_app()) {
237 launch_type = LAUNCH_TYPE_WINDOW;
238 } else {
239 launch_type =
240 GetLaunchType(ExtensionPrefs::Get(service->profile()), &extension);
241 }
242
243 switch (launch_type) {
244 case LAUNCH_TYPE_PINNED:
245 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB;
246 break;
247 case LAUNCH_TYPE_REGULAR:
248 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB;
249 break;
250 case LAUNCH_TYPE_FULLSCREEN:
251 info->launch_type = management::LAUNCH_TYPE_OPEN_FULL_SCREEN;
252 break;
253 case LAUNCH_TYPE_WINDOW:
254 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_WINDOW;
255 break;
256 case LAUNCH_TYPE_INVALID:
257 case NUM_LAUNCH_TYPES:
258 NOTREACHED();
259 }
260
261 info->available_launch_types.reset(new std::vector<management::LaunchType>(
262 GetAvailableLaunchTypes(extension)));
263 }
264
265 return info.Pass();
266 }
267
268 void AddExtensionInfo(const ExtensionSet& extensions,
269 ExtensionSystem* system,
270 ExtensionInfoList* extension_list,
271 content::BrowserContext* context) {
272 for (ExtensionSet::const_iterator iter = extensions.begin();
273 iter != extensions.end(); ++iter) {
274 const Extension& extension = *iter->get();
275
276 if (ui_util::ShouldNotBeVisible(&extension, context))
277 continue; // Skip built-in extensions/apps.
278
279 extension_list->push_back(make_linked_ptr<management::ExtensionInfo>(
280 CreateExtensionInfo(extension, system).release()));
281 }
282 }
283
284 } // namespace
285
286 ExtensionService* ManagementFunction::service() {
287 return ExtensionSystem::Get(GetProfile())->extension_service();
288 }
289
290 ExtensionService* AsyncManagementFunction::service() {
291 return ExtensionSystem::Get(GetProfile())->extension_service();
292 }
293
294 bool ManagementGetAllFunction::RunSync() {
295 ExtensionInfoList extensions;
296 ExtensionRegistry* registry = ExtensionRegistry::Get(GetProfile());
297 ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
298
299 AddExtensionInfo(registry->enabled_extensions(),
300 system, &extensions, browser_context());
301 AddExtensionInfo(registry->disabled_extensions(),
302 system, &extensions, browser_context());
303 AddExtensionInfo(registry->terminated_extensions(),
304 system, &extensions, browser_context());
305
306 results_ = management::GetAll::Results::Create(extensions);
307 return true;
308 }
309
310 bool ManagementGetFunction::RunSync() {
311 scoped_ptr<management::Get::Params> params(
312 management::Get::Params::Create(*args_));
313 EXTENSION_FUNCTION_VALIDATE(params.get());
314
315 const Extension* extension = service()->GetExtensionById(params->id, true);
316 if (!extension) {
317 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
318 params->id);
319 return false;
320 }
321
322 scoped_ptr<management::ExtensionInfo> info =
323 CreateExtensionInfo(*extension, ExtensionSystem::Get(GetProfile()));
324 results_ = management::Get::Results::Create(*info);
325
326 return true;
327 }
328
329 bool ManagementGetSelfFunction::RunSync() {
330 scoped_ptr<management::ExtensionInfo> info =
331 CreateExtensionInfo(*extension_, ExtensionSystem::Get(GetProfile()));
332 results_ = management::Get::Results::Create(*info);
333
334 return true;
335 }
336
337 bool ManagementGetPermissionWarningsByIdFunction::RunSync() {
338 scoped_ptr<management::GetPermissionWarningsById::Params> params(
339 management::GetPermissionWarningsById::Params::Create(*args_));
340 EXTENSION_FUNCTION_VALIDATE(params.get());
341
342 const Extension* extension = service()->GetExtensionById(params->id, true);
343 if (!extension) {
344 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
345 params->id);
346 return false;
347 }
348
349 std::vector<std::string> warnings = CreateWarningsList(extension);
350 results_ = management::GetPermissionWarningsById::Results::Create(warnings);
351 return true;
352 }
353
354 namespace {
355
356 // This class helps ManagementGetPermissionWarningsByManifestFunction manage
357 // sending manifest JSON strings to the utility process for parsing.
358 class SafeManifestJSONParser : public UtilityProcessHostClient {
359 public:
360 SafeManifestJSONParser(
361 ManagementGetPermissionWarningsByManifestFunction* client,
362 const std::string& manifest)
363 : client_(client),
364 manifest_(manifest) {}
365
366 void Start() {
367 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
368 BrowserThread::PostTask(
369 BrowserThread::IO,
370 FROM_HERE,
371 base::Bind(&SafeManifestJSONParser::StartWorkOnIOThread, this));
372 }
373
374 void StartWorkOnIOThread() {
375 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
376 UtilityProcessHost* host = UtilityProcessHost::Create(
377 this, base::MessageLoopProxy::current().get());
378 host->Send(new ChromeUtilityMsg_ParseJSON(manifest_));
379 }
380
381 bool OnMessageReceived(const IPC::Message& message) override {
382 bool handled = true;
383 IPC_BEGIN_MESSAGE_MAP(SafeManifestJSONParser, message)
384 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded,
385 OnJSONParseSucceeded)
386 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed,
387 OnJSONParseFailed)
388 IPC_MESSAGE_UNHANDLED(handled = false)
389 IPC_END_MESSAGE_MAP()
390 return handled;
391 }
392
393 void OnJSONParseSucceeded(const base::ListValue& wrapper) {
394 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
395 const base::Value* value = NULL;
396 CHECK(wrapper.Get(0, &value));
397 if (value->IsType(base::Value::TYPE_DICTIONARY))
398 parsed_manifest_.reset(
399 static_cast<const base::DictionaryValue*>(value)->DeepCopy());
400 else
401 error_ = keys::kManifestParseError;
402
403 BrowserThread::PostTask(
404 BrowserThread::UI,
405 FROM_HERE,
406 base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this));
407 }
408
409 void OnJSONParseFailed(const std::string& error) {
410 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
411 error_ = error;
412 BrowserThread::PostTask(
413 BrowserThread::UI,
414 FROM_HERE,
415 base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this));
416 }
417
418 void ReportResultFromUIThread() {
419 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
420 if (error_.empty() && parsed_manifest_.get())
421 client_->OnParseSuccess(parsed_manifest_.Pass());
422 else
423 client_->OnParseFailure(error_);
424 }
425
426 private:
427 ~SafeManifestJSONParser() override {}
428
429 // The client who we'll report results back to.
430 ManagementGetPermissionWarningsByManifestFunction* client_;
431
432 // Data to parse.
433 std::string manifest_;
434
435 // Results of parsing.
436 scoped_ptr<base::DictionaryValue> parsed_manifest_;
437
438 std::string error_;
439 };
440
441 } // namespace
442
443 bool ManagementGetPermissionWarningsByManifestFunction::RunAsync() {
444 scoped_ptr<management::GetPermissionWarningsByManifest::Params> params(
445 management::GetPermissionWarningsByManifest::Params::Create(*args_));
446 EXTENSION_FUNCTION_VALIDATE(params.get());
447
448 scoped_refptr<SafeManifestJSONParser> parser =
449 new SafeManifestJSONParser(this, params->manifest_str);
450 parser->Start();
451
452 // Matched with a Release() in OnParseSuccess/Failure().
453 AddRef();
454
455 // Response is sent async in OnParseSuccess/Failure().
456 return true;
457 }
458
459 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
460 scoped_ptr<base::DictionaryValue> parsed_manifest) {
461 CHECK(parsed_manifest.get());
462
463 scoped_refptr<Extension> extension = Extension::Create(
464 base::FilePath(), Manifest::INVALID_LOCATION, *parsed_manifest,
465 Extension::NO_FLAGS, &error_);
466 if (!extension.get()) {
467 OnParseFailure(keys::kExtensionCreateError);
468 return;
469 }
470
471 std::vector<std::string> warnings = CreateWarningsList(extension.get());
472 results_ =
473 management::GetPermissionWarningsByManifest::Results::Create(warnings);
474 SendResponse(true);
475
476 // Matched with AddRef() in RunAsync().
477 Release();
478 }
479
480 void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure(
481 const std::string& error) {
482 error_ = error;
483 SendResponse(false);
484
485 // Matched with AddRef() in RunAsync().
486 Release();
487 }
488
489 bool ManagementLaunchAppFunction::RunSync() {
490 scoped_ptr<management::LaunchApp::Params> params(
491 management::LaunchApp::Params::Create(*args_));
492 EXTENSION_FUNCTION_VALIDATE(params.get());
493 const Extension* extension = service()->GetExtensionById(params->id, true);
494 if (!extension) {
495 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
496 params->id);
497 return false;
498 }
499 if (!extension->is_app()) {
500 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError,
501 params->id);
502 return false;
503 }
504
505 // Look at prefs to find the right launch container.
506 // If the user has not set a preference, the default launch value will be
507 // returned.
508 LaunchContainer launch_container =
509 GetLaunchContainer(ExtensionPrefs::Get(GetProfile()), extension);
510 OpenApplication(AppLaunchParams(
511 GetProfile(), extension, launch_container, NEW_FOREGROUND_TAB));
512 CoreAppLauncherHandler::RecordAppLaunchType(
513 extension_misc::APP_LAUNCH_EXTENSION_API,
514 extension->GetType());
515
516 return true;
517 }
518
519 ManagementSetEnabledFunction::ManagementSetEnabledFunction() {
520 }
521
522 ManagementSetEnabledFunction::~ManagementSetEnabledFunction() {
523 }
524
525 bool ManagementSetEnabledFunction::RunAsync() {
526 scoped_ptr<management::SetEnabled::Params> params(
527 management::SetEnabled::Params::Create(*args_));
528 EXTENSION_FUNCTION_VALIDATE(params.get());
529
530 extension_id_ = params->id;
531
532 const Extension* extension =
533 ExtensionRegistry::Get(GetProfile())
534 ->GetExtensionById(extension_id_, ExtensionRegistry::EVERYTHING);
535 if (!extension || ui_util::ShouldNotBeVisible(extension, browser_context())) {
536 error_ = ErrorUtils::FormatErrorMessage(
537 keys::kNoExtensionError, extension_id_);
538 return false;
539 }
540
541 const ManagementPolicy* policy =
542 ExtensionSystem::Get(GetProfile())->management_policy();
543 if (!policy->UserMayModifySettings(extension, NULL) ||
544 (!params->enabled && policy->MustRemainEnabled(extension, NULL)) ||
545 (params->enabled && policy->MustRemainDisabled(extension, NULL, NULL))) {
546 error_ = ErrorUtils::FormatErrorMessage(
547 keys::kUserCantModifyError, extension_id_);
548 return false;
549 }
550
551 bool currently_enabled = service()->IsExtensionEnabled(extension_id_);
552
553 if (!currently_enabled && params->enabled) {
554 ExtensionPrefs* prefs = ExtensionPrefs::Get(GetProfile());
555 if (prefs->DidExtensionEscalatePermissions(extension_id_)) {
556 if (!user_gesture()) {
557 error_ = keys::kGestureNeededForEscalationError;
558 return false;
559 }
560 AddRef(); // Matched in InstallUIProceed/InstallUIAbort
561 install_prompt_.reset(
562 new ExtensionInstallPrompt(GetAssociatedWebContents()));
563 install_prompt_->ConfirmReEnable(this, extension);
564 return true;
565 }
566 service()->EnableExtension(extension_id_);
567 } else if (currently_enabled && !params->enabled) {
568 service()->DisableExtension(extension_id_, Extension::DISABLE_USER_ACTION);
569 }
570
571 BrowserThread::PostTask(
572 BrowserThread::UI,
573 FROM_HERE,
574 base::Bind(&ManagementSetEnabledFunction::SendResponse, this, true));
575
576 return true;
577 }
578
579 void ManagementSetEnabledFunction::InstallUIProceed() {
580 service()->EnableExtension(extension_id_);
581 SendResponse(true);
582 Release();
583 }
584
585 void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated) {
586 error_ = keys::kUserDidNotReEnableError;
587 SendResponse(false);
588 Release();
589 }
590
591 ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() {
592 }
593
594 ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() {
595 }
596
597 bool ManagementUninstallFunctionBase::Uninstall(
598 const std::string& target_extension_id,
599 bool show_confirm_dialog) {
600 extension_id_ = target_extension_id;
601 const Extension* target_extension =
602 extensions::ExtensionRegistry::Get(browser_context())->
603 GetExtensionById(extension_id_, ExtensionRegistry::EVERYTHING);
604 if (!target_extension ||
605 ui_util::ShouldNotBeVisible(target_extension, browser_context())) {
606 error_ = ErrorUtils::FormatErrorMessage(
607 keys::kNoExtensionError, extension_id_);
608 return false;
609 }
610
611 if (!ExtensionSystem::Get(GetProfile())
612 ->management_policy()
613 ->UserMayModifySettings(target_extension, NULL)) {
614 error_ = ErrorUtils::FormatErrorMessage(
615 keys::kUserCantModifyError, extension_id_);
616 return false;
617 }
618
619 if (auto_confirm_for_test == DO_NOT_SKIP) {
620 if (show_confirm_dialog) {
621 AddRef(); // Balanced in ExtensionUninstallAccepted/Canceled
622 content::WebContents* web_contents = GetAssociatedWebContents();
623 extension_uninstall_dialog_.reset(ExtensionUninstallDialog::Create(
624 GetProfile(),
625 web_contents ? web_contents->GetTopLevelNativeWindow() : NULL,
626 this));
627 if (extension_id() != target_extension_id) {
628 extension_uninstall_dialog_->ConfirmProgrammaticUninstall(
629 target_extension, extension());
630 } else {
631 // If this is a self uninstall, show the generic uninstall dialog.
632 extension_uninstall_dialog_->ConfirmUninstall(target_extension);
633 }
634 } else {
635 Finish(true);
636 }
637 } else {
638 Finish(auto_confirm_for_test == PROCEED);
639 }
640
641 return true;
642 }
643
644 // static
645 void ManagementUninstallFunctionBase::SetAutoConfirmForTest(
646 bool should_proceed) {
647 auto_confirm_for_test = should_proceed ? PROCEED : ABORT;
648 }
649
650 void ManagementUninstallFunctionBase::Finish(bool should_uninstall) {
651 if (should_uninstall) {
652 // The extension can be uninstalled in another window while the UI was
653 // showing. Do nothing in that case.
654 ExtensionRegistry* registry = ExtensionRegistry::Get(GetProfile());
655 const Extension* extension = registry->GetExtensionById(
656 extension_id_, ExtensionRegistry::EVERYTHING);
657 if (!extension) {
658 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
659 extension_id_);
660 SendResponse(false);
661 } else {
662 bool success = service()->UninstallExtension(
663 extension_id_,
664 extensions::UNINSTALL_REASON_MANAGEMENT_API,
665 base::Bind(&base::DoNothing),
666 NULL);
667
668 // TODO set error_ if !success
669 SendResponse(success);
670 }
671 } else {
672 error_ = ErrorUtils::FormatErrorMessage(
673 keys::kUninstallCanceledError, extension_id_);
674 SendResponse(false);
675 }
676 }
677
678 void ManagementUninstallFunctionBase::ExtensionUninstallAccepted() {
679 Finish(true);
680 Release();
681 }
682
683 void ManagementUninstallFunctionBase::ExtensionUninstallCanceled() {
684 Finish(false);
685 Release();
686 }
687
688 ManagementUninstallFunction::ManagementUninstallFunction() {
689 }
690
691 ManagementUninstallFunction::~ManagementUninstallFunction() {
692 }
693
694 bool ManagementUninstallFunction::RunAsync() {
695 scoped_ptr<management::Uninstall::Params> params(
696 management::Uninstall::Params::Create(*args_));
697 EXTENSION_FUNCTION_VALIDATE(extension_.get());
698 EXTENSION_FUNCTION_VALIDATE(params.get());
699
700 bool show_confirm_dialog = true;
701 // By default confirmation dialog isn't shown when uninstalling self, but this
702 // can be overridden with showConfirmDialog.
703 if (params->id == extension_->id()) {
704 show_confirm_dialog = params->options.get() &&
705 params->options->show_confirm_dialog.get() &&
706 *params->options->show_confirm_dialog;
707 }
708 if (show_confirm_dialog && !user_gesture()) {
709 error_ = keys::kGestureNeededForUninstallError;
710 return false;
711 }
712 return Uninstall(params->id, show_confirm_dialog);
713 }
714
715 ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() {
716 }
717
718 ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() {
719 }
720
721 bool ManagementUninstallSelfFunction::RunAsync() {
722 scoped_ptr<management::UninstallSelf::Params> params(
723 management::UninstallSelf::Params::Create(*args_));
724 EXTENSION_FUNCTION_VALIDATE(params.get());
725
726 bool show_confirm_dialog = false;
727 if (params->options.get() && params->options->show_confirm_dialog.get())
728 show_confirm_dialog = *params->options->show_confirm_dialog;
729 return Uninstall(extension_->id(), show_confirm_dialog);
730 }
731
732 ManagementCreateAppShortcutFunction::ManagementCreateAppShortcutFunction() {
733 }
734
735 ManagementCreateAppShortcutFunction::~ManagementCreateAppShortcutFunction() {
736 }
737
738 // static
739 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
740 bool should_proceed) {
741 auto_confirm_for_test = should_proceed ? PROCEED : ABORT;
742 }
743
744 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created) {
745 if (!created)
746 error_ = keys::kCreateShortcutCanceledError;
747 SendResponse(created);
748 Release();
749 }
750
751 bool ManagementCreateAppShortcutFunction::RunAsync() {
752 if (!user_gesture()) {
753 error_ = keys::kGestureNeededForCreateAppShortcutError;
754 return false;
755 }
756
757 scoped_ptr<management::CreateAppShortcut::Params> params(
758 management::CreateAppShortcut::Params::Create(*args_));
759 EXTENSION_FUNCTION_VALIDATE(params.get());
760 const Extension* extension = service()->GetExtensionById(params->id, true);
761 if (!extension) {
762 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
763 params->id);
764 return false;
765 }
766
767 if (!extension->is_app()) {
768 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
769 return false;
770 }
771
772 #if defined(OS_MACOSX)
773 if (!extension->is_platform_app()) {
774 error_ = keys::kCreateOnlyPackagedAppShortcutMac;
775 return false;
776 }
777 #endif
778
779 Browser* browser = chrome::FindBrowserWithProfile(
780 GetProfile(), chrome::HOST_DESKTOP_TYPE_NATIVE);
781 if (!browser) {
782 // Shouldn't happen if we have user gesture.
783 error_ = keys::kNoBrowserToCreateShortcut;
784 return false;
785 }
786
787 // Matched with a Release() in OnCloseShortcutPrompt().
788 AddRef();
789
790 if (auto_confirm_for_test == DO_NOT_SKIP) {
791 chrome::ShowCreateChromeAppShortcutsDialog(
792 browser->window()->GetNativeWindow(), browser->profile(), extension,
793 base::Bind(&ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt,
794 this));
795 } else {
796 OnCloseShortcutPrompt(auto_confirm_for_test == PROCEED);
797 }
798
799 // Response is sent async in OnCloseShortcutPrompt().
800 return true;
801 }
802
803 bool ManagementSetLaunchTypeFunction::RunSync() {
804 if (!user_gesture()) {
805 error_ = keys::kGestureNeededForSetLaunchTypeError;
806 return false;
807 }
808
809 scoped_ptr<management::SetLaunchType::Params> params(
810 management::SetLaunchType::Params::Create(*args_));
811 EXTENSION_FUNCTION_VALIDATE(params.get());
812 const Extension* extension = service()->GetExtensionById(params->id, true);
813 if (!extension) {
814 error_ =
815 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
816 return false;
817 }
818
819 if (!extension->is_app()) {
820 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
821 return false;
822 }
823
824 std::vector<management::LaunchType> available_launch_types =
825 GetAvailableLaunchTypes(*extension);
826
827 management::LaunchType app_launch_type = params->launch_type;
828 if (std::find(available_launch_types.begin(),
829 available_launch_types.end(),
830 app_launch_type) == available_launch_types.end()) {
831 error_ = keys::kLaunchTypeNotAvailableError;
832 return false;
833 }
834
835 LaunchType launch_type = LAUNCH_TYPE_DEFAULT;
836 switch (app_launch_type) {
837 case management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB:
838 launch_type = LAUNCH_TYPE_PINNED;
839 break;
840 case management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB:
841 launch_type = LAUNCH_TYPE_REGULAR;
842 break;
843 case management::LAUNCH_TYPE_OPEN_FULL_SCREEN:
844 launch_type = LAUNCH_TYPE_FULLSCREEN;
845 break;
846 case management::LAUNCH_TYPE_OPEN_AS_WINDOW:
847 launch_type = LAUNCH_TYPE_WINDOW;
848 break;
849 case management::LAUNCH_TYPE_NONE:
850 NOTREACHED();
851 }
852
853 SetLaunchType(service(), params->id, launch_type);
854
855 return true;
856 }
857
858 ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {
859 }
860
861 ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {
862 }
863
864 void ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp(
865 const Extension* extension,
866 const WebApplicationInfo& web_app_info) {
867 if (extension) {
868 scoped_ptr<management::ExtensionInfo> info =
869 CreateExtensionInfo(*extension, ExtensionSystem::Get(GetProfile()));
870 results_ = management::GenerateAppForLink::Results::Create(*info);
871
872 SendResponse(true);
873 Release();
874 } else {
875 error_ = keys::kGenerateAppForLinkInstallError;
876 SendResponse(false);
877 Release();
878 }
879 }
880
881 void ManagementGenerateAppForLinkFunction::OnFaviconForApp(
882 const favicon_base::FaviconImageResult& image_result) {
883 WebApplicationInfo web_app;
884 web_app.title = base::UTF8ToUTF16(title_);
885 web_app.app_url = launch_url_;
886
887 if (!image_result.image.IsEmpty()) {
888 WebApplicationInfo::IconInfo icon;
889 icon.data = image_result.image.AsBitmap();
890 icon.width = icon.data.width();
891 icon.height = icon.data.height();
892 web_app.icons.push_back(icon);
893 }
894
895 bookmark_app_helper_.reset(new BookmarkAppHelper(service(), web_app, NULL));
896 bookmark_app_helper_->Create(base::Bind(
897 &ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp, this));
898 }
899
900 bool ManagementGenerateAppForLinkFunction::RunAsync() {
901 if (!user_gesture()) {
902 error_ = keys::kGestureNeededForGenerateAppForLinkError;
903 return false;
904 }
905
906 scoped_ptr<management::GenerateAppForLink::Params> params(
907 management::GenerateAppForLink::Params::Create(*args_));
908 EXTENSION_FUNCTION_VALIDATE(params.get());
909
910 GURL launch_url(params->url);
911 if (!launch_url.is_valid() || !launch_url.SchemeIsHTTPOrHTTPS()) {
912 error_ = ErrorUtils::FormatErrorMessage(keys::kInvalidURLError,
913 params->url);
914 return false;
915 }
916
917 if (params->title.empty()) {
918 error_ = keys::kEmptyTitleError;
919 return false;
920 }
921
922 FaviconService* favicon_service =
923 FaviconServiceFactory::GetForProfile(GetProfile(),
924 Profile::EXPLICIT_ACCESS);
925 DCHECK(favicon_service);
926
927 title_ = params->title;
928 launch_url_ = launch_url;
929
930 favicon_service->GetFaviconImageForPageURL(
931 launch_url,
932 base::Bind(&ManagementGenerateAppForLinkFunction::OnFaviconForApp, this),
933 &cancelable_task_tracker_);
934
935 // Matched with a Release() in OnExtensionLoaded().
936 AddRef();
937
938 // Response is sent async in OnExtensionLoaded().
939 return true;
940 }
941
942 ManagementEventRouter::ManagementEventRouter(content::BrowserContext* context)
943 : browser_context_(context), extension_registry_observer_(this) {
944 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
945 }
946
947 ManagementEventRouter::~ManagementEventRouter() {}
948
949 void ManagementEventRouter::OnExtensionLoaded(
950 content::BrowserContext* browser_context,
951 const Extension* extension) {
952 BroadcastEvent(extension, management::OnEnabled::kEventName);
953 }
954
955 void ManagementEventRouter::OnExtensionUnloaded(
956 content::BrowserContext* browser_context,
957 const Extension* extension,
958 UnloadedExtensionInfo::Reason reason) {
959 BroadcastEvent(extension, management::OnDisabled::kEventName);
960 }
961
962 void ManagementEventRouter::OnExtensionInstalled(
963 content::BrowserContext* browser_context,
964 const Extension* extension,
965 bool is_update) {
966 BroadcastEvent(extension, management::OnInstalled::kEventName);
967 }
968
969 void ManagementEventRouter::OnExtensionUninstalled(
970 content::BrowserContext* browser_context,
971 const Extension* extension,
972 extensions::UninstallReason reason) {
973 BroadcastEvent(extension, management::OnUninstalled::kEventName);
974 }
975
976 void ManagementEventRouter::BroadcastEvent(const Extension* extension,
977 const char* event_name) {
978 if (ui_util::ShouldNotBeVisible(extension, browser_context_))
979 return; // Don't dispatch events for built-in extenions.
980 scoped_ptr<base::ListValue> args(new base::ListValue());
981 if (event_name == management::OnUninstalled::kEventName) {
982 args->Append(new base::StringValue(extension->id()));
983 } else {
984 scoped_ptr<management::ExtensionInfo> info =
985 CreateExtensionInfo(*extension, ExtensionSystem::Get(browser_context_));
986 args->Append(info->ToValue().release());
987 }
988
989 EventRouter::Get(browser_context_)
990 ->BroadcastEvent(scoped_ptr<Event>(new Event(event_name, args.Pass())));
991 }
992
993 ManagementAPI::ManagementAPI(content::BrowserContext* context)
994 : browser_context_(context) {
995 EventRouter* event_router = EventRouter::Get(browser_context_);
996 event_router->RegisterObserver(this, management::OnInstalled::kEventName);
997 event_router->RegisterObserver(this, management::OnUninstalled::kEventName);
998 event_router->RegisterObserver(this, management::OnEnabled::kEventName);
999 event_router->RegisterObserver(this, management::OnDisabled::kEventName);
1000 }
1001
1002 ManagementAPI::~ManagementAPI() {
1003 }
1004
1005 void ManagementAPI::Shutdown() {
1006 EventRouter::Get(browser_context_)->UnregisterObserver(this);
1007 }
1008
1009 static base::LazyInstance<BrowserContextKeyedAPIFactory<ManagementAPI> >
1010 g_factory = LAZY_INSTANCE_INITIALIZER;
1011
1012 // static
1013 BrowserContextKeyedAPIFactory<ManagementAPI>*
1014 ManagementAPI::GetFactoryInstance() {
1015 return g_factory.Pointer();
1016 }
1017
1018 void ManagementAPI::OnListenerAdded(const EventListenerInfo& details) {
1019 management_event_router_.reset(new ManagementEventRouter(browser_context_));
1020 EventRouter::Get(browser_context_)->UnregisterObserver(this);
1021 }
1022
1023 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698