1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// found in the LICENSE file.
4a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "omnibox_prerender.h"
6a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/android/jni_string.h"
8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/logging.h"
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/android/tab_android.h"
10a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/predictors/autocomplete_action_predictor.h"
11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/profiles/profile_android.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/ui/search/instant_search_prerenderer.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_match.h"
166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/omnibox/autocomplete_result.h"
17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "content/public/browser/web_contents.h"
18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "jni/OmniboxPrerender_jni.h"
19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "url/gurl.h"
20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using predictors::AutocompleteActionPredictor;
22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using predictors::AutocompleteActionPredictorFactory;
23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)OmniboxPrerender::OmniboxPrerender(JNIEnv* env, jobject obj)
25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : weak_java_omnibox_(env, obj) {
26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)OmniboxPrerender::~OmniboxPrerender() {
29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static jlong Init(JNIEnv* env, jobject obj) {
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  OmniboxPrerender* omnibox = new OmniboxPrerender(env, obj);
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return reinterpret_cast<intptr_t>(omnibox);
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool RegisterOmniboxPrerender(JNIEnv* env) {
37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return RegisterNativesImpl(env);
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void OmniboxPrerender::Clear(JNIEnv* env,
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                             jobject obj,
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                             jobject j_profile_android) {
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(profile);
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!profile)
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  AutocompleteActionPredictor* action_predictor =
48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      AutocompleteActionPredictorFactory::GetForProfile(profile);
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  action_predictor->ClearTransitionalMatches();
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  action_predictor->CancelPrerender();
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void OmniboxPrerender::InitializeForProfile(
54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    JNIEnv* env,
55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    jobject obj,
56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    jobject j_profile_android) {
57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Initialize the AutocompleteActionPredictor for this profile.
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // It needs to register for notifications as part of its initialization.
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  AutocompleteActionPredictorFactory::GetForProfile(profile);
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void OmniboxPrerender::PrerenderMaybe(JNIEnv* env,
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                      jobject obj,
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                      jstring j_url,
66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                      jstring j_current_url,
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      jlong jsource_match,
68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                      jobject j_profile_android,
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                      jobject j_tab) {
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  AutocompleteResult* autocomplete_result =
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      reinterpret_cast<AutocompleteResult*>(jsource_match);
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::string16 url_string =
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::android::ConvertJavaStringToUTF16(env, j_url);
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::string16 current_url_string =
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::android::ConvertJavaStringToUTF16(env, j_current_url);
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  content::WebContents* web_contents =
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      TabAndroid::GetNativeTab(env, j_tab)->web_contents();
79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // TODO(apiccion) Use a delegate for communicating with web_contents.
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // This can happen in OmniboxTests since the results are generated
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // in Java only.
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!autocomplete_result)
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!profile)
85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const AutocompleteResult::const_iterator default_match(
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      autocomplete_result->default_match());
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (default_match == autocomplete_result->end())
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  AutocompleteActionPredictor::Action recommended_action =
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      AutocompleteActionPredictor::ACTION_NONE;
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  InstantSearchPrerenderer* prerenderer =
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      InstantSearchPrerenderer::GetForProfile(profile);
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (prerenderer &&
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      prerenderer->IsAllowed(*default_match, web_contents)) {
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    recommended_action = AutocompleteActionPredictor::ACTION_PRERENDER;
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    AutocompleteActionPredictor* action_predictor =
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        AutocompleteActionPredictorFactory::GetForProfile(profile);
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!action_predictor)
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return;
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (action_predictor) {
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      action_predictor->
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          RegisterTransitionalMatches(url_string, *autocomplete_result);
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      recommended_action =
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          action_predictor->RecommendAction(url_string, *default_match);
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  GURL current_url = GURL(current_url_string);
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  switch (recommended_action) {
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case AutocompleteActionPredictor::ACTION_PRERENDER:
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      // Ask for prerendering if the destination URL is different than the
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      // current URL.
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (default_match->destination_url != current_url) {
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        DoPrerender(
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            *default_match,
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            profile,
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            web_contents);
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      }
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case AutocompleteActionPredictor::ACTION_PRECONNECT:
126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      // TODO (apiccion) add preconnect logic
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case AutocompleteActionPredictor::ACTION_NONE:
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    default:
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      NOTREACHED();
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void OmniboxPrerender::DoPrerender(const AutocompleteMatch& match,
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                   Profile* profile,
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                   content::WebContents* web_contents) {
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(profile);
140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!profile)
141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(web_contents);
143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!web_contents)
144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  gfx::Rect container_bounds = web_contents->GetContainerBounds();
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  InstantSearchPrerenderer* prerenderer =
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      InstantSearchPrerenderer::GetForProfile(profile);
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (prerenderer && prerenderer->IsAllowed(match, web_contents)) {
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    prerenderer->Init(
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        web_contents->GetController().GetSessionStorageNamespaceMap(),
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        container_bounds.size());
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  predictors::AutocompleteActionPredictorFactory::GetForProfile(profile)->
155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      StartPrerendering(
156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          match.destination_url,
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          web_contents->GetController().GetSessionStorageNamespaceMap(),
158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          container_bounds.size());
159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
160