Index: chrome/browser/extensions/api/management/chrome_management_api_delegate.cc |
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..51abd3141a1a51ad95542de12b37e83b1ebef5fb |
--- /dev/null |
+++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc |
@@ -0,0 +1,395 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/extensions/api/management/chrome_management_api_delegate.h" |
+ |
+#include "base/strings/utf_string_conversions.h" |
+#include "chrome/browser/extensions/bookmark_app_helper.h" |
+#include "chrome/browser/extensions/chrome_extension_function_details.h" |
+#include "chrome/browser/extensions/extension_service.h" |
+#include "chrome/browser/extensions/extension_util.h" |
+#include "chrome/browser/extensions/launch_util.h" |
+#include "chrome/browser/favicon/favicon_service.h" |
+#include "chrome/browser/favicon/favicon_service_factory.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/ui/browser_dialogs.h" |
+#include "chrome/browser/ui/browser_finder.h" |
+#include "chrome/browser/ui/browser_window.h" |
+#include "chrome/browser/ui/extensions/app_launch_params.h" |
+#include "chrome/browser/ui/extensions/application_launch.h" |
+#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" |
+#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h" |
+#include "chrome/common/extensions/chrome_utility_extensions_messages.h" |
+#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
+#include "chrome/common/web_application_info.h" |
+#include "content/public/browser/browser_context.h" |
+#include "content/public/browser/utility_process_host.h" |
+#include "content/public/browser/utility_process_host_client.h" |
+#include "content/public/browser/web_contents.h" |
+#include "extensions/browser/api/management/management_api.h" |
+#include "extensions/browser/api/management/management_api_constants.h" |
+#include "extensions/browser/extension_prefs.h" |
+#include "extensions/browser/extension_registry.h" |
+#include "extensions/browser/extension_system.h" |
+#include "extensions/common/constants.h" |
+#include "extensions/common/extension.h" |
+ |
+namespace { |
+ |
+// This class helps ManagementGetPermissionWarningsByManifestFunction manage |
+// sending manifest JSON strings to the utility process for parsing. |
+class SafeManifestJSONParser : public content::UtilityProcessHostClient { |
+ public: |
+ SafeManifestJSONParser( |
+ extensions::ManagementGetPermissionWarningsByManifestFunction* client, |
+ const std::string& manifest) |
+ : client_(client), manifest_(manifest) {} |
+ |
+ void Start() { |
+ CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::IO, |
+ FROM_HERE, |
+ base::Bind(&SafeManifestJSONParser::StartWorkOnIOThread, this)); |
+ } |
+ |
+ void StartWorkOnIOThread() { |
+ CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
+ content::UtilityProcessHost* host = content::UtilityProcessHost::Create( |
+ this, base::MessageLoopProxy::current().get()); |
+ host->Send(new ChromeUtilityMsg_ParseJSON(manifest_)); |
+ } |
+ |
+ bool OnMessageReceived(const IPC::Message& message) override { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(SafeManifestJSONParser, message) |
+ IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded, |
+ OnJSONParseSucceeded) |
+ IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed, |
+ OnJSONParseFailed) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ return handled; |
+ } |
+ |
+ void OnJSONParseSucceeded(const base::ListValue& wrapper) { |
+ CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
+ const base::Value* value = NULL; |
+ CHECK(wrapper.Get(0, &value)); |
+ if (value->IsType(base::Value::TYPE_DICTIONARY)) |
+ parsed_manifest_.reset( |
+ static_cast<const base::DictionaryValue*>(value)->DeepCopy()); |
+ else |
+ error_ = extension_management_api_constants::kManifestParseError; |
+ |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this)); |
+ } |
+ |
+ void OnJSONParseFailed(const std::string& error) { |
+ CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
+ error_ = error; |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this)); |
+ } |
+ |
+ void ReportResultFromUIThread() { |
+ CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
+ if (error_.empty() && parsed_manifest_.get()) |
+ client_->OnParseSuccess(parsed_manifest_.Pass()); |
+ else |
+ client_->OnParseFailure(error_); |
+ } |
+ |
+ private: |
+ ~SafeManifestJSONParser() override {} |
+ |
+ // The client who we'll report results back to. |
+ extensions::ManagementGetPermissionWarningsByManifestFunction* client_; |
+ |
+ // Data to parse. |
+ std::string manifest_; |
+ |
+ // Results of parsing. |
+ scoped_ptr<base::DictionaryValue> parsed_manifest_; |
+ |
+ std::string error_; |
+}; |
+ |
+class ManagementSetEnabledFunctionInstallPromptDelegate |
+ : public ExtensionInstallPrompt::Delegate, |
+ public extensions::InstallPromptDelegate { |
+ public: |
+ ManagementSetEnabledFunctionInstallPromptDelegate( |
+ extensions::ManagementSetEnabledFunction* function, |
+ const extensions::Extension* extension) |
+ : function_(function), details_(function) { |
+ install_prompt_.reset( |
+ new ExtensionInstallPrompt(details_.GetAssociatedWebContents())); |
+ install_prompt_->ConfirmReEnable(this, extension); |
+ } |
+ virtual ~ManagementSetEnabledFunctionInstallPromptDelegate() {} |
+ |
+ protected: |
+ // ExtensionInstallPrompt::Delegate. |
+ void InstallUIProceed() override { function_->InstallUIProceed(); } |
+ void InstallUIAbort(bool user_initiated) override { |
+ function_->InstallUIAbort(user_initiated); |
+ } |
+ |
+ private: |
+ extensions::ManagementSetEnabledFunction* function_; |
+ ChromeExtensionFunctionDetails details_; |
+ |
+ // Used for prompting to re-enable items with permissions escalation updates. |
+ scoped_ptr<ExtensionInstallPrompt> install_prompt_; |
+}; |
+ |
+class ManagementUninstallFunctionUninstallDialogDelegate |
+ : public extensions::ExtensionUninstallDialog::Delegate, |
+ public extensions::UninstallDialogDelegate { |
+ public: |
+ ManagementUninstallFunctionUninstallDialogDelegate( |
+ extensions::ManagementUninstallFunctionBase* function, |
+ const std::string& target_extension_id) |
+ : function_(function) { |
+ const extensions::Extension* target_extension = |
+ extensions::ExtensionRegistry::Get(function->browser_context()) |
+ ->GetExtensionById(target_extension_id, |
+ extensions::ExtensionRegistry::EVERYTHING); |
+ content::WebContents* web_contents = function->GetAssociatedWebContents(); |
+ extension_uninstall_dialog_.reset( |
+ extensions::ExtensionUninstallDialog::Create( |
+ Profile::FromBrowserContext(function->browser_context()), |
+ web_contents ? web_contents->GetTopLevelNativeWindow() : NULL, |
+ this)); |
+ if (function->extension_id() != target_extension_id) { |
+ extension_uninstall_dialog_->ConfirmProgrammaticUninstall( |
+ target_extension, function->extension()); |
+ } else { |
+ // If this is a self uninstall, show the generic uninstall dialog. |
+ extension_uninstall_dialog_->ConfirmUninstall(target_extension); |
+ } |
+ } |
+ ~ManagementUninstallFunctionUninstallDialogDelegate() override {} |
+ |
+ // ExtensionUninstallDialog::Delegate implementation. |
+ void ExtensionUninstallAccepted() override { |
+ function_->ExtensionUninstallAccepted(); |
+ } |
+ void ExtensionUninstallCanceled() override { |
+ function_->ExtensionUninstallCanceled(); |
+ } |
+ |
+ protected: |
+ extensions::ManagementUninstallFunctionBase* function_; |
+ scoped_ptr<extensions::ExtensionUninstallDialog> extension_uninstall_dialog_; |
+}; |
+ |
+class ChromeAppForLinkDelegate : public extensions::AppForLinkDelegate { |
+ public: |
+ ChromeAppForLinkDelegate() {} |
+ ~ChromeAppForLinkDelegate() override {} |
+ |
+ void OnFaviconForApp( |
+ extensions::ManagementGenerateAppForLinkFunction* function, |
+ content::BrowserContext* context, |
+ const std::string& title, |
+ const GURL& launch_url, |
+ const favicon_base::FaviconImageResult& image_result) { |
+ WebApplicationInfo web_app; |
+ web_app.title = base::UTF8ToUTF16(std::string(title)); |
+ web_app.app_url = launch_url; |
+ |
+ if (!image_result.image.IsEmpty()) { |
+ WebApplicationInfo::IconInfo icon; |
+ icon.data = image_result.image.AsBitmap(); |
+ icon.width = icon.data.width(); |
+ icon.height = icon.data.height(); |
+ web_app.icons.push_back(icon); |
+ } |
+ |
+ bookmark_app_helper_.reset(new extensions::BookmarkAppHelper( |
+ extensions::ExtensionSystem::Get(context)->extension_service(), |
+ web_app, |
+ NULL)); |
+ bookmark_app_helper_->Create( |
+ base::Bind(&extensions::ManagementGenerateAppForLinkFunction:: |
+ FinishCreateBookmarkApp, |
+ function)); |
+ } |
+ |
+ scoped_ptr<extensions::BookmarkAppHelper> bookmark_app_helper_; |
+ |
+ // Used for favicon loading tasks. |
+ base::CancelableTaskTracker cancelable_task_tracker_; |
+}; |
+ |
+} // namespace |
+ |
+namespace extensions { |
+ |
+ChromeManagementAPIDelegate::ChromeManagementAPIDelegate() { |
+} |
+ |
+ChromeManagementAPIDelegate::~ChromeManagementAPIDelegate() { |
+} |
+ |
+bool ChromeManagementAPIDelegate::LaunchAppFunctionDelegate( |
+ const Extension* extension, |
+ content::BrowserContext* context) const { |
+ // Look at prefs to find the right launch container. |
+ // If the user has not set a preference, the default launch value will be |
+ // returned. |
+ LaunchContainer launch_container = |
+ GetLaunchContainer(ExtensionPrefs::Get(context), extension); |
+ OpenApplication(AppLaunchParams(Profile::FromBrowserContext(context), |
+ extension, |
+ launch_container, |
+ NEW_FOREGROUND_TAB)); |
+ CoreAppLauncherHandler::RecordAppLaunchType( |
+ extension_misc::APP_LAUNCH_EXTENSION_API, extension->GetType()); |
+ |
+ return true; |
+} |
+ |
+GURL ChromeManagementAPIDelegate::GetFullLaunchURL( |
+ const Extension* extension) const { |
+ return AppLaunchInfo::GetFullLaunchURL(extension); |
+} |
+ |
+LaunchType ChromeManagementAPIDelegate::GetLaunchType( |
+ const ExtensionPrefs* prefs, |
+ const Extension* extension) const { |
+ return extensions::GetLaunchType(prefs, extension); |
+} |
+ |
+void |
+ChromeManagementAPIDelegate::GetPermissionWarningsByManifestFunctionDelegate( |
+ ManagementGetPermissionWarningsByManifestFunction* function, |
+ const std::string& manifest_str) const { |
+ scoped_refptr<SafeManifestJSONParser> parser = |
+ new SafeManifestJSONParser(function, manifest_str); |
+ parser->Start(); |
+} |
+ |
+scoped_ptr<InstallPromptDelegate> |
+ChromeManagementAPIDelegate::SetEnabledFunctionDelegate( |
+ ManagementSetEnabledFunction* function, |
+ const Extension* extension) const { |
+ return scoped_ptr<ManagementSetEnabledFunctionInstallPromptDelegate>( |
+ new ManagementSetEnabledFunctionInstallPromptDelegate(function, |
+ extension)); |
+} |
+ |
+scoped_ptr<UninstallDialogDelegate> |
+ChromeManagementAPIDelegate::UninstallFunctionDelegate( |
+ ManagementUninstallFunctionBase* function, |
+ const std::string& target_extension_id) const { |
+ return scoped_ptr<UninstallDialogDelegate>( |
+ new ManagementUninstallFunctionUninstallDialogDelegate( |
+ function, target_extension_id)); |
+} |
+ |
+bool ChromeManagementAPIDelegate::CreateAppShortcutFunctionDelegate( |
+ ManagementCreateAppShortcutFunction* function, |
+ const Extension* extension) const { |
+ Browser* browser = chrome::FindBrowserWithProfile( |
+ Profile::FromBrowserContext(function->browser_context()), |
+ chrome::HOST_DESKTOP_TYPE_NATIVE); |
+ if (!browser) { |
+ // Shouldn't happen if we have user gesture. |
+ function->SetError( |
+ extension_management_api_constants::kNoBrowserToCreateShortcut); |
+ return false; |
+ } |
+ |
+ chrome::ShowCreateChromeAppShortcutsDialog( |
+ browser->window()->GetNativeWindow(), |
+ browser->profile(), |
+ extension, |
+ base::Bind(&ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt, |
+ function)); |
+ |
+ return true; |
+} |
+ |
+scoped_ptr<AppForLinkDelegate> |
+ChromeManagementAPIDelegate::GenerateAppForLinkFunctionDelegate( |
+ ManagementGenerateAppForLinkFunction* function, |
+ content::BrowserContext* context, |
+ const std::string& title, |
+ const GURL& launch_url) const { |
+ FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( |
+ Profile::FromBrowserContext(context), Profile::EXPLICIT_ACCESS); |
+ DCHECK(favicon_service); |
+ |
+ ChromeAppForLinkDelegate* delegate = new ChromeAppForLinkDelegate; |
+ |
+ favicon_service->GetFaviconImageForPageURL( |
+ launch_url, |
+ base::Bind(&ChromeAppForLinkDelegate::OnFaviconForApp, |
+ base::Unretained(delegate), |
+ scoped_refptr<ManagementGenerateAppForLinkFunction>(function), |
+ context, |
+ title, |
+ launch_url), |
+ &delegate->cancelable_task_tracker_); |
+ |
+ return scoped_ptr<AppForLinkDelegate>(delegate); |
+} |
+ |
+bool ChromeManagementAPIDelegate::IsStreamlinedHostedAppsEnabled() const { |
+ return util::IsStreamlinedHostedAppsEnabled(); |
+} |
+ |
+void ChromeManagementAPIDelegate::EnableExtension( |
+ content::BrowserContext* context, |
+ const std::string& extension_id) const { |
+ ExtensionSystem::Get(context)->extension_service()->EnableExtension( |
+ extension_id); |
+} |
+ |
+void ChromeManagementAPIDelegate::DisableExtension( |
+ content::BrowserContext* context, |
+ const std::string& extension_id, |
+ Extension::DisableReason disable_reason) const { |
+ ExtensionSystem::Get(context)->extension_service()->DisableExtension( |
+ extension_id, disable_reason); |
+} |
+ |
+bool ChromeManagementAPIDelegate::UninstallExtension( |
+ content::BrowserContext* context, |
+ const std::string& transient_extension_id, |
+ UninstallReason reason, |
+ const base::Closure& deletion_done_callback, |
+ base::string16* error) const { |
+ return ExtensionSystem::Get(context)->extension_service()->UninstallExtension( |
+ transient_extension_id, reason, deletion_done_callback, error); |
+} |
+ |
+void ChromeManagementAPIDelegate::SetLaunchType( |
+ content::BrowserContext* context, |
+ const std::string& extension_id, |
+ LaunchType launch_type) const { |
+ extensions::SetLaunchType( |
+ extensions::ExtensionSystem::Get(context)->extension_service(), |
+ extension_id, |
+ launch_type); |
+} |
+ |
+GURL ChromeManagementAPIDelegate::GetIconURL(const Extension* extension, |
+ int icon_size, |
+ ExtensionIconSet::MatchType match, |
+ bool grayscale, |
+ bool* exists) const { |
+ return ExtensionIconSource::GetIconURL( |
+ extension, icon_size, match, grayscale, exists); |
+} |
+ |
+} // namespace extensions |