Upstream oodles of Chrome for Android code into Chromium.
[chromium-blink-merge.git] / chrome / browser / android / contextualsearch / contextual_search_manager.cc
blob64bd88c3c70553a5e67bbe215a57133d62fa9ea0
1 // Copyright 2015 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.
5 #include "chrome/browser/android/contextualsearch/contextual_search_manager.h"
7 #include <set>
9 #include "base/android/jni_string.h"
10 #include "base/callback.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/time/time.h"
13 #include "chrome/browser/android/contextualsearch/contextual_search_delegate.h"
14 #include "chrome/browser/android/tab_android.h"
15 #include "chrome/browser/history/history_service_factory.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/search/contextual_search_promo_source_android.h"
18 #include "chrome/browser/search_engines/template_url_service_factory.h"
19 #include "chrome/browser/ui/android/window_android_helper.h"
20 #include "components/history/core/browser/history_service.h"
21 #include "components/navigation_interception/intercept_navigation_delegate.h"
22 #include "components/variations/variations_associated_data.h"
23 #include "components/web_contents_delegate_android/web_contents_delegate_android.h"
24 #include "content/public/browser/android/content_view_core.h"
25 #include "content/public/browser/web_contents.h"
26 #include "jni/ContextualSearchManager_jni.h"
27 #include "net/url_request/url_fetcher_impl.h"
29 using content::ContentViewCore;
31 namespace {
33 // Field trial related constants.
34 const char kContextualSearchFieldTrialName[] = "ContextualSearch";
35 const char kContextualSearchHidePromoHeaderParam[] = "hide_promo_header";
36 const char kContextualSearchEnabledValue[] = "enabled";
38 const int kHistoryDeletionWindowSeconds = 2;
40 // Because we need a callback, this needs to exist.
41 void OnHistoryDeletionDone() {
44 } // namespace
46 // This class manages the native behavior of the Contextual Search feature.
47 // Instances of this class are owned by the Java ContextualSearchManager.
48 // Most of the work is actually done in an associated delegate to this class:
49 // the ContextualSearchDelegate.
50 ContextualSearchManager::ContextualSearchManager(JNIEnv* env, jobject obj) {
51 java_manager_.Reset(env, obj);
52 Java_ContextualSearchManager_setNativeManager(
53 env, obj, reinterpret_cast<intptr_t>(this));
54 Profile* profile = ProfileManager::GetActiveUserProfile();
55 delegate_.reset(new ContextualSearchDelegate(
56 profile->GetRequestContext(),
57 TemplateURLServiceFactory::GetForProfile(profile),
58 base::Bind(&ContextualSearchManager::OnSearchTermResolutionResponse,
59 base::Unretained(this)),
60 base::Bind(&ContextualSearchManager::OnSurroundingTextAvailable,
61 base::Unretained(this)),
62 base::Bind(&ContextualSearchManager::OnIcingSelectionAvailable,
63 base::Unretained(this))));
64 content::URLDataSource::Add(ProfileManager::GetActiveUserProfile(),
65 new ContextualSearchPromoSourceAndroid());
68 ContextualSearchManager::~ContextualSearchManager() {
69 JNIEnv* env = base::android::AttachCurrentThread();
70 Java_ContextualSearchManager_clearNativeManager(env, java_manager_.obj());
73 void ContextualSearchManager::Destroy(JNIEnv* env, jobject obj) { delete this; }
75 void ContextualSearchManager::StartSearchTermResolutionRequest(
76 JNIEnv* env,
77 jobject obj,
78 jstring j_selection,
79 jboolean j_use_resolved_search_term,
80 jobject j_base_content_view_core) {
81 ContentViewCore* base_content_view_core =
82 ContentViewCore::GetNativeContentViewCore(env, j_base_content_view_core);
83 DCHECK(base_content_view_core);
84 std::string selection(
85 base::android::ConvertJavaStringToUTF8(env, j_selection));
86 bool use_resolved_search_term = j_use_resolved_search_term;
87 // Calls back to OnSearchTermResolutionResponse.
88 delegate_->StartSearchTermResolutionRequest(
89 selection, use_resolved_search_term, base_content_view_core);
92 void ContextualSearchManager::GatherSurroundingText(
93 JNIEnv* env,
94 jobject obj,
95 jstring j_selection,
96 jboolean j_use_resolved_search_term,
97 jobject j_base_content_view_core) {
98 ContentViewCore* base_content_view_core =
99 ContentViewCore::GetNativeContentViewCore(env, j_base_content_view_core);
100 DCHECK(base_content_view_core);
101 std::string selection(
102 base::android::ConvertJavaStringToUTF8(env, j_selection));
103 bool use_resolved_search_term = j_use_resolved_search_term;
104 delegate_->GatherAndSaveSurroundingText(
105 selection, use_resolved_search_term, base_content_view_core);
108 void ContextualSearchManager::ContinueSearchTermResolutionRequest(JNIEnv* env,
109 jobject obj) {
110 delegate_->ContinueSearchTermResolutionRequest();
113 void ContextualSearchManager::OnSearchTermResolutionResponse(
114 bool is_invalid,
115 int response_code,
116 const std::string& search_term,
117 const std::string& display_text,
118 const std::string& alternate_term,
119 bool prevent_preload) {
120 // Notify the Java UX of the result.
121 JNIEnv* env = base::android::AttachCurrentThread();
122 base::android::ScopedJavaLocalRef<jstring> j_search_term =
123 base::android::ConvertUTF8ToJavaString(env, search_term.c_str());
124 base::android::ScopedJavaLocalRef<jstring> j_display_text =
125 base::android::ConvertUTF8ToJavaString(env, display_text.c_str());
126 base::android::ScopedJavaLocalRef<jstring> j_alternate_term =
127 base::android::ConvertUTF8ToJavaString(env, alternate_term.c_str());
128 Java_ContextualSearchManager_onSearchTermResolutionResponse(
129 env,
130 java_manager_.obj(),
131 is_invalid,
132 response_code,
133 j_search_term.obj(),
134 j_display_text.obj(),
135 j_alternate_term.obj(),
136 prevent_preload);
139 void ContextualSearchManager::OnSurroundingTextAvailable(
140 const std::string& before_text,
141 const std::string& after_text) {
142 JNIEnv* env = base::android::AttachCurrentThread();
143 base::android::ScopedJavaLocalRef<jstring> j_before_text =
144 base::android::ConvertUTF8ToJavaString(env, before_text.c_str());
145 base::android::ScopedJavaLocalRef<jstring> j_after_text =
146 base::android::ConvertUTF8ToJavaString(env, after_text.c_str());
147 Java_ContextualSearchManager_onSurroundingTextAvailable(
148 env,
149 java_manager_.obj(),
150 j_before_text.obj(),
151 j_after_text.obj());
154 void ContextualSearchManager::OnIcingSelectionAvailable(
155 const std::string& encoding,
156 const base::string16& surrounding_text,
157 size_t start_offset,
158 size_t end_offset) {
159 JNIEnv* env = base::android::AttachCurrentThread();
160 base::android::ScopedJavaLocalRef<jstring> j_encoding =
161 base::android::ConvertUTF8ToJavaString(env, encoding.c_str());
162 base::android::ScopedJavaLocalRef<jstring> j_surrounding_text =
163 base::android::ConvertUTF16ToJavaString(env, surrounding_text.c_str());
164 Java_ContextualSearchManager_onIcingSelectionAvailable(
165 env, java_manager_.obj(), j_encoding.obj(), j_surrounding_text.obj(),
166 start_offset, end_offset);
169 void ContextualSearchManager::RemoveLastSearchVisit(
170 JNIEnv* env,
171 jobject obj,
172 jstring search_url,
173 jlong search_start_time_ms) {
174 // The deletion window is from the time a search URL was put in history, up
175 // to a short amount of time later.
176 base::Time begin_time = base::Time::FromJsTime(search_start_time_ms);
177 base::Time end_time = begin_time +
178 base::TimeDelta::FromSeconds(kHistoryDeletionWindowSeconds);
180 history::HistoryService* service = HistoryServiceFactory::GetForProfile(
181 ProfileManager::GetActiveUserProfile(),
182 ServiceAccessType::EXPLICIT_ACCESS);
183 if (service) {
184 // NOTE(mathp): We are only removing |search_url| from the local history
185 // because search results that are not promoted to a Tab do not make it to
186 // the web history, only local.
187 std::set<GURL> restrict_set;
188 restrict_set.insert(
189 GURL(base::android::ConvertJavaStringToUTF8(env, search_url)));
190 service->ExpireHistoryBetween(
191 restrict_set,
192 begin_time,
193 end_time,
194 base::Bind(&OnHistoryDeletionDone),
195 &history_task_tracker_);
199 void ContextualSearchManager::SetWebContents(JNIEnv* env,
200 jobject obj,
201 jobject jcontent_view_core,
202 jobject jweb_contents_delegate) {
203 content::ContentViewCore* content_view_core =
204 content::ContentViewCore::GetNativeContentViewCore(env,
205 jcontent_view_core);
206 DCHECK(content_view_core);
207 DCHECK(content_view_core->GetWebContents());
209 // NOTE(pedrosimonetti): Takes ownership of the WebContents associated
210 // with the ContentViewCore. This is to make sure that the WebContens
211 // and the Compositor are in the same process.
212 // TODO(pedrosimonetti): Confirm with dtrainor@ if the comment above
213 // is accurate.
214 web_contents_.reset(content_view_core->GetWebContents());
215 // TODO(pedrosimonetti): confirm if we need this after promoting it
216 // to a real tab.
217 TabAndroid::AttachTabHelpers(web_contents_.get());
218 WindowAndroidHelper::FromWebContents(web_contents_.get())
219 ->SetWindowAndroid(content_view_core->GetWindowAndroid());
220 web_contents_delegate_.reset(
221 new web_contents_delegate_android::WebContentsDelegateAndroid(
222 env, jweb_contents_delegate));
223 web_contents_->SetDelegate(web_contents_delegate_.get());
226 void ContextualSearchManager::DestroyWebContents(JNIEnv* env, jobject jobj) {
227 DCHECK(web_contents_.get());
228 web_contents_.reset();
229 // |web_contents_delegate_| may already be NULL at this point.
230 web_contents_delegate_.reset();
233 void ContextualSearchManager::ReleaseWebContents(JNIEnv* env, jobject jboj) {
234 DCHECK(web_contents_.get());
235 web_contents_delegate_.reset();
236 ignore_result(web_contents_.release());
239 void ContextualSearchManager::DestroyWebContentsFromContentViewCore(
240 JNIEnv* env,
241 jobject jobj,
242 jobject jcontent_view_core) {
243 content::ContentViewCore* content_view_core =
244 content::ContentViewCore::GetNativeContentViewCore(env,
245 jcontent_view_core);
246 DCHECK(content_view_core);
247 DCHECK(content_view_core->GetWebContents());
249 delete content_view_core->GetWebContents();
252 bool ContextualSearchManager::ShouldHidePromoHeader(JNIEnv* env,
253 jobject jobj) {
254 return variations::GetVariationParamValue(
255 kContextualSearchFieldTrialName,
256 kContextualSearchHidePromoHeaderParam) ==
257 kContextualSearchEnabledValue;
260 void ContextualSearchManager::SetInterceptNavigationDelegate(
261 JNIEnv* env,
262 jobject obj,
263 jobject delegate,
264 jobject jweb_contents) {
265 content::WebContents* web_contents =
266 content::WebContents::FromJavaWebContents(jweb_contents);
267 DCHECK(web_contents);
268 navigation_interception::InterceptNavigationDelegate::Associate(
269 web_contents,
270 make_scoped_ptr(new navigation_interception::InterceptNavigationDelegate(
271 env, delegate)));
274 bool RegisterContextualSearchManager(JNIEnv* env) {
275 return RegisterNativesImpl(env);
278 jlong Init(JNIEnv* env, jobject obj) {
279 ContextualSearchManager* manager = new ContextualSearchManager(env, obj);
280 return reinterpret_cast<intptr_t>(manager);