| OLD | NEW |
| 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" |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 file = file.InsertBeforeExtensionASCII(StringPrintf(" (%d)", uniquifier)); | 129 file = file.InsertBeforeExtensionASCII(StringPrintf(" (%d)", uniquifier)); |
| 130 | 130 |
| 131 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 131 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 132 base::Bind(callback, file)); | 132 base::Bind(callback, file)); |
| 133 } | 133 } |
| 134 | 134 |
| 135 } // namespace | 135 } // namespace |
| 136 | 136 |
| 137 namespace extensions { | 137 namespace extensions { |
| 138 | 138 |
| 139 void WebstoreInstaller::Delegate::OnExtensionDownloadStarted( |
| 140 const std::string& id, |
| 141 content::DownloadItem* item) { |
| 142 } |
| 143 |
| 144 void WebstoreInstaller::Delegate::OnExtensionDownloadProgress( |
| 145 const std::string& id, |
| 146 content::DownloadItem* item) { |
| 147 } |
| 148 |
| 139 WebstoreInstaller::Approval::Approval() | 149 WebstoreInstaller::Approval::Approval() |
| 140 : profile(NULL), | 150 : profile(NULL), |
| 141 use_app_installed_bubble(false), | 151 use_app_installed_bubble(false), |
| 142 skip_post_install_ui(false), | 152 skip_post_install_ui(false), |
| 143 skip_install_dialog(false), | 153 skip_install_dialog(false), |
| 144 record_oauth2_grant(false) { | 154 record_oauth2_grant(false) { |
| 145 } | 155 } |
| 146 | 156 |
| 147 scoped_ptr<WebstoreInstaller::Approval> | 157 scoped_ptr<WebstoreInstaller::Approval> |
| 148 WebstoreInstaller::Approval::CreateWithInstallPrompt(Profile* profile) { | 158 WebstoreInstaller::Approval::CreateWithInstallPrompt(Profile* profile) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 content::Source<Profile>(profile->GetOriginalProfile())); | 204 content::Source<Profile>(profile->GetOriginalProfile())); |
| 195 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, | 205 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, |
| 196 content::Source<CrxInstaller>(NULL)); | 206 content::Source<CrxInstaller>(NULL)); |
| 197 } | 207 } |
| 198 | 208 |
| 199 void WebstoreInstaller::Start() { | 209 void WebstoreInstaller::Start() { |
| 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 201 AddRef(); // Balanced in ReportSuccess and ReportFailure. | 211 AddRef(); // Balanced in ReportSuccess and ReportFailure. |
| 202 | 212 |
| 203 if (!Extension::IdIsValid(id_)) { | 213 if (!Extension::IdIsValid(id_)) { |
| 204 ReportFailure(kInvalidIdError); | 214 ReportFailure(kInvalidIdError, FAILURE_REASON_OTHER); |
| 205 return; | 215 return; |
| 206 } | 216 } |
| 207 | 217 |
| 208 FilePath download_path = DownloadPrefs::FromDownloadManager( | 218 FilePath download_path = DownloadPrefs::FromDownloadManager( |
| 209 BrowserContext::GetDownloadManager(profile_))->DownloadPath(); | 219 BrowserContext::GetDownloadManager(profile_))->DownloadPath(); |
| 210 BrowserThread::PostTask( | 220 BrowserThread::PostTask( |
| 211 BrowserThread::FILE, FROM_HERE, | 221 BrowserThread::FILE, FROM_HERE, |
| 212 base::Bind(&GetDownloadFilePath, download_path, id_, | 222 base::Bind(&GetDownloadFilePath, download_path, id_, |
| 213 base::Bind(&WebstoreInstaller::StartDownload, this))); | 223 base::Bind(&WebstoreInstaller::StartDownload, this))); |
| 214 } | 224 } |
| 215 | 225 |
| 216 void WebstoreInstaller::Observe(int type, | 226 void WebstoreInstaller::Observe(int type, |
| 217 const content::NotificationSource& source, | 227 const content::NotificationSource& source, |
| 218 const content::NotificationDetails& details) { | 228 const content::NotificationDetails& details) { |
| 219 switch (type) { | 229 switch (type) { |
| 220 case chrome::NOTIFICATION_CRX_INSTALLER_DONE: { | 230 case chrome::NOTIFICATION_CRX_INSTALLER_DONE: { |
| 221 const Extension* extension = | 231 const Extension* extension = |
| 222 content::Details<const Extension>(details).ptr(); | 232 content::Details<const Extension>(details).ptr(); |
| 223 CrxInstaller* installer = content::Source<CrxInstaller>(source).ptr(); | 233 CrxInstaller* installer = content::Source<CrxInstaller>(source).ptr(); |
| 224 if (extension == NULL && download_item_ != NULL && | 234 if (extension == NULL && download_item_ != NULL && |
| 225 installer->download_url() == download_item_->GetURL() && | 235 installer->download_url() == download_item_->GetURL() && |
| 226 installer->profile()->IsSameProfile(profile_)) { | 236 installer->profile()->IsSameProfile(profile_)) { |
| 227 ReportFailure(kInstallCanceledError); | 237 ReportFailure(kInstallCanceledError, FAILURE_REASON_CANCELLED); |
| 228 } | 238 } |
| 229 break; | 239 break; |
| 230 } | 240 } |
| 231 | 241 |
| 232 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { | 242 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { |
| 233 CHECK(profile_->IsSameProfile(content::Source<Profile>(source).ptr())); | 243 CHECK(profile_->IsSameProfile(content::Source<Profile>(source).ptr())); |
| 234 const Extension* extension = | 244 const Extension* extension = |
| 235 content::Details<const Extension>(details).ptr(); | 245 content::Details<const Extension>(details).ptr(); |
| 236 if (id_ == extension->id()) | 246 if (id_ == extension->id()) |
| 237 ReportSuccess(); | 247 ReportSuccess(); |
| 238 break; | 248 break; |
| 239 } | 249 } |
| 240 | 250 |
| 241 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: { | 251 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: { |
| 242 CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr(); | 252 CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr(); |
| 243 CHECK(crx_installer); | 253 CHECK(crx_installer); |
| 244 if (!profile_->IsSameProfile(crx_installer->profile())) | 254 if (!profile_->IsSameProfile(crx_installer->profile())) |
| 245 return; | 255 return; |
| 246 | 256 |
| 247 // TODO(rdevlin.cronin): Continue removing std::string errors and | 257 // TODO(rdevlin.cronin): Continue removing std::string errors and |
| 248 // replacing with string16 | 258 // replacing with string16 |
| 249 const string16* error = content::Details<const string16>(details).ptr(); | 259 const string16* error = content::Details<const string16>(details).ptr(); |
| 250 const std::string utf8_error = UTF16ToUTF8(*error); | 260 const std::string utf8_error = UTF16ToUTF8(*error); |
| 251 if (download_url_ == crx_installer->original_download_url()) | 261 if (download_url_ == crx_installer->original_download_url()) |
| 252 ReportFailure(utf8_error); | 262 ReportFailure(utf8_error, FAILURE_REASON_OTHER); |
| 253 break; | 263 break; |
| 254 } | 264 } |
| 255 | 265 |
| 256 default: | 266 default: |
| 257 NOTREACHED(); | 267 NOTREACHED(); |
| 258 } | 268 } |
| 259 } | 269 } |
| 260 | 270 |
| 261 void WebstoreInstaller::SetDownloadDirectoryForTests(FilePath* directory) { | 271 void WebstoreInstaller::SetDownloadDirectoryForTests(FilePath* directory) { |
| 262 g_download_directory_for_tests = directory; | 272 g_download_directory_for_tests = directory; |
| 263 } | 273 } |
| 264 | 274 |
| 265 WebstoreInstaller::~WebstoreInstaller() { | 275 WebstoreInstaller::~WebstoreInstaller() { |
| 266 if (download_item_) { | 276 if (download_item_) { |
| 267 download_item_->RemoveObserver(this); | 277 download_item_->RemoveObserver(this); |
| 268 download_item_ = NULL; | 278 download_item_ = NULL; |
| 269 } | 279 } |
| 270 } | 280 } |
| 271 | 281 |
| 272 void WebstoreInstaller::OnDownloadStarted(DownloadId id, net::Error error) { | 282 void WebstoreInstaller::OnDownloadStarted(DownloadId id, net::Error error) { |
| 273 if (error != net::OK) { | 283 if (error != net::OK) { |
| 274 ReportFailure(net::ErrorToString(error)); | 284 ReportFailure(net::ErrorToString(error), FAILURE_REASON_OTHER); |
| 275 return; | 285 return; |
| 276 } | 286 } |
| 277 | 287 |
| 278 CHECK(id.IsValid()); | 288 CHECK(id.IsValid()); |
| 279 | 289 |
| 280 DownloadManager* download_manager = | 290 DownloadManager* download_manager = |
| 281 BrowserContext::GetDownloadManager(profile_); | 291 BrowserContext::GetDownloadManager(profile_); |
| 282 if (!download_manager) | 292 if (!download_manager) |
| 283 return; | 293 return; |
| 284 download_item_ = download_manager->GetDownload(id.local()); | 294 download_item_ = download_manager->GetDownload(id.local()); |
| 285 // TODO(benjhayden): DCHECK(item && item->IsInProgress()) after investigating | 295 // TODO(benjhayden): DCHECK(item && item->IsInProgress()) after investigating |
| 286 // the relationship between net::OK and invalid id. | 296 // the relationship between net::OK and invalid id. |
| 287 if (download_item_) { | 297 if (download_item_) { |
| 288 download_item_->AddObserver(this); | 298 download_item_->AddObserver(this); |
| 289 if (approval_.get()) | 299 if (approval_.get()) |
| 290 download_item_->SetUserData(kApprovalKey, approval_.release()); | 300 download_item_->SetUserData(kApprovalKey, approval_.release()); |
| 301 if (delegate_) |
| 302 delegate_->OnExtensionDownloadStarted(id_, download_item_); |
| 291 } | 303 } |
| 292 } | 304 } |
| 293 | 305 |
| 294 void WebstoreInstaller::OnDownloadUpdated(DownloadItem* download) { | 306 void WebstoreInstaller::OnDownloadUpdated(DownloadItem* download) { |
| 295 CHECK_EQ(download_item_, download); | 307 CHECK_EQ(download_item_, download); |
| 296 | 308 |
| 297 switch (download->GetState()) { | 309 switch (download->GetState()) { |
| 298 case DownloadItem::CANCELLED: | 310 case DownloadItem::CANCELLED: |
| 299 ReportFailure(kDownloadCanceledError); | 311 ReportFailure(kDownloadCanceledError, FAILURE_REASON_CANCELLED); |
| 300 break; | 312 break; |
| 301 case DownloadItem::INTERRUPTED: | 313 case DownloadItem::INTERRUPTED: |
| 302 ReportFailure(kDownloadInterruptedError); | 314 ReportFailure(kDownloadInterruptedError, FAILURE_REASON_OTHER); |
| 303 break; | 315 break; |
| 304 case DownloadItem::COMPLETE: | 316 case DownloadItem::COMPLETE: |
| 305 // Wait for other notifications if the download is really an extension. | 317 // Wait for other notifications if the download is really an extension. |
| 306 if (!download_crx_util::IsExtensionDownload(*download)) | 318 if (!download_crx_util::IsExtensionDownload(*download)) |
| 307 ReportFailure(kInvalidDownloadError); | 319 ReportFailure(kInvalidDownloadError, FAILURE_REASON_OTHER); |
| 320 else if (delegate_) |
| 321 delegate_->OnExtensionDownloadProgress(id_, download); |
| 322 break; |
| 323 case DownloadItem::IN_PROGRESS: |
| 324 if (delegate_) |
| 325 delegate_->OnExtensionDownloadProgress(id_, download); |
| 308 break; | 326 break; |
| 309 default: | 327 default: |
| 310 // Continue listening if the download is not in one of the above states. | 328 // Continue listening if the download is not in one of the above states. |
| 311 break; | 329 break; |
| 312 } | 330 } |
| 313 } | 331 } |
| 314 | 332 |
| 315 void WebstoreInstaller::OnDownloadDestroyed(DownloadItem* download) { | 333 void WebstoreInstaller::OnDownloadDestroyed(DownloadItem* download) { |
| 316 CHECK_EQ(download_item_, download); | 334 CHECK_EQ(download_item_, download); |
| 317 download_item_->RemoveObserver(this); | 335 download_item_->RemoveObserver(this); |
| 318 download_item_ = NULL; | 336 download_item_ = NULL; |
| 319 } | 337 } |
| 320 | 338 |
| 321 void WebstoreInstaller::StartDownload(const FilePath& file) { | 339 void WebstoreInstaller::StartDownload(const FilePath& file) { |
| 322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 323 | 341 |
| 324 DownloadManager* download_manager = | 342 DownloadManager* download_manager = |
| 325 BrowserContext::GetDownloadManager(profile_); | 343 BrowserContext::GetDownloadManager(profile_); |
| 326 if (file.empty() || | 344 if (file.empty() || |
| 327 !download_manager || | 345 !download_manager || |
| 328 !controller_->GetWebContents() || | 346 !controller_->GetWebContents() || |
| 329 !controller_->GetWebContents()->GetRenderProcessHost() || | 347 !controller_->GetWebContents()->GetRenderProcessHost() || |
| 330 !controller_->GetWebContents()->GetRenderViewHost() || | 348 !controller_->GetWebContents()->GetRenderViewHost() || |
| 331 !controller_->GetWebContents()->GetBrowserContext() || | 349 !controller_->GetWebContents()->GetBrowserContext() || |
| 332 !controller_->GetWebContents()->GetBrowserContext() | 350 !controller_->GetWebContents()->GetBrowserContext() |
| 333 ->GetResourceContext()) { | 351 ->GetResourceContext()) { |
| 334 ReportFailure(kDownloadDirectoryError); | 352 ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER); |
| 335 return; | 353 return; |
| 336 } | 354 } |
| 337 | 355 |
| 338 content::DownloadSaveInfo save_info; | 356 content::DownloadSaveInfo save_info; |
| 339 save_info.file_path = file; | 357 save_info.file_path = file; |
| 340 | 358 |
| 341 // The download url for the given extension is contained in |download_url_|. | 359 // The download url for the given extension is contained in |download_url_|. |
| 342 // We will navigate the current tab to this url to start the download. The | 360 // We will navigate the current tab to this url to start the download. The |
| 343 // download system will then pass the crx to the CrxInstaller. | 361 // download system will then pass the crx to the CrxInstaller. |
| 344 download_util::RecordDownloadSource( | 362 download_util::RecordDownloadSource( |
| 345 download_util::INITIATED_BY_WEBSTORE_INSTALLER); | 363 download_util::INITIATED_BY_WEBSTORE_INSTALLER); |
| 346 scoped_ptr<DownloadUrlParameters> params( | 364 scoped_ptr<DownloadUrlParameters> params( |
| 347 DownloadUrlParameters::FromWebContents( | 365 DownloadUrlParameters::FromWebContents( |
| 348 controller_->GetWebContents(), download_url_, save_info)); | 366 controller_->GetWebContents(), download_url_, save_info)); |
| 349 if (controller_->GetActiveEntry()) | 367 if (controller_->GetActiveEntry()) |
| 350 params->set_referrer( | 368 params->set_referrer( |
| 351 content::Referrer(controller_->GetActiveEntry()->GetURL(), | 369 content::Referrer(controller_->GetActiveEntry()->GetURL(), |
| 352 WebKit::WebReferrerPolicyDefault)); | 370 WebKit::WebReferrerPolicyDefault)); |
| 353 params->set_callback(base::Bind(&WebstoreInstaller::OnDownloadStarted, this)); | 371 params->set_callback(base::Bind(&WebstoreInstaller::OnDownloadStarted, this)); |
| 354 download_manager->DownloadUrl(params.Pass()); | 372 download_manager->DownloadUrl(params.Pass()); |
| 355 } | 373 } |
| 356 | 374 |
| 357 void WebstoreInstaller::ReportFailure(const std::string& error) { | 375 void WebstoreInstaller::ReportFailure(const std::string& error, |
| 376 FailureReason reason) { |
| 358 if (delegate_) { | 377 if (delegate_) { |
| 359 delegate_->OnExtensionInstallFailure(id_, error); | 378 delegate_->OnExtensionInstallFailure(id_, error, reason); |
| 360 delegate_ = NULL; | 379 delegate_ = NULL; |
| 361 } | 380 } |
| 362 | 381 |
| 363 Release(); // Balanced in Start(). | 382 Release(); // Balanced in Start(). |
| 364 } | 383 } |
| 365 | 384 |
| 366 void WebstoreInstaller::ReportSuccess() { | 385 void WebstoreInstaller::ReportSuccess() { |
| 367 if (delegate_) { | 386 if (delegate_) { |
| 368 delegate_->OnExtensionInstallSuccess(id_); | 387 delegate_->OnExtensionInstallSuccess(id_); |
| 369 delegate_ = NULL; | 388 delegate_ = NULL; |
| 370 } | 389 } |
| 371 | 390 |
| 372 Release(); // Balanced in Start(). | 391 Release(); // Balanced in Start(). |
| 373 } | 392 } |
| 374 | 393 |
| 375 } // namespace extensions | 394 } // namespace extensions |
| OLD | NEW |