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