[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 1 | // Copyright (c) 2011 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/webstore_installer.h" |
| 6 | |
[email protected] | 99dfecd | 2011-10-18 01:11:50 | [diff] [blame] | 7 | #include "base/string_util.h" |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 8 | #include "chrome/browser/browser_process.h" |
| 9 | #include "chrome/browser/extensions/crx_installer.h" |
| 10 | #include "chrome/browser/profiles/profile.h" |
| 11 | #include "chrome/browser/tabs/tab_strip_model.h" |
| 12 | #include "chrome/browser/ui/browser_list.h" |
| 13 | #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 14 | #include "chrome/common/chrome_notification_types.h" |
| 15 | #include "chrome/common/extensions/extension.h" |
[email protected] | 99dfecd | 2011-10-18 01:11:50 | [diff] [blame] | 16 | #include "chrome/common/extensions/extension_constants.h" |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 17 | #include "content/browser/tab_contents/navigation_controller.h" |
[email protected] | 86ab86b | 2011-10-19 03:07:55 | [diff] [blame] | 18 | #include "content/public/browser/notification_details.h" |
| 19 | #include "content/public/browser/notification_source.h" |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 20 | #include "googleurl/src/gurl.h" |
[email protected] | 99dfecd | 2011-10-18 01:11:50 | [diff] [blame] | 21 | #include "net/base/escape.h" |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 22 | |
| 23 | namespace { |
| 24 | |
| 25 | const char kInvalidIdError[] = "Invalid id"; |
| 26 | const char kNoBrowserError[] = "No browser found"; |
| 27 | |
[email protected] | 99dfecd | 2011-10-18 01:11:50 | [diff] [blame] | 28 | const char kInlineInstallSource[] = "inline"; |
| 29 | const char kDefaultInstallSource[] = ""; |
| 30 | |
[email protected] | e577c59 | 2011-10-25 22:53:30 | [diff] [blame^] | 31 | GURL GetWebstoreInstallURL( |
[email protected] | 99dfecd | 2011-10-18 01:11:50 | [diff] [blame] | 32 | const std::string& extension_id, const std::string& install_source) { |
| 33 | std::vector<std::string> params; |
| 34 | params.push_back("id=" + extension_id); |
| 35 | if (!install_source.empty()) { |
| 36 | params.push_back("installsource=" + install_source); |
| 37 | } |
| 38 | params.push_back("lang=" + g_browser_process->GetApplicationLocale()); |
| 39 | params.push_back("uc"); |
| 40 | std::string url_string = extension_urls::GetWebstoreUpdateUrl(true).spec(); |
| 41 | |
| 42 | GURL url(url_string + "?response=redirect&x=" + |
| 43 | net::EscapeQueryParamValue(JoinString(params, '&'), true)); |
| 44 | DCHECK(url.is_valid()); |
| 45 | |
| 46 | return url; |
| 47 | } |
| 48 | |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 49 | } // namespace |
| 50 | |
| 51 | |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 52 | WebstoreInstaller::WebstoreInstaller(Profile* profile, |
| 53 | Delegate* delegate, |
| 54 | NavigationController* controller, |
| 55 | const std::string& id, |
| 56 | int flags) |
| 57 | : profile_(profile), |
| 58 | delegate_(delegate), |
| 59 | controller_(controller), |
| 60 | id_(id), |
| 61 | flags_(flags) { |
[email protected] | e577c59 | 2011-10-25 22:53:30 | [diff] [blame^] | 62 | download_url_ = GetWebstoreInstallURL(id, flags & FLAG_INLINE_INSTALL ? |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 63 | kInlineInstallSource : kDefaultInstallSource); |
| 64 | |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 65 | registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, |
[email protected] | 86ab86b | 2011-10-19 03:07:55 | [diff] [blame] | 66 | content::Source<Profile>(profile)); |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 67 | registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, |
[email protected] | 86ab86b | 2011-10-19 03:07:55 | [diff] [blame] | 68 | content::Source<CrxInstaller>(NULL)); |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | WebstoreInstaller::~WebstoreInstaller() {} |
| 72 | |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 73 | void WebstoreInstaller::Start() { |
| 74 | AddRef(); // Balanced in ReportSuccess and ReportFailure. |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 75 | |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 76 | if (!Extension::IdIsValid(id_)) { |
| 77 | ReportFailure(kInvalidIdError); |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 78 | return; |
| 79 | } |
| 80 | |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 81 | // TODO(mihaip): For inline installs, we pretend like the referrer is the |
| 82 | // gallery, even though this could be an inline install, in order to pass the |
| 83 | // checks in ExtensionService::IsDownloadFromGallery. We should instead pass |
| 84 | // the real referrer, track if this is an inline install in the whitelist |
| 85 | // entry and look that up when checking that this is a valid download. |
| 86 | GURL referrer = controller_->GetActiveEntry()->url(); |
| 87 | if (flags_ & FLAG_INLINE_INSTALL) |
| 88 | referrer = GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + id_); |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 89 | |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 90 | // The download url for the given extension is contained in |download_url_|. |
| 91 | // We will navigate the current tab to this url to start the download. The |
| 92 | // download system will then pass the crx to the CrxInstaller. |
| 93 | controller_->LoadURL(download_url_, |
| 94 | referrer, |
| 95 | content::PAGE_TRANSITION_LINK, |
| 96 | std::string()); |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 97 | |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | void WebstoreInstaller::Observe(int type, |
[email protected] | 86ab86b | 2011-10-19 03:07:55 | [diff] [blame] | 101 | const content::NotificationSource& source, |
| 102 | const content::NotificationDetails& details) { |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 103 | switch (type) { |
| 104 | case chrome::NOTIFICATION_EXTENSION_INSTALLED: { |
[email protected] | 86ab86b | 2011-10-19 03:07:55 | [diff] [blame] | 105 | CHECK(profile_->IsSameProfile(content::Source<Profile>(source).ptr())); |
| 106 | const Extension* extension = |
| 107 | content::Details<const Extension>(details).ptr(); |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 108 | if (id_ == extension->id()) |
| 109 | ReportSuccess(); |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 110 | break; |
| 111 | } |
| 112 | |
| 113 | case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: { |
[email protected] | 86ab86b | 2011-10-19 03:07:55 | [diff] [blame] | 114 | CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr(); |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 115 | CHECK(crx_installer); |
| 116 | if (!profile_->IsSameProfile(crx_installer->profile())) |
| 117 | return; |
| 118 | |
[email protected] | 86ab86b | 2011-10-19 03:07:55 | [diff] [blame] | 119 | const std::string* error = |
| 120 | content::Details<const std::string>(details).ptr(); |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 121 | if (download_url_ == crx_installer->original_download_url()) |
| 122 | ReportFailure(*error); |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 123 | break; |
| 124 | } |
| 125 | |
| 126 | default: |
| 127 | NOTREACHED(); |
| 128 | } |
| 129 | } |
| 130 | |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 131 | void WebstoreInstaller::ReportFailure(const std::string& error) { |
| 132 | if (delegate_) |
| 133 | delegate_->OnExtensionInstallFailure(id_, error); |
| 134 | |
| 135 | Release(); // Balanced in Start(). |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 136 | } |
| 137 | |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 138 | void WebstoreInstaller::ReportSuccess() { |
| 139 | if (delegate_) |
| 140 | delegate_->OnExtensionInstallSuccess(id_); |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 141 | |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 142 | Release(); // Balanced in Start(). |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 143 | } |