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" |
7 #include "base/callback.h" | 9 #include "base/callback.h" |
8 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
9 #include "chrome/browser/intents/default_web_intent_service.h" | 11 #include "chrome/browser/intents/default_web_intent_service.h" |
10 #include "chrome/browser/webdata/web_data_service.h" | 12 #include "chrome/browser/webdata/web_data_service.h" |
| 13 #include "chrome/common/extensions/extension.h" |
11 #include "chrome/common/extensions/extension_set.h" | 14 #include "chrome/common/extensions/extension_set.h" |
12 #include "googleurl/src/gurl.h" | 15 #include "googleurl/src/gurl.h" |
13 #include "net/base/mime_util.h" | 16 #include "net/base/mime_util.h" |
14 | 17 |
15 namespace { | 18 namespace { |
16 | 19 |
| 20 typedef WebIntentsRegistry::IntentServiceList IntentServiceList; |
| 21 |
17 // Compares two mime types for equality. Supports wild cards in both | 22 // Compares two mime types for equality. Supports wild cards in both |
18 // |type1| and |type2|. Wild cards are of the form '<type>/*' or '*'. | 23 // |type1| and |type2|. Wild cards are of the form '<type>/*' or '*'. |
19 bool MimeTypesAreEqual(const string16& type1, const string16& type2) { | 24 bool MimeTypesAreEqual(const string16& type1, const string16& type2) { |
20 // We don't have a MIME matcher that allows patterns on both sides | 25 // We don't have a MIME matcher that allows patterns on both sides |
21 // Instead, we do two comparisons, treating each type in turn as a | 26 // Instead, we do two comparisons, treating each type in turn as a |
22 // pattern. If either one matches, we consider this a MIME match. | 27 // pattern. If either one matches, we consider this a MIME match. |
23 if (net::MatchesMimeType(UTF16ToUTF8(type1), UTF16ToUTF8(type2))) | 28 if (net::MatchesMimeType(UTF16ToUTF8(type1), UTF16ToUTF8(type2))) |
24 return true; | 29 return true; |
25 return net::MatchesMimeType(UTF16ToUTF8(type2), UTF16ToUTF8(type1)); | 30 return net::MatchesMimeType(UTF16ToUTF8(type2), UTF16ToUTF8(type1)); |
26 } | 31 } |
27 | 32 |
| 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 |
28 } // namespace | 60 } // namespace |
29 | 61 |
30 using webkit_glue::WebIntentServiceData; | 62 using webkit_glue::WebIntentServiceData; |
31 | 63 |
32 // Internal object representing all data associated with a single query. | 64 // Internal object representing all data associated with a single query. |
33 struct WebIntentsRegistry::IntentsQuery { | 65 struct WebIntentsRegistry::IntentsQuery { |
34 // Unique query identifier. | 66 // Unique query identifier. |
35 QueryID query_id_; | 67 QueryID query_id_; |
36 | 68 |
37 // Underlying data query. | 69 // Underlying data query. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 IntentServiceList matching_services = static_cast< | 136 IntentServiceList matching_services = static_cast< |
105 const WDResult<IntentServiceList>*>(result)->GetValue(); | 137 const WDResult<IntentServiceList>*>(result)->GetValue(); |
106 | 138 |
107 // Loop over all services in all extensions, collect ones | 139 // Loop over all services in all extensions, collect ones |
108 // matching the query. | 140 // matching the query. |
109 if (extension_service_) { | 141 if (extension_service_) { |
110 const ExtensionSet* extensions = extension_service_->extensions(); | 142 const ExtensionSet* extensions = extension_service_->extensions(); |
111 if (extensions) { | 143 if (extensions) { |
112 for (ExtensionSet::const_iterator i(extensions->begin()); | 144 for (ExtensionSet::const_iterator i(extensions->begin()); |
113 i != extensions->end(); ++i) { | 145 i != extensions->end(); ++i) { |
114 const IntentServiceList& services((*i)->intents_services()); | 146 AddMatchingServicesForExtension(**i, query->action_, |
115 for (IntentServiceList::const_iterator j(services.begin()); | 147 &matching_services); |
116 j != services.end(); ++j) { | |
117 if (query->action_.empty() || query->action_ == j->action) | |
118 matching_services.push_back(*j); | |
119 } | |
120 } | 148 } |
121 } | 149 } |
122 } | 150 } |
123 | 151 |
124 // Filter out all services not matching the query type. | 152 // Filter out all services not matching the query type. |
125 IntentServiceList::iterator iter(matching_services.begin()); | 153 FilterServicesByMimetype(query->type_, &matching_services); |
126 while (iter != matching_services.end()) { | |
127 if (MimeTypesAreEqual(iter->type, query->type_)) | |
128 ++iter; | |
129 else | |
130 iter = matching_services.erase(iter); | |
131 } | |
132 | 154 |
133 query->consumer_->OnIntentsQueryDone(query->query_id_, matching_services); | 155 query->consumer_->OnIntentsQueryDone(query->query_id_, matching_services); |
134 delete query; | 156 delete query; |
135 } | 157 } |
136 | 158 |
137 const Extension* WebIntentsRegistry::ExtensionForURL(const std::string& url) { | 159 const Extension* WebIntentsRegistry::ExtensionForURL(const std::string& url) { |
138 const ExtensionSet* extensions = extension_service_->extensions(); | 160 const ExtensionSet* extensions = extension_service_->extensions(); |
139 if (!extensions) | 161 if (!extensions) |
140 return NULL; | 162 return NULL; |
141 | 163 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 const base::Callback<void(bool)>& callback) { | 284 const base::Callback<void(bool)>& callback) { |
263 IntentsQuery* query = new IntentsQuery( | 285 IntentsQuery* query = new IntentsQuery( |
264 next_query_id_++, new ServiceCheckConsumer(service, callback)); | 286 next_query_id_++, new ServiceCheckConsumer(service, callback)); |
265 query->pending_query_ = wds_->GetWebIntentServicesForURL( | 287 query->pending_query_ = wds_->GetWebIntentServicesForURL( |
266 UTF8ToUTF16(service.service_url.spec()), this); | 288 UTF8ToUTF16(service.service_url.spec()), this); |
267 queries_[query->pending_query_] = query; | 289 queries_[query->pending_query_] = query; |
268 | 290 |
269 return query->query_id_; | 291 return query->query_id_; |
270 } | 292 } |
271 | 293 |
| 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 |
272 void WebIntentsRegistry::RegisterDefaultIntentService( | 333 void WebIntentsRegistry::RegisterDefaultIntentService( |
273 const DefaultWebIntentService& default_service) { | 334 const DefaultWebIntentService& default_service) { |
274 DCHECK(wds_.get()); | 335 DCHECK(wds_.get()); |
275 wds_->AddDefaultWebIntentService(default_service); | 336 wds_->AddDefaultWebIntentService(default_service); |
276 } | 337 } |
277 | 338 |
278 void WebIntentsRegistry::UnregisterDefaultIntentService( | 339 void WebIntentsRegistry::UnregisterDefaultIntentService( |
279 const DefaultWebIntentService& default_service) { | 340 const DefaultWebIntentService& default_service) { |
280 DCHECK(wds_.get()); | 341 DCHECK(wds_.get()); |
281 wds_->RemoveDefaultWebIntentService(default_service); | 342 wds_->RemoveDefaultWebIntentService(default_service); |
(...skipping 17 matching lines...) Expand all Loading... |
299 const WebIntentServiceData& service) { | 360 const WebIntentServiceData& service) { |
300 DCHECK(wds_.get()); | 361 DCHECK(wds_.get()); |
301 wds_->AddWebIntentService(service); | 362 wds_->AddWebIntentService(service); |
302 } | 363 } |
303 | 364 |
304 void WebIntentsRegistry::UnregisterIntentService( | 365 void WebIntentsRegistry::UnregisterIntentService( |
305 const WebIntentServiceData& service) { | 366 const WebIntentServiceData& service) { |
306 DCHECK(wds_.get()); | 367 DCHECK(wds_.get()); |
307 wds_->RemoveWebIntentService(service); | 368 wds_->RemoveWebIntentService(service); |
308 } | 369 } |
OLD | NEW |