omnibox_prerender.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
1// Copyright 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 "omnibox_prerender.h"
6
7#include "base/android/jni_string.h"
8#include "base/logging.h"
9#include "chrome/browser/android/tab_android.h"
10#include "chrome/browser/autocomplete/autocomplete_match.h"
11#include "chrome/browser/autocomplete/autocomplete_result.h"
12#include "chrome/browser/predictors/autocomplete_action_predictor.h"
13#include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
14#include "chrome/browser/profiles/profile.h"
15#include "chrome/browser/profiles/profile_android.h"
16#include "content/public/browser/web_contents.h"
17#include "content/public/browser/web_contents_view.h"
18#include "jni/OmniboxPrerender_jni.h"
19#include "url/gurl.h"
20
21using predictors::AutocompleteActionPredictor;
22using predictors::AutocompleteActionPredictorFactory;
23
24OmniboxPrerender::OmniboxPrerender(JNIEnv* env, jobject obj)
25    : weak_java_omnibox_(env, obj) {
26}
27
28OmniboxPrerender::~OmniboxPrerender() {
29}
30
31static jlong Init(JNIEnv* env, jobject obj) {
32  OmniboxPrerender* omnibox = new OmniboxPrerender(env, obj);
33  return reinterpret_cast<intptr_t>(omnibox);
34}
35
36bool RegisterOmniboxPrerender(JNIEnv* env) {
37  return RegisterNativesImpl(env);
38}
39
40void OmniboxPrerender::Clear(JNIEnv* env,
41                             jobject obj,
42                             jobject j_profile_android) {
43  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
44  DCHECK(profile);
45  if (!profile)
46    return;
47  AutocompleteActionPredictor* action_predictor =
48      AutocompleteActionPredictorFactory::GetForProfile(profile);
49  action_predictor->ClearTransitionalMatches();
50}
51
52void OmniboxPrerender::InitializeForProfile(
53    JNIEnv* env,
54    jobject obj,
55    jobject j_profile_android) {
56  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
57  // Initialize the AutocompleteActionPredictor for this profile.
58  // It needs to register for notifications as part of its initialization.
59  AutocompleteActionPredictorFactory::GetForProfile(profile);
60}
61
62void OmniboxPrerender::PrerenderMaybe(JNIEnv* env,
63                                      jobject obj,
64                                      jstring j_url,
65                                      jstring j_current_url,
66                                      jint jsource_match,
67                                      jobject j_profile_android,
68                                      jobject j_tab) {
69  AutocompleteResult* autocomplete_result =
70      reinterpret_cast<AutocompleteResult*>(jsource_match);
71  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
72  base::string16 url_string =
73      base::android::ConvertJavaStringToUTF16(env, j_url);
74  base::string16 current_url_string =
75      base::android::ConvertJavaStringToUTF16(env, j_current_url);
76  content::WebContents* web_contents =
77      TabAndroid::GetNativeTab(env, j_tab)->web_contents();
78  // TODO(apiccion) Use a delegate for communicating with web_contents.
79  // This can happen in OmniboxTests since the results are generated
80  // in Java only.
81  if (!autocomplete_result)
82    return;
83  if (!profile)
84    return;
85
86  const AutocompleteResult::const_iterator default_match(
87      autocomplete_result->default_match());
88  if (default_match == autocomplete_result->end())
89    return;
90
91  AutocompleteActionPredictor* action_predictor =
92      AutocompleteActionPredictorFactory::GetForProfile(profile);
93  if (!action_predictor)
94    return;
95
96  AutocompleteActionPredictor::Action recommended_action =
97      AutocompleteActionPredictor::ACTION_NONE;
98  if (action_predictor) {
99    action_predictor->
100        RegisterTransitionalMatches(url_string, *autocomplete_result);
101    recommended_action =
102        action_predictor->RecommendAction(url_string, *default_match);
103  }
104
105  GURL current_url = GURL(current_url_string);
106  switch (recommended_action) {
107    case AutocompleteActionPredictor::ACTION_PRERENDER:
108      // Ask for prerendering if the destination URL is different than the
109      // current URL.
110      if (default_match->destination_url != current_url) {
111        DoPrerender(
112            *default_match,
113            profile,
114            web_contents);
115      }
116      break;
117    case AutocompleteActionPredictor::ACTION_PRECONNECT:
118      // TODO (apiccion) add preconnect logic
119      break;
120    case AutocompleteActionPredictor::ACTION_NONE:
121      break;
122    default:
123      NOTREACHED();
124      break;
125  }
126}
127
128void OmniboxPrerender::DoPrerender(const AutocompleteMatch& match,
129                                   Profile* profile,
130                                   content::WebContents* web_contents) {
131  DCHECK(profile);
132  if (!profile)
133    return;
134  DCHECK(web_contents);
135  if (!web_contents)
136    return;
137  gfx::Rect container_bounds;
138  web_contents->GetView()->GetContainerBounds(&container_bounds);
139  predictors::AutocompleteActionPredictorFactory::GetForProfile(profile)->
140      StartPrerendering(
141          match.destination_url,
142          web_contents->GetController().GetSessionStorageNamespaceMap(),
143          container_bounds.size());
144}
145