OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/intents/web_intents_registry.h" | 5 #include "chrome/browser/intents/web_intents_registry.h" |
6 | 6 |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/callback.h" | 7 #include "base/callback.h" |
10 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
11 #include "chrome/browser/intents/default_web_intent_service.h" | 9 #include "chrome/browser/intents/default_web_intent_service.h" |
12 #include "chrome/browser/webdata/web_data_service.h" | 10 #include "chrome/browser/webdata/web_data_service.h" |
13 #include "chrome/common/extensions/extension.h" | |
14 #include "chrome/common/extensions/extension_set.h" | 11 #include "chrome/common/extensions/extension_set.h" |
15 #include "googleurl/src/gurl.h" | 12 #include "googleurl/src/gurl.h" |
16 #include "net/base/mime_util.h" | 13 #include "net/base/mime_util.h" |
17 | 14 |
18 namespace { | 15 namespace { |
19 | 16 |
20 typedef WebIntentsRegistry::IntentServiceList IntentServiceList; | |
21 | |
22 // Compares two mime types for equality. Supports wild cards in both | 17 // Compares two mime types for equality. Supports wild cards in both |
23 // |type1| and |type2|. Wild cards are of the form '<type>/*' or '*'. | 18 // |type1| and |type2|. Wild cards are of the form '<type>/*' or '*'. |
24 bool MimeTypesAreEqual(const string16& type1, const string16& type2) { | 19 bool MimeTypesAreEqual(const string16& type1, const string16& type2) { |
25 // We don't have a MIME matcher that allows patterns on both sides | 20 // We don't have a MIME matcher that allows patterns on both sides |
26 // Instead, we do two comparisons, treating each type in turn as a | 21 // Instead, we do two comparisons, treating each type in turn as a |
27 // pattern. If either one matches, we consider this a MIME match. | 22 // pattern. If either one matches, we consider this a MIME match. |
28 if (net::MatchesMimeType(UTF16ToUTF8(type1), UTF16ToUTF8(type2))) | 23 if (net::MatchesMimeType(UTF16ToUTF8(type1), UTF16ToUTF8(type2))) |
29 return true; | 24 return true; |
30 return net::MatchesMimeType(UTF16ToUTF8(type2), UTF16ToUTF8(type1)); | 25 return net::MatchesMimeType(UTF16ToUTF8(type2), UTF16ToUTF8(type1)); |
31 } | 26 } |
32 | 27 |
33 // Adds any intent services of |extension| that match |action| to | |
34 // |matching_services|. | |
35 void AddMatchingServicesForExtension(const Extension& extension, | |
36 const string16& action, | |
37 IntentServiceList* matching_services) { | |
38 const IntentServiceList& services = extension.intents_services(); | |
39 for (IntentServiceList::const_iterator i = services.begin(); | |
40 i != services.end(); ++i) { | |
41 if (action.empty() || action == i->action) | |
42 matching_services->push_back(*i); | |
43 } | |
44 } | |
45 | |
46 // Removes all services from |matching_services| that do not match |mimetype|. | |
47 // Wildcards are supported, of the form '<type>/*' or '*'. | |
48 void FilterServicesByMimetype(const string16& mimetype, | |
49 IntentServiceList* matching_services) { | |
50 // Filter out all services not matching the query type. | |
51 IntentServiceList::iterator iter(matching_services->begin()); | |
52 while (iter != matching_services->end()) { | |
53 if (MimeTypesAreEqual(iter->type, mimetype)) | |
54 ++iter; | |
55 else | |
56 iter = matching_services->erase(iter); | |
57 } | |
58 } | |
59 | |
60 } // namespace | 28 } // namespace |
61 | 29 |
62 using webkit_glue::WebIntentServiceData; | 30 using webkit_glue::WebIntentServiceData; |
63 | 31 |
64 // Internal object representing all data associated with a single query. | 32 // Internal object representing all data associated with a single query. |
65 struct WebIntentsRegistry::IntentsQuery { | 33 struct WebIntentsRegistry::IntentsQuery { |
66 // Unique query identifier. | 34 // Unique query identifier. |
67 QueryID query_id_; | 35 QueryID query_id_; |
68 | 36 |
69 // Underlying data query. | 37 // Underlying data query. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 IntentServiceList matching_services = static_cast< | 104 IntentServiceList matching_services = static_cast< |
137 const WDResult<IntentServiceList>*>(result)->GetValue(); | 105 const WDResult<IntentServiceList>*>(result)->GetValue(); |
138 | 106 |
139 // Loop over all services in all extensions, collect ones | 107 // Loop over all services in all extensions, collect ones |
140 // matching the query. | 108 // matching the query. |
141 if (extension_service_) { | 109 if (extension_service_) { |
142 const ExtensionSet* extensions = extension_service_->extensions(); | 110 const ExtensionSet* extensions = extension_service_->extensions(); |
143 if (extensions) { | 111 if (extensions) { |
144 for (ExtensionSet::const_iterator i(extensions->begin()); | 112 for (ExtensionSet::const_iterator i(extensions->begin()); |
145 i != extensions->end(); ++i) { | 113 i != extensions->end(); ++i) { |
146 AddMatchingServicesForExtension(**i, query->action_, | 114 const IntentServiceList& services((*i)->intents_services()); |
147 &matching_services); | 115 for (IntentServiceList::const_iterator j(services.begin()); |
| 116 j != services.end(); ++j) { |
| 117 if (query->action_.empty() || query->action_ == j->action) |
| 118 matching_services.push_back(*j); |
| 119 } |
148 } | 120 } |
149 } | 121 } |
150 } | 122 } |
151 | 123 |
152 // Filter out all services not matching the query type. | 124 // Filter out all services not matching the query type. |
153 FilterServicesByMimetype(query->type_, &matching_services); | 125 IntentServiceList::iterator iter(matching_services.begin()); |
| 126 while (iter != matching_services.end()) { |
| 127 if (MimeTypesAreEqual(iter->type, query->type_)) |
| 128 ++iter; |
| 129 else |
| 130 iter = matching_services.erase(iter); |
| 131 } |
154 | 132 |
155 query->consumer_->OnIntentsQueryDone(query->query_id_, matching_services); | 133 query->consumer_->OnIntentsQueryDone(query->query_id_, matching_services); |
156 delete query; | 134 delete query; |
157 } | 135 } |
158 | 136 |
159 const Extension* WebIntentsRegistry::ExtensionForURL(const std::string& url) { | 137 const Extension* WebIntentsRegistry::ExtensionForURL(const std::string& url) { |
160 const ExtensionSet* extensions = extension_service_->extensions(); | 138 const ExtensionSet* extensions = extension_service_->extensions(); |
161 if (!extensions) | 139 if (!extensions) |
162 return NULL; | 140 return NULL; |
163 | 141 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 const base::Callback<void(bool)>& callback) { | 262 const base::Callback<void(bool)>& callback) { |
285 IntentsQuery* query = new IntentsQuery( | 263 IntentsQuery* query = new IntentsQuery( |
286 next_query_id_++, new ServiceCheckConsumer(service, callback)); | 264 next_query_id_++, new ServiceCheckConsumer(service, callback)); |
287 query->pending_query_ = wds_->GetWebIntentServicesForURL( | 265 query->pending_query_ = wds_->GetWebIntentServicesForURL( |
288 UTF8ToUTF16(service.service_url.spec()), this); | 266 UTF8ToUTF16(service.service_url.spec()), this); |
289 queries_[query->pending_query_] = query; | 267 queries_[query->pending_query_] = query; |
290 | 268 |
291 return query->query_id_; | 269 return query->query_id_; |
292 } | 270 } |
293 | 271 |
294 WebIntentsRegistry::QueryID | |
295 WebIntentsRegistry::GetIntentServicesForExtensionFilter( | |
296 const string16& action, | |
297 const string16& mimetype, | |
298 const std::string& extension_id, | |
299 Consumer* consumer) { | |
300 DCHECK(consumer); | |
301 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
302 | |
303 scoped_ptr<IntentsQuery> query( | |
304 new IntentsQuery(next_query_id_++, consumer, action, mimetype)); | |
305 int query_id = query->query_id_; | |
306 content::BrowserThread::PostTask( | |
307 content::BrowserThread::UI, | |
308 FROM_HERE, | |
309 base::Bind(&WebIntentsRegistry::DoGetIntentServicesForExtensionFilter, | |
310 base::Unretained(this), | |
311 base::Passed(&query), extension_id)); | |
312 | |
313 return query_id; | |
314 } | |
315 | |
316 void WebIntentsRegistry::DoGetIntentServicesForExtensionFilter( | |
317 scoped_ptr<IntentsQuery> query, | |
318 const std::string& extension_id) { | |
319 IntentServiceList matching_services; | |
320 | |
321 if (extension_service_) { | |
322 const Extension* extension = | |
323 extension_service_->GetExtensionById(extension_id, false); | |
324 AddMatchingServicesForExtension(*extension, | |
325 query->action_, | |
326 &matching_services); | |
327 FilterServicesByMimetype(query->type_, &matching_services); | |
328 } | |
329 | |
330 query->consumer_->OnIntentsQueryDone(query->query_id_, matching_services); | |
331 } | |
332 | |
333 void WebIntentsRegistry::RegisterDefaultIntentService( | 272 void WebIntentsRegistry::RegisterDefaultIntentService( |
334 const DefaultWebIntentService& default_service) { | 273 const DefaultWebIntentService& default_service) { |
335 DCHECK(wds_.get()); | 274 DCHECK(wds_.get()); |
336 wds_->AddDefaultWebIntentService(default_service); | 275 wds_->AddDefaultWebIntentService(default_service); |
337 } | 276 } |
338 | 277 |
339 void WebIntentsRegistry::UnregisterDefaultIntentService( | 278 void WebIntentsRegistry::UnregisterDefaultIntentService( |
340 const DefaultWebIntentService& default_service) { | 279 const DefaultWebIntentService& default_service) { |
341 DCHECK(wds_.get()); | 280 DCHECK(wds_.get()); |
342 wds_->RemoveDefaultWebIntentService(default_service); | 281 wds_->RemoveDefaultWebIntentService(default_service); |
(...skipping 17 matching lines...) Expand all Loading... |
360 const WebIntentServiceData& service) { | 299 const WebIntentServiceData& service) { |
361 DCHECK(wds_.get()); | 300 DCHECK(wds_.get()); |
362 wds_->AddWebIntentService(service); | 301 wds_->AddWebIntentService(service); |
363 } | 302 } |
364 | 303 |
365 void WebIntentsRegistry::UnregisterIntentService( | 304 void WebIntentsRegistry::UnregisterIntentService( |
366 const WebIntentServiceData& service) { | 305 const WebIntentServiceData& service) { |
367 DCHECK(wds_.get()); | 306 DCHECK(wds_.get()); |
368 wds_->RemoveWebIntentService(service); | 307 wds_->RemoveWebIntentService(service); |
369 } | 308 } |
OLD | NEW |