Index: extensions/common/api/declarative/declarative_manifest_data.cc |
diff --git a/extensions/common/api/declarative/declarative_manifest_data.cc b/extensions/common/api/declarative/declarative_manifest_data.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d37857f0144ac641edb605d369b754cf21d84edd |
--- /dev/null |
+++ b/extensions/common/api/declarative/declarative_manifest_data.cc |
@@ -0,0 +1,160 @@ |
+// Copyright 2015 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 "extensions/common/api/declarative/declarative_manifest_data.h" |
+ |
+#include "base/strings/utf_string_conversions.h" |
+#include "extensions/common/api/extensions_manifest_types.h" |
not at google - send to devlin
2015/06/08 21:44:58
What are you using from this?
danduong
2015/06/09 01:21:26
Done.
|
+#include "extensions/common/manifest_constants.h" |
+ |
+using base::UTF8ToUTF16; |
+ |
+namespace extensions { |
+ |
+namespace { |
+ |
+std::string ValueTypeToString(base::Value::Type type) { |
not at google - send to devlin
2015/06/08 21:44:58
You might as well pass the whole Value into here,
danduong
2015/06/09 01:21:26
Done.
|
+ static const char* strings[] = {"null", |
+ "boolean", |
+ "integer", |
+ "double", |
+ "string", |
+ "binary", |
+ "dictionary", |
+ "list"}; |
+ CHECK(static_cast<size_t>(type) < arraysize(strings)); |
+ return std::string(strings[type]); |
not at google - send to devlin
2015/06/08 21:44:58
you could also make it return a const char* if you
|
+} |
+ |
+// Converts a rule defined in the manifest into a JSON internal format. The |
+// difference is that actions and conditions use a "type" key to define the |
+// type of rule/condition, while the internal format uses a "instanceType" key |
+// for this. This function walks through all the conditions and rules to swap |
+// the manifest key for the internal key. |
+bool ConvertManifestRule(const linked_ptr<DeclarativeManifestData::Rule>& rule, |
+ base::string16* error) { |
+ auto convert_list = [error](std::vector<linked_ptr<base::Value>>& list) { |
+ for (const linked_ptr<base::Value>& value : list) { |
+ base::DictionaryValue* dictionary = nullptr; |
+ if (!value->GetAsDictionary(&dictionary)) { |
+ if (error->length()) |
+ error->append(UTF8ToUTF16("; ")); |
+ error->append(UTF8ToUTF16("expected dictionary, got " + |
+ ValueTypeToString(value->GetType()))); |
+ return false; |
+ } |
+ std::string type; |
+ if (!dictionary->GetString("type", &type)) { |
+ if (error->length()) |
+ error->append(UTF8ToUTF16("; ")); |
+ error->append(UTF8ToUTF16("'type' is required")); |
+ return false; |
+ } |
+ dictionary->Remove("type", nullptr); |
+ dictionary->SetString("instanceType", type); |
+ } |
+ return true; |
+ }; |
+ return convert_list(rule->actions) && convert_list(rule->conditions); |
+} |
+ |
+} // namespace |
+ |
+DeclarativeManifestData::DeclarativeManifestData() { |
+} |
+ |
+DeclarativeManifestData::~DeclarativeManifestData() { |
+} |
+ |
+// static |
+DeclarativeManifestData* DeclarativeManifestData::Get( |
+ const Extension* extension) { |
+ return static_cast<DeclarativeManifestData*>( |
+ extension->GetManifestData(manifest_keys::kEventRules)); |
+} |
+ |
+// static |
+scoped_ptr<DeclarativeManifestData> DeclarativeManifestData::FromValue( |
+ const base::Value& value, |
+ base::string16* error) { |
+ // The following is an example of how an event programmatic rule definition |
+ // translates to a manifest definition. |
+ // |
+ // From javascript: |
+ // |
+ // chrome.declarativeContent.onPageChanged.addRules([{ |
+ // actions: [ |
+ // new chrome.declarativeContent.ShowPageAction() |
+ // ], |
+ // conditions: [ |
+ // new chrome.declarativeContent.PageStateMatcher({css: ["video"]}) |
+ // ] |
+ // }]); |
+ // |
+ // In manifest: |
+ // |
+ // "event_rules": [{ |
+ // "event" : "declarativeContent.onPageChanged", |
+ // "actions" : [{ |
+ // "type": "declarativeContent.ShowPageAction" |
+ // }], |
+ // "conditions" : [{ |
+ // "css": ["video"], |
+ // "type" : "declarativeContent.PageStateMatcher" |
+ // }] |
+ // }] |
+ // |
+ // The javascript objects get translated into JSON objects with a "type" |
+ // field to indicate the instance type. Instead of adding rules to a |
+ // specific event list, each rule has an "event" field to indicate which |
+ // event it applies to. |
+ // |
+ scoped_ptr<DeclarativeManifestData> result(new DeclarativeManifestData()); |
+ const base::ListValue* list = nullptr; |
+ if (!value.GetAsList(&list)) { |
+ if (error->length()) |
+ error->append(UTF8ToUTF16("; ")); |
+ error->append(UTF8ToUTF16("'event_rules' expected list, got " + |
+ ValueTypeToString(value.GetType()))); |
+ return scoped_ptr<DeclarativeManifestData>(); |
+ } |
+ |
not at google - send to devlin
2015/06/08 21:44:58
There is a lot of code here for generating errors.
danduong
2015/06/09 01:21:26
Done.
|
+ for (size_t i = 0; i < list->GetSize(); ++i) { |
+ const base::DictionaryValue* dict = nullptr; |
+ if (!list->GetDictionary(i, &dict)) { |
+ if (error->length()) |
+ error->append(base::UTF8ToUTF16("; ")); |
+ const base::Value* value = nullptr; |
+ if (list->Get(i, &value)) |
+ error->append(base::UTF8ToUTF16("expected dictionary, got " + |
+ ValueTypeToString(value->GetType()))); |
+ else |
+ error->append(base::UTF8ToUTF16("expected dictionary")); |
+ return scoped_ptr<DeclarativeManifestData>(); |
+ } |
+ std::string event; |
+ if (!dict->GetString("event", &event)) { |
+ if (error->length()) |
+ error->append(UTF8ToUTF16("; ")); |
+ error->append(UTF8ToUTF16("'event' is required")); |
+ } |
+ linked_ptr<Rule> rule(new Rule()); |
+ if (Rule::Populate(*dict, rule.get()) && ConvertManifestRule(rule, error)) { |
+ result->event_rules_map_[event].push_back(rule); |
+ } else { |
+ if (error->length()) |
+ error->append(UTF8ToUTF16("; ")); |
+ error->append(UTF8ToUTF16("rule failed to populate")); |
+ return scoped_ptr<DeclarativeManifestData>(); |
+ } |
+ } |
+ return result.Pass(); |
+} |
+ |
+std::vector<linked_ptr<DeclarativeManifestData::Rule>>& |
+DeclarativeManifestData::RulesForEvent(const std::string& event) { |
+ return event_rules_map_[event]; |
+} |
+ |
+} // namespace extensions |