Chromium Code Reviews| 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/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
| 9 #include "chrome/browser/intents/default_web_intent_service.h" | |
| 9 #include "chrome/browser/webdata/web_data_service.h" | 10 #include "chrome/browser/webdata/web_data_service.h" |
| 11 #include "chrome/common/extensions/extension_set.h" | |
| 12 #include "googleurl/src/gurl.h" | |
| 10 #include "net/base/mime_util.h" | 13 #include "net/base/mime_util.h" |
| 11 | 14 |
| 12 namespace { | 15 namespace { |
| 13 | 16 |
| 14 // Compares two mime types for equality. Supports wild cards in both | 17 // Compares two mime types for equality. Supports wild cards in both |
| 15 // |type1| and |type2|. Wild cards are of the form '<type>/*' or '*'. | 18 // |type1| and |type2|. Wild cards are of the form '<type>/*' or '*'. |
| 16 bool MimeTypesAreEqual(const string16& type1, const string16& type2) { | 19 bool MimeTypesAreEqual(const string16& type1, const string16& type2) { |
| 17 // 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 |
| 18 // 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 |
| 19 // pattern. If either one matches, we consider this a MIME match. | 22 // pattern. If either one matches, we consider this a MIME match. |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 37 // The consumer for this particular query. | 40 // The consumer for this particular query. |
| 38 Consumer* consumer_; | 41 Consumer* consumer_; |
| 39 | 42 |
| 40 // The particular action to filter for while searching through extensions. | 43 // The particular action to filter for while searching through extensions. |
| 41 // If |action_| is empty, return all extension-provided services. | 44 // If |action_| is empty, return all extension-provided services. |
| 42 string16 action_; | 45 string16 action_; |
| 43 | 46 |
| 44 // The MIME type that was requested for this service query. | 47 // The MIME type that was requested for this service query. |
| 45 // Suppports wild cards. | 48 // Suppports wild cards. |
| 46 string16 type_; | 49 string16 type_; |
| 50 | |
| 51 // The url of the invoking page. | |
| 52 GURL url_; | |
| 53 | |
| 54 // Create a new IntentsQuery for services with the specified action/type. | |
| 55 IntentsQuery(QueryID id, Consumer* consumer, | |
| 56 const string16& action, const string16& type) | |
| 57 : query_id_(id), consumer_(consumer), action_(action), type_(type) {} | |
| 58 | |
| 59 // Create a new IntentsQuery for all intent services or for existence checks. | |
| 60 IntentsQuery(QueryID id, Consumer* consumer) | |
| 61 : query_id_(id), consumer_(consumer), type_(ASCIIToUTF16("*")) {} | |
| 62 | |
| 63 // Create a new IntentsQuery for default services. | |
| 64 IntentsQuery(QueryID id, Consumer* consumer, | |
| 65 const string16& action, const string16& type, const GURL& url) | |
| 66 : query_id_(id), consumer_(consumer), | |
| 67 action_(action), type_(type), url_(url) {} | |
| 47 }; | 68 }; |
| 48 | 69 |
| 49 WebIntentsRegistry::WebIntentsRegistry() : next_query_id_(0) {} | 70 WebIntentsRegistry::WebIntentsRegistry() : next_query_id_(0) {} |
| 50 | 71 |
| 51 WebIntentsRegistry::~WebIntentsRegistry() { | 72 WebIntentsRegistry::~WebIntentsRegistry() { |
| 52 // Cancel all pending queries, since we can't handle them any more. | 73 // Cancel all pending queries, since we can't handle them any more. |
| 53 for (QueryMap::iterator it(queries_.begin()); it != queries_.end(); ++it) { | 74 for (QueryMap::iterator it(queries_.begin()); it != queries_.end(); ++it) { |
| 54 wds_->CancelRequest(it->first); | 75 wds_->CancelRequest(it->first); |
| 55 delete it->second; | 76 delete it->second; |
| 56 } | 77 } |
| 57 } | 78 } |
| 58 | 79 |
| 59 void WebIntentsRegistry::Initialize( | 80 void WebIntentsRegistry::Initialize( |
| 60 scoped_refptr<WebDataService> wds, | 81 scoped_refptr<WebDataService> wds, |
| 61 ExtensionServiceInterface* extension_service) { | 82 ExtensionServiceInterface* extension_service) { |
| 62 wds_ = wds; | 83 wds_ = wds; |
| 63 extension_service_ = extension_service; | 84 extension_service_ = extension_service; |
| 64 } | 85 } |
| 65 | 86 |
| 66 void WebIntentsRegistry::OnWebDataServiceRequestDone( | 87 void WebIntentsRegistry::OnWebDataServiceRequestDone( |
| 67 WebDataService::Handle h, | 88 WebDataService::Handle h, |
| 68 const WDTypedResult* result) { | 89 const WDTypedResult* result) { |
| 69 DCHECK(result); | 90 DCHECK(result); |
| 91 if (result->GetType() == WEB_INTENTS_DEFAULTS_RESULT) { | |
| 92 OnWebDataServiceDefaultsRequestDone(h, result); | |
| 93 return; | |
| 94 } | |
| 70 DCHECK(result->GetType() == WEB_INTENTS_RESULT); | 95 DCHECK(result->GetType() == WEB_INTENTS_RESULT); |
| 71 | 96 |
| 72 QueryMap::iterator it = queries_.find(h); | 97 QueryMap::iterator it = queries_.find(h); |
| 73 DCHECK(it != queries_.end()); | 98 DCHECK(it != queries_.end()); |
| 74 | 99 |
| 75 IntentsQuery* query(it->second); | 100 IntentsQuery* query(it->second); |
| 76 DCHECK(query); | 101 DCHECK(query); |
| 77 queries_.erase(it); | 102 queries_.erase(it); |
| 78 | 103 |
| 79 IntentServiceList matching_services = static_cast< | 104 IntentServiceList matching_services = static_cast< |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 102 if (MimeTypesAreEqual(iter->type, query->type_)) | 127 if (MimeTypesAreEqual(iter->type, query->type_)) |
| 103 ++iter; | 128 ++iter; |
| 104 else | 129 else |
| 105 iter = matching_services.erase(iter); | 130 iter = matching_services.erase(iter); |
| 106 } | 131 } |
| 107 | 132 |
| 108 query->consumer_->OnIntentsQueryDone(query->query_id_, matching_services); | 133 query->consumer_->OnIntentsQueryDone(query->query_id_, matching_services); |
| 109 delete query; | 134 delete query; |
| 110 } | 135 } |
| 111 | 136 |
| 137 bool WebIntentsRegistry::IsContainingExtensionDisabled(const std::string& url) { | |
|
groby-ooo-7-16
2012/02/27 18:23:29
nit: I'd prefer Is..Enabled - negations in 'Is' fu
Greg Billock
2012/02/28 18:31:56
Done.
| |
| 138 const ExtensionSet* extensions = extension_service_->extensions(); | |
| 139 if (!extensions) | |
| 140 return false; | |
| 141 | |
| 142 // Use the unsafe ExtensionURLInfo constructor: we don't care if the extension | |
| 143 // is running or not. | |
| 144 GURL gurl(url); | |
| 145 ExtensionURLInfo info(gurl); | |
| 146 const Extension* extension = extensions->GetExtensionOrAppByURL(info); | |
| 147 if (extension == NULL) | |
| 148 return false; | |
| 149 | |
| 150 return !extension_service_->IsExtensionEnabled(extension->id()); | |
| 151 } | |
| 152 | |
| 153 void WebIntentsRegistry::OnWebDataServiceDefaultsRequestDone( | |
| 154 WebDataService::Handle h, | |
| 155 const WDTypedResult* result) { | |
| 156 QueryMap::iterator it = queries_.find(h); | |
| 157 DCHECK(it != queries_.end()); | |
| 158 | |
| 159 IntentsQuery* query(it->second); | |
| 160 DCHECK(query); | |
| 161 queries_.erase(it); | |
| 162 | |
| 163 std::vector<DefaultWebIntentService> services = static_cast< | |
| 164 const WDResult<std::vector<DefaultWebIntentService> >*>(result)-> | |
| 165 GetValue(); | |
| 166 | |
| 167 DefaultWebIntentService default_service; | |
| 168 std::vector<DefaultWebIntentService>::iterator iter(services.begin()); | |
| 169 for (; iter != services.end(); ++iter) { | |
| 170 if (!MimeTypesAreEqual(iter->type, query->type_)) { | |
| 171 continue; | |
| 172 } | |
| 173 if (!iter->url_pattern.MatchesURL(query->url_)) { | |
| 174 continue; | |
| 175 } | |
| 176 if (IsContainingExtensionDisabled(iter->service_url)) | |
| 177 continue; | |
| 178 | |
| 179 // Found a match. If it is better than default_service, use it. | |
| 180 // Currently the metric is that if the new value is user-set, | |
| 181 // prefer it. If the present value is suppressed, prefer it. | |
| 182 // If the new value has a more specific pattern, prefer it. | |
| 183 if (default_service.user_date <= 0 && iter->user_date >= 0) | |
| 184 default_service = *iter; | |
| 185 else if (default_service.suppression > 0 && iter->suppression <= 0) | |
| 186 default_service = *iter; | |
| 187 else if (default_service.url_pattern.match_all_urls() && | |
| 188 !iter->url_pattern.match_all_urls()) | |
| 189 default_service = *iter; | |
| 190 else if (iter->url_pattern < default_service.url_pattern) | |
| 191 default_service = *iter; | |
| 192 } | |
| 193 | |
| 194 query->consumer_->OnIntentsDefaultsQueryDone(query->query_id_, | |
| 195 default_service); | |
| 196 delete query; | |
| 197 } | |
| 198 | |
| 112 WebIntentsRegistry::QueryID WebIntentsRegistry::GetIntentServices( | 199 WebIntentsRegistry::QueryID WebIntentsRegistry::GetIntentServices( |
| 113 const string16& action, const string16& mimetype, Consumer* consumer) { | 200 const string16& action, const string16& mimetype, Consumer* consumer) { |
| 114 DCHECK(consumer); | 201 DCHECK(consumer); |
| 115 DCHECK(wds_.get()); | 202 DCHECK(wds_.get()); |
| 116 | 203 |
| 117 IntentsQuery* query = new IntentsQuery; | 204 IntentsQuery* query = |
| 118 query->query_id_ = next_query_id_++; | 205 new IntentsQuery(next_query_id_++, consumer, action, mimetype); |
| 119 query->consumer_ = consumer; | |
| 120 query->action_ = action; | |
| 121 query->type_ = mimetype; | |
| 122 query->pending_query_ = wds_->GetWebIntentServices(action, this); | 206 query->pending_query_ = wds_->GetWebIntentServices(action, this); |
| 123 queries_[query->pending_query_] = query; | 207 queries_[query->pending_query_] = query; |
| 124 | 208 |
| 125 return query->query_id_; | 209 return query->query_id_; |
| 126 } | 210 } |
| 127 | 211 |
| 128 WebIntentsRegistry::QueryID WebIntentsRegistry::GetAllIntentServices( | 212 WebIntentsRegistry::QueryID WebIntentsRegistry::GetAllIntentServices( |
| 129 Consumer* consumer) { | 213 Consumer* consumer) { |
| 130 DCHECK(consumer); | 214 DCHECK(consumer); |
| 131 DCHECK(wds_.get()); | 215 DCHECK(wds_.get()); |
| 132 | 216 |
| 133 IntentsQuery* query = new IntentsQuery; | 217 IntentsQuery* query = new IntentsQuery(next_query_id_++, consumer); |
| 134 query->query_id_ = next_query_id_++; | |
| 135 query->consumer_ = consumer; | |
| 136 query->type_ = ASCIIToUTF16("*"); | |
| 137 query->pending_query_ = wds_->GetAllWebIntentServices(this); | 218 query->pending_query_ = wds_->GetAllWebIntentServices(this); |
| 138 queries_[query->pending_query_] = query; | 219 queries_[query->pending_query_] = query; |
| 139 | 220 |
| 140 return query->query_id_; | 221 return query->query_id_; |
| 141 } | 222 } |
| 142 | 223 |
| 143 // Trampoline consumer for calls to IntentServiceExists. Forwards existence | 224 // Trampoline consumer for calls to IntentServiceExists. Forwards existence |
| 144 // of the provided |service| to the provided |callback|. | 225 // of the provided |service| to the provided |callback|. |
| 145 class ServiceCheckConsumer : public WebIntentsRegistry::Consumer { | 226 class ServiceCheckConsumer : public WebIntentsRegistry::Consumer { |
| 146 public: | 227 public: |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 161 i != list.end(); ++i) { | 242 i != list.end(); ++i) { |
| 162 if (*i == service_) { | 243 if (*i == service_) { |
| 163 callback_.Run(true); | 244 callback_.Run(true); |
| 164 return; | 245 return; |
| 165 } | 246 } |
| 166 } | 247 } |
| 167 | 248 |
| 168 callback_.Run(false); | 249 callback_.Run(false); |
| 169 } | 250 } |
| 170 | 251 |
| 252 virtual void OnIntentsDefaultsQueryDone( | |
| 253 WebIntentsRegistry::QueryID query_id, | |
| 254 const DefaultWebIntentService& default_service) {} | |
| 255 | |
| 171 private: | 256 private: |
| 172 base::Callback<void(bool)> callback_; | 257 base::Callback<void(bool)> callback_; |
| 173 WebIntentServiceData service_; | 258 WebIntentServiceData service_; |
| 174 }; | 259 }; |
| 175 | 260 |
| 176 WebIntentsRegistry::QueryID WebIntentsRegistry::IntentServiceExists( | 261 WebIntentsRegistry::QueryID WebIntentsRegistry::IntentServiceExists( |
| 177 const WebIntentServiceData& service, | 262 const WebIntentServiceData& service, |
| 178 const base::Callback<void(bool)>& callback) { | 263 const base::Callback<void(bool)>& callback) { |
| 179 IntentsQuery* query = new IntentsQuery; | 264 IntentsQuery* query = new IntentsQuery( |
| 180 query->query_id_ = next_query_id_++; | 265 next_query_id_++, new ServiceCheckConsumer(service, callback)); |
| 181 query->type_ = ASCIIToUTF16("*"); | |
| 182 query->consumer_ = new ServiceCheckConsumer(service, callback); | |
| 183 query->pending_query_ = wds_->GetWebIntentServicesForURL( | 266 query->pending_query_ = wds_->GetWebIntentServicesForURL( |
| 184 UTF8ToUTF16(service.service_url.spec()), this); | 267 UTF8ToUTF16(service.service_url.spec()), this); |
| 185 queries_[query->pending_query_] = query; | 268 queries_[query->pending_query_] = query; |
| 186 | 269 |
| 187 return query->query_id_; | 270 return query->query_id_; |
| 188 } | 271 } |
| 189 | 272 |
| 273 void WebIntentsRegistry::RegisterDefaultIntentService( | |
| 274 const DefaultWebIntentService& default_service) { | |
| 275 DCHECK(wds_.get()); | |
| 276 wds_->AddDefaultWebIntentService(default_service); | |
| 277 } | |
| 278 | |
| 279 void WebIntentsRegistry::UnregisterDefaultIntentService( | |
| 280 const DefaultWebIntentService& default_service) { | |
| 281 DCHECK(wds_.get()); | |
| 282 wds_->RemoveDefaultWebIntentService(default_service); | |
| 283 } | |
| 284 | |
| 285 WebIntentsRegistry::QueryID WebIntentsRegistry::GetDefaultIntentService( | |
| 286 const string16& action, | |
| 287 const string16& type, | |
| 288 const GURL& invoking_url, | |
| 289 Consumer* consumer) { | |
| 290 IntentsQuery* query = | |
| 291 new IntentsQuery(next_query_id_++, consumer, action, type, invoking_url); | |
| 292 query->pending_query_ = | |
| 293 wds_->GetDefaultWebIntentServicesForAction(action, this); | |
| 294 queries_[query->pending_query_] = query; | |
| 295 | |
| 296 return query->query_id_; | |
| 297 } | |
| 298 | |
| 190 void WebIntentsRegistry::RegisterIntentService( | 299 void WebIntentsRegistry::RegisterIntentService( |
| 191 const WebIntentServiceData& service) { | 300 const WebIntentServiceData& service) { |
| 192 DCHECK(wds_.get()); | 301 DCHECK(wds_.get()); |
| 193 wds_->AddWebIntentService(service); | 302 wds_->AddWebIntentService(service); |
| 194 } | 303 } |
| 195 | 304 |
| 196 void WebIntentsRegistry::UnregisterIntentService( | 305 void WebIntentsRegistry::UnregisterIntentService( |
| 197 const WebIntentServiceData& service) { | 306 const WebIntentServiceData& service) { |
| 198 DCHECK(wds_.get()); | 307 DCHECK(wds_.get()); |
| 199 wds_->RemoveWebIntentService(service); | 308 wds_->RemoveWebIntentService(service); |
| 200 } | 309 } |
| OLD | NEW |