OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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/chrome_management_api_delegat
e.h" |
| 6 |
| 7 #include "base/strings/utf_string_conversions.h" |
| 8 #include "chrome/browser/extensions/bookmark_app_helper.h" |
| 9 #include "chrome/browser/extensions/chrome_extension_function_details.h" |
| 10 #include "chrome/browser/extensions/extension_service.h" |
| 11 #include "chrome/browser/extensions/extension_util.h" |
| 12 #include "chrome/browser/extensions/launch_util.h" |
| 13 #include "chrome/browser/favicon/favicon_service.h" |
| 14 #include "chrome/browser/favicon/favicon_service_factory.h" |
| 15 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/browser/ui/browser_dialogs.h" |
| 17 #include "chrome/browser/ui/browser_finder.h" |
| 18 #include "chrome/browser/ui/browser_window.h" |
| 19 #include "chrome/browser/ui/extensions/app_launch_params.h" |
| 20 #include "chrome/browser/ui/extensions/application_launch.h" |
| 21 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" |
| 22 #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h" |
| 23 #include "chrome/common/extensions/chrome_utility_extensions_messages.h" |
| 24 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
| 25 #include "chrome/common/web_application_info.h" |
| 26 #include "content/public/browser/browser_context.h" |
| 27 #include "content/public/browser/utility_process_host.h" |
| 28 #include "content/public/browser/utility_process_host_client.h" |
| 29 #include "content/public/browser/web_contents.h" |
| 30 #include "extensions/browser/api/management/management_api.h" |
| 31 #include "extensions/browser/api/management/management_api_constants.h" |
| 32 #include "extensions/browser/extension_prefs.h" |
| 33 #include "extensions/browser/extension_registry.h" |
| 34 #include "extensions/browser/extension_system.h" |
| 35 #include "extensions/common/constants.h" |
| 36 #include "extensions/common/extension.h" |
| 37 |
| 38 namespace { |
| 39 |
| 40 // This class helps ManagementGetPermissionWarningsByManifestFunction manage |
| 41 // sending manifest JSON strings to the utility process for parsing. |
| 42 class SafeManifestJSONParser : public content::UtilityProcessHostClient { |
| 43 public: |
| 44 SafeManifestJSONParser( |
| 45 extensions::ManagementGetPermissionWarningsByManifestFunction* client, |
| 46 const std::string& manifest) |
| 47 : client_(client), manifest_(manifest) {} |
| 48 |
| 49 void Start() { |
| 50 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 51 content::BrowserThread::PostTask( |
| 52 content::BrowserThread::IO, FROM_HERE, |
| 53 base::Bind(&SafeManifestJSONParser::StartWorkOnIOThread, this)); |
| 54 } |
| 55 |
| 56 void StartWorkOnIOThread() { |
| 57 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 58 content::UtilityProcessHost* host = content::UtilityProcessHost::Create( |
| 59 this, base::MessageLoopProxy::current().get()); |
| 60 host->Send(new ChromeUtilityMsg_ParseJSON(manifest_)); |
| 61 } |
| 62 |
| 63 bool OnMessageReceived(const IPC::Message& message) override { |
| 64 bool handled = true; |
| 65 IPC_BEGIN_MESSAGE_MAP(SafeManifestJSONParser, message) |
| 66 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded, |
| 67 OnJSONParseSucceeded) |
| 68 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed, |
| 69 OnJSONParseFailed) |
| 70 IPC_MESSAGE_UNHANDLED(handled = false) |
| 71 IPC_END_MESSAGE_MAP() |
| 72 return handled; |
| 73 } |
| 74 |
| 75 void OnJSONParseSucceeded(const base::ListValue& wrapper) { |
| 76 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 77 const base::Value* value = NULL; |
| 78 CHECK(wrapper.Get(0, &value)); |
| 79 if (value->IsType(base::Value::TYPE_DICTIONARY)) |
| 80 parsed_manifest_.reset( |
| 81 static_cast<const base::DictionaryValue*>(value)->DeepCopy()); |
| 82 else |
| 83 error_ = extension_management_api_constants::kManifestParseError; |
| 84 |
| 85 content::BrowserThread::PostTask( |
| 86 content::BrowserThread::UI, FROM_HERE, |
| 87 base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this)); |
| 88 } |
| 89 |
| 90 void OnJSONParseFailed(const std::string& error) { |
| 91 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 92 error_ = error; |
| 93 content::BrowserThread::PostTask( |
| 94 content::BrowserThread::UI, FROM_HERE, |
| 95 base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this)); |
| 96 } |
| 97 |
| 98 void ReportResultFromUIThread() { |
| 99 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 100 if (error_.empty() && parsed_manifest_.get()) |
| 101 client_->OnParseSuccess(parsed_manifest_.Pass()); |
| 102 else |
| 103 client_->OnParseFailure(error_); |
| 104 } |
| 105 |
| 106 private: |
| 107 ~SafeManifestJSONParser() override {} |
| 108 |
| 109 // The client who we'll report results back to. |
| 110 extensions::ManagementGetPermissionWarningsByManifestFunction* client_; |
| 111 |
| 112 // Data to parse. |
| 113 std::string manifest_; |
| 114 |
| 115 // Results of parsing. |
| 116 scoped_ptr<base::DictionaryValue> parsed_manifest_; |
| 117 |
| 118 std::string error_; |
| 119 }; |
| 120 |
| 121 class ManagementSetEnabledFunctionInstallPromptDelegate |
| 122 : public ExtensionInstallPrompt::Delegate, |
| 123 public extensions::InstallPromptDelegate { |
| 124 public: |
| 125 ManagementSetEnabledFunctionInstallPromptDelegate( |
| 126 extensions::ManagementSetEnabledFunction* function, |
| 127 const extensions::Extension* extension) |
| 128 : function_(function), details_(function) { |
| 129 install_prompt_.reset( |
| 130 new ExtensionInstallPrompt(details_.GetAssociatedWebContents())); |
| 131 install_prompt_->ConfirmReEnable(this, extension); |
| 132 } |
| 133 virtual ~ManagementSetEnabledFunctionInstallPromptDelegate() {} |
| 134 |
| 135 protected: |
| 136 // ExtensionInstallPrompt::Delegate. |
| 137 void InstallUIProceed() override { function_->InstallUIProceed(); } |
| 138 void InstallUIAbort(bool user_initiated) override { |
| 139 function_->InstallUIAbort(user_initiated); |
| 140 } |
| 141 |
| 142 private: |
| 143 extensions::ManagementSetEnabledFunction* function_; |
| 144 ChromeExtensionFunctionDetails details_; |
| 145 |
| 146 // Used for prompting to re-enable items with permissions escalation updates. |
| 147 scoped_ptr<ExtensionInstallPrompt> install_prompt_; |
| 148 }; |
| 149 |
| 150 class ManagementUninstallFunctionUninstallDialogDelegate |
| 151 : public extensions::ExtensionUninstallDialog::Delegate, |
| 152 public extensions::UninstallDialogDelegate { |
| 153 public: |
| 154 ManagementUninstallFunctionUninstallDialogDelegate( |
| 155 extensions::ManagementUninstallFunctionBase* function, |
| 156 const std::string& target_extension_id) |
| 157 : function_(function) { |
| 158 const extensions::Extension* target_extension = |
| 159 extensions::ExtensionRegistry::Get(function->browser_context()) |
| 160 ->GetExtensionById(target_extension_id, |
| 161 extensions::ExtensionRegistry::EVERYTHING); |
| 162 content::WebContents* web_contents = function->GetAssociatedWebContents(); |
| 163 extension_uninstall_dialog_.reset( |
| 164 extensions::ExtensionUninstallDialog::Create( |
| 165 Profile::FromBrowserContext(function->browser_context()), |
| 166 web_contents ? web_contents->GetTopLevelNativeWindow() : NULL, |
| 167 this)); |
| 168 if (function->extension_id() != target_extension_id) { |
| 169 extension_uninstall_dialog_->ConfirmProgrammaticUninstall( |
| 170 target_extension, function->extension()); |
| 171 } else { |
| 172 // If this is a self uninstall, show the generic uninstall dialog. |
| 173 extension_uninstall_dialog_->ConfirmUninstall(target_extension); |
| 174 } |
| 175 } |
| 176 ~ManagementUninstallFunctionUninstallDialogDelegate() override {} |
| 177 |
| 178 // ExtensionUninstallDialog::Delegate implementation. |
| 179 void ExtensionUninstallAccepted() override { |
| 180 function_->ExtensionUninstallAccepted(); |
| 181 } |
| 182 void ExtensionUninstallCanceled() override { |
| 183 function_->ExtensionUninstallCanceled(); |
| 184 } |
| 185 |
| 186 protected: |
| 187 extensions::ManagementUninstallFunctionBase* function_; |
| 188 scoped_ptr<extensions::ExtensionUninstallDialog> extension_uninstall_dialog_; |
| 189 }; |
| 190 |
| 191 class ChromeAppForLinkDelegate : public extensions::AppForLinkDelegate { |
| 192 public: |
| 193 ChromeAppForLinkDelegate() {} |
| 194 ~ChromeAppForLinkDelegate() override {} |
| 195 |
| 196 void OnFaviconForApp( |
| 197 extensions::ManagementGenerateAppForLinkFunction* function, |
| 198 content::BrowserContext* context, |
| 199 const std::string& title, |
| 200 const GURL& launch_url, |
| 201 const favicon_base::FaviconImageResult& image_result) { |
| 202 WebApplicationInfo web_app; |
| 203 web_app.title = base::UTF8ToUTF16(std::string(title)); |
| 204 web_app.app_url = launch_url; |
| 205 |
| 206 if (!image_result.image.IsEmpty()) { |
| 207 WebApplicationInfo::IconInfo icon; |
| 208 icon.data = image_result.image.AsBitmap(); |
| 209 icon.width = icon.data.width(); |
| 210 icon.height = icon.data.height(); |
| 211 web_app.icons.push_back(icon); |
| 212 } |
| 213 |
| 214 bookmark_app_helper_.reset(new extensions::BookmarkAppHelper( |
| 215 extensions::ExtensionSystem::Get(context)->extension_service(), web_app, |
| 216 NULL)); |
| 217 bookmark_app_helper_->Create( |
| 218 base::Bind(&extensions::ManagementGenerateAppForLinkFunction:: |
| 219 FinishCreateBookmarkApp, |
| 220 function)); |
| 221 } |
| 222 |
| 223 scoped_ptr<extensions::BookmarkAppHelper> bookmark_app_helper_; |
| 224 |
| 225 // Used for favicon loading tasks. |
| 226 base::CancelableTaskTracker cancelable_task_tracker_; |
| 227 }; |
| 228 |
| 229 } // namespace |
| 230 |
| 231 ChromeManagementAPIDelegate::ChromeManagementAPIDelegate() { |
| 232 } |
| 233 |
| 234 ChromeManagementAPIDelegate::~ChromeManagementAPIDelegate() { |
| 235 } |
| 236 |
| 237 bool ChromeManagementAPIDelegate::LaunchAppFunctionDelegate( |
| 238 const extensions::Extension* extension, |
| 239 content::BrowserContext* context) const { |
| 240 // Look at prefs to find the right launch container. |
| 241 // If the user has not set a preference, the default launch value will be |
| 242 // returned. |
| 243 extensions::LaunchContainer launch_container = |
| 244 GetLaunchContainer(extensions::ExtensionPrefs::Get(context), extension); |
| 245 OpenApplication(AppLaunchParams(Profile::FromBrowserContext(context), |
| 246 extension, launch_container, |
| 247 NEW_FOREGROUND_TAB)); |
| 248 CoreAppLauncherHandler::RecordAppLaunchType( |
| 249 extension_misc::APP_LAUNCH_EXTENSION_API, extension->GetType()); |
| 250 |
| 251 return true; |
| 252 } |
| 253 |
| 254 GURL ChromeManagementAPIDelegate::GetFullLaunchURL( |
| 255 const extensions::Extension* extension) const { |
| 256 return extensions::AppLaunchInfo::GetFullLaunchURL(extension); |
| 257 } |
| 258 |
| 259 extensions::LaunchType ChromeManagementAPIDelegate::GetLaunchType( |
| 260 const extensions::ExtensionPrefs* prefs, |
| 261 const extensions::Extension* extension) const { |
| 262 return extensions::GetLaunchType(prefs, extension); |
| 263 } |
| 264 |
| 265 void ChromeManagementAPIDelegate:: |
| 266 GetPermissionWarningsByManifestFunctionDelegate( |
| 267 extensions::ManagementGetPermissionWarningsByManifestFunction* function, |
| 268 const std::string& manifest_str) const { |
| 269 scoped_refptr<SafeManifestJSONParser> parser = |
| 270 new SafeManifestJSONParser(function, manifest_str); |
| 271 parser->Start(); |
| 272 } |
| 273 |
| 274 scoped_ptr<extensions::InstallPromptDelegate> |
| 275 ChromeManagementAPIDelegate::SetEnabledFunctionDelegate( |
| 276 extensions::ManagementSetEnabledFunction* function, |
| 277 const extensions::Extension* extension) const { |
| 278 return scoped_ptr<ManagementSetEnabledFunctionInstallPromptDelegate>( |
| 279 new ManagementSetEnabledFunctionInstallPromptDelegate(function, |
| 280 extension)); |
| 281 } |
| 282 |
| 283 scoped_ptr<extensions::UninstallDialogDelegate> |
| 284 ChromeManagementAPIDelegate::UninstallFunctionDelegate( |
| 285 extensions::ManagementUninstallFunctionBase* function, |
| 286 const std::string& target_extension_id) const { |
| 287 return scoped_ptr<extensions::UninstallDialogDelegate>( |
| 288 new ManagementUninstallFunctionUninstallDialogDelegate( |
| 289 function, target_extension_id)); |
| 290 } |
| 291 |
| 292 bool ChromeManagementAPIDelegate::CreateAppShortcutFunctionDelegate( |
| 293 extensions::ManagementCreateAppShortcutFunction* function, |
| 294 const extensions::Extension* extension) const { |
| 295 Browser* browser = chrome::FindBrowserWithProfile( |
| 296 Profile::FromBrowserContext(function->browser_context()), |
| 297 chrome::HOST_DESKTOP_TYPE_NATIVE); |
| 298 if (!browser) { |
| 299 // Shouldn't happen if we have user gesture. |
| 300 function->SetError( |
| 301 extension_management_api_constants::kNoBrowserToCreateShortcut); |
| 302 return false; |
| 303 } |
| 304 |
| 305 chrome::ShowCreateChromeAppShortcutsDialog( |
| 306 browser->window()->GetNativeWindow(), browser->profile(), extension, |
| 307 base::Bind(&extensions::ManagementCreateAppShortcutFunction:: |
| 308 OnCloseShortcutPrompt, |
| 309 function)); |
| 310 |
| 311 return true; |
| 312 } |
| 313 |
| 314 scoped_ptr<extensions::AppForLinkDelegate> |
| 315 ChromeManagementAPIDelegate::GenerateAppForLinkFunctionDelegate( |
| 316 extensions::ManagementGenerateAppForLinkFunction* function, |
| 317 content::BrowserContext* context, |
| 318 const std::string& title, |
| 319 const GURL& launch_url) const { |
| 320 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( |
| 321 Profile::FromBrowserContext(context), Profile::EXPLICIT_ACCESS); |
| 322 DCHECK(favicon_service); |
| 323 |
| 324 ChromeAppForLinkDelegate* delegate = new ChromeAppForLinkDelegate; |
| 325 |
| 326 favicon_service->GetFaviconImageForPageURL( |
| 327 launch_url, |
| 328 base::Bind( |
| 329 &ChromeAppForLinkDelegate::OnFaviconForApp, |
| 330 base::Unretained(delegate), |
| 331 scoped_refptr<extensions::ManagementGenerateAppForLinkFunction>( |
| 332 function), |
| 333 context, title, launch_url), |
| 334 &delegate->cancelable_task_tracker_); |
| 335 |
| 336 return scoped_ptr<extensions::AppForLinkDelegate>(delegate); |
| 337 } |
| 338 |
| 339 bool ChromeManagementAPIDelegate::IsStreamlinedHostedAppsEnabled() const { |
| 340 return extensions::util::IsStreamlinedHostedAppsEnabled(); |
| 341 } |
| 342 |
| 343 void ChromeManagementAPIDelegate::EnableExtension( |
| 344 content::BrowserContext* context, |
| 345 const std::string& extension_id) const { |
| 346 extensions::ExtensionSystem::Get(context) |
| 347 ->extension_service() |
| 348 ->EnableExtension(extension_id); |
| 349 } |
| 350 |
| 351 void ChromeManagementAPIDelegate::DisableExtension( |
| 352 content::BrowserContext* context, |
| 353 const std::string& extension_id, |
| 354 extensions::Extension::DisableReason disable_reason) const { |
| 355 extensions::ExtensionSystem::Get(context) |
| 356 ->extension_service() |
| 357 ->DisableExtension(extension_id, disable_reason); |
| 358 } |
| 359 |
| 360 bool ChromeManagementAPIDelegate::UninstallExtension( |
| 361 content::BrowserContext* context, |
| 362 const std::string& transient_extension_id, |
| 363 extensions::UninstallReason reason, |
| 364 const base::Closure& deletion_done_callback, |
| 365 base::string16* error) const { |
| 366 return extensions::ExtensionSystem::Get(context) |
| 367 ->extension_service() |
| 368 ->UninstallExtension(transient_extension_id, reason, |
| 369 deletion_done_callback, error); |
| 370 } |
| 371 |
| 372 void ChromeManagementAPIDelegate::SetLaunchType( |
| 373 content::BrowserContext* context, |
| 374 const std::string& extension_id, |
| 375 extensions::LaunchType launch_type) const { |
| 376 extensions::SetLaunchType( |
| 377 extensions::ExtensionSystem::Get(context)->extension_service(), |
| 378 extension_id, launch_type); |
| 379 } |
| 380 |
| 381 GURL ChromeManagementAPIDelegate::GetIconURL( |
| 382 const extensions::Extension* extension, |
| 383 int icon_size, |
| 384 ExtensionIconSet::MatchType match, |
| 385 bool grayscale, |
| 386 bool* exists) const { |
| 387 return extensions::ExtensionIconSource::GetIconURL(extension, icon_size, |
| 388 match, grayscale, exists); |
| 389 } |
OLD | NEW |