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( |