| 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 const Extension* WebIntentsRegistry::ExtensionForURL(const std::string& url) { | 
 |  138   const ExtensionSet* extensions = extension_service_->extensions(); | 
 |  139   if (!extensions) | 
 |  140     return NULL; | 
 |  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   return extensions->GetExtensionOrAppByURL(info); | 
 |  147 } | 
 |  148  | 
 |  149 void WebIntentsRegistry::OnWebDataServiceDefaultsRequestDone( | 
 |  150     WebDataService::Handle h, | 
 |  151     const WDTypedResult* result) { | 
 |  152   QueryMap::iterator it = queries_.find(h); | 
 |  153   DCHECK(it != queries_.end()); | 
 |  154  | 
 |  155   IntentsQuery* query(it->second); | 
 |  156   DCHECK(query); | 
 |  157   queries_.erase(it); | 
 |  158  | 
 |  159   std::vector<DefaultWebIntentService> services = static_cast< | 
 |  160       const WDResult<std::vector<DefaultWebIntentService> >*>(result)-> | 
 |  161           GetValue(); | 
 |  162  | 
 |  163   DefaultWebIntentService default_service; | 
 |  164   std::vector<DefaultWebIntentService>::iterator iter(services.begin()); | 
 |  165   for (; iter != services.end(); ++iter) { | 
 |  166     if (!MimeTypesAreEqual(iter->type, query->type_)) { | 
 |  167       continue; | 
 |  168     } | 
 |  169     if (!iter->url_pattern.MatchesURL(query->url_)) { | 
 |  170       continue; | 
 |  171     } | 
 |  172     const Extension* extension = ExtensionForURL(iter->service_url); | 
 |  173     if (extension != NULL && | 
 |  174         !extension_service_->IsExtensionEnabled(extension->id())) { | 
 |  175       continue; | 
 |  176     } | 
 |  177  | 
 |  178     // Found a match. If it is better than default_service, use it. | 
 |  179     // Currently the metric is that if the new value is user-set, | 
 |  180     // prefer it. If the present value is suppressed, prefer it. | 
 |  181     // If the new value has a more specific pattern, prefer it. | 
 |  182     if (default_service.user_date <= 0 && iter->user_date >= 0) | 
 |  183       default_service = *iter; | 
 |  184     else if (default_service.suppression > 0 && iter->suppression <= 0) | 
 |  185       default_service = *iter; | 
 |  186     else if (default_service.url_pattern.match_all_urls() && | 
 |  187              !iter->url_pattern.match_all_urls()) | 
 |  188       default_service = *iter; | 
 |  189     else if (iter->url_pattern < default_service.url_pattern) | 
 |  190       default_service = *iter; | 
 |  191   } | 
 |  192  | 
 |  193   query->consumer_->OnIntentsDefaultsQueryDone(query->query_id_, | 
 |  194                                                default_service); | 
 |  195   delete query; | 
 |  196 } | 
 |  197  | 
|  112 WebIntentsRegistry::QueryID WebIntentsRegistry::GetIntentServices( |  198 WebIntentsRegistry::QueryID WebIntentsRegistry::GetIntentServices( | 
|  113     const string16& action, const string16& mimetype, Consumer* consumer) { |  199     const string16& action, const string16& mimetype, Consumer* consumer) { | 
|  114   DCHECK(consumer); |  200   DCHECK(consumer); | 
|  115   DCHECK(wds_.get()); |  201   DCHECK(wds_.get()); | 
|  116  |  202  | 
|  117   IntentsQuery* query = new IntentsQuery; |  203   IntentsQuery* query = | 
|  118   query->query_id_ = next_query_id_++; |  204       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); |  205   query->pending_query_ = wds_->GetWebIntentServices(action, this); | 
|  123   queries_[query->pending_query_] = query; |  206   queries_[query->pending_query_] = query; | 
|  124  |  207  | 
|  125   return query->query_id_; |  208   return query->query_id_; | 
|  126 } |  209 } | 
|  127  |  210  | 
|  128 WebIntentsRegistry::QueryID WebIntentsRegistry::GetAllIntentServices( |  211 WebIntentsRegistry::QueryID WebIntentsRegistry::GetAllIntentServices( | 
|  129     Consumer* consumer) { |  212     Consumer* consumer) { | 
|  130   DCHECK(consumer); |  213   DCHECK(consumer); | 
|  131   DCHECK(wds_.get()); |  214   DCHECK(wds_.get()); | 
|  132  |  215  | 
|  133   IntentsQuery* query = new IntentsQuery; |  216   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); |  217   query->pending_query_ = wds_->GetAllWebIntentServices(this); | 
|  138   queries_[query->pending_query_] = query; |  218   queries_[query->pending_query_] = query; | 
|  139  |  219  | 
|  140   return query->query_id_; |  220   return query->query_id_; | 
|  141 } |  221 } | 
|  142  |  222  | 
|  143 // Trampoline consumer for calls to IntentServiceExists. Forwards existence |  223 // Trampoline consumer for calls to IntentServiceExists. Forwards existence | 
|  144 // of the provided |service| to the provided |callback|. |  224 // of the provided |service| to the provided |callback|. | 
|  145 class ServiceCheckConsumer : public WebIntentsRegistry::Consumer { |  225 class ServiceCheckConsumer : public WebIntentsRegistry::Consumer { | 
|  146  public: |  226  public: | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|  161          i != list.end(); ++i) { |  241          i != list.end(); ++i) { | 
|  162       if (*i == service_) { |  242       if (*i == service_) { | 
|  163         callback_.Run(true); |  243         callback_.Run(true); | 
|  164         return; |  244         return; | 
|  165       } |  245       } | 
|  166     } |  246     } | 
|  167  |  247  | 
|  168     callback_.Run(false); |  248     callback_.Run(false); | 
|  169   } |  249   } | 
|  170  |  250  | 
 |  251   virtual void OnIntentsDefaultsQueryDone( | 
 |  252       WebIntentsRegistry::QueryID query_id, | 
 |  253       const DefaultWebIntentService& default_service) {} | 
 |  254  | 
|  171  private: |  255  private: | 
|  172   base::Callback<void(bool)> callback_; |  256   base::Callback<void(bool)> callback_; | 
|  173   WebIntentServiceData service_; |  257   WebIntentServiceData service_; | 
|  174 }; |  258 }; | 
|  175  |  259  | 
|  176 WebIntentsRegistry::QueryID WebIntentsRegistry::IntentServiceExists( |  260 WebIntentsRegistry::QueryID WebIntentsRegistry::IntentServiceExists( | 
|  177     const WebIntentServiceData& service, |  261     const WebIntentServiceData& service, | 
|  178     const base::Callback<void(bool)>& callback) { |  262     const base::Callback<void(bool)>& callback) { | 
|  179   IntentsQuery* query = new IntentsQuery; |  263   IntentsQuery* query = new IntentsQuery( | 
|  180   query->query_id_ = next_query_id_++; |  264       next_query_id_++, new ServiceCheckConsumer(service, callback)); | 
|  181   query->type_ = ASCIIToUTF16("*"); |  | 
|  182   query->consumer_ = new ServiceCheckConsumer(service, callback); |  | 
|  183   query->pending_query_ = wds_->GetWebIntentServicesForURL( |  265   query->pending_query_ = wds_->GetWebIntentServicesForURL( | 
|  184       UTF8ToUTF16(service.service_url.spec()), this); |  266       UTF8ToUTF16(service.service_url.spec()), this); | 
|  185   queries_[query->pending_query_] = query; |  267   queries_[query->pending_query_] = query; | 
|  186  |  268  | 
|  187   return query->query_id_; |  269   return query->query_id_; | 
|  188 } |  270 } | 
|  189  |  271  | 
 |  272 void WebIntentsRegistry::RegisterDefaultIntentService( | 
 |  273     const DefaultWebIntentService& default_service) { | 
 |  274   DCHECK(wds_.get()); | 
 |  275   wds_->AddDefaultWebIntentService(default_service); | 
 |  276 } | 
 |  277  | 
 |  278 void WebIntentsRegistry::UnregisterDefaultIntentService( | 
 |  279     const DefaultWebIntentService& default_service) { | 
 |  280   DCHECK(wds_.get()); | 
 |  281   wds_->RemoveDefaultWebIntentService(default_service); | 
 |  282 } | 
 |  283  | 
 |  284 WebIntentsRegistry::QueryID WebIntentsRegistry::GetDefaultIntentService( | 
 |  285     const string16& action, | 
 |  286     const string16& type, | 
 |  287     const GURL& invoking_url, | 
 |  288     Consumer* consumer) { | 
 |  289   IntentsQuery* query = | 
 |  290       new IntentsQuery(next_query_id_++, consumer, action, type, invoking_url); | 
 |  291   query->pending_query_ = | 
 |  292       wds_->GetDefaultWebIntentServicesForAction(action, this); | 
 |  293   queries_[query->pending_query_] = query; | 
 |  294  | 
 |  295   return query->query_id_; | 
 |  296 } | 
 |  297  | 
|  190 void WebIntentsRegistry::RegisterIntentService( |  298 void WebIntentsRegistry::RegisterIntentService( | 
|  191     const WebIntentServiceData& service) { |  299     const WebIntentServiceData& service) { | 
|  192   DCHECK(wds_.get()); |  300   DCHECK(wds_.get()); | 
|  193   wds_->AddWebIntentService(service); |  301   wds_->AddWebIntentService(service); | 
|  194 } |  302 } | 
|  195  |  303  | 
|  196 void WebIntentsRegistry::UnregisterIntentService( |  304 void WebIntentsRegistry::UnregisterIntentService( | 
|  197     const WebIntentServiceData& service) { |  305     const WebIntentServiceData& service) { | 
|  198   DCHECK(wds_.get()); |  306   DCHECK(wds_.get()); | 
|  199   wds_->RemoveWebIntentService(service); |  307   wds_->RemoveWebIntentService(service); | 
|  200 } |  308 } | 
| OLD | NEW |