Chromium Code Reviews| OLD | NEW |
|---|---|
| (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/utf_string_conversions.h" | |
| 8 #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.
| |
| 9 #include "extensions/common/manifest_constants.h" | |
| 10 | |
| 11 using base::UTF8ToUTF16; | |
| 12 | |
| 13 namespace extensions { | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 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.
| |
| 18 static const char* strings[] = {"null", | |
| 19 "boolean", | |
| 20 "integer", | |
| 21 "double", | |
| 22 "string", | |
| 23 "binary", | |
| 24 "dictionary", | |
| 25 "list"}; | |
| 26 CHECK(static_cast<size_t>(type) < arraysize(strings)); | |
| 27 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
| |
| 28 } | |
| 29 | |
| 30 // Converts a rule defined in the manifest into a JSON internal format. The | |
| 31 // difference is that actions and conditions use a "type" key to define the | |
| 32 // type of rule/condition, while the internal format uses a "instanceType" key | |
| 33 // for this. This function walks through all the conditions and rules to swap | |
| 34 // the manifest key for the internal key. | |
| 35 bool ConvertManifestRule(const linked_ptr<DeclarativeManifestData::Rule>& rule, | |
| 36 base::string16* error) { | |
| 37 auto convert_list = [error](std::vector<linked_ptr<base::Value>>& list) { | |
| 38 for (const linked_ptr<base::Value>& value : list) { | |
| 39 base::DictionaryValue* dictionary = nullptr; | |
| 40 if (!value->GetAsDictionary(&dictionary)) { | |
| 41 if (error->length()) | |
| 42 error->append(UTF8ToUTF16("; ")); | |
| 43 error->append(UTF8ToUTF16("expected dictionary, got " + | |
| 44 ValueTypeToString(value->GetType()))); | |
| 45 return false; | |
| 46 } | |
| 47 std::string type; | |
| 48 if (!dictionary->GetString("type", &type)) { | |
| 49 if (error->length()) | |
| 50 error->append(UTF8ToUTF16("; ")); | |
| 51 error->append(UTF8ToUTF16("'type' is required")); | |
| 52 return false; | |
| 53 } | |
| 54 dictionary->Remove("type", nullptr); | |
| 55 dictionary->SetString("instanceType", type); | |
| 56 } | |
| 57 return true; | |
| 58 }; | |
| 59 return convert_list(rule->actions) && convert_list(rule->conditions); | |
| 60 } | |
| 61 | |
| 62 } // namespace | |
| 63 | |
| 64 DeclarativeManifestData::DeclarativeManifestData() { | |
| 65 } | |
| 66 | |
| 67 DeclarativeManifestData::~DeclarativeManifestData() { | |
| 68 } | |
| 69 | |
| 70 // static | |
| 71 DeclarativeManifestData* DeclarativeManifestData::Get( | |
| 72 const Extension* extension) { | |
| 73 return static_cast<DeclarativeManifestData*>( | |
| 74 extension->GetManifestData(manifest_keys::kEventRules)); | |
| 75 } | |
| 76 | |
| 77 // static | |
| 78 scoped_ptr<DeclarativeManifestData> DeclarativeManifestData::FromValue( | |
| 79 const base::Value& value, | |
| 80 base::string16* error) { | |
| 81 // The following is an example of how an event programmatic rule definition | |
| 82 // translates to a manifest definition. | |
| 83 // | |
| 84 // From javascript: | |
| 85 // | |
| 86 // chrome.declarativeContent.onPageChanged.addRules([{ | |
| 87 // actions: [ | |
| 88 // new chrome.declarativeContent.ShowPageAction() | |
| 89 // ], | |
| 90 // conditions: [ | |
| 91 // new chrome.declarativeContent.PageStateMatcher({css: ["video"]}) | |
| 92 // ] | |
| 93 // }]); | |
| 94 // | |
| 95 // In manifest: | |
| 96 // | |
| 97 // "event_rules": [{ | |
| 98 // "event" : "declarativeContent.onPageChanged", | |
| 99 // "actions" : [{ | |
| 100 // "type": "declarativeContent.ShowPageAction" | |
| 101 // }], | |
| 102 // "conditions" : [{ | |
| 103 // "css": ["video"], | |
| 104 // "type" : "declarativeContent.PageStateMatcher" | |
| 105 // }] | |
| 106 // }] | |
| 107 // | |
| 108 // The javascript objects get translated into JSON objects with a "type" | |
| 109 // field to indicate the instance type. Instead of adding rules to a | |
| 110 // specific event list, each rule has an "event" field to indicate which | |
| 111 // event it applies to. | |
| 112 // | |
| 113 scoped_ptr<DeclarativeManifestData> result(new DeclarativeManifestData()); | |
| 114 const base::ListValue* list = nullptr; | |
| 115 if (!value.GetAsList(&list)) { | |
| 116 if (error->length()) | |
| 117 error->append(UTF8ToUTF16("; ")); | |
| 118 error->append(UTF8ToUTF16("'event_rules' expected list, got " + | |
| 119 ValueTypeToString(value.GetType()))); | |
| 120 return scoped_ptr<DeclarativeManifestData>(); | |
| 121 } | |
| 122 | |
|
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.
| |
| 123 for (size_t i = 0; i < list->GetSize(); ++i) { | |
| 124 const base::DictionaryValue* dict = nullptr; | |
| 125 if (!list->GetDictionary(i, &dict)) { | |
| 126 if (error->length()) | |
| 127 error->append(base::UTF8ToUTF16("; ")); | |
| 128 const base::Value* value = nullptr; | |
| 129 if (list->Get(i, &value)) | |
| 130 error->append(base::UTF8ToUTF16("expected dictionary, got " + | |
| 131 ValueTypeToString(value->GetType()))); | |
| 132 else | |
| 133 error->append(base::UTF8ToUTF16("expected dictionary")); | |
| 134 return scoped_ptr<DeclarativeManifestData>(); | |
| 135 } | |
| 136 std::string event; | |
| 137 if (!dict->GetString("event", &event)) { | |
| 138 if (error->length()) | |
| 139 error->append(UTF8ToUTF16("; ")); | |
| 140 error->append(UTF8ToUTF16("'event' is required")); | |
| 141 } | |
| 142 linked_ptr<Rule> rule(new Rule()); | |
| 143 if (Rule::Populate(*dict, rule.get()) && ConvertManifestRule(rule, error)) { | |
| 144 result->event_rules_map_[event].push_back(rule); | |
| 145 } else { | |
| 146 if (error->length()) | |
| 147 error->append(UTF8ToUTF16("; ")); | |
| 148 error->append(UTF8ToUTF16("rule failed to populate")); | |
| 149 return scoped_ptr<DeclarativeManifestData>(); | |
| 150 } | |
| 151 } | |
| 152 return result.Pass(); | |
| 153 } | |
| 154 | |
| 155 std::vector<linked_ptr<DeclarativeManifestData::Rule>>& | |
| 156 DeclarativeManifestData::RulesForEvent(const std::string& event) { | |
| 157 return event_rules_map_[event]; | |
| 158 } | |
| 159 | |
| 160 } // namespace extensions | |
| OLD | NEW |