Home | History | Annotate | Download | only in frame_host
      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 "content/browser/frame_host/navigation_controller_android.h"
      6 
      7 #include "base/android/jni_android.h"
      8 #include "base/android/jni_array.h"
      9 #include "base/android/jni_string.h"
     10 #include "content/browser/frame_host/navigation_entry_impl.h"
     11 #include "content/public/browser/browser_context.h"
     12 #include "content/public/browser/navigation_controller.h"
     13 #include "content/public/browser/ssl_host_state_delegate.h"
     14 #include "jni/NavigationControllerImpl_jni.h"
     15 #include "ui/gfx/android/java_bitmap.h"
     16 
     17 using base::android::AttachCurrentThread;
     18 using base::android::ConvertJavaStringToUTF16;
     19 using base::android::ConvertJavaStringToUTF8;
     20 using base::android::ConvertUTF16ToJavaString;
     21 using base::android::ConvertUTF8ToJavaString;
     22 namespace {
     23 
     24 // static
     25 static base::android::ScopedJavaLocalRef<jobject> CreateJavaNavigationEntry(
     26     JNIEnv* env,
     27     content::NavigationEntry* entry,
     28     int index) {
     29   DCHECK(entry);
     30 
     31   // Get the details of the current entry
     32   ScopedJavaLocalRef<jstring> j_url(
     33       ConvertUTF8ToJavaString(env, entry->GetURL().spec()));
     34   ScopedJavaLocalRef<jstring> j_virtual_url(
     35       ConvertUTF8ToJavaString(env, entry->GetVirtualURL().spec()));
     36   ScopedJavaLocalRef<jstring> j_original_url(
     37       ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
     38   ScopedJavaLocalRef<jstring> j_title(
     39       ConvertUTF16ToJavaString(env, entry->GetTitle()));
     40   ScopedJavaLocalRef<jobject> j_bitmap;
     41   const content::FaviconStatus& status = entry->GetFavicon();
     42   if (status.valid && status.image.ToSkBitmap()->getSize() > 0)
     43     j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
     44 
     45   return content::Java_NavigationControllerImpl_createNavigationEntry(
     46       env,
     47       index,
     48       j_url.obj(),
     49       j_virtual_url.obj(),
     50       j_original_url.obj(),
     51       j_title.obj(),
     52       j_bitmap.obj());
     53 }
     54 
     55 static void AddNavigationEntryToHistory(JNIEnv* env,
     56                                         jobject history,
     57                                         content::NavigationEntry* entry,
     58                                         int index) {
     59   content::Java_NavigationControllerImpl_addToNavigationHistory(
     60       env,
     61       history,
     62       CreateJavaNavigationEntry(env, entry, index).obj());
     63 }
     64 
     65 }  // namespace
     66 
     67 namespace content {
     68 
     69 // static
     70 bool NavigationControllerAndroid::Register(JNIEnv* env) {
     71   return RegisterNativesImpl(env);
     72 }
     73 
     74 NavigationControllerAndroid::NavigationControllerAndroid(
     75     NavigationController* navigation_controller)
     76     : navigation_controller_(navigation_controller) {
     77   JNIEnv* env = AttachCurrentThread();
     78   obj_.Reset(env,
     79              Java_NavigationControllerImpl_create(
     80                  env, reinterpret_cast<intptr_t>(this)).obj());
     81 }
     82 
     83 NavigationControllerAndroid::~NavigationControllerAndroid() {
     84   Java_NavigationControllerImpl_destroy(AttachCurrentThread(), obj_.obj());
     85 }
     86 
     87 base::android::ScopedJavaLocalRef<jobject>
     88 NavigationControllerAndroid::GetJavaObject() {
     89   return base::android::ScopedJavaLocalRef<jobject>(obj_);
     90 }
     91 
     92 jboolean NavigationControllerAndroid::CanGoBack(JNIEnv* env, jobject obj) {
     93   return navigation_controller_->CanGoBack();
     94 }
     95 
     96 jboolean NavigationControllerAndroid::CanGoForward(JNIEnv* env,
     97                                                    jobject obj) {
     98   return navigation_controller_->CanGoForward();
     99 }
    100 
    101 jboolean NavigationControllerAndroid::CanGoToOffset(JNIEnv* env,
    102                                                     jobject obj,
    103                                                     jint offset) {
    104   return navigation_controller_->CanGoToOffset(offset);
    105 }
    106 
    107 void NavigationControllerAndroid::GoBack(JNIEnv* env, jobject obj) {
    108   navigation_controller_->GoBack();
    109 }
    110 
    111 void NavigationControllerAndroid::GoForward(JNIEnv* env, jobject obj) {
    112   navigation_controller_->GoForward();
    113 }
    114 
    115 void NavigationControllerAndroid::GoToOffset(JNIEnv* env,
    116                                              jobject obj,
    117                                              jint offset) {
    118   navigation_controller_->GoToOffset(offset);
    119 }
    120 
    121 void NavigationControllerAndroid::LoadIfNecessary(JNIEnv* env, jobject obj) {
    122   navigation_controller_->LoadIfNecessary();
    123 }
    124 
    125 void NavigationControllerAndroid::ContinuePendingReload(JNIEnv* env,
    126                                                         jobject obj) {
    127   navigation_controller_->ContinuePendingReload();
    128 }
    129 
    130 void NavigationControllerAndroid::Reload(JNIEnv* env,
    131                                          jobject obj,
    132                                          jboolean check_for_repost) {
    133   navigation_controller_->Reload(check_for_repost);
    134 }
    135 
    136 void NavigationControllerAndroid::ReloadIgnoringCache(
    137     JNIEnv* env,
    138     jobject obj,
    139     jboolean check_for_repost) {
    140   navigation_controller_->ReloadIgnoringCache(check_for_repost);
    141 }
    142 
    143 void NavigationControllerAndroid::RequestRestoreLoad(JNIEnv* env, jobject obj) {
    144   navigation_controller_->SetNeedsReload();
    145 }
    146 
    147 void NavigationControllerAndroid::CancelPendingReload(JNIEnv* env,
    148                                                       jobject obj) {
    149   navigation_controller_->CancelPendingReload();
    150 }
    151 
    152 void NavigationControllerAndroid::GoToNavigationIndex(JNIEnv* env,
    153                                                       jobject obj,
    154                                                       jint index) {
    155   navigation_controller_->GoToIndex(index);
    156 }
    157 
    158 void NavigationControllerAndroid::LoadUrl(JNIEnv* env,
    159                                           jobject obj,
    160                                           jstring url,
    161                                           jint load_url_type,
    162                                           jint transition_type,
    163                                           jstring j_referrer_url,
    164                                           jint referrer_policy,
    165                                           jint ua_override_option,
    166                                           jstring extra_headers,
    167                                           jbyteArray post_data,
    168                                           jstring base_url_for_data_url,
    169                                           jstring virtual_url_for_data_url,
    170                                           jboolean can_load_local_resources,
    171                                           jboolean is_renderer_initiated) {
    172   DCHECK(url);
    173   NavigationController::LoadURLParams params(
    174       GURL(ConvertJavaStringToUTF8(env, url)));
    175 
    176   params.load_type =
    177       static_cast<NavigationController::LoadURLType>(load_url_type);
    178   params.transition_type = ui::PageTransitionFromInt(transition_type);
    179   params.override_user_agent =
    180       static_cast<NavigationController::UserAgentOverrideOption>(
    181           ua_override_option);
    182   params.can_load_local_resources = can_load_local_resources;
    183   params.is_renderer_initiated = is_renderer_initiated;
    184 
    185   if (extra_headers)
    186     params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
    187 
    188   if (post_data) {
    189     std::vector<uint8> http_body_vector;
    190     base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
    191     params.browser_initiated_post_data =
    192         base::RefCountedBytes::TakeVector(&http_body_vector);
    193   }
    194 
    195   if (base_url_for_data_url) {
    196     params.base_url_for_data_url =
    197         GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
    198   }
    199 
    200   if (virtual_url_for_data_url) {
    201     params.virtual_url_for_data_url =
    202         GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
    203   }
    204 
    205   if (j_referrer_url) {
    206     params.referrer = content::Referrer(
    207         GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
    208         static_cast<blink::WebReferrerPolicy>(referrer_policy));
    209   }
    210 
    211   navigation_controller_->LoadURLWithParams(params);
    212 }
    213 
    214 void NavigationControllerAndroid::ClearHistory(JNIEnv* env, jobject obj) {
    215   // TODO(creis): Do callers of this need to know if it fails?
    216   if (navigation_controller_->CanPruneAllButLastCommitted())
    217     navigation_controller_->PruneAllButLastCommitted();
    218 }
    219 
    220 jint NavigationControllerAndroid::GetNavigationHistory(JNIEnv* env,
    221                                                        jobject obj,
    222                                                        jobject history) {
    223   // Iterate through navigation entries to populate the list
    224   int count = navigation_controller_->GetEntryCount();
    225   for (int i = 0; i < count; ++i) {
    226     AddNavigationEntryToHistory(
    227         env, history, navigation_controller_->GetEntryAtIndex(i), i);
    228   }
    229 
    230   return navigation_controller_->GetCurrentEntryIndex();
    231 }
    232 
    233 void NavigationControllerAndroid::GetDirectedNavigationHistory(
    234     JNIEnv* env,
    235     jobject obj,
    236     jobject history,
    237     jboolean is_forward,
    238     jint max_entries) {
    239   // Iterate through navigation entries to populate the list
    240   int count = navigation_controller_->GetEntryCount();
    241   int num_added = 0;
    242   int increment_value = is_forward ? 1 : -1;
    243   for (int i = navigation_controller_->GetCurrentEntryIndex() + increment_value;
    244        i >= 0 && i < count;
    245        i += increment_value) {
    246     if (num_added >= max_entries)
    247       break;
    248 
    249     AddNavigationEntryToHistory(
    250         env, history, navigation_controller_->GetEntryAtIndex(i), i);
    251     num_added++;
    252   }
    253 }
    254 
    255 ScopedJavaLocalRef<jstring>
    256 NavigationControllerAndroid::GetOriginalUrlForVisibleNavigationEntry(
    257     JNIEnv* env,
    258     jobject obj) {
    259   NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
    260   if (entry == NULL)
    261     return ScopedJavaLocalRef<jstring>(env, NULL);
    262   return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
    263 }
    264 
    265 void NavigationControllerAndroid::ClearSslPreferences(JNIEnv* env,
    266                                                       jobject obj) {
    267   content::SSLHostStateDelegate* delegate =
    268       navigation_controller_->GetBrowserContext()->GetSSLHostStateDelegate();
    269   if (delegate)
    270     delegate->Clear();
    271 }
    272 
    273 bool NavigationControllerAndroid::GetUseDesktopUserAgent(JNIEnv* env,
    274                                                          jobject obj) {
    275   NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
    276   return entry && entry->GetIsOverridingUserAgent();
    277 }
    278 
    279 void NavigationControllerAndroid::SetUseDesktopUserAgent(
    280     JNIEnv* env,
    281     jobject obj,
    282     jboolean enabled,
    283     jboolean reload_on_state_change) {
    284   if (GetUseDesktopUserAgent(env, obj) == enabled)
    285     return;
    286 
    287   // Make sure the navigation entry actually exists.
    288   NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
    289   if (!entry)
    290     return;
    291 
    292   // Set the flag in the NavigationEntry.
    293   entry->SetIsOverridingUserAgent(enabled);
    294 
    295   // Send the override to the renderer.
    296   if (reload_on_state_change) {
    297     // Reloading the page will send the override down as part of the
    298     // navigation IPC message.
    299     navigation_controller_->ReloadOriginalRequestURL(false);
    300   }
    301 }
    302 
    303 base::android::ScopedJavaLocalRef<jobject>
    304 NavigationControllerAndroid::GetPendingEntry(JNIEnv* env, jobject obj) {
    305   content::NavigationEntry* entry = navigation_controller_->GetPendingEntry();
    306 
    307   if (!entry)
    308     return base::android::ScopedJavaLocalRef<jobject>();
    309 
    310   return CreateJavaNavigationEntry(
    311       env, entry, navigation_controller_->GetPendingEntryIndex());
    312 }
    313 
    314 }  // namespace content
    315