diff options
-rw-r--r-- | build/common.gypi | 13 | ||||
-rw-r--r-- | chrome/browser/chrome_browser_main.cc | 5 | ||||
-rw-r--r-- | chrome/browser/component_updater/cld_component_installer.cc | 157 | ||||
-rw-r--r-- | chrome/browser/component_updater/cld_component_installer.h | 24 | ||||
-rw-r--r-- | chrome/browser/component_updater/component_unpacker.cc | 7 | ||||
-rw-r--r-- | chrome/browser/component_updater/component_updater_service.cc | 22 | ||||
-rw-r--r-- | chrome/browser/component_updater/update_checker.cc | 4 | ||||
-rw-r--r-- | chrome/browser/component_updater/url_fetcher_downloader.cc | 8 | ||||
-rw-r--r-- | chrome/browser/translate/translate_tab_helper.cc | 10 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/common/chrome_paths.cc | 7 | ||||
-rw-r--r-- | chrome/common/chrome_paths.h | 2 | ||||
-rw-r--r-- | third_party/cld_2/crx_gen/manifest.json | 12 |
13 files changed, 272 insertions, 1 deletions
diff --git a/build/common.gypi b/build/common.gypi index df2858e..9fae86e 100644 --- a/build/common.gypi +++ b/build/common.gypi @@ -446,6 +446,14 @@ # be loaded at runtime. 'cld2_dynamic%': 0, + # Whether CLD2 is a component. Only evaluated if cld_version == 2 and + # cld2_dynamic == 1. + # 0: Not a component. If cld2_dynamic == 1, it is up to the distribution + # to ensure that the data file is provided if desired. + # 1: Componentized. CLD data should be obtained via the Component + # Updater. + 'cld2_is_component%': 0, + # Enable spell checker. 'enable_spellcheck%': 1, @@ -646,6 +654,7 @@ 'enable_google_now%': 0, 'cld_version%': 1, 'cld2_dynamic%': 0, + 'cld2_is_component%': 0, 'enable_spellcheck%': 0, 'enable_themes%': 0, 'remoting%': 0, @@ -1015,6 +1024,7 @@ 'cld_version%': '<(cld_version)', 'cld2_table_size%': '<(cld2_table_size)', 'cld2_dynamic%': '<(cld2_dynamic)', + 'cld2_is_component%': '<(cld2_is_component)', 'enable_captive_portal_detection%': '<(enable_captive_portal_detection)', 'disable_ftp_support%': '<(disable_ftp_support)', 'enable_task_manager%': '<(enable_task_manager)', @@ -2562,6 +2572,9 @@ ['cld2_dynamic!=0', { 'defines': ['CLD2_DYNAMIC_MODE=1'], }], + ['cld2_is_component!=0', { + 'defines': ['CLD2_IS_COMPONENT=1'], + }], ['enable_printing==1', { 'defines': ['ENABLE_FULL_PRINTING=1', 'ENABLE_PRINTING=1'], }], diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 558942f..19c4cad 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc @@ -42,6 +42,7 @@ #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/chrome_browser_main_extra_parts.h" +#include "chrome/browser/component_updater/cld_component_installer.h" #include "chrome/browser/component_updater/component_updater_service.h" #include "chrome/browser/component_updater/flash_component_installer.h" #include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h" @@ -406,6 +407,10 @@ void RegisterComponentsForUpdate(const CommandLine& command_line) { g_browser_process->crl_set_fetcher()->StartInitialLoad(cus); #endif +#if defined(CLD2_DYNAMIC_MODE) && defined(CLD2_IS_COMPONENT) + RegisterCldComponent(cus); +#endif + cus->Start(); } diff --git a/chrome/browser/component_updater/cld_component_installer.cc b/chrome/browser/component_updater/cld_component_installer.cc new file mode 100644 index 0000000..6e493ac --- /dev/null +++ b/chrome/browser/component_updater/cld_component_installer.cc @@ -0,0 +1,157 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/component_updater/cld_component_installer.h" + +#include "base/bind.h" +#include "base/file_util.h" +#include "base/files/file_path.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/platform_file.h" +#include "chrome/browser/component_updater/default_component_installer.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" +#include "content/public/browser/browser_thread.h" +#include "net/ssl/ssl_config_service.h" + +using component_updater::ComponentUpdateService; +using content::BrowserThread; + +namespace { + +// Once we have acquired a valid file from the component installer, we need to +// make the path available to other parts of the system such as the +// translation libraries. We create a global to hold onto the path, and a +// lock to guard it. See GetLatestCldDataFile(...) for more info. +base::LazyInstance<base::Lock> cld_file_lock = LAZY_INSTANCE_INITIALIZER; +base::LazyInstance<base::FilePath> cld_file = LAZY_INSTANCE_INITIALIZER; + +} + +namespace component_updater { + +// The SHA256 of the SubjectPublicKeyInfo used to sign the extension. +// The extension id is: dpedmmgabcgnikllifiidmijgoiihfgf +const uint8 kPublicKeySHA256[32] = { + 0x3f, 0x43, 0xcc, 0x60, 0x12, 0x6d, 0x8a, 0xbb, + 0x85, 0x88, 0x3c, 0x89, 0x6e, 0x88, 0x75, 0x65, + 0xb9, 0x46, 0x09, 0xe8, 0xca, 0x92, 0xdd, 0x82, + 0x4e, 0x6d, 0x0e, 0xe6, 0x79, 0x8a, 0x87, 0xf5 +}; + +const char kCldManifestName[] = "CLD2 Data"; + +class CldComponentInstallerTraits : public ComponentInstallerTraits { + public: + CldComponentInstallerTraits(); + virtual ~CldComponentInstallerTraits() {} + + private: + // The following methods override ComponentInstallerTraits. + virtual bool CanAutoUpdate() const OVERRIDE; + virtual bool OnCustomInstall(const base::DictionaryValue& manifest, + const base::FilePath& install_dir) OVERRIDE; + virtual bool VerifyInstallation( + const base::FilePath& install_dir) const OVERRIDE; + virtual void ComponentReady( + const base::Version& version, + const base::FilePath& path, + scoped_ptr<base::DictionaryValue> manifest) OVERRIDE; + virtual base::FilePath GetBaseDirectory() const OVERRIDE; + virtual void GetHash(std::vector<uint8>* hash) const OVERRIDE; + virtual std::string GetName() const OVERRIDE; + + base::FilePath GetInstalledPath(const base::FilePath& base) const; + void SetLatestCldDataFile(const base::FilePath& path); + DISALLOW_COPY_AND_ASSIGN(CldComponentInstallerTraits); +}; + +CldComponentInstallerTraits::CldComponentInstallerTraits() { +} + +bool CldComponentInstallerTraits::CanAutoUpdate() const { + return true; +} + +bool CldComponentInstallerTraits::OnCustomInstall( + const base::DictionaryValue& manifest, + const base::FilePath& install_dir) { + return true; // Nothing custom here. +} + +base::FilePath CldComponentInstallerTraits::GetInstalledPath( + const base::FilePath& base) const { + // Currently, all platforms have the file at the same location because there + // is no binary difference in the generated file on any supported platform. + // NB: This may change when 64-bit is officially supported. + return base.Append(FILE_PATH_LITERAL("_platform_specific")) + .Append(FILE_PATH_LITERAL("all")) + .Append(chrome::kCLDDataFilename); +} + +void CldComponentInstallerTraits::ComponentReady( + const base::Version& version, + const base::FilePath& path, + scoped_ptr<base::DictionaryValue> manifest) { + VLOG(1) << "Component ready, version " << version.GetString() + << " in " << path.value(); + SetLatestCldDataFile(GetInstalledPath(path)); +} + +bool CldComponentInstallerTraits::VerifyInstallation( + const base::FilePath& install_dir) const { + // We can't really do much to verify the CLD2 data file. In theory we could + // read the headers, but that won't do much other than tell us whether or + // not the headers are valid. So just check if the file exists. + const base::FilePath expected_file = GetInstalledPath(install_dir); + VLOG(1) << "Verifying install: " << expected_file.value(); + const bool result = base::PathExists(expected_file); + VLOG(1) << "Verification result: " << (result ? "valid" : "invalid"); + return result; +} + +base::FilePath CldComponentInstallerTraits::GetBaseDirectory() const { + base::FilePath result; + PathService::Get(chrome::DIR_COMPONENT_CLD2, &result); + return result; +} + +void CldComponentInstallerTraits::GetHash(std::vector<uint8>* hash) const { + hash->assign(kPublicKeySHA256, + kPublicKeySHA256 + arraysize(kPublicKeySHA256)); +} + +std::string CldComponentInstallerTraits::GetName() const { + return kCldManifestName; +} + +void RegisterCldComponent(ComponentUpdateService* cus) { + scoped_ptr<ComponentInstallerTraits> traits( + new CldComponentInstallerTraits()); + // |cus| will take ownership of |installer| during installer->Register(cus). + DefaultComponentInstaller* installer + = new DefaultComponentInstaller(traits.Pass()); + installer->Register(cus); +} + +// This method is completely threadsafe. +void CldComponentInstallerTraits::SetLatestCldDataFile( + const base::FilePath& path) { + VLOG(1) << "Setting CLD data file location: " << path.value(); + base::AutoLock lock(cld_file_lock.Get()); + cld_file.Get() = path; +} + +bool GetLatestCldDataFile(base::FilePath* path) { + base::AutoLock lock(cld_file_lock.Get()); + const base::FilePath cached = cld_file.Get(); + if (cached.empty()) return false; + *path = cached; + return true; +} + +} // namespace component_updater diff --git a/chrome/browser/component_updater/cld_component_installer.h b/chrome/browser/component_updater/cld_component_installer.h new file mode 100644 index 0000000..20a4b3c --- /dev/null +++ b/chrome/browser/component_updater/cld_component_installer.h @@ -0,0 +1,24 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COMPONENT_UPDATER_CLD_COMPONENT_INSTALLER_H_ +#define CHROME_BROWSER_COMPONENT_UPDATER_CLD_COMPONENT_INSTALLER_H_ + +#include "base/files/file_path.h" + +namespace component_updater { + +class ComponentUpdateService; + +void RegisterCldComponent(ComponentUpdateService* cus); + +// Places the path to the latest CLD data file into the specified path object. +// Returns true if and only if the file has been observed to exist at least +// once and was valid when it was observed; if the function returns false, the +// path parameter is not modified. This function is threadsafe. +bool GetLatestCldDataFile(base::FilePath* path); + +} // namespace component_updater + +#endif // CHROME_BROWSER_COMPONENT_UPDATER_CLD_COMPONENT_INSTALLER_H_ diff --git a/chrome/browser/component_updater/component_unpacker.cc b/chrome/browser/component_updater/component_unpacker.cc index 49aafac..48c584c 100644 --- a/chrome/browser/component_updater/component_unpacker.cc +++ b/chrome/browser/component_updater/component_unpacker.cc @@ -143,6 +143,7 @@ void ComponentUnpacker::Unpack(const Callback& callback) { } bool ComponentUnpacker::Verify() { + VLOG(1) << "Verifying component: " << path_.value(); if (pk_hash_.empty() || path_.empty()) { error_ = kInvalidParams; return false; @@ -171,23 +172,29 @@ bool ComponentUnpacker::Verify() { sha256->Finish(hash, arraysize(hash)); if (!std::equal(pk_hash_.begin(), pk_hash_.end(), hash)) { + VLOG(1) << "Hash mismatch: " << path_.value(); error_ = kInvalidId; return false; } + VLOG(1) << "Verification successful: " << path_.value(); return true; } bool ComponentUnpacker::Unzip() { base::FilePath& destination = is_delta_ ? unpack_diff_path_ : unpack_path_; + VLOG(1) << "Unpacking in: " << destination.value(); if (!base::CreateNewTempDirectory(base::FilePath::StringType(), &destination)) { + VLOG(1) << "Unable to create temporary directory for unpacking."; error_ = kUnzipPathError; return false; } if (!zip::Unzip(path_, destination)) { + VLOG(1) << "Unzipping failed."; error_ = kUnzipFailed; return false; } + VLOG(1) << "Unpacked successfully"; return true; } diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc index 2a8d14f..5d6e71d 100644 --- a/chrome/browser/component_updater/component_updater_service.cc +++ b/chrome/browser/component_updater/component_updater_service.cc @@ -313,12 +313,15 @@ ComponentUpdateService::Status CrxUpdateService::Start() { // Note that RegisterComponent will call Start() when the first // component is registered, so it can be called twice. This way // we avoid scheduling the timer if there is no work to do. + VLOG(1) << "CrxUpdateService starting up"; running_ = true; if (work_items_.empty()) return kOk; NotifyObservers(Observer::COMPONENT_UPDATER_STARTED, ""); + VLOG(1) << "First update attempt will take place in " + << config_->InitialDelay() << " seconds"; timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(config_->InitialDelay()), this, &CrxUpdateService::ProcessPendingItems); return kOk; @@ -327,6 +330,7 @@ ComponentUpdateService::Status CrxUpdateService::Start() { // Stop the main check + update loop. In flight operations will be // completed. ComponentUpdateService::Status CrxUpdateService::Stop() { + VLOG(1) << "CrxUpdateService stopping"; running_ = false; timer_.Stop(); return kOk; @@ -389,6 +393,7 @@ void CrxUpdateService::ScheduleNextRun(StepDelayInterval step_delay) { return; } + VLOG(1) << "Scheduling next run to occur in " << delay_seconds << " seconds"; timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(delay_seconds), this, &CrxUpdateService::ProcessPendingItems); } @@ -620,9 +625,18 @@ bool CrxUpdateService::CheckForUpdates() { if (!item->on_demand && time_since_last_checked < minimum_recheck_wait_time) { + VLOG(1) << "Skipping check for component update: id=" << item->id + << ", time_since_last_checked=" + << time_since_last_checked.InSeconds() + << " seconds: too soon to check for an update"; continue; } + VLOG(1) << "Scheduling update check for component id=" << item->id + << ", time_since_last_checked=" + << time_since_last_checked.InSeconds() + << " seconds"; + ChangeItemState(item, CrxUpdateItem::kChecking); item->last_check = now; @@ -710,6 +724,7 @@ void CrxUpdateService::OnUpdateCheckSucceeded( const UpdateResponse::Results& results) { size_t num_updates_pending = 0; DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + VLOG(1) << "Update check succeeded."; std::vector<UpdateResponse::Result>::const_iterator it; for (it = results.list.begin(); it != results.list.end(); ++it) { CrxUpdateItem* crx = FindUpdateItemById(it->extension_id); @@ -724,18 +739,21 @@ void CrxUpdateService::OnUpdateCheckSucceeded( if (it->manifest.version.empty()) { // No version means no update available. ChangeItemState(crx, CrxUpdateItem::kNoUpdate); + VLOG(1) << "No update available for component: " << crx->id; continue; } if (!IsVersionNewer(crx->component.version, it->manifest.version)) { // The component is up to date. ChangeItemState(crx, CrxUpdateItem::kUpToDate); + VLOG(1) << "Component already up-to-date: " << crx->id; continue; } if (!it->manifest.browser_min_version.empty()) { if (IsVersionNewer(chrome_version_, it->manifest.browser_min_version)) { // The component is not compatible with this Chrome version. + VLOG(1) << "Ignoring incompatible component: " << crx->id; ChangeItemState(crx, CrxUpdateItem::kNoUpdate); continue; } @@ -743,6 +761,7 @@ void CrxUpdateService::OnUpdateCheckSucceeded( if (it->manifest.packages.size() != 1) { // Assume one and only one package per component. + VLOG(1) << "Ignoring multiple packages for component: " << crx->id; ChangeItemState(crx, CrxUpdateItem::kNoUpdate); continue; } @@ -750,6 +769,8 @@ void CrxUpdateService::OnUpdateCheckSucceeded( // Parse the members of the result and queue an upgrade for this component. crx->next_version = Version(it->manifest.version); + VLOG(1) << "Update found for component: " << crx->id; + typedef UpdateResponse::Result::Manifest::Package Package; const Package& package(it->manifest.packages[0]); crx->next_fp = package.fingerprint; @@ -787,6 +808,7 @@ void CrxUpdateService::OnUpdateCheckFailed(int error, size_t count = ChangeItemStatus(CrxUpdateItem::kChecking, CrxUpdateItem::kNoUpdate); DCHECK_GT(count, 0ul); + VLOG(1) << "Update check failed."; ScheduleNextRun(kStepDelayLong); } diff --git a/chrome/browser/component_updater/update_checker.cc b/chrome/browser/component_updater/update_checker.cc index f1800cd..bd2fc0a 100644 --- a/chrome/browser/component_updater/update_checker.cc +++ b/chrome/browser/component_updater/update_checker.cc @@ -5,6 +5,7 @@ #include "chrome/browser/component_updater/update_checker.h" #include "base/compiler_specific.h" +#include "base/logging.h" #include "base/strings/stringprintf.h" #include "chrome/browser/component_updater/component_updater_utils.h" #include "chrome/browser/component_updater/crx_update_item.h" @@ -54,6 +55,7 @@ std::string BuildUpdateCheckRequest(const std::vector<CrxUpdateItem*>& items, } base::StringAppendF(&app, "</app>"); app_elements.append(app); + VLOG(1) << "Appending to update request: " << app; } return BuildProtocolRequest(app_elements, additional_attributes); @@ -140,10 +142,12 @@ void UpdateCheckerImpl::OnURLFetchComplete(const net::URLFetcher* source) { if (!update_response.Parse(xml)) { error = -1; error_message = update_response.errors(); + VLOG(1) << "Update request failed: " << error_message; } } else { error = GetFetchError(*source); error_message.assign("network error"); + VLOG(1) << "Update request failed: network error"; } url_fetcher_.reset(); diff --git a/chrome/browser/component_updater/url_fetcher_downloader.cc b/chrome/browser/component_updater/url_fetcher_downloader.cc index d2d2f31..39579cd 100644 --- a/chrome/browser/component_updater/url_fetcher_downloader.cc +++ b/chrome/browser/component_updater/url_fetcher_downloader.cc @@ -4,6 +4,7 @@ #include "chrome/browser/component_updater/url_fetcher_downloader.h" +#include "base/logging.h" #include "chrome/browser/component_updater/component_updater_utils.h" #include "content/public/browser/browser_thread.h" #include "net/base/load_flags.h" @@ -42,6 +43,7 @@ void UrlFetcherDownloader::DoStartDownload(const GURL& url) { url_fetcher_->SetAutomaticallyRetryOn5xx(false); url_fetcher_->SaveResponseToTemporaryFile(task_runner_); + VLOG(1) << "Starting background download: " << url.spec(); url_fetcher_->Start(); download_start_time_ = base::Time::Now(); @@ -78,6 +80,12 @@ void UrlFetcherDownloader::OnURLFetchComplete(const net::URLFetcher* source) { download_metrics.bytes_total = total_bytes_; download_metrics.download_time_ms = download_time.InMilliseconds(); + base::FilePath local_path_; + source->GetResponseAsFilePath(false, &local_path_); + VLOG(1) << "Downloaded " << downloaded_bytes_ << " bytes in " + << download_time.InMilliseconds() << "ms from " + << source->GetURL().spec() + << " to " << local_path_.value(); CrxDownloader::OnDownloadComplete(is_handled, result, download_metrics); } diff --git a/chrome/browser/translate/translate_tab_helper.cc b/chrome/browser/translate/translate_tab_helper.cc index 3ad5942..9af958f7 100644 --- a/chrome/browser/translate/translate_tab_helper.cc +++ b/chrome/browser/translate/translate_tab_helper.cc @@ -43,6 +43,10 @@ #include "content/public/browser/render_view_host.h" #endif +#if defined(CLD2_IS_COMPONENT) +#include "chrome/browser/component_updater/cld_component_installer.h" +#endif + namespace { // The maximum number of attempts we'll do to see if the page has finshed @@ -387,16 +391,20 @@ void TranslateTabHelper::HandleCLDDataRequest() { } base::FilePath path; +#if defined(CLD2_IS_COMPONENT) + if (!component_updater::GetLatestCldDataFile(&path)) + return; +#else if (!PathService::Get(chrome::DIR_USER_DATA, &path)) { LOG(WARNING) << "Unable to locate user data directory"; return; // Chrome isn't properly installed. } - // If the file exists, we can send an IPC-safe construct back to the // renderer process immediately. path = path.Append(chrome::kCLDDataFilename); if (!base::PathExists(path)) return; +#endif // Attempt to open the file for reading. scoped_ptr<base::File> file( diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 8983941..851ab1aa 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -430,6 +430,8 @@ 'browser/common/cancelable_request.h', 'browser/component_updater/background_downloader_win.cc', 'browser/component_updater/background_downloader_win.h', + 'browser/component_updater/cld_component_installer.cc', + 'browser/component_updater/cld_component_installer.h', 'browser/component_updater/component_patcher.cc', 'browser/component_updater/component_patcher.h', 'browser/component_updater/component_patcher_operation.cc', diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc index 352b51a..0cdfbd40 100644 --- a/chrome/common/chrome_paths.cc +++ b/chrome/common/chrome_paths.cc @@ -364,6 +364,13 @@ bool PathProvider(int key, base::FilePath* result) { cur = cur.Append(kGTalkPluginFileName); break; #endif +#if defined(CLD2_IS_COMPONENT) + case chrome::DIR_COMPONENT_CLD2: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("CLD")); + break; +#endif // defined(CLD2_IS_COMPONENT) #if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) #if defined(WIDEVINE_CDM_IS_COMPONENT) case chrome::DIR_COMPONENT_WIDEVINE_CDM: diff --git a/chrome/common/chrome_paths.h b/chrome/common/chrome_paths.h index e03fe9f..407715d 100644 --- a/chrome/common/chrome_paths.h +++ b/chrome/common/chrome_paths.h @@ -94,6 +94,8 @@ enum { FILE_O1D_PLUGIN, // Full path to the O1D Pepper plugin file. FILE_EFFECTS_PLUGIN, // Full path to the Effects Pepper plugin file. FILE_GTALK_PLUGIN, // Full path to the GTalk Pepper plugin file. + DIR_COMPONENT_CLD2, // Directory that contains component-updated + // Compact Language Detector files DIR_COMPONENT_WIDEVINE_CDM, // Directory that contains component-updated // Widevine CDM files. FILE_WIDEVINE_CDM_ADAPTER, // Full path to the Widevine CDM adapter file. diff --git a/third_party/cld_2/crx_gen/manifest.json b/third_party/cld_2/crx_gen/manifest.json new file mode 100644 index 0000000..4b3a098 --- /dev/null +++ b/third_party/cld_2/crx_gen/manifest.json @@ -0,0 +1,12 @@ +{ + "manifest_version": 2, + "name": "CLD2 Data", + "description": "Compact Language Detector 2 (CLD2) data for Chrome", + "minimum_chrome_version": "36", + "version": "160", + "platforms": [ + { + "sub_package_path": "_platform_specific/all/" + } + ] +}
\ No newline at end of file |