15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/webstore_installer.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include <vector> 88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/metrics/field_trial.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/metrics/histogram.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/metrics/sparse_histogram.h" 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/path_service.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/time/time.h" 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/download_crx_util.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/download_prefs.h" 26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/download/download_stats.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/crx_installer.h" 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/extensions/install_tracker.h" 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/extensions/install_tracker_factory.h" 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/install_verifier.h" 31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/shared_module_service.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/common/chrome_paths.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h" 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/omaha_query_params/omaha_query_params.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_manager.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_save_info.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_url_parameters.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/render_process_host.h" 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/render_view_host.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_registry.h" 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/extension_urls.h" 553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest_constants.h" 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/shared_module_info.h" 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h" 587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h" 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserContext; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadItem; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadManager; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadUrlParameters; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Key used to attach the Approval to the DownloadItem. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kApprovalKey[] = "extensions.webstore_installer"; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidIdError[] = "Invalid id"; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDownloadDirectoryError[] = "Could not create download directory"; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDownloadCanceledError[] = "Download canceled"; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDownloadInterruptedError[] = "Download interrupted"; 80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kInvalidDownloadError[] = 81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "Download was not a valid extension or user script"; 828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const char kDependencyNotFoundError[] = "Dependency not found"; 838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const char kDependencyNotSharedModuleError[] = 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "Dependency is not shared module"; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInlineInstallSource[] = "inline"; 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char kDefaultInstallSource[] = "ondemand"; 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kAppLauncherInstallSource[] = "applauncher"; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 890de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// TODO(rockot): Share this duplicated constant with the extension updater. 900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// See http://crbug.com/371398. 910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)const char kAuthUserQueryKey[] = "authuser"; 920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst size_t kTimeRemainingMinutesThreshold = 1u; 94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Folder for downloading crx files from the webstore. This is used so that the 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// crx files don't go via the usual downloads folder. 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const base::FilePath::CharType kWebstoreDownloadFolder[] = 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FILE_PATH_LITERAL("Webstore Downloads"); 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath* g_download_directory_for_tests = NULL; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Must be executed on the FILE thread. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetDownloadFilePath( 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::FilePath& download_directory, 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& id, 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Callback<void(const base::FilePath&)>& callback) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure the download directory exists. TODO(asargent) - make this use 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // common code from the downloads system. 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::DirectoryExists(download_directory)) { 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::CreateDirectory(download_directory)) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(callback, base::FilePath())); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is to help avoid a race condition between when we generate this 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // filename and when the download starts writing to it (think concurrently 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // running sharded browser tests installing the same test file, for 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instance). 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string random_number = 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Uint64ToString(base::RandGenerator(kuint16max)); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file = 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) download_directory.AppendASCII(id + "_" + random_number + ".crx"); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int uniquifier = 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::GetUniquePathNumber(file, base::FilePath::StringType()); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (uniquifier > 0) { 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file = file.InsertBeforeExtensionASCII( 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StringPrintf(" (%d)", uniquifier)); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(callback, file)); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void MaybeAppendAuthUserParameter(const std::string& authuser, GURL* url) { 1390de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (authuser.empty()) 1400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return; 1410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) std::string old_query = url->query(); 1420de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) url::Component query(0, old_query.length()); 1430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) url::Component key, value; 1440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // Ensure that the URL doesn't already specify an authuser parameter. 1450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) while (url::ExtractQueryKeyValue( 1460de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) old_query.c_str(), &query, &key, &value)) { 1470de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) std::string key_string = old_query.substr(key.begin, key.len); 1480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (key_string == kAuthUserQueryKey) { 1490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return; 1500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 1510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 1520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (!old_query.empty()) { 1530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) old_query += "&"; 1540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 1550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) std::string authuser_param = base::StringPrintf( 1560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) "%s=%s", 1570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kAuthUserQueryKey, 1580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) authuser.c_str()); 1590de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 1600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // TODO(rockot): Share this duplicated code with the extension updater. 1610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // See http://crbug.com/371398. 1620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) std::string new_query_string = old_query + authuser_param; 1630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) url::Component new_query(0, new_query_string.length()); 1640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) url::Replacements<char> replacements; 1650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) replacements.SetQuery(new_query_string.c_str(), new_query); 1660de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) *url = url->ReplaceComponents(replacements); 1670de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 1680de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL WebstoreInstaller::GetWebstoreInstallURL( 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& extension_id, 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) InstallSource source) { 1778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string install_source; 1788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) switch (source) { 1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) case INSTALL_SOURCE_INLINE: 1808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) install_source = kInlineInstallSource; 1818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) break; 1828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) case INSTALL_SOURCE_APP_LAUNCHER: 1838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) install_source = kAppLauncherInstallSource; 1848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) break; 1858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) case INSTALL_SOURCE_OTHER: 1868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) install_source = kDefaultInstallSource; 1878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (cmd_line->HasSwitch(switches::kAppsGalleryDownloadURL)) { 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string download_url = 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd_line->GetSwitchValueASCII(switches::kAppsGalleryDownloadURL); 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(base::StringPrintf(download_url.c_str(), 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_id.c_str())); 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector<std::string> params; 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) params.push_back("id=" + extension_id); 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!install_source.empty()) 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) params.push_back("installsource=" + install_source); 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) params.push_back("uc"); 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string url_string = extension_urls::GetWebstoreUpdateUrl().spec(); 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL url(url_string + "?response=redirect&" + 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch omaha_query_params::OmahaQueryParams::Get( 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch omaha_query_params::OmahaQueryParams::CRX) + 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch "&x=" + net::EscapeQueryParamValue(JoinString(params, '&'), true)); 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(url.is_valid()); 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return url; 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreInstaller::Delegate::OnExtensionDownloadStarted( 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& id, 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::DownloadItem* item) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreInstaller::Delegate::OnExtensionDownloadProgress( 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& id, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::DownloadItem* item) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebstoreInstaller::Approval::Approval() 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : profile(NULL), 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_app_installed_bubble(false), 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) skip_post_install_ui(false), 2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch skip_install_dialog(false), 227424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) enable_launcher(false), 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) manifest_check_level(MANIFEST_CHECK_LEVEL_STRICT), 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) is_ephemeral(false) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<WebstoreInstaller::Approval> 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebstoreInstaller::Approval::CreateWithInstallPrompt(Profile* profile) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Approval> result(new Approval()); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->profile = profile; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result.Pass(); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<WebstoreInstaller::Approval> 2408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)WebstoreInstaller::Approval::CreateForSharedModule(Profile* profile) { 2418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) scoped_ptr<Approval> result(new Approval()); 2428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) result->profile = profile; 2438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) result->skip_install_dialog = true; 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result->skip_post_install_ui = true; 2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) result->manifest_check_level = MANIFEST_CHECK_LEVEL_NONE; 2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return result.Pass(); 2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 2488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 2498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)scoped_ptr<WebstoreInstaller::Approval> 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebstoreInstaller::Approval::CreateWithNoInstallPrompt( 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 253424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) scoped_ptr<base::DictionaryValue> parsed_manifest, 254424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool strict_manifest_check) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Approval> result(new Approval()); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->extension_id = extension_id; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->profile = profile; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->manifest = scoped_ptr<Manifest>( 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new Manifest(Manifest::INVALID_LOCATION, 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue>( 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parsed_manifest->DeepCopy()))); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->skip_install_dialog = true; 2638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) result->manifest_check_level = strict_manifest_check ? 2648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) MANIFEST_CHECK_LEVEL_STRICT : MANIFEST_CHECK_LEVEL_LOOSE; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result.Pass(); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebstoreInstaller::Approval::~Approval() {} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const WebstoreInstaller::Approval* WebstoreInstaller::GetAssociatedApproval( 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DownloadItem& download) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<const Approval*>(download.GetUserData(kApprovalKey)); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebstoreInstaller::WebstoreInstaller(Profile* profile, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate, 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::WebContents* web_contents, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& id, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Approval> approval, 28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) InstallSource source) 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : content::WebContentsObserver(web_contents), 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_registry_observer_(this), 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile_(profile), 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_(delegate), 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_(id), 2868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) install_source_(source), 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_item_(NULL), 2888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) approval_(approval.release()), 2898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) total_modules_(0), 2908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) download_started_(false) { 291effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(web_contents); 29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) registrar_.Add(this, 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR, 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<CrxInstaller>(NULL)); 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_registry_observer_.Add(ExtensionRegistry::Get(profile)); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreInstaller::Start() { 301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddRef(); // Balanced in ReportSuccess and ReportFailure. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!crx_file::id_util::IdIsValid(id_)) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure(kInvalidIdError, FAILURE_REASON_OTHER); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ExtensionService* extension_service = 3108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ExtensionSystem::Get(profile_)->extension_service(); 3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (approval_.get() && approval_->dummy_extension.get()) { 3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_service->shared_module_service()->CheckImports( 3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci approval_->dummy_extension.get(), &pending_modules_, &pending_modules_); 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Do not check the return value of CheckImports, the CRX installer 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // will report appropriate error messages and fail to install if there 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // is an import error. 3178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 3188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 3198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Add the extension main module into the list. 3208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SharedModuleInfo::ImportInfo info; 3218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) info.extension_id = id_; 3228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) pending_modules_.push_back(info); 3238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 3248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) total_modules_ = pending_modules_.size(); 3258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::set<std::string> ids; 327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::list<SharedModuleInfo::ImportInfo>::const_iterator i; 328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (i = pending_modules_.begin(); i != pending_modules_.end(); ++i) { 329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ids.insert(i->extension_id); 330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ExtensionSystem::Get(profile_)->install_verifier()->AddProvisional(ids); 332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string name; 3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!approval_->manifest->value()->GetString(manifest_keys::kName, &name)) { 335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch extensions::InstallTracker* tracker = 3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::InstallTrackerFactory::GetForBrowserContext(profile_); 339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::InstallObserver::ExtensionInstallParams params( 340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) id_, 341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) name, 342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) approval_->installing_icon, 343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) approval_->manifest->is_app(), 344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch approval_->manifest->is_platform_app()); 345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) params.is_ephemeral = approval_->is_ephemeral; 346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) tracker->OnBeginExtensionInstall(params); 347effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 348effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch tracker->OnBeginExtensionDownload(id_); 349effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 350effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // TODO(crbug.com/305343): Query manifest of dependencies before 351effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // downloading & installing those dependencies. 352effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DownloadNextPendingModule(); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreInstaller::Observe(int type, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR: { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr(); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(crx_installer); 3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (crx_installer != crx_installer_.get()) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rdevlin.cronin): Continue removing std::string errors and 366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // replacing with base::string16. See crbug.com/71980. 367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16* error = 368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) content::Details<const base::string16>(details).ptr(); 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string utf8_error = base::UTF16ToUTF8(*error); 3700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch crx_installer_ = NULL; 3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // ReportFailure releases a reference to this object so it must be the 3720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // last operation in this method. 3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReportFailure(utf8_error, FAILURE_REASON_OTHER); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void WebstoreInstaller::OnExtensionInstalled( 383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Extension* extension, 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool is_update) { 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECK(profile_->IsSameProfile(Profile::FromBrowserContext(browser_context))); 387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (pending_modules_.empty()) 388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SharedModuleInfo::ImportInfo info = pending_modules_.front(); 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (extension->id() != info.extension_id) 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pending_modules_.pop_front(); 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Clean up local state from the current download. 395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (download_item_) { 396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch download_item_->RemoveObserver(this); 397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch download_item_->Remove(); 398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch download_item_ = NULL; 399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crx_installer_ = NULL; 401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (pending_modules_.empty()) { 403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECK_EQ(extension->id(), id_); 404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ReportSuccess(); 405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Version version_required(info.minimum_version); 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (version_required.IsValid() && 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension->version()->CompareTo(version_required) < 0) { 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // It should not happen, CrxInstaller will make sure the version is 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // equal or newer than version_required. 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ReportFailure(kDependencyNotFoundError, 412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FAILURE_REASON_DEPENDENCY_NOT_FOUND); 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (!SharedModuleInfo::IsSharedModule(extension)) { 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // It should not happen, CrxInstaller will make sure it is a shared 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // module. 416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ReportFailure(kDependencyNotSharedModuleError, 417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE); 418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DownloadNextPendingModule(); 420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreInstaller::InvalidateDelegate() { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_ = NULL; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebstoreInstaller::SetDownloadDirectoryForTests( 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath* directory) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_download_directory_for_tests = directory; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebstoreInstaller::~WebstoreInstaller() { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (download_item_) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_item_->RemoveObserver(this); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_item_ = NULL; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreInstaller::OnDownloadStarted( 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DownloadItem* item, 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::DownloadInterruptReason interrupt_reason) { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!item) { 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_NE(content::DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason); 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReportFailure(content::DownloadInterruptReasonToString(interrupt_reason), 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FAILURE_REASON_OTHER); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason); 4518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(!pending_modules_.empty()); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_item_ = item; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_item_->AddObserver(this); 4548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (pending_modules_.size() > 1) { 4558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // We are downloading a shared module. We need create an approval for it. 4568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) scoped_ptr<Approval> approval = Approval::CreateForSharedModule(profile_); 4578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const SharedModuleInfo::ImportInfo& info = pending_modules_.front(); 4588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) approval->extension_id = info.extension_id; 4598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const Version version_required(info.minimum_version); 4608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 4618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (version_required.IsValid()) { 4628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) approval->minimum_version.reset( 4638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) new Version(version_required)); 4648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 4658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) download_item_->SetUserData(kApprovalKey, approval.release()); 4668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else { 4678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // It is for the main module of the extension. We should use the provided 4688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // |approval_|. 4698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (approval_) 4708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) download_item_->SetUserData(kApprovalKey, approval_.release()); 4718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 4728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 4738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!download_started_) { 4748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (delegate_) 4758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) delegate_->OnExtensionDownloadStarted(id_, download_item_); 4768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) download_started_ = true; 4778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreInstaller::OnDownloadUpdated(DownloadItem* download) { 481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHECK_EQ(download_item_, download); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (download->GetState()) { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DownloadItem::CANCELLED: 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure(kDownloadCanceledError, FAILURE_REASON_CANCELLED); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DownloadItem::INTERRUPTED: 488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RecordInterrupt(download); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure(kDownloadInterruptedError, FAILURE_REASON_OTHER); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DownloadItem::COMPLETE: 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for other notifications if the download is really an extension. 493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!download_crx_util::IsExtensionDownload(*download)) { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure(kInvalidDownloadError, FAILURE_REASON_OTHER); 4950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 4960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (crx_installer_.get()) 4970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; // DownloadItemImpl calls the observer twice, ignore it. 4980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch StartCrxInstaller(*download); 4990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 500116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (pending_modules_.size() == 1) { 5010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The download is the last module - the extension main module. 5020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (delegate_) 5030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch delegate_->OnExtensionDownloadProgress(id_, download); 5040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch extensions::InstallTracker* tracker = 5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::InstallTrackerFactory::GetForBrowserContext(profile_); 5060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch tracker->OnDownloadProgress(id_, 100); 5070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 509effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Stop the progress timer if it's running. 510effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch download_progress_timer_.Stop(); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case DownloadItem::IN_PROGRESS: { 5138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (delegate_ && pending_modules_.size() == 1) { 5148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Only report download progress for the main module to |delegrate_|. 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnExtensionDownloadProgress(id_, download); 5168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 517effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UpdateDownloadProgress(); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Continue listening if the download is not in one of the above states. 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreInstaller::OnDownloadDestroyed(DownloadItem* download) { 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(download_item_, download); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_item_->RemoveObserver(this); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_item_ = NULL; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void WebstoreInstaller::DownloadNextPendingModule() { 5338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CHECK(!pending_modules_.empty()); 5348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (pending_modules_.size() == 1) { 5358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK_EQ(id_, pending_modules_.front().extension_id); 5368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DownloadCrx(id_, install_source_); 5378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else { 5388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DownloadCrx(pending_modules_.front().extension_id, INSTALL_SOURCE_OTHER); 5398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 5408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 5418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void WebstoreInstaller::DownloadCrx( 543f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& extension_id, 544f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) InstallSource source) { 5458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) download_url_ = GetWebstoreInstallURL(extension_id, source); 5460de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) MaybeAppendAuthUserParameter(approval_->authuser, &download_url_); 547f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath user_data_dir; 549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); 550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath download_path = user_data_dir.Append(kWebstoreDownloadFolder); 551f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath download_directory(g_download_directory_for_tests ? 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *g_download_directory_for_tests : download_path); 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS) 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Do not use drive for extension downloads. 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (drive::util::IsUnderDriveMountPoint(download_directory)) { 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) download_directory = DownloadPrefs::FromBrowserContext( 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile_)->GetDefaultDownloadDirectoryForProfile(); 5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) BrowserThread::PostTask( 5648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) BrowserThread::FILE, FROM_HERE, 565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&GetDownloadFilePath, download_directory, extension_id, 5668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::Bind(&WebstoreInstaller::StartDownload, this))); 5678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 5688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// http://crbug.com/165634 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// http://crbug.com/126013 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The current working theory is that one of the many pointers dereferenced in 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// here is occasionally deleted before all of its referers are nullified, 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// probably in a callback race. After this comment is released, the crash 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// reports should narrow down exactly which pointer it is. Collapsing all the 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// early-returns into a single branch makes it hard to see exactly which pointer 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// it is. 5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebstoreInstaller::StartDownload(const base::FilePath& file) { 578effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (file.empty()) { 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER); 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DownloadManager* download_manager = 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserContext::GetDownloadManager(profile_); 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!download_manager) { 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER); 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::WebContents* contents = web_contents(); 5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!contents) { 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER); 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!contents->GetRenderProcessHost()) { 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER); 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!contents->GetRenderViewHost()) { 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER); 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::NavigationController& controller = contents->GetController(); 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!controller.GetBrowserContext()) { 6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER); 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!controller.GetBrowserContext()->GetResourceContext()) { 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The download url for the given extension is contained in |download_url_|. 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will navigate the current tab to this url to start the download. The 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // download system will then pass the crx to the CrxInstaller. 619ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch RecordDownloadSource(DOWNLOAD_INITIATED_BY_WEBSTORE_INSTALLER); 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int render_process_host_id = contents->GetRenderProcessHost()->GetID(); 6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int render_view_host_routing_id = 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) contents->GetRenderViewHost()->GetRoutingID(); 6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::ResourceContext* resource_context = 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller.GetBrowserContext()->GetResourceContext(); 6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<DownloadUrlParameters> params(new DownloadUrlParameters( 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) download_url_, 6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_process_host_id, 6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_view_host_routing_id , 6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource_context)); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->set_file_path(file); 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (controller.GetVisibleEntry()) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->set_referrer( 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::Referrer(controller.GetVisibleEntry()->GetURL(), 634f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebReferrerPolicyDefault)); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->set_callback(base::Bind(&WebstoreInstaller::OnDownloadStarted, this)); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_manager->DownloadUrl(params.Pass()); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 639effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid WebstoreInstaller::UpdateDownloadProgress() { 640effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If the download has gone away, or isn't in progress (in which case we can't 641effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // give a good progress estimate), stop any running timers and return. 642effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!download_item_ || 643effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch download_item_->GetState() != DownloadItem::IN_PROGRESS) { 644effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch download_progress_timer_.Stop(); 645effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 646effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 647effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 648effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int percent = download_item_->PercentComplete(); 649116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Only report progress if percent is more than 0 or we have finished 650116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // downloading at least one of the pending modules. 651116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int finished_modules = total_modules_ - pending_modules_.size(); 652116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (finished_modules > 0 && percent < 0) 653116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch percent = 0; 654effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (percent >= 0) { 655effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch percent = (percent + (finished_modules * 100)) / total_modules_; 656effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch extensions::InstallTracker* tracker = 6575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::InstallTrackerFactory::GetForBrowserContext(profile_); 658effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch tracker->OnDownloadProgress(id_, percent); 659effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 660effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 661effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If there's enough time remaining on the download to warrant an update, 662effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // set the timer (overwriting any current timers). Otherwise, stop the 663effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // timer. 664effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::TimeDelta time_remaining; 665effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (download_item_->TimeRemaining(&time_remaining) && 666effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch time_remaining > 667effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::TimeDelta::FromSeconds(kTimeRemainingMinutesThreshold)) { 668effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch download_progress_timer_.Start( 669effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 670effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::TimeDelta::FromSeconds(kTimeRemainingMinutesThreshold), 671effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch this, 672effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &WebstoreInstaller::UpdateDownloadProgress); 673effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 674effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch download_progress_timer_.Stop(); 675effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 676effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 677effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 6780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid WebstoreInstaller::StartCrxInstaller(const DownloadItem& download) { 6790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 6800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!crx_installer_.get()); 6810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ExtensionService* service = ExtensionSystem::Get(profile_)-> 6830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch extension_service(); 6840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CHECK(service); 6850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const Approval* approval = GetAssociatedApproval(download); 6870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(approval); 6880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch crx_installer_ = download_crx_util::CreateCrxInstaller(profile_, download); 6900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch crx_installer_->set_expected_id(approval->extension_id); 6920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch crx_installer_->set_is_gallery_install(true); 6930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch crx_installer_->set_allow_silent_install(true); 6940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch crx_installer_->InstallCrx(download.GetFullPath()); 6960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 6970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreInstaller::ReportFailure(const std::string& error, 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FailureReason reason) { 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delegate_) { 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnExtensionInstallFailure(id_, error, reason); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_ = NULL; 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch extensions::InstallTracker* tracker = 7065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::InstallTrackerFactory::GetForBrowserContext(profile_); 707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch tracker->OnInstallFailure(id_); 708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); // Balanced in Start(). 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreInstaller::ReportSuccess() { 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delegate_) { 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnExtensionInstallSuccess(id_); 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_ = NULL; 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); // Balanced in Start(). 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 721f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WebstoreInstaller::RecordInterrupt(const DownloadItem* download) const { 722f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.WebstoreDownload.InterruptReason", 723f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) download->GetLastReason()); 724f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 725f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Use logarithmic bin sizes up to 1 TB. 726f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const int kNumBuckets = 30; 727f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const int64 kMaxSizeKb = 1 << kNumBuckets; 728f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS( 729f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "Extensions.WebstoreDownload.InterruptReceivedKBytes", 730f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) download->GetReceivedBytes() / 1024, 731f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1, 732f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) kMaxSizeKb, 733f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) kNumBuckets); 734f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64 total_bytes = download->GetTotalBytes(); 735f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (total_bytes >= 0) { 736f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS( 737f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "Extensions.WebstoreDownload.InterruptTotalKBytes", 738f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) total_bytes / 1024, 739f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1, 740f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) kMaxSizeKb, 741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) kNumBuckets); 742f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN( 744f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "Extensions.WebstoreDownload.InterruptTotalSizeUnknown", 745f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) total_bytes <= 0); 746f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 747f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 749