Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: chrome/browser/extensions/webstore_installer.cc

Issue 9837054: Improve WebstoreInstaller error handling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/rand_util.h" 11 #include "base/rand_util.h"
12 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
13 #include "base/string_util.h" 13 #include "base/string_util.h"
14 #include "base/string_number_conversions.h" 14 #include "base/string_number_conversions.h"
15 #include "base/utf_string_conversions.h" 15 #include "base/utf_string_conversions.h"
16 #include "chrome/browser/browser_process.h" 16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/download/chrome_download_manager_delegate.h"
17 #include "chrome/browser/download/download_prefs.h" 18 #include "chrome/browser/download/download_prefs.h"
18 #include "chrome/browser/download/download_util.h" 19 #include "chrome/browser/download/download_util.h"
19 #include "chrome/browser/extensions/crx_installer.h" 20 #include "chrome/browser/extensions/crx_installer.h"
20 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/tabs/tab_strip_model.h" 22 #include "chrome/browser/tabs/tab_strip_model.h"
22 #include "chrome/browser/ui/browser_list.h" 23 #include "chrome/browser/ui/browser_list.h"
23 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 24 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
24 #include "chrome/common/chrome_notification_types.h" 25 #include "chrome/common/chrome_notification_types.h"
25 #include "chrome/common/chrome_switches.h" 26 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/extensions/extension.h" 27 #include "chrome/common/extensions/extension.h"
27 #include "chrome/common/extensions/extension_constants.h" 28 #include "chrome/common/extensions/extension_constants.h"
28 #include "content/public/browser/browser_thread.h" 29 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/download_manager.h" 30 #include "content/public/browser/download_manager.h"
30 #include "content/public/browser/download_save_info.h" 31 #include "content/public/browser/download_save_info.h"
31 #include "content/public/browser/navigation_controller.h" 32 #include "content/public/browser/navigation_controller.h"
32 #include "content/public/browser/navigation_entry.h" 33 #include "content/public/browser/navigation_entry.h"
33 #include "content/public/browser/notification_details.h" 34 #include "content/public/browser/notification_details.h"
35 #include "content/public/browser/notification_service.h"
34 #include "content/public/browser/notification_source.h" 36 #include "content/public/browser/notification_source.h"
35 #include "googleurl/src/gurl.h" 37 #include "googleurl/src/gurl.h"
36 #include "net/base/escape.h" 38 #include "net/base/escape.h"
37 39
38 using content::BrowserThread; 40 using content::BrowserThread;
41 using content::DownloadId;
42 using content::DownloadItem;
Randy Smith (Not in Mondays) 2012/03/23 20:57:19 I thought the style guide generally preferred actu
jstritar 2012/03/23 21:52:53 I think this is okay in .cc files, but we're not s
39 using content::NavigationController; 43 using content::NavigationController;
40 44
41 namespace { 45 namespace {
42 46
43 const char kInvalidIdError[] = "Invalid id"; 47 const char kInvalidIdError[] = "Invalid id";
44 const char kNoBrowserError[] = "No browser found"; 48 const char kNoBrowserError[] = "No browser found";
45 const char kDownloadDirectoryError[] = "Could not create download directory"; 49 const char kDownloadDirectoryError[] = "Could not create download directory";
46 50 const char kDownloadCanceledError[] = "Download canceled";
51 const char kDownloadInterruptedError[] = "Download interrupted";
52 const char kInvalidDownloadError[] = "Download was not a CRX";
47 const char kInlineInstallSource[] = "inline"; 53 const char kInlineInstallSource[] = "inline";
48 const char kDefaultInstallSource[] = ""; 54 const char kDefaultInstallSource[] = "";
49 55
50 FilePath* g_download_directory_for_tests = NULL; 56 FilePath* g_download_directory_for_tests = NULL;
51 57
52 GURL GetWebstoreInstallURL( 58 GURL GetWebstoreInstallURL(
53 const std::string& extension_id, const std::string& install_source) { 59 const std::string& extension_id, const std::string& install_source) {
54 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 60 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
55 if (cmd_line->HasSwitch(switches::kAppsGalleryDownloadURL)) { 61 if (cmd_line->HasSwitch(switches::kAppsGalleryDownloadURL)) {
56 std::string download_url = 62 std::string download_url =
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 WebstoreInstaller::WebstoreInstaller(Profile* profile, 120 WebstoreInstaller::WebstoreInstaller(Profile* profile,
115 Delegate* delegate, 121 Delegate* delegate,
116 NavigationController* controller, 122 NavigationController* controller,
117 const std::string& id, 123 const std::string& id,
118 int flags) 124 int flags)
119 : profile_(profile), 125 : profile_(profile),
120 delegate_(delegate), 126 delegate_(delegate),
121 controller_(controller), 127 controller_(controller),
122 id_(id), 128 id_(id),
123 flags_(flags) { 129 flags_(flags) {
130 // The caller should have already prompted to accept the permissions.
131 CHECK(CrxInstaller::GetWhitelistEntry(id) ||
132 CrxInstaller::IsIdWhitelisted(id));
133
124 download_url_ = GetWebstoreInstallURL(id, flags & FLAG_INLINE_INSTALL ? 134 download_url_ = GetWebstoreInstallURL(id, flags & FLAG_INLINE_INSTALL ?
125 kInlineInstallSource : kDefaultInstallSource); 135 kInlineInstallSource : kDefaultInstallSource);
126 136
127 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, 137 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
128 content::Source<Profile>(profile)); 138 content::Source<Profile>(profile));
129 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, 139 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
130 content::Source<CrxInstaller>(NULL)); 140 content::Source<CrxInstaller>(NULL));
131 } 141 }
132 142
133 WebstoreInstaller::~WebstoreInstaller() {} 143 WebstoreInstaller::~WebstoreInstaller() {
144 // Stop observing the DownloadItem, if applicable.
145 if (!download_id_.IsValid())
146 return;
147
148 content::DownloadManager* download_manager = profile_->GetDownloadManager();
149 DownloadItem* item = download_manager->GetActiveDownloadItem(
150 download_id_.local());
151 if (item)
152 item->RemoveObserver(this);
Randy Smith (Not in Mondays) 2012/03/23 20:57:19 This scares me. I'm not certain as to the lifetim
jstritar 2012/03/23 21:52:53 Ah, I see. A GetDownloadItem method that returned
Randy Smith (Not in Mondays) 2012/03/23 22:18:29 You are completely right. Mea culpa, and I hope t
153 }
134 154
135 void WebstoreInstaller::Start() { 155 void WebstoreInstaller::Start() {
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
137 AddRef(); // Balanced in ReportSuccess and ReportFailure. 157 AddRef(); // Balanced in ReportSuccess and ReportFailure.
138 158
139 if (!Extension::IdIsValid(id_)) { 159 if (!Extension::IdIsValid(id_)) {
140 ReportFailure(kInvalidIdError); 160 ReportFailure(kInvalidIdError);
141 return; 161 return;
142 } 162 }
143 163
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 201
182 default: 202 default:
183 NOTREACHED(); 203 NOTREACHED();
184 } 204 }
185 } 205 }
186 206
187 void WebstoreInstaller::SetDownloadDirectoryForTests(FilePath* directory) { 207 void WebstoreInstaller::SetDownloadDirectoryForTests(FilePath* directory) {
188 g_download_directory_for_tests = directory; 208 g_download_directory_for_tests = directory;
189 } 209 }
190 210
211 void WebstoreInstaller::OnDownloadStarted(DownloadId id, net::Error error) {
212 if (error != net::OK) {
213 ReportFailure(net::ErrorToString(error));
214 return;
215 }
216
217 download_id_ = id;
218 CHECK(id.IsValid());
219
220 content::DownloadManager* download_manager = profile_->GetDownloadManager();
221 DownloadItem* item = download_manager->GetActiveDownloadItem(id.local());
222 if (item)
Randy Smith (Not in Mondays) 2012/03/23 20:57:19 YOu should be able to make this a DCHECK; the DI s
jstritar 2012/03/23 21:52:53 Done. I removed the if but didn't add a CHECK sinc
223 item->AddObserver(this);
224 }
225
226 void WebstoreInstaller::OnDownloadUpdated(DownloadItem* download) {
227 CHECK_EQ(download_id_, download->GetGlobalId());
228
229 switch (download->GetState()) {
230 case DownloadItem::CANCELLED:
231 ReportFailure(kDownloadCanceledError);
232 break;
233 case DownloadItem::INTERRUPTED:
234 ReportFailure(kDownloadInterruptedError);
235 break;
236 case DownloadItem::REMOVING:
237 break;
238 case DownloadItem::COMPLETE:
239 // Wait for other notifications if the download is really an extension.
240 if (!ChromeDownloadManagerDelegate::IsExtensionDownload(download))
241 ReportFailure(kInvalidDownloadError);
242 break;
243 default:
244 // Continue listening if the download is not in one of the above states.
245 return;
246 }
247
248 download->RemoveObserver(this);
249 }
250
251 void WebstoreInstaller::OnDownloadOpened(DownloadItem* download) {
252 CHECK_EQ(download_id_, download->GetGlobalId());
253 }
254
191 void WebstoreInstaller::StartDownload(const FilePath& file) { 255 void WebstoreInstaller::StartDownload(const FilePath& file) {
192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
193 257
194 if (file.empty()) { 258 if (file.empty()) {
195 ReportFailure(kDownloadDirectoryError); 259 ReportFailure(kDownloadDirectoryError);
196 return; 260 return;
197 } 261 }
198 262
199 // TODO(mihaip): For inline installs, we pretend like the referrer is the 263 // TODO(mihaip): For inline installs, we pretend like the referrer is the
200 // gallery, even though this could be an inline install, in order to pass the 264 // gallery, even though this could be an inline install, in order to pass the
201 // checks in ExtensionService::IsDownloadFromGallery. We should instead pass 265 // checks in ExtensionService::IsDownloadFromGallery. We should instead pass
202 // the real referrer, track if this is an inline install in the whitelist 266 // the real referrer, track if this is an inline install in the whitelist
203 // entry and look that up when checking that this is a valid download. 267 // entry and look that up when checking that this is a valid download.
204 GURL referrer = controller_->GetActiveEntry()->GetURL(); 268 GURL referrer = controller_->GetActiveEntry()->GetURL();
205 if (flags_ & FLAG_INLINE_INSTALL) 269 if (flags_ & FLAG_INLINE_INSTALL)
206 referrer = GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + id_); 270 referrer = GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + id_);
207 271
208 content::DownloadSaveInfo save_info; 272 content::DownloadSaveInfo save_info;
209 save_info.file_path = file; 273 save_info.file_path = file;
210 274
211 // The download url for the given extension is contained in |download_url_|. 275 // The download url for the given extension is contained in |download_url_|.
212 // We will navigate the current tab to this url to start the download. The 276 // We will navigate the current tab to this url to start the download. The
213 // download system will then pass the crx to the CrxInstaller. 277 // download system will then pass the crx to the CrxInstaller.
214 download_util::RecordDownloadSource( 278 download_util::RecordDownloadSource(
215 download_util::INITIATED_BY_WEBSTORE_INSTALLER); 279 download_util::INITIATED_BY_WEBSTORE_INSTALLER);
216 profile_->GetDownloadManager()->DownloadUrl( 280 profile_->GetDownloadManager()->DownloadUrl(
217 download_url_, referrer, "", 281 download_url_, referrer, "",
218 false, -1, save_info, controller_->GetWebContents(), 282 false, -1, save_info, controller_->GetWebContents(),
219 content::DownloadManager::OnStartedCallback()); 283 base::Bind(&WebstoreInstaller::OnDownloadStarted, this));
220 } 284 }
221 285
222 void WebstoreInstaller::ReportFailure(const std::string& error) { 286 void WebstoreInstaller::ReportFailure(const std::string& error) {
223 if (delegate_) 287 if (delegate_)
224 delegate_->OnExtensionInstallFailure(id_, error); 288 delegate_->OnExtensionInstallFailure(id_, error);
225 289
226 Release(); // Balanced in Start(). 290 Release(); // Balanced in Start().
227 } 291 }
228 292
229 void WebstoreInstaller::ReportSuccess() { 293 void WebstoreInstaller::ReportSuccess() {
230 if (delegate_) 294 if (delegate_)
231 delegate_->OnExtensionInstallSuccess(id_); 295 delegate_->OnExtensionInstallSuccess(id_);
232 296
233 Release(); // Balanced in Start(). 297 Release(); // Balanced in Start().
234 } 298 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698