| Index: chrome/browser/chromeos/customization_document.cc
|
| ===================================================================
|
| --- chrome/browser/chromeos/customization_document.cc (revision 83304)
|
| +++ chrome/browser/chromeos/customization_document.cc (working copy)
|
| @@ -1,14 +1,22 @@
|
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| +// Copyright (c) 2011 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/chromeos/customization_document.h"
|
|
|
| +#include "base/file_path.h"
|
| #include "base/file_util.h"
|
| #include "base/json/json_reader.h"
|
| #include "base/logging.h"
|
| #include "base/string_tokenizer.h"
|
| #include "base/string_util.h"
|
| +#include "chrome/browser/browser_process.h"
|
| +#include "chrome/browser/chromeos/cros/cros_library.h"
|
| +#include "chrome/browser/chromeos/cros/network_library.h"
|
| +#include "chrome/browser/chromeos/system_access.h"
|
| +#include "chrome/browser/prefs/pref_service.h"
|
| +#include "chrome/browser/profiles/profile_manager.h"
|
| +#include "content/browser/browser_thread.h"
|
|
|
| // Manifest attributes names.
|
|
|
| @@ -31,14 +39,34 @@
|
|
|
| const char kAcceptedManifestVersion[] = "1.0";
|
|
|
| -const char kHWIDPath[] = "/sys/devices/platform/chromeos_acpi/HWID";
|
| -const char kVPDPath[] = "/var/log/vpd_2.0.txt";
|
| +const char kHwid[] = "hwid";
|
|
|
| +// Path to OEM partner startup customization manifest.
|
| +const char kStartupCustomizationManifestPath[] =
|
| + "/opt/oem/etc/startup_manifest.json";
|
| +
|
| +// URL where to fetch OEM services customization manifest from.
|
| +const char kServicesCustomizationManifestUrl[] =
|
| + "file:///opt/oem/etc/services_manifest.json";
|
| +
|
| +// Name of local state option that tracks if services customization has been
|
| +// applied.
|
| +const char kServicesCustomizationAppliedPref[] = "ServicesCustomizationApplied";
|
| +
|
| +// Maximum number of retries to fetch file if network is not available.
|
| +const int kMaxFetchRetries = 3;
|
| +
|
| +// Delay between file fetch retries if network is not available.
|
| +const int kRetriesDelayInSec = 2;
|
| +
|
| } // anonymous namespace
|
|
|
| +DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::ServicesCustomizationDocument);
|
| +
|
| namespace chromeos {
|
|
|
| -// CustomizationDocument implementation.
|
| +// CustomizationDocument implementation. ---------------------------------------
|
| +
|
| bool CustomizationDocument::LoadManifestFromFile(
|
| const FilePath& manifest_path) {
|
| std::string manifest;
|
| @@ -72,7 +100,8 @@
|
| const std::string& dictionary_name,
|
| const std::string& entry_name) const {
|
| DictionaryValue* dictionary_content = NULL;
|
| - if (!root_->GetDictionary(dictionary_name, &dictionary_content))
|
| + if (!root_.get() ||
|
| + !root_->GetDictionary(dictionary_name, &dictionary_content))
|
| return std::string();
|
|
|
| DictionaryValue* locale_dictionary = NULL;
|
| @@ -92,20 +121,40 @@
|
| return std::string();
|
| }
|
|
|
| -// StartupCustomizationDocument implementation.
|
| -bool StartupCustomizationDocument::LoadManifestFromString(
|
| - const std::string& manifest) {
|
| - if (!CustomizationDocument::LoadManifestFromString(manifest)) {
|
| - return false;
|
| +// StartupCustomizationDocument implementation. --------------------------------
|
| +
|
| +StartupCustomizationDocument::StartupCustomizationDocument() {
|
| + {
|
| + // Loading manifest causes us to do blocking IO on UI thread.
|
| + // Temporarily allow it until we fix http://crosbug.com/11103
|
| + base::ThreadRestrictions::ScopedAllowIO allow_io;
|
| + LoadManifestFromFile(FilePath(kStartupCustomizationManifestPath));
|
| }
|
| + Init(SystemAccess::GetInstance());
|
| +}
|
|
|
| +StartupCustomizationDocument::StartupCustomizationDocument(
|
| + SystemAccess* system_access, const std::string& manifest) {
|
| + LoadManifestFromString(manifest);
|
| + Init(system_access);
|
| +}
|
| +
|
| +StartupCustomizationDocument* StartupCustomizationDocument::GetInstance() {
|
| + return Singleton<StartupCustomizationDocument,
|
| + DefaultSingletonTraits<StartupCustomizationDocument> >::get();
|
| +}
|
| +
|
| +void StartupCustomizationDocument::Init(SystemAccess* system_access) {
|
| + if (!IsReady())
|
| + return;
|
| +
|
| root_->GetString(kInitialLocaleAttr, &initial_locale_);
|
| root_->GetString(kInitialTimezoneAttr, &initial_timezone_);
|
| root_->GetString(kKeyboardLayoutAttr, &keyboard_layout_);
|
| root_->GetString(kRegistrationUrlAttr, ®istration_url_);
|
|
|
| - std::string hwid = GetHWID();
|
| - if (!hwid.empty()) {
|
| + std::string hwid;
|
| + if (system_access->GetMachineStatistic(kHwid, &hwid)) {
|
| ListValue* hwid_list = NULL;
|
| if (root_->GetList(kHwidMapAttr, &hwid_list)) {
|
| for (size_t i = 0; i < hwid_list->GetSize(); ++i) {
|
| @@ -133,101 +182,122 @@
|
| }
|
| }
|
| } else {
|
| - LOG(ERROR) << "Can't read HWID from " << kHWIDPath;
|
| + LOG(ERROR) << "HWID is missing in machine statistics";
|
| }
|
|
|
| - VPDMap vpd_map;
|
| - if (ParseVPD(GetVPD(), &vpd_map)) {
|
| - InitFromVPD(vpd_map, kInitialLocaleAttr, &initial_locale_);
|
| - InitFromVPD(vpd_map, kInitialTimezoneAttr, &initial_timezone_);
|
| - InitFromVPD(vpd_map, kKeyboardLayoutAttr, &keyboard_layout_);
|
| - }
|
| + system_access->GetMachineStatistic(kInitialLocaleAttr, &initial_locale_);
|
| + system_access->GetMachineStatistic(kInitialTimezoneAttr, &initial_timezone_);
|
| + system_access->GetMachineStatistic(kKeyboardLayoutAttr, &keyboard_layout_);
|
| +}
|
|
|
| - return true;
|
| +std::string StartupCustomizationDocument::GetHelpPage(
|
| + const std::string& locale) const {
|
| + return GetLocaleSpecificString(locale, kSetupContentAttr, kHelpPageAttr);
|
| }
|
|
|
| -std::string StartupCustomizationDocument::GetHWID() const {
|
| - // TODO(dpolukhin): move to SystemLibrary to be reusable.
|
| - std::string hwid;
|
| - FilePath hwid_file_path(kHWIDPath);
|
| - if (!file_util::ReadFileToString(hwid_file_path, &hwid))
|
| - LOG(ERROR) << "Can't read HWID from " << kHWIDPath;
|
| - return hwid;
|
| +std::string StartupCustomizationDocument::GetEULAPage(
|
| + const std::string& locale) const {
|
| + return GetLocaleSpecificString(locale, kSetupContentAttr, kEulaPageAttr);
|
| }
|
|
|
| -std::string StartupCustomizationDocument::GetVPD() const {
|
| - // TODO(dpolukhin): move to SystemLibrary to be reusable.
|
| - std::string vpd;
|
| - FilePath vpd_file_path(kVPDPath);
|
| - if (!file_util::ReadFileToString(vpd_file_path, &vpd))
|
| - LOG(ERROR) << "Can't read VPD from " << kVPDPath;
|
| - return vpd;
|
| +// ServicesCustomizationDocument implementation. -------------------------------
|
| +
|
| +ServicesCustomizationDocument::ServicesCustomizationDocument()
|
| + : url_(kServicesCustomizationManifestUrl) {
|
| }
|
|
|
| -bool StartupCustomizationDocument::ParseVPD(const std::string& vpd_string,
|
| - VPDMap* vpd_map) {
|
| - // TODO(dpolukhin): move to SystemLibrary to be reusable.
|
| - const char kDelimiterChars[] = "= \n";
|
| - const char kQuotaChars[] = "\"\'";
|
| +ServicesCustomizationDocument::ServicesCustomizationDocument(
|
| + const std::string& manifest) {
|
| + LoadManifestFromString(manifest);
|
| +}
|
|
|
| - StringTokenizer tok(vpd_string, kDelimiterChars);
|
| - tok.set_quote_chars(kQuotaChars);
|
| - tok.set_options(StringTokenizer::RETURN_DELIMS);
|
| - bool next_is_equal = false;
|
| - bool next_is_value = false;
|
| - std::string name;
|
| - std::string value;
|
| - while (tok.GetNext()) {
|
| - // Skip all delimiters that are not '='.
|
| - if (tok.token_is_delim() && tok.token() != "=")
|
| - continue;
|
| +// static
|
| +ServicesCustomizationDocument* ServicesCustomizationDocument::GetInstance() {
|
| + return Singleton<ServicesCustomizationDocument,
|
| + DefaultSingletonTraits<ServicesCustomizationDocument> >::get();
|
| +}
|
|
|
| - if (next_is_equal) {
|
| - if (tok.token() != "=")
|
| - break;
|
| +// static
|
| +void ServicesCustomizationDocument::RegisterPrefs(PrefService* local_state) {
|
| + local_state->RegisterBooleanPref(kServicesCustomizationAppliedPref, false);
|
| +}
|
|
|
| - next_is_equal = false;
|
| - next_is_value = true;
|
| - } else if (next_is_value) {
|
| - TrimString(tok.token(), kQuotaChars, &value);
|
| - next_is_value = false;
|
| +// static
|
| +bool ServicesCustomizationDocument::WasApplied() {
|
| + PrefService* prefs = g_browser_process->local_state();
|
| + return prefs->GetBoolean(kServicesCustomizationAppliedPref);
|
| +}
|
|
|
| - if (!vpd_map->insert(VPDMap::value_type(name, value)).second) {
|
| - LOG(ERROR) << "Identical keys in VPD " << name;
|
| - return false;
|
| - }
|
| - } else {
|
| - TrimString(tok.token(), kQuotaChars, &name);
|
| - next_is_equal = true;
|
| - }
|
| +// static
|
| +void ServicesCustomizationDocument::SetApplied(bool val) {
|
| + PrefService* prefs = g_browser_process->local_state();
|
| + prefs->SetBoolean(kServicesCustomizationAppliedPref, val);
|
| +}
|
| +
|
| +void ServicesCustomizationDocument::StartFetching() {
|
| + if (url_.SchemeIsFile()) {
|
| + BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
|
| + NewRunnableMethod(this,
|
| + &ServicesCustomizationDocument::ReadFileInBackground,
|
| + FilePath(url_.path())));
|
| + } else {
|
| + StartFileFetch();
|
| }
|
| +}
|
|
|
| - if (next_is_equal || next_is_value) {
|
| - LOG(ERROR) << "Syntax error in VPD " << vpd_string;
|
| - return false;
|
| +void ServicesCustomizationDocument::ReadFileInBackground(const FilePath& file) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| +
|
| + std::string manifest;
|
| + if (file_util::ReadFileToString(file, &manifest)) {
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| + NewRunnableMethod(
|
| + this,
|
| + &ServicesCustomizationDocument::LoadManifestFromString,
|
| + manifest));
|
| + } else {
|
| + VLOG(1) << "Failed to load services customization manifest from: "
|
| + << file.value();
|
| }
|
| -
|
| - return true;
|
| }
|
|
|
| -void StartupCustomizationDocument::InitFromVPD(
|
| - const VPDMap& vpd_map, const char* attr, std::string* value) {
|
| - VPDMap::const_iterator it = vpd_map.find(attr);
|
| - if (it != vpd_map.end())
|
| - *value = it->second;
|
| +void ServicesCustomizationDocument::StartFileFetch() {
|
| + DCHECK(url_.is_valid());
|
| + url_fetcher_.reset(new URLFetcher(url_, URLFetcher::GET, this));
|
| + url_fetcher_->set_request_context(
|
| + ProfileManager::GetDefaultProfile()->GetRequestContext());
|
| + url_fetcher_->Start();
|
| }
|
|
|
| -std::string StartupCustomizationDocument::GetHelpPage(
|
| - const std::string& locale) const {
|
| - return GetLocaleSpecificString(locale, kSetupContentAttr, kHelpPageAttr);
|
| +void ServicesCustomizationDocument::OnURLFetchComplete(
|
| + const URLFetcher* source,
|
| + const GURL& url,
|
| + const net::URLRequestStatus& status,
|
| + int response_code,
|
| + const ResponseCookies& cookies,
|
| + const std::string& data) {
|
| + if (response_code == 200) {
|
| + LoadManifestFromString(data);
|
| + } else {
|
| + NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary();
|
| + if (!network->Connected() && num_retries_ < kMaxFetchRetries) {
|
| + num_retries_++;
|
| + retry_timer_.Start(base::TimeDelta::FromSeconds(kRetriesDelayInSec),
|
| + this, &ServicesCustomizationDocument::StartFileFetch);
|
| + return;
|
| + }
|
| + LOG(ERROR) << "URL fetch for services customization failed:"
|
| + << " response code = " << response_code
|
| + << " URL = " << url.spec();
|
| + }
|
| }
|
|
|
| -std::string StartupCustomizationDocument::GetEULAPage(
|
| - const std::string& locale) const {
|
| - return GetLocaleSpecificString(locale, kSetupContentAttr, kEulaPageAttr);
|
| +bool ServicesCustomizationDocument::ApplyCustomization() {
|
| + // TODO(dpolukhin): apply customized apps, exts and support page.
|
| + SetApplied(true);
|
| + return true;
|
| }
|
|
|
| -// ServicesCustomizationDocument implementation.
|
| std::string ServicesCustomizationDocument::GetInitialStartPage(
|
| const std::string& locale) const {
|
| return GetLocaleSpecificString(
|
|
|