Home | History | Annotate | Download | only in search_engines
      1 // Copyright (c) 2013 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/browser/search_engines/template_url_service_android.h"
      6 
      7 #include "base/android/jni_string.h"
      8 #include "base/bind.h"
      9 #include "base/format_macros.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "chrome/browser/profiles/profile_manager.h"
     13 #include "chrome/browser/search_engines/template_url_service_factory.h"
     14 #include "components/google/core/browser/google_util.h"
     15 #include "components/search_engines/template_url.h"
     16 #include "components/search_engines/template_url_prepopulate_data.h"
     17 #include "components/search_engines/template_url_service.h"
     18 #include "components/search_engines/util.h"
     19 #include "jni/TemplateUrlService_jni.h"
     20 #include "net/base/url_util.h"
     21 
     22 namespace {
     23 
     24 Profile* GetOriginalProfile() {
     25   return ProfileManager::GetActiveUserProfile()->GetOriginalProfile();
     26 }
     27 
     28 }  // namespace
     29 
     30 TemplateUrlServiceAndroid::TemplateUrlServiceAndroid(JNIEnv* env,
     31                                                      jobject obj)
     32     : weak_java_obj_(env, obj),
     33       template_url_service_(
     34           TemplateURLServiceFactory::GetForProfile(GetOriginalProfile())) {
     35   template_url_subscription_ =
     36       template_url_service_->RegisterOnLoadedCallback(
     37           base::Bind(&TemplateUrlServiceAndroid::OnTemplateURLServiceLoaded,
     38                      base::Unretained(this)));
     39 }
     40 
     41 TemplateUrlServiceAndroid::~TemplateUrlServiceAndroid() {
     42 }
     43 
     44 void TemplateUrlServiceAndroid::Load(JNIEnv* env, jobject obj) {
     45   template_url_service_->Load();
     46 }
     47 
     48 void TemplateUrlServiceAndroid::SetUserSelectedDefaultSearchProvider(
     49     JNIEnv* env,
     50     jobject obj,
     51     jint selected_index) {
     52   std::vector<TemplateURL*> template_urls =
     53       template_url_service_->GetTemplateURLs();
     54   size_t selected_index_size_t = static_cast<size_t>(selected_index);
     55   DCHECK_LT(selected_index_size_t, template_urls.size()) <<
     56       "Wrong index for search engine";
     57 
     58   TemplateURL* template_url = template_urls[selected_index_size_t];
     59   DCHECK_GT(template_url->prepopulate_id(), 0) <<
     60       "Tried to select non-prepopulated search engine";
     61   template_url_service_->SetUserSelectedDefaultSearchProvider(template_url);
     62 }
     63 
     64 jint TemplateUrlServiceAndroid::GetDefaultSearchProvider(JNIEnv* env,
     65                                                          jobject obj) {
     66   std::vector<TemplateURL*> template_urls =
     67       template_url_service_->GetTemplateURLs();
     68   TemplateURL* default_search_provider =
     69       template_url_service_->GetDefaultSearchProvider();
     70   for (size_t i = 0; i < template_urls.size(); ++i) {
     71     if (default_search_provider == template_urls[i])
     72       return i;
     73   }
     74   return -1;
     75 }
     76 
     77 jboolean TemplateUrlServiceAndroid::IsLoaded(JNIEnv* env, jobject obj) {
     78   return template_url_service_->loaded();
     79 }
     80 
     81 jint TemplateUrlServiceAndroid::GetTemplateUrlCount(JNIEnv* env, jobject obj) {
     82   return template_url_service_->GetTemplateURLs().size();
     83 }
     84 
     85 jboolean TemplateUrlServiceAndroid::IsSearchProviderManaged(JNIEnv* env,
     86                                                             jobject obj) {
     87   return template_url_service_->is_default_search_managed();
     88 }
     89 
     90 jboolean TemplateUrlServiceAndroid::IsSearchByImageAvailable(JNIEnv* env,
     91                                                              jobject obj) {
     92   const TemplateURL* default_search_provider =
     93       template_url_service_->GetDefaultSearchProvider();
     94   return default_search_provider &&
     95       !default_search_provider->image_url().empty() &&
     96       default_search_provider->image_url_ref().IsValid(
     97           template_url_service_->search_terms_data());
     98 }
     99 
    100 jboolean TemplateUrlServiceAndroid::IsDefaultSearchEngineGoogle(JNIEnv* env,
    101                                                                 jobject obj) {
    102   TemplateURL* default_search_provider =
    103       template_url_service_->GetDefaultSearchProvider();
    104   return default_search_provider &&
    105       default_search_provider->url_ref().HasGoogleBaseURLs(
    106           template_url_service_->search_terms_data());
    107 }
    108 
    109 base::android::ScopedJavaLocalRef<jobject>
    110 TemplateUrlServiceAndroid::GetPrepopulatedTemplateUrlAt(JNIEnv* env,
    111                                                         jobject obj,
    112                                                         jint index) {
    113   TemplateURL* template_url = template_url_service_->GetTemplateURLs()[index];
    114   if (!IsPrepopulatedTemplate(template_url) &&
    115       !template_url->created_by_policy())
    116    return ScopedJavaLocalRef<jobject>();
    117 
    118   return Java_TemplateUrl_create(
    119       env,
    120       index,
    121       base::android::ConvertUTF16ToJavaString(
    122           env, template_url->short_name()).obj(),
    123       base::android::ConvertUTF16ToJavaString(
    124           env, template_url->keyword()).obj());
    125 }
    126 
    127 bool TemplateUrlServiceAndroid::IsPrepopulatedTemplate(TemplateURL* url) {
    128   return url->prepopulate_id() > 0;
    129 }
    130 
    131 void TemplateUrlServiceAndroid::OnTemplateURLServiceLoaded() {
    132   template_url_subscription_.reset();
    133   JNIEnv* env = base::android::AttachCurrentThread();
    134   if (weak_java_obj_.get(env).is_null())
    135     return;
    136 
    137   Java_TemplateUrlService_templateUrlServiceLoaded(
    138       env, weak_java_obj_.get(env).obj());
    139 }
    140 
    141 base::android::ScopedJavaLocalRef<jstring>
    142 TemplateUrlServiceAndroid::GetUrlForSearchQuery(JNIEnv* env,
    143                                                 jobject obj,
    144                                                 jstring jquery) {
    145   const TemplateURL* default_provider =
    146       template_url_service_->GetDefaultSearchProvider();
    147 
    148   base::string16 query(base::android::ConvertJavaStringToUTF16(env, jquery));
    149 
    150   std::string url;
    151   if (default_provider &&
    152       default_provider->url_ref().SupportsReplacement(
    153           template_url_service_->search_terms_data()) &&
    154       !query.empty()) {
    155     url = default_provider->url_ref().ReplaceSearchTerms(
    156         TemplateURLRef::SearchTermsArgs(query),
    157         template_url_service_->search_terms_data());
    158   }
    159 
    160   return base::android::ConvertUTF8ToJavaString(env, url);
    161 }
    162 
    163 base::android::ScopedJavaLocalRef<jstring>
    164 TemplateUrlServiceAndroid::GetUrlForVoiceSearchQuery(JNIEnv* env,
    165                                                      jobject obj,
    166                                                      jstring jquery) {
    167   base::string16 query(base::android::ConvertJavaStringToUTF16(env, jquery));
    168   std::string url;
    169 
    170   if (!query.empty()) {
    171     GURL gurl(GetDefaultSearchURLForSearchTerms(template_url_service_, query));
    172     if (google_util::IsGoogleSearchUrl(gurl))
    173       gurl = net::AppendQueryParameter(gurl, "inm", "vs");
    174     url = gurl.spec();
    175   }
    176 
    177   return base::android::ConvertUTF8ToJavaString(env, url);
    178 }
    179 
    180 base::android::ScopedJavaLocalRef<jstring>
    181 TemplateUrlServiceAndroid::ReplaceSearchTermsInUrl(JNIEnv* env,
    182                                                    jobject obj,
    183                                                    jstring jquery,
    184                                                    jstring jcurrent_url) {
    185   TemplateURL* default_provider =
    186       template_url_service_->GetDefaultSearchProvider();
    187 
    188   base::string16 query(base::android::ConvertJavaStringToUTF16(env, jquery));
    189   GURL current_url(base::android::ConvertJavaStringToUTF16(env, jcurrent_url));
    190   GURL destination_url(current_url);
    191   if (default_provider && !query.empty()) {
    192     bool refined_query = default_provider->ReplaceSearchTermsInURL(
    193         current_url, TemplateURLRef::SearchTermsArgs(query),
    194         template_url_service_->search_terms_data(), &destination_url);
    195     if (refined_query)
    196       return base::android::ConvertUTF8ToJavaString(
    197           env, destination_url.spec());
    198   }
    199   return base::android::ScopedJavaLocalRef<jstring>(env, NULL);
    200 }
    201 
    202 base::android::ScopedJavaLocalRef<jstring>
    203 TemplateUrlServiceAndroid::GetUrlForContextualSearchQuery(
    204     JNIEnv* env,
    205     jobject obj,
    206     jstring jquery,
    207     jstring jalternate_term,
    208     jboolean jshould_prefetch) {
    209   base::string16 query(base::android::ConvertJavaStringToUTF16(env, jquery));
    210   std::string url;
    211 
    212   if (!query.empty()) {
    213     GURL gurl(GetDefaultSearchURLForSearchTerms(template_url_service_, query));
    214     if (google_util::IsGoogleSearchUrl(gurl)) {
    215       gurl = net::AppendQueryParameter(gurl, "ctxs", "2");
    216       if (jshould_prefetch) {
    217         // Indicate that the search page is being prefetched.
    218         gurl = net::AppendQueryParameter(gurl, "pf", "c");
    219       }
    220 
    221       if (jalternate_term) {
    222         std::string alternate_term(
    223             base::android::ConvertJavaStringToUTF8(env, jalternate_term));
    224         if (!alternate_term.empty()) {
    225           gurl = net::AppendQueryParameter(
    226               gurl, "ctxsl_alternate_term", alternate_term);
    227         }
    228       }
    229     }
    230     url = gurl.spec();
    231   }
    232 
    233   return base::android::ConvertUTF8ToJavaString(env, url);
    234 }
    235 
    236 static jlong Init(JNIEnv* env, jobject obj) {
    237   TemplateUrlServiceAndroid* template_url_service_android =
    238       new TemplateUrlServiceAndroid(env, obj);
    239   return reinterpret_cast<intptr_t>(template_url_service_android);
    240 }
    241 
    242 // static
    243 bool TemplateUrlServiceAndroid::Register(JNIEnv* env) {
    244   return RegisterNativesImpl(env);
    245 }
    246