navigation_controller_android.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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
17using base::android::AttachCurrentThread;
18using base::android::ConvertJavaStringToUTF16;
19using base::android::ConvertJavaStringToUTF8;
20using base::android::ConvertUTF16ToJavaString;
21using base::android::ConvertUTF8ToJavaString;
22namespace {
23
24// static
25static 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
55static 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
67namespace content {
68
69// static
70bool NavigationControllerAndroid::Register(JNIEnv* env) {
71  return RegisterNativesImpl(env);
72}
73
74NavigationControllerAndroid::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
83NavigationControllerAndroid::~NavigationControllerAndroid() {
84  Java_NavigationControllerImpl_destroy(AttachCurrentThread(), obj_.obj());
85}
86
87base::android::ScopedJavaLocalRef<jobject>
88NavigationControllerAndroid::GetJavaObject() {
89  return base::android::ScopedJavaLocalRef<jobject>(obj_);
90}
91
92jboolean NavigationControllerAndroid::CanGoBack(JNIEnv* env, jobject obj) {
93  return navigation_controller_->CanGoBack();
94}
95
96jboolean NavigationControllerAndroid::CanGoForward(JNIEnv* env,
97                                                   jobject obj) {
98  return navigation_controller_->CanGoForward();
99}
100
101jboolean NavigationControllerAndroid::CanGoToOffset(JNIEnv* env,
102                                                    jobject obj,
103                                                    jint offset) {
104  return navigation_controller_->CanGoToOffset(offset);
105}
106
107void NavigationControllerAndroid::GoBack(JNIEnv* env, jobject obj) {
108  navigation_controller_->GoBack();
109}
110
111void NavigationControllerAndroid::GoForward(JNIEnv* env, jobject obj) {
112  navigation_controller_->GoForward();
113}
114
115void NavigationControllerAndroid::GoToOffset(JNIEnv* env,
116                                             jobject obj,
117                                             jint offset) {
118  navigation_controller_->GoToOffset(offset);
119}
120
121void NavigationControllerAndroid::LoadIfNecessary(JNIEnv* env, jobject obj) {
122  navigation_controller_->LoadIfNecessary();
123}
124
125void NavigationControllerAndroid::ContinuePendingReload(JNIEnv* env,
126                                                        jobject obj) {
127  navigation_controller_->ContinuePendingReload();
128}
129
130void NavigationControllerAndroid::Reload(JNIEnv* env,
131                                         jobject obj,
132                                         jboolean check_for_repost) {
133  navigation_controller_->Reload(check_for_repost);
134}
135
136void NavigationControllerAndroid::ReloadIgnoringCache(
137    JNIEnv* env,
138    jobject obj,
139    jboolean check_for_repost) {
140  navigation_controller_->ReloadIgnoringCache(check_for_repost);
141}
142
143void NavigationControllerAndroid::RequestRestoreLoad(JNIEnv* env, jobject obj) {
144  navigation_controller_->SetNeedsReload();
145}
146
147void NavigationControllerAndroid::CancelPendingReload(JNIEnv* env,
148                                                      jobject obj) {
149  navigation_controller_->CancelPendingReload();
150}
151
152void NavigationControllerAndroid::GoToNavigationIndex(JNIEnv* env,
153                                                      jobject obj,
154                                                      jint index) {
155  navigation_controller_->GoToIndex(index);
156}
157
158void 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
214void 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
220jint 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
233void 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
255ScopedJavaLocalRef<jstring>
256NavigationControllerAndroid::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
265void NavigationControllerAndroid::ClearSslPreferences(JNIEnv* env,
266                                                      jobject obj) {
267  content::SSLHostStateDelegate* delegate =
268      navigation_controller_->GetBrowserContext()->GetSSLHostStateDelegate();
269  if (delegate)
270    delegate->Clear();
271}
272
273bool NavigationControllerAndroid::GetUseDesktopUserAgent(JNIEnv* env,
274                                                         jobject obj) {
275  NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
276  return entry && entry->GetIsOverridingUserAgent();
277}
278
279void 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
303base::android::ScopedJavaLocalRef<jobject>
304NavigationControllerAndroid::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