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