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 22namespace { 23 24Profile* GetOriginalProfile() { 25 return ProfileManager::GetActiveUserProfile()->GetOriginalProfile(); 26} 27 28} // namespace 29 30TemplateUrlServiceAndroid::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 41TemplateUrlServiceAndroid::~TemplateUrlServiceAndroid() { 42} 43 44void TemplateUrlServiceAndroid::Load(JNIEnv* env, jobject obj) { 45 template_url_service_->Load(); 46} 47 48void 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 64jint 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 77jboolean TemplateUrlServiceAndroid::IsLoaded(JNIEnv* env, jobject obj) { 78 return template_url_service_->loaded(); 79} 80 81jint TemplateUrlServiceAndroid::GetTemplateUrlCount(JNIEnv* env, jobject obj) { 82 return template_url_service_->GetTemplateURLs().size(); 83} 84 85jboolean TemplateUrlServiceAndroid::IsSearchProviderManaged(JNIEnv* env, 86 jobject obj) { 87 return template_url_service_->is_default_search_managed(); 88} 89 90jboolean 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 100jboolean 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 109base::android::ScopedJavaLocalRef<jobject> 110TemplateUrlServiceAndroid::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 127bool TemplateUrlServiceAndroid::IsPrepopulatedTemplate(TemplateURL* url) { 128 return url->prepopulate_id() > 0; 129} 130 131void 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 141base::android::ScopedJavaLocalRef<jstring> 142TemplateUrlServiceAndroid::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 163base::android::ScopedJavaLocalRef<jstring> 164TemplateUrlServiceAndroid::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 180base::android::ScopedJavaLocalRef<jstring> 181TemplateUrlServiceAndroid::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 202base::android::ScopedJavaLocalRef<jstring> 203TemplateUrlServiceAndroid::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 236static 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 243bool TemplateUrlServiceAndroid::Register(JNIEnv* env) { 244 return RegisterNativesImpl(env); 245} 246