| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/apps/ephemeral_app_launcher.h" | 5 #include "chrome/browser/apps/ephemeral_app_launcher.h" |
| 6 | 6 |
| 7 #include "chrome/browser/extensions/extension_install_prompt.h" | 7 #include "chrome/browser/extensions/extension_install_prompt.h" |
| 8 #include "chrome/browser/extensions/extension_service.h" | |
| 9 #include "chrome/browser/extensions/extension_util.h" | 8 #include "chrome/browser/extensions/extension_util.h" |
| 10 #include "chrome/browser/profiles/profile.h" | 9 #include "chrome/browser/profiles/profile.h" |
| 11 #include "chrome/browser/ui/extensions/application_launch.h" | 10 #include "chrome/browser/ui/extensions/application_launch.h" |
| 12 #include "chrome/browser/ui/extensions/extension_enable_flow.h" | 11 #include "chrome/browser/ui/extensions/extension_enable_flow.h" |
| 13 #include "content/public/browser/web_contents.h" | 12 #include "content/public/browser/web_contents.h" |
| 14 #include "extensions/browser/extension_registry.h" | 13 #include "extensions/browser/extension_registry.h" |
| 15 #include "extensions/browser/extension_system.h" | |
| 16 #include "extensions/common/permissions/permissions_data.h" | 14 #include "extensions/common/permissions/permissions_data.h" |
| 17 | 15 |
| 18 using content::WebContents; | 16 using content::WebContents; |
| 19 using extensions::Extension; | 17 using extensions::Extension; |
| 20 using extensions::ExtensionSystem; | 18 using extensions::ExtensionRegistry; |
| 21 using extensions::WebstoreInstaller; | 19 using extensions::WebstoreInstaller; |
| 22 | 20 |
| 23 namespace { | 21 namespace { |
| 24 | 22 |
| 25 const char kInvalidManifestError[] = "Invalid manifest"; | 23 const char kInvalidManifestError[] = "Invalid manifest"; |
| 26 const char kExtensionTypeError[] = "Ephemeral extensions are not permitted"; | 24 const char kExtensionTypeError[] = "Ephemeral extensions are not permitted"; |
| 27 const char kLaunchAbortedError[] = "Launch aborted"; | 25 const char kLaunchAbortedError[] = "Launch aborted"; |
| 28 | 26 |
| 29 Profile* ProfileForWebContents(content::WebContents* contents) { | 27 Profile* ProfileForWebContents(content::WebContents* contents) { |
| 30 if (!contents) | 28 if (!contents) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 content::WebContents* web_contents) { | 63 content::WebContents* web_contents) { |
| 66 scoped_refptr<EphemeralAppLauncher> installer = | 64 scoped_refptr<EphemeralAppLauncher> installer = |
| 67 new EphemeralAppLauncher(webstore_item_id, | 65 new EphemeralAppLauncher(webstore_item_id, |
| 68 web_contents, | 66 web_contents, |
| 69 Callback()); | 67 Callback()); |
| 70 installer->set_install_source(WebstoreInstaller::INSTALL_SOURCE_OTHER); | 68 installer->set_install_source(WebstoreInstaller::INSTALL_SOURCE_OTHER); |
| 71 return installer; | 69 return installer; |
| 72 } | 70 } |
| 73 | 71 |
| 74 void EphemeralAppLauncher::Start() { | 72 void EphemeralAppLauncher::Start() { |
| 75 ExtensionService* extension_service = | 73 const Extension* extension = |
| 76 extensions::ExtensionSystem::Get(profile())->extension_service(); | 74 ExtensionRegistry::Get(profile()) |
| 77 DCHECK(extension_service); | 75 ->GetExtensionById(id(), ExtensionRegistry::EVERYTHING); |
| 78 | |
| 79 const Extension* extension = extension_service->GetInstalledExtension(id()); | |
| 80 if (extension) { | 76 if (extension) { |
| 81 if (extensions::util::IsAppLaunchableWithoutEnabling(extension->id(), | 77 if (extensions::util::IsAppLaunchableWithoutEnabling(extension->id(), |
| 82 profile())) { | 78 profile())) { |
| 83 LaunchApp(extension); | 79 LaunchApp(extension); |
| 84 InvokeCallback(std::string()); | 80 InvokeCallback(std::string()); |
| 85 return; | 81 return; |
| 86 } | 82 } |
| 87 | 83 |
| 88 // The ephemeral app may have been updated and disabled as it requests | 84 // The ephemeral app may have been updated and disabled as it requests |
| 89 // more permissions. In this case we should always prompt before | 85 // more permissions. In this case we should always prompt before |
| 90 // launching. | 86 // launching. |
| 91 extension_enable_flow_.reset( | 87 extension_enable_flow_.reset( |
| 92 new ExtensionEnableFlow(profile(), extension->id(), this)); | 88 new ExtensionEnableFlow(profile(), extension->id(), this)); |
| 93 if (web_contents()) | 89 if (web_contents()) |
| 94 extension_enable_flow_->StartForWebContents(web_contents()); | 90 extension_enable_flow_->StartForWebContents(web_contents()); |
| 95 else | 91 else |
| 96 extension_enable_flow_->StartForNativeWindow(parent_window_); | 92 extension_enable_flow_->StartForNativeWindow(parent_window_); |
| 97 | 93 |
| 98 // Keep this object alive until the enable flow is complete. | 94 // Keep this object alive until the enable flow is complete. |
| 99 AddRef(); // Balanced in WebstoreStandaloneInstaller::CompleteInstall. | 95 AddRef(); // Balanced in WebstoreStandaloneInstaller::CompleteInstall. |
| 100 return; | 96 return; |
| 101 } | 97 } |
| 102 | 98 |
| 103 // Fetch the app from the webstore. | 99 // Fetch the app from the webstore. |
| 104 StartObserving(); | |
| 105 BeginInstall(); | 100 BeginInstall(); |
| 106 } | 101 } |
| 107 | 102 |
| 108 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id, | 103 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id, |
| 109 Profile* profile, | 104 Profile* profile, |
| 110 gfx::NativeWindow parent_window, | 105 gfx::NativeWindow parent_window, |
| 111 const Callback& callback) | 106 const Callback& callback) |
| 112 : WebstoreStandaloneInstaller(webstore_item_id, profile, callback), | 107 : WebstoreStandaloneInstaller(webstore_item_id, profile, callback), |
| 113 extension_registry_observer_(this), | |
| 114 parent_window_(parent_window), | 108 parent_window_(parent_window), |
| 115 dummy_web_contents_( | 109 dummy_web_contents_( |
| 116 WebContents::Create(WebContents::CreateParams(profile))) { | 110 WebContents::Create(WebContents::CreateParams(profile))) { |
| 117 } | 111 } |
| 118 | 112 |
| 119 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id, | 113 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id, |
| 120 content::WebContents* web_contents, | 114 content::WebContents* web_contents, |
| 121 const Callback& callback) | 115 const Callback& callback) |
| 122 : WebstoreStandaloneInstaller(webstore_item_id, | 116 : WebstoreStandaloneInstaller(webstore_item_id, |
| 123 ProfileForWebContents(web_contents), | 117 ProfileForWebContents(web_contents), |
| 124 callback), | 118 callback), |
| 125 content::WebContentsObserver(web_contents), | 119 content::WebContentsObserver(web_contents), |
| 126 extension_registry_observer_(this), | |
| 127 parent_window_(NativeWindowForWebContents(web_contents)) { | 120 parent_window_(NativeWindowForWebContents(web_contents)) { |
| 128 } | 121 } |
| 129 | 122 |
| 130 EphemeralAppLauncher::~EphemeralAppLauncher() {} | 123 EphemeralAppLauncher::~EphemeralAppLauncher() {} |
| 131 | 124 |
| 132 void EphemeralAppLauncher::StartObserving() { | |
| 133 extension_registry_observer_.Add( | |
| 134 extensions::ExtensionRegistry::Get(profile())); | |
| 135 } | |
| 136 | |
| 137 void EphemeralAppLauncher::LaunchApp(const Extension* extension) const { | 125 void EphemeralAppLauncher::LaunchApp(const Extension* extension) const { |
| 138 DCHECK(extension); | 126 DCHECK(extension); |
| 139 if (!extension->is_app()) { | 127 if (!extension->is_app()) { |
| 140 LOG(ERROR) << "Unable to launch extension " << extension->id() | 128 LOG(ERROR) << "Unable to launch extension " << extension->id() |
| 141 << ". It is not an app."; | 129 << ". It is not an app."; |
| 142 return; | 130 return; |
| 143 } | 131 } |
| 144 | 132 |
| 145 AppLaunchParams params(profile(), extension, NEW_FOREGROUND_TAB); | 133 AppLaunchParams params(profile(), extension, NEW_FOREGROUND_TAB); |
| 146 params.desktop_type = | 134 params.desktop_type = |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 | 219 |
| 232 scoped_ptr<WebstoreInstaller::Approval> | 220 scoped_ptr<WebstoreInstaller::Approval> |
| 233 EphemeralAppLauncher::CreateApproval() const { | 221 EphemeralAppLauncher::CreateApproval() const { |
| 234 scoped_ptr<WebstoreInstaller::Approval> approval = | 222 scoped_ptr<WebstoreInstaller::Approval> approval = |
| 235 WebstoreStandaloneInstaller::CreateApproval(); | 223 WebstoreStandaloneInstaller::CreateApproval(); |
| 236 approval->is_ephemeral = true; | 224 approval->is_ephemeral = true; |
| 237 return approval.Pass(); | 225 return approval.Pass(); |
| 238 } | 226 } |
| 239 | 227 |
| 240 void EphemeralAppLauncher::CompleteInstall(const std::string& error) { | 228 void EphemeralAppLauncher::CompleteInstall(const std::string& error) { |
| 241 if (!error.empty()) | 229 if (error.empty()) { |
| 242 WebstoreStandaloneInstaller::CompleteInstall(error); | 230 const Extension* extension = |
| 231 ExtensionRegistry::Get(profile()) |
| 232 ->GetExtensionById(id(), ExtensionRegistry::ENABLED); |
| 233 if (extension) |
| 234 LaunchApp(extension); |
| 235 } |
| 243 | 236 |
| 244 // If the installation succeeds, we reach this point as a result of | 237 WebstoreStandaloneInstaller::CompleteInstall(error); |
| 245 // chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED, but this is | |
| 246 // broadcasted before | |
| 247 // ExtensionService has added the extension to its list of installed | |
| 248 // extensions and is too early to launch the app. Instead, we will launch at | |
| 249 // EphemeralAppLauncher::OnExtensionLoaded(). | |
| 250 // TODO(tmdiep): Refactor extensions/WebstoreInstaller or | |
| 251 // WebstoreStandaloneInstaller to support this cleanly. | |
| 252 } | 238 } |
| 253 | 239 |
| 254 void EphemeralAppLauncher::WebContentsDestroyed() { | 240 void EphemeralAppLauncher::WebContentsDestroyed() { |
| 255 AbortInstall(); | 241 AbortInstall(); |
| 256 } | 242 } |
| 257 | 243 |
| 258 void EphemeralAppLauncher::OnExtensionLoaded( | |
| 259 content::BrowserContext* browser_context, | |
| 260 const Extension* extension) { | |
| 261 if (extension->id() == id()) { | |
| 262 LaunchApp(extension); | |
| 263 WebstoreStandaloneInstaller::CompleteInstall(std::string()); | |
| 264 } | |
| 265 } | |
| 266 | |
| 267 void EphemeralAppLauncher::ExtensionEnableFlowFinished() { | 244 void EphemeralAppLauncher::ExtensionEnableFlowFinished() { |
| 268 ExtensionService* extension_service = | 245 CompleteInstall(std::string()); |
| 269 extensions::ExtensionSystem::Get(profile())->extension_service(); | |
| 270 DCHECK(extension_service); | |
| 271 | |
| 272 const Extension* extension = extension_service->GetExtensionById(id(), false); | |
| 273 if (extension) { | |
| 274 LaunchApp(extension); | |
| 275 WebstoreStandaloneInstaller::CompleteInstall(std::string()); | |
| 276 } else { | |
| 277 WebstoreStandaloneInstaller::CompleteInstall(kLaunchAbortedError); | |
| 278 } | |
| 279 } | 246 } |
| 280 | 247 |
| 281 void EphemeralAppLauncher::ExtensionEnableFlowAborted(bool user_initiated) { | 248 void EphemeralAppLauncher::ExtensionEnableFlowAborted(bool user_initiated) { |
| 282 WebstoreStandaloneInstaller::CompleteInstall(kLaunchAbortedError); | 249 CompleteInstall(kLaunchAbortedError); |
| 283 } | 250 } |
| OLD | NEW |