summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/api/management/chrome_management_api_delegate.cc')
-rw-r--r--chrome/browser/extensions/api/management/chrome_management_api_delegate.cc389
1 files changed, 389 insertions, 0 deletions
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 0000000..c5e5740
--- /dev/null
+++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
@@ -0,0 +1,389 @@
+// 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
+
+ChromeManagementAPIDelegate::ChromeManagementAPIDelegate() {
+}
+
+ChromeManagementAPIDelegate::~ChromeManagementAPIDelegate() {
+}
+
+bool ChromeManagementAPIDelegate::LaunchAppFunctionDelegate(
+ const extensions::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.
+ extensions::LaunchContainer launch_container =
+ GetLaunchContainer(extensions::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 extensions::Extension* extension) const {
+ return extensions::AppLaunchInfo::GetFullLaunchURL(extension);
+}
+
+extensions::LaunchType ChromeManagementAPIDelegate::GetLaunchType(
+ const extensions::ExtensionPrefs* prefs,
+ const extensions::Extension* extension) const {
+ return extensions::GetLaunchType(prefs, extension);
+}
+
+void ChromeManagementAPIDelegate::
+ GetPermissionWarningsByManifestFunctionDelegate(
+ extensions::ManagementGetPermissionWarningsByManifestFunction* function,
+ const std::string& manifest_str) const {
+ scoped_refptr<SafeManifestJSONParser> parser =
+ new SafeManifestJSONParser(function, manifest_str);
+ parser->Start();
+}
+
+scoped_ptr<extensions::InstallPromptDelegate>
+ChromeManagementAPIDelegate::SetEnabledFunctionDelegate(
+ extensions::ManagementSetEnabledFunction* function,
+ const extensions::Extension* extension) const {
+ return scoped_ptr<ManagementSetEnabledFunctionInstallPromptDelegate>(
+ new ManagementSetEnabledFunctionInstallPromptDelegate(function,
+ extension));
+}
+
+scoped_ptr<extensions::UninstallDialogDelegate>
+ChromeManagementAPIDelegate::UninstallFunctionDelegate(
+ extensions::ManagementUninstallFunctionBase* function,
+ const std::string& target_extension_id) const {
+ return scoped_ptr<extensions::UninstallDialogDelegate>(
+ new ManagementUninstallFunctionUninstallDialogDelegate(
+ function, target_extension_id));
+}
+
+bool ChromeManagementAPIDelegate::CreateAppShortcutFunctionDelegate(
+ extensions::ManagementCreateAppShortcutFunction* function,
+ const extensions::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(&extensions::ManagementCreateAppShortcutFunction::
+ OnCloseShortcutPrompt,
+ function));
+
+ return true;
+}
+
+scoped_ptr<extensions::AppForLinkDelegate>
+ChromeManagementAPIDelegate::GenerateAppForLinkFunctionDelegate(
+ extensions::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<extensions::ManagementGenerateAppForLinkFunction>(
+ function),
+ context, title, launch_url),
+ &delegate->cancelable_task_tracker_);
+
+ return scoped_ptr<extensions::AppForLinkDelegate>(delegate);
+}
+
+bool ChromeManagementAPIDelegate::IsStreamlinedHostedAppsEnabled() const {
+ return extensions::util::IsStreamlinedHostedAppsEnabled();
+}
+
+void ChromeManagementAPIDelegate::EnableExtension(
+ content::BrowserContext* context,
+ const std::string& extension_id) const {
+ extensions::ExtensionSystem::Get(context)
+ ->extension_service()
+ ->EnableExtension(extension_id);
+}
+
+void ChromeManagementAPIDelegate::DisableExtension(
+ content::BrowserContext* context,
+ const std::string& extension_id,
+ extensions::Extension::DisableReason disable_reason) const {
+ extensions::ExtensionSystem::Get(context)
+ ->extension_service()
+ ->DisableExtension(extension_id, disable_reason);
+}
+
+bool ChromeManagementAPIDelegate::UninstallExtension(
+ content::BrowserContext* context,
+ const std::string& transient_extension_id,
+ extensions::UninstallReason reason,
+ const base::Closure& deletion_done_callback,
+ base::string16* error) const {
+ return extensions::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,
+ extensions::LaunchType launch_type) const {
+ extensions::SetLaunchType(
+ extensions::ExtensionSystem::Get(context)->extension_service(),
+ extension_id, launch_type);
+}
+
+GURL ChromeManagementAPIDelegate::GetIconURL(
+ const extensions::Extension* extension,
+ int icon_size,
+ ExtensionIconSet::MatchType match,
+ bool grayscale,
+ bool* exists) const {
+ return extensions::ExtensionIconSource::GetIconURL(extension, icon_size,
+ match, grayscale, exists);
+}