| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/extensions/webstore_installer.h" | 5 #include "chrome/browser/extensions/webstore_installer.h" |
| 6 | 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" |
| 9 #include "base/file_util.h" |
| 10 #include "base/stringprintf.h" |
| 7 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 8 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
| 13 #include "chrome/browser/download/download_util.h" |
| 9 #include "chrome/browser/extensions/crx_installer.h" | 14 #include "chrome/browser/extensions/crx_installer.h" |
| 10 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 11 #include "chrome/browser/tabs/tab_strip_model.h" | 16 #include "chrome/browser/tabs/tab_strip_model.h" |
| 12 #include "chrome/browser/ui/browser_list.h" | 17 #include "chrome/browser/ui/browser_list.h" |
| 13 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 18 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 14 #include "chrome/common/chrome_notification_types.h" | 19 #include "chrome/common/chrome_notification_types.h" |
| 20 #include "chrome/common/chrome_switches.h" |
| 15 #include "chrome/common/extensions/extension.h" | 21 #include "chrome/common/extensions/extension.h" |
| 16 #include "chrome/common/extensions/extension_constants.h" | 22 #include "chrome/common/extensions/extension_constants.h" |
| 23 #include "content/browser/download/download_file.h" |
| 24 #include "content/browser/download/download_manager.h" |
| 25 #include "content/browser/download/download_types.h" |
| 17 #include "content/browser/tab_contents/navigation_controller.h" | 26 #include "content/browser/tab_contents/navigation_controller.h" |
| 27 #include "content/public/browser/browser_thread.h" |
| 18 #include "content/public/browser/notification_details.h" | 28 #include "content/public/browser/notification_details.h" |
| 19 #include "content/public/browser/notification_source.h" | 29 #include "content/public/browser/notification_source.h" |
| 20 #include "googleurl/src/gurl.h" | 30 #include "googleurl/src/gurl.h" |
| 21 #include "net/base/escape.h" | 31 #include "net/base/escape.h" |
| 22 | 32 |
| 23 namespace { | 33 namespace { |
| 24 | 34 |
| 25 const char kInvalidIdError[] = "Invalid id"; | 35 const char kInvalidIdError[] = "Invalid id"; |
| 26 const char kNoBrowserError[] = "No browser found"; | 36 const char kNoBrowserError[] = "No browser found"; |
| 27 | 37 |
| 28 const char kInlineInstallSource[] = "inline"; | 38 const char kInlineInstallSource[] = "inline"; |
| 29 const char kDefaultInstallSource[] = ""; | 39 const char kDefaultInstallSource[] = ""; |
| 30 | 40 |
| 31 GURL GetWebstoreInstallURL( | 41 GURL GetWebstoreInstallURL( |
| 32 const std::string& extension_id, const std::string& install_source) { | 42 const std::string& extension_id, const std::string& install_source) { |
| 43 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
| 44 if (cmd_line->HasSwitch(switches::kAppsGalleryDownloadURL)) { |
| 45 std::string download_url = |
| 46 cmd_line->GetSwitchValueASCII(switches::kAppsGalleryDownloadURL); |
| 47 return GURL(base::StringPrintf(download_url.c_str(), |
| 48 extension_id.c_str())); |
| 49 } |
| 33 std::vector<std::string> params; | 50 std::vector<std::string> params; |
| 34 params.push_back("id=" + extension_id); | 51 params.push_back("id=" + extension_id); |
| 35 if (!install_source.empty()) { | 52 if (!install_source.empty()) { |
| 36 params.push_back("installsource=" + install_source); | 53 params.push_back("installsource=" + install_source); |
| 37 } | 54 } |
| 38 params.push_back("lang=" + g_browser_process->GetApplicationLocale()); | 55 params.push_back("lang=" + g_browser_process->GetApplicationLocale()); |
| 39 params.push_back("uc"); | 56 params.push_back("uc"); |
| 40 std::string url_string = extension_urls::GetWebstoreUpdateUrl(true).spec(); | 57 std::string url_string = extension_urls::GetWebstoreUpdateUrl(true).spec(); |
| 41 | 58 |
| 42 GURL url(url_string + "?response=redirect&x=" + | 59 GURL url(url_string + "?response=redirect&x=" + |
| 43 net::EscapeQueryParamValue(JoinString(params, '&'), true)); | 60 net::EscapeQueryParamValue(JoinString(params, '&'), true)); |
| 44 DCHECK(url.is_valid()); | 61 DCHECK(url.is_valid()); |
| 45 | 62 |
| 46 return url; | 63 return url; |
| 47 } | 64 } |
| 48 | 65 |
| 66 // Must be executed on the FILE thread. |
| 67 void GetDownloadFilePath(const std::string& id, |
| 68 const base::Callback<void(FilePath)>& callback) { |
| 69 FilePath file = |
| 70 download_util::GetDefaultDownloadDirectory().AppendASCII(id + ".crx"); |
| 71 |
| 72 int uniquifier = DownloadFile::GetUniquePathNumber(file); |
| 73 if (uniquifier > 0) |
| 74 DownloadFile::AppendNumberToPath(&file, uniquifier); |
| 75 |
| 76 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 77 base::Bind(callback, file)); |
| 78 } |
| 79 |
| 49 } // namespace | 80 } // namespace |
| 50 | 81 |
| 51 | 82 |
| 52 WebstoreInstaller::WebstoreInstaller(Profile* profile, | 83 WebstoreInstaller::WebstoreInstaller(Profile* profile, |
| 53 Delegate* delegate, | 84 Delegate* delegate, |
| 54 NavigationController* controller, | 85 NavigationController* controller, |
| 55 const std::string& id, | 86 const std::string& id, |
| 56 int flags) | 87 int flags) |
| 57 : profile_(profile), | 88 : profile_(profile), |
| 58 delegate_(delegate), | 89 delegate_(delegate), |
| 59 controller_(controller), | 90 controller_(controller), |
| 60 id_(id), | 91 id_(id), |
| 61 flags_(flags) { | 92 flags_(flags) { |
| 62 download_url_ = GetWebstoreInstallURL(id, flags & FLAG_INLINE_INSTALL ? | 93 download_url_ = GetWebstoreInstallURL(id, flags & FLAG_INLINE_INSTALL ? |
| 63 kInlineInstallSource : kDefaultInstallSource); | 94 kInlineInstallSource : kDefaultInstallSource); |
| 64 | 95 |
| 65 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, | 96 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, |
| 66 content::Source<Profile>(profile)); | 97 content::Source<Profile>(profile)); |
| 67 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, | 98 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, |
| 68 content::Source<CrxInstaller>(NULL)); | 99 content::Source<CrxInstaller>(NULL)); |
| 69 } | 100 } |
| 70 | 101 |
| 71 WebstoreInstaller::~WebstoreInstaller() {} | 102 WebstoreInstaller::~WebstoreInstaller() {} |
| 72 | 103 |
| 73 void WebstoreInstaller::Start() { | 104 void WebstoreInstaller::Start() { |
| 105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 74 AddRef(); // Balanced in ReportSuccess and ReportFailure. | 106 AddRef(); // Balanced in ReportSuccess and ReportFailure. |
| 75 | 107 |
| 76 if (!Extension::IdIsValid(id_)) { | 108 if (!Extension::IdIsValid(id_)) { |
| 77 ReportFailure(kInvalidIdError); | 109 ReportFailure(kInvalidIdError); |
| 78 return; | 110 return; |
| 79 } | 111 } |
| 80 | 112 |
| 81 // TODO(mihaip): For inline installs, we pretend like the referrer is the | 113 BrowserThread::PostTask( |
| 82 // gallery, even though this could be an inline install, in order to pass the | 114 BrowserThread::FILE, FROM_HERE, |
| 83 // checks in ExtensionService::IsDownloadFromGallery. We should instead pass | 115 base::Bind(&GetDownloadFilePath, id_, |
| 84 // the real referrer, track if this is an inline install in the whitelist | 116 base::Bind(&WebstoreInstaller::StartDownload, |
| 85 // entry and look that up when checking that this is a valid download. | 117 base::Unretained(this)))); |
| 86 GURL referrer = controller_->GetActiveEntry()->url(); | |
| 87 if (flags_ & FLAG_INLINE_INSTALL) | |
| 88 referrer = GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + id_); | |
| 89 | |
| 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()); | |
| 97 | 118 |
| 98 } | 119 } |
| 99 | 120 |
| 100 void WebstoreInstaller::Observe(int type, | 121 void WebstoreInstaller::Observe(int type, |
| 101 const content::NotificationSource& source, | 122 const content::NotificationSource& source, |
| 102 const content::NotificationDetails& details) { | 123 const content::NotificationDetails& details) { |
| 103 switch (type) { | 124 switch (type) { |
| 104 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { | 125 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { |
| 105 CHECK(profile_->IsSameProfile(content::Source<Profile>(source).ptr())); | 126 CHECK(profile_->IsSameProfile(content::Source<Profile>(source).ptr())); |
| 106 const Extension* extension = | 127 const Extension* extension = |
| (...skipping 14 matching lines...) Expand all Loading... |
| 121 if (download_url_ == crx_installer->original_download_url()) | 142 if (download_url_ == crx_installer->original_download_url()) |
| 122 ReportFailure(*error); | 143 ReportFailure(*error); |
| 123 break; | 144 break; |
| 124 } | 145 } |
| 125 | 146 |
| 126 default: | 147 default: |
| 127 NOTREACHED(); | 148 NOTREACHED(); |
| 128 } | 149 } |
| 129 } | 150 } |
| 130 | 151 |
| 152 void WebstoreInstaller::StartDownload(FilePath file) { |
| 153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 154 |
| 155 // TODO(mihaip): For inline installs, we pretend like the referrer is the |
| 156 // gallery, even though this could be an inline install, in order to pass the |
| 157 // checks in ExtensionService::IsDownloadFromGallery. We should instead pass |
| 158 // the real referrer, track if this is an inline install in the whitelist |
| 159 // entry and look that up when checking that this is a valid download. |
| 160 GURL referrer = controller_->GetActiveEntry()->url(); |
| 161 if (flags_ & FLAG_INLINE_INSTALL) |
| 162 referrer = GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + id_); |
| 163 |
| 164 DownloadSaveInfo save_info; |
| 165 save_info.file_path = file; |
| 166 |
| 167 // The download url for the given extension is contained in |download_url_|. |
| 168 // We will navigate the current tab to this url to start the download. The |
| 169 // download system will then pass the crx to the CrxInstaller. |
| 170 profile_->GetDownloadManager()->DownloadUrlToFile( |
| 171 download_url_, referrer, "", save_info, controller_->tab_contents()); |
| 172 } |
| 173 |
| 131 void WebstoreInstaller::ReportFailure(const std::string& error) { | 174 void WebstoreInstaller::ReportFailure(const std::string& error) { |
| 132 if (delegate_) | 175 if (delegate_) |
| 133 delegate_->OnExtensionInstallFailure(id_, error); | 176 delegate_->OnExtensionInstallFailure(id_, error); |
| 134 | 177 |
| 135 Release(); // Balanced in Start(). | 178 Release(); // Balanced in Start(). |
| 136 } | 179 } |
| 137 | 180 |
| 138 void WebstoreInstaller::ReportSuccess() { | 181 void WebstoreInstaller::ReportSuccess() { |
| 139 if (delegate_) | 182 if (delegate_) |
| 140 delegate_->OnExtensionInstallSuccess(id_); | 183 delegate_->OnExtensionInstallSuccess(id_); |
| 141 | 184 |
| 142 Release(); // Balanced in Start(). | 185 Release(); // Balanced in Start(). |
| 143 } | 186 } |
| OLD | NEW |