| 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..c5e574061daf9570fdde76ed1a71595de6610714
|
| --- /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);
|
| +}
|
|
|