Added extensions API to provide customization values.
This CL adds API that could be used only by component extensions.
Currently, API only returns device's HWID.
BUG=chromium-os:13076
TEST=browser_tests
Review URL: http://codereview.chromium.org/6681038
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79264 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/chromeos/customization_document.h b/chrome/browser/chromeos/customization_document.h
index 019ca74..1917228 100644
--- a/chrome/browser/chromeos/customization_document.h
+++ b/chrome/browser/chromeos/customization_document.h
@@ -52,12 +52,12 @@
std::string GetHelpPage(const std::string& locale) const;
std::string GetEULAPage(const std::string& locale) const;
- private:
- typedef std::map<std::string, std::string> VPDMap;
-
// Returns HWID for the machine. Declared as virtual to override in tests.
virtual std::string GetHWID() const;
+ private:
+ typedef std::map<std::string, std::string> VPDMap;
+
// Returns VPD as string. Declared as virtual to override in tests.
virtual std::string GetVPD() const;
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc
index bebf4576..a3e10aa1 100644
--- a/chrome/browser/extensions/extension_apitest.cc
+++ b/chrome/browser/extensions/extension_apitest.cc
@@ -100,26 +100,30 @@
}
bool ExtensionApiTest::RunExtensionTest(const char* extension_name) {
- return RunExtensionTestImpl(extension_name, "", false, true);
+ return RunExtensionTestImpl(extension_name, "", false, true, false);
}
bool ExtensionApiTest::RunExtensionTestIncognito(const char* extension_name) {
- return RunExtensionTestImpl(extension_name, "", true, true);
+ return RunExtensionTestImpl(extension_name, "", true, true, false);
+}
+
+bool ExtensionApiTest::RunComponentExtensionTest(const char* extension_name) {
+ return RunExtensionTestImpl(extension_name, "", false, true, true);
}
bool ExtensionApiTest::RunExtensionTestNoFileAccess(
const char* extension_name) {
- return RunExtensionTestImpl(extension_name, "", false, false);
+ return RunExtensionTestImpl(extension_name, "", false, false, false);
}
bool ExtensionApiTest::RunExtensionTestIncognitoNoFileAccess(
const char* extension_name) {
- return RunExtensionTestImpl(extension_name, "", true, false);
+ return RunExtensionTestImpl(extension_name, "", true, false, false);
}
bool ExtensionApiTest::RunExtensionSubtest(const char* extension_name,
const std::string& page_url) {
DCHECK(!page_url.empty()) << "Argument page_url is required.";
- return RunExtensionTestImpl(extension_name, page_url, false, true);
+ return RunExtensionTestImpl(extension_name, page_url, false, true, false);
}
bool ExtensionApiTest::RunPageTest(const std::string& page_url) {
@@ -131,22 +135,28 @@
bool ExtensionApiTest::RunExtensionTestImpl(const char* extension_name,
const std::string& page_url,
bool enable_incognito,
- bool enable_fileaccess) {
+ bool enable_fileaccess,
+ bool load_as_component) {
ResultCatcher catcher;
DCHECK(!std::string(extension_name).empty() || !page_url.empty()) <<
"extension_name and page_url cannot both be empty";
if (!std::string(extension_name).empty()) {
- bool loaded;
- if (enable_incognito) {
- loaded = enable_fileaccess ?
- LoadExtensionIncognito(test_data_dir_.AppendASCII(extension_name)) :
- LoadExtensionIncognitoNoFileAccess(
- test_data_dir_.AppendASCII(extension_name));
+ bool loaded = false;
+ if (load_as_component) {
+ loaded =
+ LoadExtensionAsComponent(test_data_dir_.AppendASCII(extension_name));
} else {
- loaded = enable_fileaccess ?
- LoadExtension(test_data_dir_.AppendASCII(extension_name)) :
- LoadExtensionNoFileAccess(test_data_dir_.AppendASCII(extension_name));
+ if (enable_incognito) {
+ loaded = enable_fileaccess ?
+ LoadExtensionIncognito(test_data_dir_.AppendASCII(extension_name)) :
+ LoadExtensionIncognitoNoFileAccess(
+ test_data_dir_.AppendASCII(extension_name));
+ } else {
+ loaded = enable_fileaccess ?
+ LoadExtension(test_data_dir_.AppendASCII(extension_name)) :
+ LoadExtensionNoFileAccess(test_data_dir_.AppendASCII(extension_name));
+ }
}
if (!loaded) {
message_ = "Failed to load extension.";
diff --git a/chrome/browser/extensions/extension_apitest.h b/chrome/browser/extensions/extension_apitest.h
index 5ab3748a..52b492e 100644
--- a/chrome/browser/extensions/extension_apitest.h
+++ b/chrome/browser/extensions/extension_apitest.h
@@ -80,6 +80,9 @@
// Same as RunExtensionTest, but enables the extension for incognito mode.
bool RunExtensionTestIncognito(const char* extension_name);
+ // Same as RunExtensionTest, but loads extension as component.
+ bool RunComponentExtensionTest(const char* extension_name);
+
// Same as RunExtensionTest, but disables file access.
bool RunExtensionTestNoFileAccess(const char* extension_name);
@@ -116,7 +119,8 @@
bool RunExtensionTestImpl(const char* extension_name,
const std::string& test_page,
bool enable_incogntio,
- bool enable_fileaccess);
+ bool enable_fileaccess,
+ bool load_as_component);
// Hold details of the test, set in C++, which can be accessed by
// javascript using chrome.test.getConfig().
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index b487dbc..a644eb7 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -111,6 +111,20 @@
return LoadExtensionImpl(path, true, false);
}
+bool ExtensionBrowserTest::LoadExtensionAsComponent(const FilePath& path) {
+ ExtensionService* service = browser()->profile()->GetExtensionService();
+
+ std::string manifest;
+ if (!file_util::ReadFileToString(path.Append(Extension::kManifestFilename),
+ &manifest))
+ return false;
+
+ service->LoadComponentExtension(
+ ExtensionService::ComponentExtensionInfo(manifest, path));
+
+ return true;
+}
+
FilePath ExtensionBrowserTest::PackExtension(const FilePath& dir_path) {
FilePath crx_path;
if (!PathService::Get(base::DIR_TEMP, &crx_path)) {
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index c5c150a0..22fb6c6 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -28,6 +28,9 @@
// Same as above, but enables the extension in incognito mode first.
bool LoadExtensionIncognito(const FilePath& path);
+ // Loads extension and imitates that it is a component extension.
+ bool LoadExtensionAsComponent(const FilePath& path);
+
// By default, unpacked extensions have file access: this loads them with
// that permission removed.
bool LoadExtensionNoFileAccess(const FilePath& path);
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index cbfc0c59..b295d69 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -65,6 +65,10 @@
#include "chrome/browser/extensions/extension_input_api.h"
#endif
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/extensions/extension_info_private_api_chromeos.h"
+#endif
+
// FactoryRegistry -------------------------------------------------------------
namespace {
@@ -304,6 +308,11 @@
RegisterFunction<SetPreferenceFunction>();
RegisterFunction<ClearPreferenceFunction>();
+#if defined(OS_CHROMEOS)
+ // Device Customization.
+ RegisterFunction<GetChromeosInfoFunction>();
+#endif
+
// Debugger
RegisterFunction<AttachDebuggerFunction>();
RegisterFunction<DetachDebuggerFunction>();
diff --git a/chrome/browser/extensions/extension_info_private_api_chromeos.cc b/chrome/browser/extensions/extension_info_private_api_chromeos.cc
new file mode 100644
index 0000000..0982add
--- /dev/null
+++ b/chrome/browser/extensions/extension_info_private_api_chromeos.cc
@@ -0,0 +1,175 @@
+// 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 "extension_info_private_api_chromeos.h"
+
+#include <map>
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/system_library.h"
+#include "chrome/browser/chromeos/customization_document.h"
+#include "chrome/common/extensions/extension_error_utils.h"
+#include "content/browser/browser_thread.h"
+
+namespace {
+
+// Key which corresponds to the HWID setting.
+const char kPropertyHWID[] = "hwid";
+
+// Path to OEM partner startup customization manifest.
+const char kStartupCustomizationManifestPath[] =
+ "/opt/oem/etc/startup_manifest.json";
+
+// Keeps cached values to avoid unnecessary file operations. Should only be
+// used from the UI thread.
+class CachedProperties : base::NonThreadSafe {
+ public:
+ ~CachedProperties();
+ // Gets value for the property with the given name. Return whether value has
+ // been found.
+ bool GetValue(const std::string& property_name, std::string* value);
+
+ // Updates cached properties with the given item.
+ void Update(const std::pair<std::string, std::string>& item);
+
+ private:
+ typedef std::map<std::string, std::string> PropertyMap;
+ PropertyMap cache_;
+};
+
+CachedProperties::~CachedProperties() {
+ // It is safe to delete this class on any thread since class is used
+ // through LazyInstance.
+ DetachFromThread();
+}
+
+bool CachedProperties::GetValue(const std::string& property_name,
+ std::string* value) {
+ DCHECK(CalledOnValidThread());
+ PropertyMap::iterator iter = cache_.find(property_name);
+ if (iter != cache_.end()) {
+ (*value) = iter->second;
+ return true;
+ }
+ return false;
+}
+
+// Updates cached properties with the given value of the property.
+void CachedProperties::Update(
+ const std::pair<std::string, std::string>& item) {
+ DCHECK(CalledOnValidThread());
+ cache_.insert(item);
+}
+
+// Provides customization properties. Should be used only on the FILE thread.
+class CustomizationData : base::NonThreadSafe {
+ public:
+ CustomizationData();
+ ~CustomizationData();
+
+ // Gets value for the property with the given name. Return whether value has
+ // been found.
+ bool GetValue(const std::string& property_name, std::string* value);
+
+ private:
+ // Keeps customization document from which properties are extracted.
+ chromeos::StartupCustomizationDocument document_;
+
+ DISALLOW_COPY_AND_ASSIGN(CustomizationData);
+};
+
+CustomizationData::CustomizationData() {
+ DCHECK(CalledOnValidThread());
+ document_.LoadManifestFromFile(FilePath(kStartupCustomizationManifestPath));
+}
+
+CustomizationData::~CustomizationData() {
+ // It is safe to delete this class on any thread since class is used
+ // through LazyInstance.
+ DetachFromThread();
+}
+
+bool CustomizationData::GetValue(const std::string& property_name,
+ std::string* value) {
+ DCHECK(CalledOnValidThread());
+ if (property_name == kPropertyHWID) {
+ (*value) = document_.GetHWID();
+ } else {
+ LOG(ERROR) << "Unknown property request: " << property_name;
+ return false;
+ }
+ return true;
+}
+
+// Shared instances.
+base::LazyInstance<CachedProperties> g_cached_properties(
+ base::LINKER_INITIALIZED);
+base::LazyInstance<CustomizationData> g_customization(base::LINKER_INITIALIZED);
+
+} // namespace
+
+GetChromeosInfoFunction::GetChromeosInfoFunction()
+ : result_dictionary_(new DictionaryValue) {
+}
+
+GetChromeosInfoFunction::~GetChromeosInfoFunction() {
+}
+
+bool GetChromeosInfoFunction::RunImpl() {
+ ListValue* list = NULL;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetList(0, &list));
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ std::string property_name;
+ EXTENSION_FUNCTION_VALIDATE(list->GetString(i, &property_name));
+ std::string value;
+ if (g_cached_properties.Get().GetValue(property_name, &value)) {
+ result_dictionary_->Set(property_name, Value::CreateStringValue(value));
+ } else {
+ properties_.push_back(property_name);
+ }
+ }
+
+ if (!properties_.empty()) {
+ // This will calls us back on UI thread.
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &GetChromeosInfoFunction::LoadValues));
+ } else {
+ // Early answer is ready.
+ result_.reset(result_dictionary_.release());
+ SendResponse(true);
+ }
+ return true;
+}
+
+void GetChromeosInfoFunction::RespondOnUIThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ for (size_t i = 0; i < new_results_.size(); ++i) {
+ result_dictionary_->Set(new_results_[i].first,
+ Value::CreateStringValue(new_results_[i].second));
+ g_cached_properties.Get().Update(new_results_[i]);
+ }
+ result_.reset(result_dictionary_.release());
+ SendResponse(true);
+}
+
+void GetChromeosInfoFunction::LoadValues() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ new_results_.clear();
+ for (size_t i = 0; i < properties_.size(); ++i) {
+ std::string value;
+ if (g_customization.Get().GetValue(properties_[i], &value))
+ new_results_.push_back(std::make_pair(properties_[i], value));
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &GetChromeosInfoFunction::RespondOnUIThread));
+}
diff --git a/chrome/browser/extensions/extension_info_private_api_chromeos.h b/chrome/browser/extensions/extension_info_private_api_chromeos.h
new file mode 100644
index 0000000..fbaa76f6
--- /dev/null
+++ b/chrome/browser/extensions/extension_info_private_api_chromeos.h
@@ -0,0 +1,43 @@
+// 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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_INFO_PRIVATE_API_CHROMEOS_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_INFO_PRIVATE_API_CHROMEOS_H_
+#pragma once
+
+#include <string>
+#include <vector>
+#include "base/scoped_ptr.h"
+#include "chrome/browser/extensions/extension_function.h"
+
+class DictionaryValue;
+
+namespace chromeos {
+class StartupCustomizationDocument;
+} // namespace chromeos
+
+class GetChromeosInfoFunction : public AsyncExtensionFunction {
+ public:
+ GetChromeosInfoFunction();
+
+ protected:
+ virtual ~GetChromeosInfoFunction();
+
+ virtual bool RunImpl();
+
+ private:
+ // This method is called on FILE thread.
+ void LoadValues();
+
+ // This method is called on UI thread.
+ void RespondOnUIThread();
+
+ scoped_ptr<DictionaryValue> result_dictionary_;
+ std::vector<std::string> properties_;
+ std::vector<std::pair<std::string, std::string> > new_results_;
+
+ DECLARE_EXTENSION_FUNCTION_NAME("chromeosInfoPrivate.get");
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INFO_PRIVATE_API_CHROMEOS_H_
diff --git a/chrome/browser/extensions/extension_info_private_apitest_chromeos.cc b/chrome/browser/extensions/extension_info_private_apitest_chromeos.cc
new file mode 100644
index 0000000..3943b5a3
--- /dev/null
+++ b/chrome/browser/extensions/extension_info_private_apitest_chromeos.cc
@@ -0,0 +1,13 @@
+// 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/extensions/extension_apitest.h"
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CustomizationPrivateTest) {
+ ASSERT_TRUE(RunComponentExtensionTest("chromeos_info_private")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CustomizationPrivateFailTest) {
+ // Only component extensions can use it.
+ ASSERT_FALSE(RunExtensionTest("chromeos_info_private")) << message_;
+}
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 9e0145b..634926744 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -835,29 +835,34 @@
for (RegisteredComponentExtensions::iterator it =
component_extension_manifests_.begin();
it != component_extension_manifests_.end(); ++it) {
- JSONStringValueSerializer serializer(it->manifest);
- scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL));
- if (!manifest.get()) {
- DLOG(ERROR) << "Failed to parse manifest for extension";
- continue;
- }
-
- std::string error;
- scoped_refptr<const Extension> extension(Extension::Create(
- it->root_directory,
- Extension::COMPONENT,
- *static_cast<DictionaryValue*>(manifest.get()),
- true, // Require key
- Extension::ShouldDoStrictErrorChecking(Extension::COMPONENT),
- &error));
- if (!extension.get()) {
- NOTREACHED() << error;
- return;
- }
- AddExtension(extension);
+ LoadComponentExtension(*it);
}
}
+void ExtensionService::LoadComponentExtension(
+ const ComponentExtensionInfo &info) {
+ JSONStringValueSerializer serializer(info.manifest);
+ scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL));
+ if (!manifest.get()) {
+ DLOG(ERROR) << "Failed to parse manifest for extension";
+ return;
+ }
+
+ std::string error;
+ scoped_refptr<const Extension> extension(Extension::Create(
+ info.root_directory,
+ Extension::COMPONENT,
+ *static_cast<DictionaryValue*>(manifest.get()),
+ true, // Require key
+ Extension::ShouldDoStrictErrorChecking(Extension::COMPONENT),
+ &error));
+ if (!extension.get()) {
+ NOTREACHED() << error;
+ return;
+ }
+ AddExtension(extension);
+}
+
void ExtensionService::LoadAllExtensions() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 5e83300..a6081d6 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -250,13 +250,16 @@
// extension.
void GrantPermissionsAndEnableExtension(const Extension* extension);
- // Load the extension from the directory |extension_path|.
+ // Loads the extension from the directory |extension_path|.
void LoadExtension(const FilePath& extension_path);
- // Load any component extensions.
+ // Loads any component extensions.
void LoadComponentExtensions();
- // Load all known extensions (used by startup and testing code).
+ // Loads particular component extension.
+ void LoadComponentExtension(const ComponentExtensionInfo& info);
+
+ // Loads all known extensions (used by startup and testing code).
void LoadAllExtensions();
// Continues loading all know extensions. It can be called from
diff --git a/chrome/browser/resources/help_app/manifest.json b/chrome/browser/resources/help_app/manifest.json
index 368171e..d34b2a1 100644
--- a/chrome/browser/resources/help_app/manifest.json
+++ b/chrome/browser/resources/help_app/manifest.json
@@ -10,6 +10,7 @@
"default_locale": "en",
"incognito": "split",
"permissions": [
+ "chromeosInfoPrivate",
"tabs",
"http://www.google.com/support/chromeos/*/*",
"https://www.google.com/support/chromeos/*/*"