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

Side by Side Diff: chrome/common/extensions/web_intents_handler.cc

Issue 11741014: Move 'intents' parsing out of Extension (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed special_storage_policy unittest Created 7 years, 11 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
« no previous file with comments | « chrome/common/extensions/web_intents_handler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "chrome/common/extensions/web_intents_handler.h"
6
7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/string_number_conversions.h"
10 #include "base/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/common/extensions/extension_manifest_constants.h"
13 #include "extensions/common/error_utils.h"
14 #include "webkit/glue/web_intent_service_data.h"
15
16 namespace extensions {
17
18 namespace keys = extension_manifest_keys;
19 namespace values = extension_manifest_values;
20 namespace errors = extension_manifest_errors;
21
22 namespace {
23
24 // Parses a single web intent action in the manifest.
25 bool LoadWebIntentsAction(const std::string& action_name,
26 const DictionaryValue& intent_service,
27 Extension* extension,
28 string16* error,
29 WebIntentServiceDataList* intents_services) {
30 DCHECK(error);
31 webkit_glue::WebIntentServiceData service;
32 std::string value;
33
34 service.action = UTF8ToUTF16(action_name);
35
36 const ListValue* mime_types = NULL;
37 if (!intent_service.HasKey(keys::kIntentType) ||
38 !intent_service.GetList(keys::kIntentType, &mime_types) ||
39 mime_types->GetSize() == 0) {
40 *error = ErrorUtils::FormatErrorMessageUTF16(
41 errors::kInvalidIntentType, action_name);
42 return false;
43 }
44
45 std::string href;
46 if (intent_service.HasKey(keys::kIntentPath)) {
47 if (!intent_service.GetString(keys::kIntentPath, &href)) {
48 *error = ASCIIToUTF16(errors::kInvalidIntentHref);
49 return false;
50 }
51 }
52
53 if (intent_service.HasKey(keys::kIntentHref)) {
54 if (!href.empty()) {
55 *error = ErrorUtils::FormatErrorMessageUTF16(
56 errors::kInvalidIntentHrefOldAndNewKey, action_name,
57 keys::kIntentPath, keys::kIntentHref);
58 return false;
59 }
60 if (!intent_service.GetString(keys::kIntentHref, &href)) {
61 *error = ASCIIToUTF16(errors::kInvalidIntentHref);
62 return false;
63 }
64 }
65
66 // For packaged/hosted apps, empty href implies the respective launch URLs.
67 if (href.empty()) {
68 if (extension->is_hosted_app()) {
69 href = extension->launch_web_url();
70 } else if (extension->is_legacy_packaged_app()) {
71 href = extension->launch_local_path();
72 }
73 }
74
75 // If there still is not an href, the manifest is malformed, unless this is a
76 // platform app in which case the href should not be present.
77 if (href.empty() && !extension->is_platform_app()) {
78 *error = ErrorUtils::FormatErrorMessageUTF16(
79 errors::kInvalidIntentHrefEmpty, action_name);
80 return false;
81 } else if (!href.empty() && extension->is_platform_app()) {
82 *error = ErrorUtils::FormatErrorMessageUTF16(
83 errors::kInvalidIntentHrefInPlatformApp, action_name);
84 return false;
85 }
86
87 GURL service_url(href);
88 if (extension->is_hosted_app()) {
89 // Hosted apps require an absolute URL for intents.
90 if (!service_url.is_valid() ||
91 !(extension->web_extent().MatchesURL(service_url))) {
92 *error = ErrorUtils::FormatErrorMessageUTF16(
93 errors::kInvalidIntentPageInHostedApp, action_name);
94 return false;
95 }
96 service.service_url = service_url;
97 } else if (extension->is_platform_app()) {
98 service.service_url = extension->GetBackgroundURL();
99 } else {
100 // We do not allow absolute intent URLs in non-hosted apps.
101 if (service_url.is_valid()) {
102 *error = ErrorUtils::FormatErrorMessageUTF16(
103 errors::kCannotAccessPage, href);
104 return false;
105 }
106 service.service_url = extension->GetResourceURL(href);
107 }
108
109 if (intent_service.HasKey(keys::kIntentTitle) &&
110 !intent_service.GetString(keys::kIntentTitle, &service.title)) {
111 *error = ASCIIToUTF16(errors::kInvalidIntentTitle);
112 return false;
113 }
114
115 if (intent_service.HasKey(keys::kIntentDisposition)) {
116 if (extension->is_platform_app()) {
117 *error = ErrorUtils::FormatErrorMessageUTF16(
118 errors::kInvalidIntentDispositionInPlatformApp, action_name);
119 return false;
120 }
121 if (!intent_service.GetString(keys::kIntentDisposition, &value) ||
122 (value != values::kIntentDispositionWindow &&
123 value != values::kIntentDispositionInline)) {
124 *error = ASCIIToUTF16(errors::kInvalidIntentDisposition);
125 return false;
126 }
127 if (value == values::kIntentDispositionInline) {
128 service.disposition =
129 webkit_glue::WebIntentServiceData::DISPOSITION_INLINE;
130 } else {
131 service.disposition =
132 webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW;
133 }
134 }
135
136 for (size_t i = 0; i < mime_types->GetSize(); ++i) {
137 if (!mime_types->GetString(i, &service.type)) {
138 *error = ErrorUtils::FormatErrorMessageUTF16(
139 errors::kInvalidIntentTypeElement, action_name,
140 std::string(base::IntToString(i)));
141 return false;
142 }
143 intents_services->push_back(service);
144 }
145 return true;
146 }
147
148 } // namespace
149
150 WebIntentsInfo::WebIntentsInfo() {}
151 WebIntentsInfo::~WebIntentsInfo() {}
152
153 static base::LazyInstance<WebIntentServiceDataList> g_empty_intents_data =
154 LAZY_INSTANCE_INITIALIZER;
155
156 // static
157 const WebIntentServiceDataList& WebIntentsInfo::GetIntentsServices(
158 const Extension* extension) {
159 WebIntentsInfo* info = static_cast<WebIntentsInfo*>(
160 extension->GetManifestData(keys::kIntents));
161 return info ? info->intents_services_ : g_empty_intents_data.Get();
162 }
163
164 WebIntentsHandler::WebIntentsHandler() {
165 }
166
167 WebIntentsHandler::~WebIntentsHandler() {
168 }
169
170 bool WebIntentsHandler::Parse(const base::Value* value,
171 Extension* extension,
172 string16* error) {
173 scoped_ptr<WebIntentsInfo> info(new WebIntentsInfo);
174 const DictionaryValue* all_services = NULL;
175 if (!value->GetAsDictionary(&all_services)) {
176 *error = ASCIIToUTF16(errors::kInvalidIntents);
177 return false;
178 }
179
180 for (DictionaryValue::key_iterator iter(all_services->begin_keys());
181 iter != all_services->end_keys(); ++iter) {
182 // Any entry in the intents dictionary can either have a list of
183 // dictionaries, or just a single dictionary attached to that. Try
184 // lists first, fall back to single dictionary.
185 const ListValue* service_list = NULL;
186 const DictionaryValue* one_service = NULL;
187 if (all_services->GetListWithoutPathExpansion(*iter, &service_list)) {
188 for (size_t i = 0; i < service_list->GetSize(); ++i) {
189 if (!service_list->GetDictionary(i, &one_service)) {
190 *error = ASCIIToUTF16(errors::kInvalidIntent);
191 return false;
192 }
193 if (!LoadWebIntentsAction(*iter, *one_service, extension,
194 error, &info->intents_services_))
195 return false;
196 }
197 } else {
198 if (!all_services->GetDictionaryWithoutPathExpansion(*iter,
199 &one_service)) {
200 *error = ASCIIToUTF16(errors::kInvalidIntent);
201 return false;
202 }
203 if (!LoadWebIntentsAction(*iter, *one_service, extension,
204 error, &info->intents_services_))
205 return false;
206 }
207 }
208 extension->SetManifestData(keys::kIntents, info.release());
209 return true;
210 }
211
212 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/common/extensions/web_intents_handler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698