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