diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-02 07:52:33 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-02 07:52:33 +0000 |
commit | 7713d63d41fad819b4031c2f30422489469ead95 (patch) | |
tree | 21bc0fe37980b49e1a2b03ca6726b695bd587f91 /chrome | |
parent | 527c739c43984bc49da5d0de4989e1d81d4a74d5 (diff) | |
download | chromium_src-7713d63d41fad819b4031c2f30422489469ead95.zip chromium_src-7713d63d41fad819b4031c2f30422489469ead95.tar.gz chromium_src-7713d63d41fad819b4031c2f30422489469ead95.tar.bz2 |
Introduce Extension class that can serializer and deserialize from Value
instances.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6211 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/browser.scons | 1 | ||||
-rw-r--r-- | chrome/browser/browser.vcproj | 12 | ||||
-rw-r--r-- | chrome/browser/extensions/extension.cc | 115 | ||||
-rw-r--r-- | chrome/browser/extensions/extension.h | 71 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_unittest.cc | 88 | ||||
-rw-r--r-- | chrome/test/unit/unit_tests.scons | 1 | ||||
-rw-r--r-- | chrome/test/unit/unittests.vcproj | 8 |
7 files changed, 296 insertions, 0 deletions
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index 1d56bdf..aeb213b 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -58,6 +58,7 @@ if env['PLATFORM'] in ('posix', 'win32'): 'chrome_thread.cc', 'cross_site_request_manager.cc', 'download/save_file.cc', + 'extensions/extension.cc', 'google_url_tracker.cc', 'google_util.cc', 'history/archived_database.cc', diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 7d79e5d..9cb07f5 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -2154,6 +2154,18 @@ > </File> </Filter> + <Filter + Name="extensions" + > + <File + RelativePath=".\extensions\extension.cc" + > + </File> + <File + RelativePath=".\extensions\extension.h" + > + </File> + </Filter> <File RelativePath=".\browser_trial.cc" > diff --git a/chrome/browser/extensions/extension.cc b/chrome/browser/extensions/extension.cc new file mode 100644 index 0000000..d4fbe9f --- /dev/null +++ b/chrome/browser/extensions/extension.cc @@ -0,0 +1,115 @@ +// Copyright (c) 2006-2008 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.h" + +#include "base/logging.h" +#include "base/string_util.h" + +const std::wstring Extension::kFormatVersionKey(L"format_version"); +const std::wstring Extension::kIdKey(L"id"); +const std::wstring Extension::kNameKey(L"name"); +const std::wstring Extension::kDescriptionKey(L"description"); +const std::wstring Extension::kContentScriptsKey(L"content_scripts"); + +const std::wstring Extension::kInvalidFormatVersionError( + StringPrintf(L"Required key '%ls' is missing or invalid", + kFormatVersionKey.c_str())); +const std::wstring Extension::kInvalidIdError( + StringPrintf(L"Required key '%ls' is missing or invalid.", + kIdKey.c_str())); +const std::wstring Extension::kInvalidNameError( + StringPrintf(L"Required key '%ls' is missing or has invalid type.", + kNameKey.c_str())); +const std::wstring Extension::kInvalidDescriptionError( + StringPrintf(L"Invalid type for '%ls' key.", + kDescriptionKey.c_str())); +const std::wstring Extension::kInvalidContentScriptsListError( + StringPrintf(L"Invalid type for '%ls' key.", + kContentScriptsKey.c_str())); +const std::wstring Extension::kInvalidContentScriptError( + StringPrintf(L"Invalid type for %ls at index ", + kContentScriptsKey.c_str())); + +bool Extension::InitFromValue(const DictionaryValue& source, + std::wstring* error) { + // Check format version. + int format_version = 0; + if (!source.GetInteger(kFormatVersionKey, &format_version) || + format_version != kExpectedFormatVersion) { + *error = kInvalidFormatVersionError; + return false; + } + + // Initialize id. + if (!source.GetString(kIdKey, &id_)) { + *error = kInvalidIdError; + return false; + } + + // Initialize name. + if (!source.GetString(kNameKey, &name_)) { + *error = kInvalidNameError; + return false; + } + + // Initialize description (optional). + Value* value = NULL; + if (source.Get(kDescriptionKey, &value)) { + if (!value->GetAsString(&description_)) { + *error = kInvalidDescriptionError; + return false; + } + } + + // Initialize content scripts (optional). + if (source.Get(kContentScriptsKey, &value)) { + ListValue* list_value = NULL; + if (value->GetType() != Value::TYPE_LIST) { + *error = kInvalidContentScriptsListError; + return false; + } else { + list_value = static_cast<ListValue*>(value); + } + + for (size_t i = 0; i < list_value->GetSize(); ++i) { + std::wstring content_script; + if (!list_value->Get(i, &value) || !value->GetAsString(&content_script)) { + *error = kInvalidContentScriptError; + *error += IntToWString(i); + return false; + } + + content_scripts_.push_back(content_script); + } + } + + return true; +} + +void Extension::CopyToValue(DictionaryValue* destination) { + // Set format version + destination->SetInteger(kFormatVersionKey, + kExpectedFormatVersion); + + // Copy id. + destination->SetString(kIdKey, id_); + + // Copy name. + destination->SetString(kNameKey, name_); + + // Copy description (optional). + if (description_.size() > 0) + destination->SetString(kDescriptionKey, description_); + + // Copy content scripts (optional). + if (content_scripts_.size() > 0) { + ListValue* list_value = new ListValue(); + destination->Set(kContentScriptsKey, list_value); + + for (size_t i = 0; i < content_scripts_.size(); ++i) { + list_value->Set(i, Value::CreateStringValue(content_scripts_[i])); + } + } +} diff --git a/chrome/browser/extensions/extension.h b/chrome/browser/extensions/extension.h new file mode 100644 index 0000000..16260e0 --- /dev/null +++ b/chrome/browser/extensions/extension.h @@ -0,0 +1,71 @@ +// Copyright (c) 2006-2008 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_H__ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_H__ + +#include <string> +#include <vector> + +#include "base/string16.h" +#include "base/values.h" + +// Represents a Chromium extension. +class Extension { + public: + Extension(){}; + + // The format for extension manifests that this code understands. + static const int kExpectedFormatVersion = 1; + + // Keys used in JSON representation of extensions. + static const std::wstring kFormatVersionKey; + static const std::wstring kIdKey; + static const std::wstring kNameKey; + static const std::wstring kDescriptionKey; + static const std::wstring kContentScriptsKey; + + // Error messages returned from InitFromValue(). + static const std::wstring kInvalidFormatVersionError; + static const std::wstring kInvalidIdError; + static const std::wstring kInvalidNameError; + static const std::wstring kInvalidDescriptionError; + static const std::wstring kInvalidContentScriptsListError; + static const std::wstring kInvalidContentScriptError; + + // A human-readable ID for the extension. The convention is to use something + // like 'com.example.myextension', but this is not currently enforced. An + // extension's ID is used in things like directory structures and URLs, and + // is expected to not change across versions. In the case of conflicts, + // updates will only be allowed if the extension can be validated using the + // previous version's update key. + const std::wstring& id() const { return id_; } + + // A human-readable name of the extension. + const std::wstring& name() const { return name_; } + + // An optional longer description of the extension. + const std::wstring& description() const { return description_; } + + // Paths to the content scripts that the extension contains. + const std::vector<std::wstring>& content_scripts() const { + return content_scripts_; + } + + // Initialize the extension from a parsed manifest. + bool InitFromValue(const DictionaryValue& value, std::wstring* error); + + // Serialize the extension to a DictionaryValue. + void CopyToValue(DictionaryValue* value); + + private: + std::wstring id_; + std::wstring name_; + std::wstring description_; + std::vector<std::wstring> content_scripts_; + + DISALLOW_COPY_AND_ASSIGN(Extension); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_H__ diff --git a/chrome/browser/extensions/extension_unittest.cc b/chrome/browser/extensions/extension_unittest.cc new file mode 100644 index 0000000..2377dae --- /dev/null +++ b/chrome/browser/extensions/extension_unittest.cc @@ -0,0 +1,88 @@ +// Copyright (c) 2006-2008 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 "base/string_util.h" +#include "chrome/browser/extensions/extension.h" +#include "testing/gtest/include/gtest/gtest.h" + +class ExtensionTest : public testing::Test { +}; + +TEST(ExtensionTest, InitFromValueInvalid) { + Extension extension; + std::wstring error; + + // Test invalid format version + DictionaryValue input_value; + input_value.SetInteger(Extension::kFormatVersionKey, 2); + EXPECT_FALSE(extension.InitFromValue(input_value, &error)); + EXPECT_EQ(Extension::kInvalidFormatVersionError, error); + input_value.SetInteger(Extension::kFormatVersionKey, 1); + + // Test missing and invalid ids + EXPECT_FALSE(extension.InitFromValue(input_value, &error)); + EXPECT_EQ(Extension::kInvalidIdError, error); + input_value.SetInteger(Extension::kIdKey, 42); + EXPECT_FALSE(extension.InitFromValue(input_value, &error)); + EXPECT_EQ(Extension::kInvalidIdError, error); + input_value.SetString(Extension::kIdKey, L"com.google.myextension"); + + // Test missing and invalid names + EXPECT_FALSE(extension.InitFromValue(input_value, &error)); + EXPECT_EQ(Extension::kInvalidNameError, error); + input_value.SetInteger(Extension::kNameKey, 42); + EXPECT_FALSE(extension.InitFromValue(input_value, &error)); + EXPECT_EQ(Extension::kInvalidNameError, error); + input_value.SetString(Extension::kNameKey, L"my extension"); + + // Test invalid description + input_value.SetInteger(Extension::kDescriptionKey, 42); + EXPECT_FALSE(extension.InitFromValue(input_value, &error)); + EXPECT_EQ(Extension::kInvalidDescriptionError, error); + input_value.Remove(Extension::kDescriptionKey, NULL); + + // Test invalid content scripts list + input_value.SetInteger(Extension::kContentScriptsKey, 42); + EXPECT_FALSE(extension.InitFromValue(input_value, &error)); + EXPECT_EQ(Extension::kInvalidContentScriptsListError, error); + + // Test invalid content script item + ListValue* content_scripts = new ListValue; + input_value.Set(Extension::kContentScriptsKey, content_scripts); + content_scripts->Set(0, Value::CreateIntegerValue(42)); + EXPECT_FALSE(extension.InitFromValue(input_value, &error)); + EXPECT_EQ(0u, error.find(Extension::kInvalidContentScriptError)); +} + +TEST(ExtensionTest, InitFromValueValid) { + Extension extension; + std::wstring error; + DictionaryValue input_value; + DictionaryValue output_value; + + // Test minimal extension + input_value.SetInteger(Extension::kFormatVersionKey, 1); + input_value.SetString(Extension::kIdKey, L"com.google.myextension"); + input_value.SetString(Extension::kNameKey, L"my extension"); + + EXPECT_TRUE(extension.InitFromValue(input_value, &error)); + extension.CopyToValue(&output_value); + EXPECT_TRUE(input_value.Equals(&output_value)); + + // Test with a description + input_value.SetString(Extension::kDescriptionKey, + L"my extension does things"); + EXPECT_TRUE(extension.InitFromValue(input_value, &error)); + extension.CopyToValue(&output_value); + EXPECT_TRUE(input_value.Equals(&output_value)); + + // Test content_scripts + ListValue* content_scripts = new ListValue(); + input_value.Set(Extension::kContentScriptsKey, content_scripts); + content_scripts->Set(0, Value::CreateStringValue(L"foo/bar.js")); + content_scripts->Set(1, Value::CreateStringValue(L"hot/dog.js")); + EXPECT_TRUE(extension.InitFromValue(input_value, &error)); + extension.CopyToValue(&output_value); + EXPECT_TRUE(input_value.Equals(&output_value)); +} diff --git a/chrome/test/unit/unit_tests.scons b/chrome/test/unit/unit_tests.scons index c90a0be..320dc09 100644 --- a/chrome/test/unit/unit_tests.scons +++ b/chrome/test/unit/unit_tests.scons @@ -115,6 +115,7 @@ if env['PLATFORM'] in ('posix', 'win32'): 'run_all_unittests.cc', '$CHROME_DIR/browser/chrome_thread_unittest.cc', + '$CHROME_DIR/browser/extensions/extension_unittest.cc', '$CHROME_DIR/browser/history/history_types_unittest.cc', '$CHROME_DIR/browser/history/snippet_unittest.cc', '$CHROME_DIR/browser/history/text_database_unittest.cc', diff --git a/chrome/test/unit/unittests.vcproj b/chrome/test/unit/unittests.vcproj index 17b9dc29..e05354a 100644 --- a/chrome/test/unit/unittests.vcproj +++ b/chrome/test/unit/unittests.vcproj @@ -1026,6 +1026,14 @@ > </File> </Filter> + <Filter + Name="TestExtension" + > + <File + RelativePath="..\..\browser\extensions\extension_unittest.cc" + > + </File> + </Filter> </Files> <Globals> </Globals> |