Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: extensions/common/api/declarative/declarative_manifest_data.cc

Issue 1158693006: Create a mechanism define declarative rules via the extension manifest. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "extensions/common/api/declarative/declarative_manifest_data.h"
6
7 #include "base/strings/stringprintf.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "extensions/common/manifest_constants.h"
10
11 using base::UTF8ToUTF16;
12 using base::StringPrintf;
13
14 namespace extensions {
15
16 namespace {
17
18 const char* ValueTypeToString(const base::Value* value) {
19 const base::Value::Type type = value->GetType();
20 static const char* strings[] = {"null",
21 "boolean",
22 "integer",
23 "double",
24 "string",
25 "binary",
26 "dictionary",
27 "list"};
28 CHECK(static_cast<size_t>(type) < arraysize(strings));
29 return strings[type];
30 }
31
32 class ErrorBuilder {
33 public:
34 ErrorBuilder(base::string16* error) : error_(error) {}
not at google - send to devlin 2015/06/09 20:55:41 explicit
danduong 2015/06/10 00:17:16 Done.
35
36 // Appends a literal string |error|.
37 void Append(const char* error) {
38 if (error_->length())
39 error_->append(UTF8ToUTF16("; "));
40 error_->append(UTF8ToUTF16(error));
41 }
42
43 // Appends a string |error| with the first %s replaced by |sub|.
44 void Append(const char* error, const char* sub) {
45 Append(base::StringPrintf(error, sub).c_str());
46 }
47
48 private:
49 base::string16* error_;
50 DISALLOW_COPY_AND_ASSIGN(ErrorBuilder);
51 };
52
53 // Converts a rule defined in the manifest into a JSON internal format. The
54 // difference is that actions and conditions use a "type" key to define the
55 // type of rule/condition, while the internal format uses a "instanceType" key
56 // for this. This function walks through all the conditions and rules to swap
57 // the manifest key for the internal key.
58 bool ConvertManifestRule(const linked_ptr<DeclarativeManifestData::Rule>& rule,
59 ErrorBuilder* error_builder) {
60 auto convert_list =
61 [error_builder](std::vector<linked_ptr<base::Value>>& list) {
62 for (const linked_ptr<base::Value>& value : list) {
63 base::DictionaryValue* dictionary = nullptr;
64 if (!value->GetAsDictionary(&dictionary)) {
65 error_builder->Append("expected dictionary, got %s",
66 ValueTypeToString(value.get()));
67 return false;
68 }
69 std::string type;
70 if (!dictionary->GetString("type", &type)) {
71 error_builder->Append("'type' is required");
not at google - send to devlin 2015/06/09 20:55:40 this will also fail if "type" is set but isn't a s
danduong 2015/06/10 00:17:16 Done.
72 return false;
73 }
74 dictionary->Remove("type", nullptr);
75 dictionary->SetString("instanceType", type);
76 }
77 return true;
78 };
79 return convert_list(rule->actions) && convert_list(rule->conditions);
80 }
81
82 } // namespace
83
84 DeclarativeManifestData::DeclarativeManifestData() {
85 }
86
87 DeclarativeManifestData::~DeclarativeManifestData() {
88 }
89
90 // static
91 DeclarativeManifestData* DeclarativeManifestData::Get(
92 const Extension* extension) {
93 return static_cast<DeclarativeManifestData*>(
94 extension->GetManifestData(manifest_keys::kEventRules));
95 }
96
97 // static
98 scoped_ptr<DeclarativeManifestData> DeclarativeManifestData::FromValue(
99 const base::Value& value,
100 base::string16* error) {
101 // The following is an example of how an event programmatic rule definition
102 // translates to a manifest definition.
103 //
104 // From javascript:
105 //
106 // chrome.declarativeContent.onPageChanged.addRules([{
107 // actions: [
108 // new chrome.declarativeContent.ShowPageAction()
109 // ],
110 // conditions: [
111 // new chrome.declarativeContent.PageStateMatcher({css: ["video"]})
112 // ]
113 // }]);
114 //
115 // In manifest:
116 //
117 // "event_rules": [{
118 // "event" : "declarativeContent.onPageChanged",
119 // "actions" : [{
120 // "type": "declarativeContent.ShowPageAction"
121 // }],
122 // "conditions" : [{
123 // "css": ["video"],
124 // "type" : "declarativeContent.PageStateMatcher"
125 // }]
126 // }]
127 //
128 // The javascript objects get translated into JSON objects with a "type"
129 // field to indicate the instance type. Instead of adding rules to a
130 // specific event list, each rule has an "event" field to indicate which
131 // event it applies to.
132 //
133 ErrorBuilder error_builder(error);
134 scoped_ptr<DeclarativeManifestData> result(new DeclarativeManifestData());
135 const base::ListValue* list = nullptr;
136 if (!value.GetAsList(&list)) {
137 error_builder.Append("'event_rules' expected list, got %s",
138 ValueTypeToString(&value));
139 return scoped_ptr<DeclarativeManifestData>();
140 }
141
142 for (size_t i = 0; i < list->GetSize(); ++i) {
143 const base::DictionaryValue* dict = nullptr;
144 if (!list->GetDictionary(i, &dict)) {
145 const base::Value* value = nullptr;
146 if (list->Get(i, &value))
147 error_builder.Append("expected dictionary, got %s",
148 ValueTypeToString(value));
149 else
150 error_builder.Append("expected dictionary");
151 return scoped_ptr<DeclarativeManifestData>();
152 }
153 std::string event;
154 if (!dict->GetString("event", &event)) {
155 error_builder.Append("'event' is required");
156 return scoped_ptr<DeclarativeManifestData>();
157 }
158
159 linked_ptr<Rule> rule(new Rule());
160 if (Rule::Populate(*dict, rule.get()) &&
161 ConvertManifestRule(rule, &error_builder)) {
162 result->event_rules_map_[event].push_back(rule);
163 } else {
164 error_builder.Append("rule failed to populate");
not at google - send to devlin 2015/06/09 20:55:40 I think that, now, the Populate and the ConvertMan
165 return scoped_ptr<DeclarativeManifestData>();
166 }
167 }
168 return result.Pass();
169 }
170
171 std::vector<linked_ptr<DeclarativeManifestData::Rule>>&
172 DeclarativeManifestData::RulesForEvent(const std::string& event) {
173 return event_rules_map_[event];
174 }
175
176 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698