blob: b67c03e04b93b520e2b86edb510c1e4f3b2028bb [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2013 The Chromium Authors
[email protected]155c7f22013-12-09 17:07:182// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakjc492bf82020-09-09 20:02:445#include "content/browser/renderer_host/navigation_controller_android.h"
[email protected]155c7f22013-12-09 17:07:186
avib7348942015-12-25 20:57:107#include <stdint.h>
8
Jan Wilken Dörriead587c32021-03-11 14:09:279#include <string>
10
[email protected]155c7f22013-12-09 17:07:1811#include "base/android/jni_android.h"
ajith.v4502cc62014-09-05 17:41:3912#include "base/android/jni_string.h"
Scott Violetf4eec902019-04-04 21:20:3413#include "base/containers/flat_map.h"
Rakina Zata Amnid605d462022-06-01 10:17:0314#include "base/debug/crash_logging.h"
Rakina Zata Amni148dcad72022-06-08 14:53:5015#include "base/debug/dump_without_crashing.h"
Avi Drissmanadac21992023-01-11 23:46:3916#include "base/functional/callback.h"
17#include "base/functional/callback_helpers.h"
Liam Brady767b85e2023-07-05 16:59:5918#include "content/browser/android/additional_navigation_params_utils.h"
danakjc492bf82020-09-09 20:02:4419#include "content/browser/renderer_host/navigation_controller_impl.h"
20#include "content/browser/renderer_host/navigation_entry_impl.h"
ajith.v4502cc62014-09-05 17:41:3921#include "content/public/browser/browser_context.h"
Lei Zhang589ef702022-08-26 19:38:0422#include "content/public/browser/browser_task_traits.h"
23#include "content/public/browser/browser_thread.h"
Pete Williamson1d87f4622022-10-18 19:36:4324#include "content/public/browser/navigation_handle.h"
ajith.v4502cc62014-09-05 17:41:3925#include "content/public/browser/ssl_host_state_delegate.h"
Lukasz Anforowicza192eb952019-10-15 19:22:2226#include "content/public/common/referrer.h"
John Abd-El-Maleka59411632018-01-10 20:08:2827#include "content/public/common/resource_request_body_android.h"
Michael Thiessend9fc0662021-06-22 22:29:1828#include "content/public/common/url_constants.h"
mnaganovbf087422015-12-16 05:10:0329#include "net/base/data_url.h"
ajith.v4502cc62014-09-05 17:41:3930#include "ui/gfx/android/java_bitmap.h"
Yaron Friedman09b9c5972020-12-15 17:47:3931#include "url/android/gurl_android.h"
Michael Thiessend3c9a032021-04-19 17:01:3732#include "url/gurl.h"
33#include "url/origin.h"
[email protected]155c7f22013-12-09 17:07:1834
Andrew Grieveecb885bb2024-05-29 18:14:1935// Must come after all headers that specialize FromJniType() / ToJniType().
36#include "content/public/android/content_jni_headers/NavigationControllerImpl_jni.h"
37
[email protected]155c7f22013-12-09 17:07:1838using base::android::AttachCurrentThread;
ajith.v4502cc62014-09-05 17:41:3939using base::android::ConvertJavaStringToUTF16;
40using base::android::ConvertJavaStringToUTF8;
41using base::android::ConvertUTF16ToJavaString;
torne86560112016-08-04 15:59:0442using base::android::JavaParamRef;
torne660061cd2016-09-07 17:47:5443using base::android::JavaRef;
torne86560112016-08-04 15:59:0444using base::android::ScopedJavaLocalRef;
torne660061cd2016-09-07 17:47:5445
ajith.v4502cc62014-09-05 17:41:3946namespace {
47
Scott Violetf4eec902019-04-04 21:20:3448const char kMapDataKey[] = "map_data_key";
49
ajith.v4502cc62014-09-05 17:41:3950// static
Daniel Bratell7aacf952017-11-21 17:51:2551static base::android::ScopedJavaLocalRef<jobject>
52JNI_NavigationControllerImpl_CreateJavaNavigationEntry(
dtrainorb316e9272014-09-19 23:30:5553 JNIEnv* env,
54 content::NavigationEntry* entry,
55 int index) {
56 DCHECK(entry);
57
ajith.v4502cc62014-09-05 17:41:3958 // Get the details of the current entry
Yaron Friedman09b9c5972020-12-15 17:47:3959 ScopedJavaLocalRef<jobject> j_url(
60 url::GURLAndroid::FromNativeGURL(env, entry->GetURL()));
61 ScopedJavaLocalRef<jobject> j_virtual_url(
62 url::GURLAndroid::FromNativeGURL(env, entry->GetVirtualURL()));
63 ScopedJavaLocalRef<jobject> j_original_url(
64 url::GURLAndroid::FromNativeGURL(env, entry->GetOriginalRequestURL()));
ajith.v4502cc62014-09-05 17:41:3965 ScopedJavaLocalRef<jstring> j_title(
66 ConvertUTF16ToJavaString(env, entry->GetTitle()));
67 ScopedJavaLocalRef<jobject> j_bitmap;
68 const content::FaviconStatus& status = entry->GetFavicon();
Rulong Chen(陈汝龙)61e3cc822020-08-29 03:29:2569 if (status.valid && status.image.ToSkBitmap()->computeByteSize() > 0) {
danakj5cc14ce2020-11-10 22:00:4070 j_bitmap = gfx::ConvertToJavaBitmap(*status.image.ToSkBitmap(),
Rulong Chen(陈汝龙)61e3cc822020-08-29 03:29:2571 gfx::OomBehavior::kReturnNullOnOom);
72 }
Peter Kasting08b91b42023-10-21 03:46:0973 jlong j_timestamp = entry->GetTimestamp().InMillisecondsSinceUnixEpoch();
ajith.v4502cc62014-09-05 17:41:3974
dtrainorb316e9272014-09-19 23:30:5575 return content::Java_NavigationControllerImpl_createNavigationEntry(
Yaron Friedmanf381f132022-11-29 21:47:4076 env, index, j_url, j_virtual_url, j_original_url, j_title, j_bitmap,
77 entry->GetTransitionType(), j_timestamp, entry->IsInitialEntry());
ajith.v4502cc62014-09-05 17:41:3978}
79
Daniel Bratell7aacf952017-11-21 17:51:2580static void JNI_NavigationControllerImpl_AddNavigationEntryToHistory(
81 JNIEnv* env,
82 const JavaRef<jobject>& history,
83 content::NavigationEntry* entry,
84 int index) {
dtrainorb316e9272014-09-19 23:30:5585 content::Java_NavigationControllerImpl_addToNavigationHistory(
Daniel Bratell7aacf952017-11-21 17:51:2586 env, history,
87 JNI_NavigationControllerImpl_CreateJavaNavigationEntry(env, entry,
88 index));
dtrainorb316e9272014-09-19 23:30:5589}
90
Scott Violetf4eec902019-04-04 21:20:3491class MapData : public base::SupportsUserData::Data {
92 public:
93 MapData() = default;
Peter Boström828b9022021-09-21 02:28:4394
95 MapData(const MapData&) = delete;
96 MapData& operator=(const MapData&) = delete;
97
Scott Violetf4eec902019-04-04 21:20:3498 ~MapData() override = default;
99
100 static MapData* Get(content::NavigationEntry* entry) {
101 MapData* map_data = static_cast<MapData*>(entry->GetUserData(kMapDataKey));
102 if (map_data)
103 return map_data;
104 auto map_data_ptr = std::make_unique<MapData>();
105 map_data = map_data_ptr.get();
106 entry->SetUserData(kMapDataKey, std::move(map_data_ptr));
107 return map_data;
108 }
109
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58110 base::flat_map<std::string, std::u16string>& map() { return map_; }
Scott Violetf4eec902019-04-04 21:20:34111
112 // base::SupportsUserData::Data:
113 std::unique_ptr<Data> Clone() override {
114 std::unique_ptr<MapData> clone = std::make_unique<MapData>();
115 clone->map_ = map_;
116 return clone;
117 }
118
119 private:
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58120 base::flat_map<std::string, std::u16string> map_;
Scott Violetf4eec902019-04-04 21:20:34121};
122
ajith.v4502cc62014-09-05 17:41:39123} // namespace
[email protected]155c7f22013-12-09 17:07:18124
125namespace content {
126
[email protected]155c7f22013-12-09 17:07:18127NavigationControllerAndroid::NavigationControllerAndroid(
aelias5252baa2016-04-10 01:18:02128 NavigationControllerImpl* navigation_controller)
[email protected]155c7f22013-12-09 17:07:18129 : navigation_controller_(navigation_controller) {
130 JNIEnv* env = AttachCurrentThread();
Aran Gilman37d11632019-10-08 23:07:15131 obj_.Reset(env, Java_NavigationControllerImpl_create(
132 env, reinterpret_cast<intptr_t>(this))
133 .obj());
[email protected]155c7f22013-12-09 17:07:18134}
135
136NavigationControllerAndroid::~NavigationControllerAndroid() {
torne948f3662016-08-16 15:10:44137 Java_NavigationControllerImpl_destroy(AttachCurrentThread(), obj_);
[email protected]155c7f22013-12-09 17:07:18138}
139
140base::android::ScopedJavaLocalRef<jobject>
141NavigationControllerAndroid::GetJavaObject() {
142 return base::android::ScopedJavaLocalRef<jobject>(obj_);
143}
144
tornee1bfee92015-12-01 14:05:01145jboolean NavigationControllerAndroid::CanGoBack(
146 JNIEnv* env,
147 const JavaParamRef<jobject>& obj) {
[email protected]155c7f22013-12-09 17:07:18148 return navigation_controller_->CanGoBack();
149}
150
tornee1bfee92015-12-01 14:05:01151jboolean NavigationControllerAndroid::CanGoForward(
152 JNIEnv* env,
153 const JavaParamRef<jobject>& obj) {
[email protected]155c7f22013-12-09 17:07:18154 return navigation_controller_->CanGoForward();
155}
156
tornee1bfee92015-12-01 14:05:01157jboolean NavigationControllerAndroid::CanGoToOffset(
158 JNIEnv* env,
159 const JavaParamRef<jobject>& obj,
160 jint offset) {
WangHui74286d52021-03-31 16:17:15161 return navigation_controller_->CanGoToOffsetWithSkipping(offset);
[email protected]155c7f22013-12-09 17:07:18162}
163
tornee1bfee92015-12-01 14:05:01164void NavigationControllerAndroid::GoBack(JNIEnv* env,
165 const JavaParamRef<jobject>& obj) {
[email protected]155c7f22013-12-09 17:07:18166 navigation_controller_->GoBack();
167}
168
tornee1bfee92015-12-01 14:05:01169void NavigationControllerAndroid::GoForward(JNIEnv* env,
170 const JavaParamRef<jobject>& obj) {
[email protected]155c7f22013-12-09 17:07:18171 navigation_controller_->GoForward();
172}
173
174void NavigationControllerAndroid::GoToOffset(JNIEnv* env,
tornee1bfee92015-12-01 14:05:01175 const JavaParamRef<jobject>& obj,
[email protected]155c7f22013-12-09 17:07:18176 jint offset) {
WangHui74286d52021-03-31 16:17:15177 navigation_controller_->GoToOffsetWithSkipping(offset);
[email protected]155c7f22013-12-09 17:07:18178}
179
tornee1bfee92015-12-01 14:05:01180jboolean NavigationControllerAndroid::IsInitialNavigation(
181 JNIEnv* env,
182 const JavaParamRef<jobject>& obj) {
dfalcantara0d314d522015-01-05 22:56:43183 return navigation_controller_->IsInitialNavigation();
184}
185
tornee1bfee92015-12-01 14:05:01186void NavigationControllerAndroid::LoadIfNecessary(
187 JNIEnv* env,
188 const JavaParamRef<jobject>& obj) {
[email protected]6d3f32f2014-07-08 08:23:29189 navigation_controller_->LoadIfNecessary();
190}
191
tornee1bfee92015-12-01 14:05:01192void NavigationControllerAndroid::ContinuePendingReload(
193 JNIEnv* env,
194 const JavaParamRef<jobject>& obj) {
[email protected]6d3f32f2014-07-08 08:23:29195 navigation_controller_->ContinuePendingReload();
196}
197
198void NavigationControllerAndroid::Reload(JNIEnv* env,
tornee1bfee92015-12-01 14:05:01199 const JavaParamRef<jobject>& obj,
[email protected]6d3f32f2014-07-08 08:23:29200 jboolean check_for_repost) {
Rakina Zata Amnid605d462022-06-01 10:17:03201 SCOPED_CRASH_KEY_BOOL("nav_reentrancy_caller2", "Reload_check",
202 (bool)check_for_repost);
toyoshim6142d96f2016-12-19 09:07:25203 navigation_controller_->Reload(ReloadType::NORMAL, check_for_repost);
[email protected]6d3f32f2014-07-08 08:23:29204}
205
toyoshim7dad4b1182016-04-01 14:28:05206void NavigationControllerAndroid::ReloadBypassingCache(
[email protected]6d3f32f2014-07-08 08:23:29207 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01208 const JavaParamRef<jobject>& obj,
[email protected]6d3f32f2014-07-08 08:23:29209 jboolean check_for_repost) {
Rakina Zata Amnid605d462022-06-01 10:17:03210 SCOPED_CRASH_KEY_BOOL("nav_reentrancy_caller2", "ReloadB_check",
211 (bool)check_for_repost);
toyoshim6142d96f2016-12-19 09:07:25212 navigation_controller_->Reload(ReloadType::BYPASSING_CACHE, check_for_repost);
[email protected]6d3f32f2014-07-08 08:23:29213}
214
Matthew Carye7da4b12018-05-02 16:14:16215jboolean NavigationControllerAndroid::NeedsReload(
216 JNIEnv* env,
217 const JavaParamRef<jobject>& obj) {
218 return navigation_controller_->NeedsReload();
219}
220
221void NavigationControllerAndroid::SetNeedsReload(
tornee1bfee92015-12-01 14:05:01222 JNIEnv* env,
223 const JavaParamRef<jobject>& obj) {
[email protected]6d3f32f2014-07-08 08:23:29224 navigation_controller_->SetNeedsReload();
225}
226
tornee1bfee92015-12-01 14:05:01227void NavigationControllerAndroid::CancelPendingReload(
228 JNIEnv* env,
229 const JavaParamRef<jobject>& obj) {
[email protected]6d3f32f2014-07-08 08:23:29230 navigation_controller_->CancelPendingReload();
231}
232
tornee1bfee92015-12-01 14:05:01233void NavigationControllerAndroid::GoToNavigationIndex(
234 JNIEnv* env,
235 const JavaParamRef<jobject>& obj,
236 jint index) {
[email protected]155c7f22013-12-09 17:07:18237 navigation_controller_->GoToIndex(index);
238}
239
Torne (Richard Coles)d07c794b2023-11-21 23:55:49240base::android::ScopedJavaLocalRef<jobject> NavigationControllerAndroid::LoadUrl(
lizebe8adeb82015-08-20 12:18:10241 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01242 const JavaParamRef<jobject>& obj,
243 const JavaParamRef<jstring>& url,
lizebe8adeb82015-08-20 12:18:10244 jint load_url_type,
245 jint transition_type,
tornee1bfee92015-12-01 14:05:01246 const JavaParamRef<jstring>& j_referrer_url,
lizebe8adeb82015-08-20 12:18:10247 jint referrer_policy,
248 jint ua_override_option,
tornee1bfee92015-12-01 14:05:01249 const JavaParamRef<jstring>& extra_headers,
lukasza477a5a22016-06-16 18:28:43250 const JavaParamRef<jobject>& j_post_data,
tornee1bfee92015-12-01 14:05:01251 const JavaParamRef<jstring>& base_url_for_data_url,
Shu Yang112ad492024-07-25 17:11:54252 const JavaParamRef<jstring>& virtual_url_for_special_cases,
mnaganovbf087422015-12-16 05:10:03253 const JavaParamRef<jstring>& data_url_as_string,
lizebe8adeb82015-08-20 12:18:10254 jboolean can_load_local_resources,
255 jboolean is_renderer_initiated,
Michael Thiessend3c9a032021-04-19 17:01:37256 jboolean should_replace_current_entry,
257 const JavaParamRef<jobject>& j_initiator_origin,
258 jboolean has_user_gesture,
259 jboolean should_clear_history_list,
Liam Brady767b85e2023-07-05 16:59:59260 const base::android::JavaParamRef<jobject>& j_additional_navigation_params,
Brandon Wyliea20e67ae2022-07-26 22:01:20261 jlong input_start,
Min Qin76ab3dd2024-02-07 21:23:50262 jlong navigation_ui_data_ptr,
263 jboolean is_pdf) {
ajith.v4502cc62014-09-05 17:41:39264 DCHECK(url);
265 NavigationController::LoadURLParams params(
266 GURL(ConvertJavaStringToUTF8(env, url)));
Brandon Wyliea20e67ae2022-07-26 22:01:20267 // Wrap the raw pointer in case on an early return.
268 std::unique_ptr<NavigationUIData> navigation_ui_data = base::WrapUnique(
269 reinterpret_cast<NavigationUIData*>(navigation_ui_data_ptr));
ajith.v4502cc62014-09-05 17:41:39270 params.load_type =
271 static_cast<NavigationController::LoadURLType>(load_url_type);
Sylvain Defresnec6ccc77d2014-09-19 10:19:35272 params.transition_type = ui::PageTransitionFromInt(transition_type);
ajith.v4502cc62014-09-05 17:41:39273 params.override_user_agent =
274 static_cast<NavigationController::UserAgentOverrideOption>(
275 ua_override_option);
276 params.can_load_local_resources = can_load_local_resources;
277 params.is_renderer_initiated = is_renderer_initiated;
lizebe8adeb82015-08-20 12:18:10278 params.should_replace_current_entry = should_replace_current_entry;
Michael Thiessend3c9a032021-04-19 17:01:37279 params.has_user_gesture = has_user_gesture;
280 params.should_clear_history_list = should_clear_history_list;
Min Qin76ab3dd2024-02-07 21:23:50281 params.is_pdf = is_pdf;
ajith.v4502cc62014-09-05 17:41:39282
Liam Brady767b85e2023-07-05 16:59:59283 if (j_additional_navigation_params) {
John Delaney43de85fd62023-05-24 17:31:39284 params.initiator_frame_token =
Liam Brady767b85e2023-07-05 16:59:59285 GetInitiatorFrameTokenFromJavaAdditionalNavigationParams(
286 env, j_additional_navigation_params);
John Delaney43de85fd62023-05-24 17:31:39287 params.initiator_process_id =
Liam Brady767b85e2023-07-05 16:59:59288 GetInitiatorProcessIdFromJavaAdditionalNavigationParams(
289 env, j_additional_navigation_params);
290
291 // If the attribution src token exists, then an impression exists with this
292 // navigation.
293 if (GetAttributionSrcTokenFromJavaAdditionalNavigationParams(
294 env, j_additional_navigation_params)
295 .has_value()) {
296 blink::Impression impression;
297 impression.attribution_src_token =
298 GetAttributionSrcTokenFromJavaAdditionalNavigationParams(
299 env, j_additional_navigation_params)
300 .value();
Liam Brady767b85e2023-07-05 16:59:59301 params.impression = impression;
302 }
John Delaney43de85fd62023-05-24 17:31:39303 }
304
ajith.v4502cc62014-09-05 17:41:39305 if (extra_headers)
306 params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
307
John Abd-El-Maleka59411632018-01-10 20:08:28308 params.post_data = ExtractResourceRequestBodyFromJavaObject(env, j_post_data);
ajith.v4502cc62014-09-05 17:41:39309
310 if (base_url_for_data_url) {
311 params.base_url_for_data_url =
312 GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
313 }
314
Shu Yang112ad492024-07-25 17:11:54315 if (virtual_url_for_special_cases) {
316 params.virtual_url_for_special_cases =
317 GURL(ConvertJavaStringToUTF8(env, virtual_url_for_special_cases));
ajith.v4502cc62014-09-05 17:41:39318 }
319
mnaganovbf087422015-12-16 05:10:03320 if (data_url_as_string) {
Daniel Chengef9f4b72017-10-18 08:56:17321 // Treat |data_url_as_string| as if we were intending to put it into a GURL
322 // field. Note that kMaxURLChars is only enforced when serializing URLs
323 // for IPC.
324 GURL data_url = GURL(ConvertJavaStringToUTF8(env, data_url_as_string));
325 DCHECK(data_url.SchemeIs(url::kDataScheme));
mnaganovbf087422015-12-16 05:10:03326 DCHECK(params.url.SchemeIs(url::kDataScheme));
327#if DCHECK_IS_ON()
328 {
329 std::string mime_type, charset, data;
330 DCHECK(net::DataURL::Parse(params.url, &mime_type, &charset, &data));
331 DCHECK(data.empty());
332 }
Daniel Chengef9f4b72017-10-18 08:56:17333#endif
334 std::string s = data_url.spec();
Jongmok Kimc5491082022-10-19 09:17:59335 params.data_url_as_string =
336 base::MakeRefCounted<base::RefCountedString>(std::move(s));
mnaganovbf087422015-12-16 05:10:03337 }
338
ajith.v4502cc62014-09-05 17:41:39339 if (j_referrer_url) {
Lukasz Anforowicza192eb952019-10-15 19:22:22340 params.referrer =
341 Referrer(GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
342 Referrer::ConvertToPolicy(referrer_policy));
ajith.v4502cc62014-09-05 17:41:39343 }
344
Michael Thiessend3c9a032021-04-19 17:01:37345 if (j_initiator_origin) {
Andrew Grieve6a37bcd2024-09-26 21:47:44346 params.initiator_origin =
347 url::Origin::FromJavaObject(env, j_initiator_origin);
Michael Thiessend3c9a032021-04-19 17:01:37348 }
349
350 if (input_start != 0)
351 params.input_start = base::TimeTicks::FromUptimeMillis(input_start);
352
Brandon Wyliea20e67ae2022-07-26 22:01:20353 params.navigation_ui_data = std::move(navigation_ui_data);
354
Pete Williamson1d87f4622022-10-18 19:36:43355 base::WeakPtr<NavigationHandle> handle =
356 navigation_controller_->LoadURLWithParams(params);
357
358 if (!handle) {
359 return nullptr;
360 }
361
Torne (Richard Coles)d07c794b2023-11-21 23:55:49362 return base::android::ScopedJavaLocalRef<jobject>(
Pete Williamson1d87f4622022-10-18 19:36:43363 handle->GetJavaNavigationHandle());
ajith.v4502cc62014-09-05 17:41:39364}
365
tornee1bfee92015-12-01 14:05:01366void NavigationControllerAndroid::ClearHistory(
367 JNIEnv* env,
368 const JavaParamRef<jobject>& obj) {
ajith.v4502cc62014-09-05 17:41:39369 // TODO(creis): Do callers of this need to know if it fails?
370 if (navigation_controller_->CanPruneAllButLastCommitted())
371 navigation_controller_->PruneAllButLastCommitted();
372}
373
tornee1bfee92015-12-01 14:05:01374jint NavigationControllerAndroid::GetNavigationHistory(
375 JNIEnv* env,
376 const JavaParamRef<jobject>& obj,
377 const JavaParamRef<jobject>& history) {
ajith.v4502cc62014-09-05 17:41:39378 // Iterate through navigation entries to populate the list
379 int count = navigation_controller_->GetEntryCount();
380 for (int i = 0; i < count; ++i) {
Daniel Bratell7aacf952017-11-21 17:51:25381 JNI_NavigationControllerImpl_AddNavigationEntryToHistory(
dtrainorb316e9272014-09-19 23:30:55382 env, history, navigation_controller_->GetEntryAtIndex(i), i);
ajith.v4502cc62014-09-05 17:41:39383 }
384
385 return navigation_controller_->GetCurrentEntryIndex();
386}
387
388void NavigationControllerAndroid::GetDirectedNavigationHistory(
389 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01390 const JavaParamRef<jobject>& obj,
391 const JavaParamRef<jobject>& history,
ajith.v4502cc62014-09-05 17:41:39392 jboolean is_forward,
393 jint max_entries) {
394 // Iterate through navigation entries to populate the list
395 int count = navigation_controller_->GetEntryCount();
396 int num_added = 0;
397 int increment_value = is_forward ? 1 : -1;
398 for (int i = navigation_controller_->GetCurrentEntryIndex() + increment_value;
Aran Gilman37d11632019-10-08 23:07:15399 i >= 0 && i < count; i += increment_value) {
ajith.v4502cc62014-09-05 17:41:39400 if (num_added >= max_entries)
401 break;
402
Daniel Bratell7aacf952017-11-21 17:51:25403 JNI_NavigationControllerImpl_AddNavigationEntryToHistory(
dtrainorb316e9272014-09-19 23:30:55404 env, history, navigation_controller_->GetEntryAtIndex(i), i);
ajith.v4502cc62014-09-05 17:41:39405 num_added++;
406 }
407}
408
tornee1bfee92015-12-01 14:05:01409void NavigationControllerAndroid::ClearSslPreferences(
410 JNIEnv* env,
411 const JavaParamRef<jobject>& obj) {
Lukasz Anforowicza192eb952019-10-15 19:22:22412 SSLHostStateDelegate* delegate =
ajith.v4502cc62014-09-05 17:41:39413 navigation_controller_->GetBrowserContext()->GetSSLHostStateDelegate();
414 if (delegate)
danakj1606c572019-11-27 22:34:03415 delegate->Clear(base::NullCallback());
ajith.v4502cc62014-09-05 17:41:39416}
417
tornee1bfee92015-12-01 14:05:01418bool NavigationControllerAndroid::GetUseDesktopUserAgent(
419 JNIEnv* env,
420 const JavaParamRef<jobject>& obj) {
Mohamed Abdelhalim676259c2019-06-18 07:27:54421 NavigationEntry* entry = navigation_controller_->GetLastCommittedEntry();
ajith.v4502cc62014-09-05 17:41:39422 return entry && entry->GetIsOverridingUserAgent();
423}
424
425void NavigationControllerAndroid::SetUseDesktopUserAgent(
426 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01427 const JavaParamRef<jobject>& obj,
ajith.v4502cc62014-09-05 17:41:39428 jboolean enabled,
Shu Yanga0b22212022-07-08 16:44:52429 jboolean reload_on_state_change,
430 jint source) {
Rakina Zata Amnid605d462022-06-01 10:17:03431 SCOPED_CRASH_KEY_BOOL("nav_reentrancy_caller2", "SetUA_enabled",
432 (bool)enabled);
ajith.v4502cc62014-09-05 17:41:39433 if (GetUseDesktopUserAgent(env, obj) == enabled)
434 return;
435
Rakina Zata Amni148dcad72022-06-08 14:53:50436 if (navigation_controller_->in_navigate_to_pending_entry() &&
437 reload_on_state_change) {
Shu Yanga0b22212022-07-08 16:44:52438 // Sometimes it's possible to call this function in response to a
Rakina Zata Amni148dcad72022-06-08 14:53:50439 // navigation to a pending entry. In this case, we should avoid triggering
440 // another navigation synchronously, as it will crash due to navigation
441 // re-entrancy checks. To do that, post a task to update the UA and
442 // reload asynchronously.
Alison Gale770f3fc2024-04-27 00:39:58443 // TODO(crbug.com/40841494): Figure out the case that leads to this
Rakina Zata Amni148dcad72022-06-08 14:53:50444 // situation and avoid calling this function entirely in that case. For now,
445 // do a do a DumpWithoutCrashing so that we can investigate.
446 GetUIThreadTaskRunner({})->PostTask(
447 FROM_HERE,
448 base::BindOnce(
449 &NavigationControllerAndroid::SetUseDesktopUserAgentInternal,
450 weak_factory_.GetWeakPtr(), enabled, reload_on_state_change));
Shu Yanga0b22212022-07-08 16:44:52451 LOG(WARNING) << "NavigationControllerAndroid::SetUseDesktopUserAgent "
452 << "triggers re-entrant navigation, override: "
453 << (bool)enabled << ", source: " << (int)source;
454 SCOPED_CRASH_KEY_NUMBER("SetUseDesktopUserAgent", "caller", (int)source);
Rakina Zata Amni148dcad72022-06-08 14:53:50455 base::debug::DumpWithoutCrashing();
456 } else {
457 SetUseDesktopUserAgentInternal(enabled, reload_on_state_change);
458 }
459}
460
461void NavigationControllerAndroid::SetUseDesktopUserAgentInternal(
462 bool enabled,
463 bool reload_on_state_change) {
ajith.v4502cc62014-09-05 17:41:39464 // Make sure the navigation entry actually exists.
Mohamed Abdelhalim676259c2019-06-18 07:27:54465 NavigationEntry* entry = navigation_controller_->GetLastCommittedEntry();
Alison Gale81f4f2c72024-04-22 19:33:31466 // TODO(crbug.com/40063008): Early return for initial NavigationEntries as a
Shu Yang31063532023-02-19 00:53:14467 // workaround. Currently, doing a reload while on the initial NavigationEntry
468 // might result in committing an unrelated pending NavigationEntry and
469 // mistakenly marking that entry as an initial NavigationEntry. That will
470 // cause problems, such as the URL bar showing about:blank instead of the URL
471 // of the NavigationEntry. To prevent that happening in this case, skip
472 // reloading initial NavigationEntries entirely. This is a short-term fix,
473 // while we work on a long-term fix to no longer mistakenly mark the unrelated
474 // pending NavigationEntry as the initial NavigationEntry.
475 if (!entry || entry->IsInitialEntry()) {
ajith.v4502cc62014-09-05 17:41:39476 return;
Shu Yang31063532023-02-19 00:53:14477 }
ajith.v4502cc62014-09-05 17:41:39478
479 // Set the flag in the NavigationEntry.
480 entry->SetIsOverridingUserAgent(enabled);
aelias5252baa2016-04-10 01:18:02481 navigation_controller_->delegate()->UpdateOverridingUserAgent();
ajith.v4502cc62014-09-05 17:41:39482
483 // Send the override to the renderer.
484 if (reload_on_state_change) {
485 // Reloading the page will send the override down as part of the
486 // navigation IPC message.
Charlie Reis4c53a962023-06-21 23:17:53487 navigation_controller_->LoadOriginalRequestURL();
ajith.v4502cc62014-09-05 17:41:39488 }
489}
490
dtrainorb316e9272014-09-19 23:30:55491base::android::ScopedJavaLocalRef<jobject>
dfalcantaraf5d7ff812015-01-16 22:58:03492NavigationControllerAndroid::GetEntryAtIndex(JNIEnv* env,
tornee1bfee92015-12-01 14:05:01493 const JavaParamRef<jobject>& obj,
dfalcantaraf5d7ff812015-01-16 22:58:03494 int index) {
495 if (index < 0 || index >= navigation_controller_->GetEntryCount())
496 return base::android::ScopedJavaLocalRef<jobject>();
497
Lukasz Anforowicza192eb952019-10-15 19:22:22498 NavigationEntry* entry = navigation_controller_->GetEntryAtIndex(index);
Daniel Bratell7aacf952017-11-21 17:51:25499 return JNI_NavigationControllerImpl_CreateJavaNavigationEntry(env, entry,
500 index);
dfalcantaraf5d7ff812015-01-16 22:58:03501}
502
503base::android::ScopedJavaLocalRef<jobject>
Ted Chocaa84a512019-04-23 19:15:40504NavigationControllerAndroid::GetVisibleEntry(JNIEnv* env,
505 const JavaParamRef<jobject>& obj) {
Lukasz Anforowicza192eb952019-10-15 19:22:22506 NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
Ted Chocaa84a512019-04-23 19:15:40507
508 if (!entry)
509 return base::android::ScopedJavaLocalRef<jobject>();
510
511 return JNI_NavigationControllerImpl_CreateJavaNavigationEntry(env, entry,
512 /*index=*/-1);
513}
514
515base::android::ScopedJavaLocalRef<jobject>
tornee1bfee92015-12-01 14:05:01516NavigationControllerAndroid::GetPendingEntry(JNIEnv* env,
517 const JavaParamRef<jobject>& obj) {
Lukasz Anforowicza192eb952019-10-15 19:22:22518 NavigationEntry* entry = navigation_controller_->GetPendingEntry();
dtrainorb316e9272014-09-19 23:30:55519
520 if (!entry)
521 return base::android::ScopedJavaLocalRef<jobject>();
522
Daniel Bratell7aacf952017-11-21 17:51:25523 return JNI_NavigationControllerImpl_CreateJavaNavigationEntry(
dtrainorb316e9272014-09-19 23:30:55524 env, entry, navigation_controller_->GetPendingEntryIndex());
525}
526
tornee1bfee92015-12-01 14:05:01527jint NavigationControllerAndroid::GetLastCommittedEntryIndex(
528 JNIEnv* env,
529 const JavaParamRef<jobject>& obj) {
jaekyun45bc8c52014-11-03 01:00:21530 return navigation_controller_->GetLastCommittedEntryIndex();
531}
532
tornee1bfee92015-12-01 14:05:01533jboolean NavigationControllerAndroid::RemoveEntryAtIndex(
534 JNIEnv* env,
535 const JavaParamRef<jobject>& obj,
536 jint index) {
jaekyun45bc8c52014-11-03 01:00:21537 return navigation_controller_->RemoveEntryAtIndex(index);
538}
539
Michael Thiessen9b14d512019-09-23 21:19:47540void NavigationControllerAndroid::PruneForwardEntries(
541 JNIEnv* env,
542 const JavaParamRef<jobject>& obj) {
543 return navigation_controller_->PruneForwardEntries();
544}
545
mvanouwerkerk5b1519e2016-09-27 15:47:46546ScopedJavaLocalRef<jstring> NavigationControllerAndroid::GetEntryExtraData(
547 JNIEnv* env,
548 const JavaParamRef<jobject>& obj,
549 jint index,
550 const JavaParamRef<jstring>& jkey) {
551 if (index < 0 || index >= navigation_controller_->GetEntryCount())
552 return ScopedJavaLocalRef<jstring>();
553
554 std::string key = base::android::ConvertJavaStringToUTF8(env, jkey);
Scott Violetf4eec902019-04-04 21:20:34555 MapData* map_data =
556 MapData::Get(navigation_controller_->GetEntryAtIndex(index));
557 auto iter = map_data->map().find(key);
558 return ConvertUTF16ToJavaString(
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58559 env, iter == map_data->map().end() ? std::u16string() : iter->second);
mvanouwerkerk5b1519e2016-09-27 15:47:46560}
561
562void NavigationControllerAndroid::SetEntryExtraData(
563 JNIEnv* env,
564 const JavaParamRef<jobject>& obj,
565 jint index,
566 const JavaParamRef<jstring>& jkey,
567 const JavaParamRef<jstring>& jvalue) {
568 if (index < 0 || index >= navigation_controller_->GetEntryCount())
569 return;
570
571 std::string key = base::android::ConvertJavaStringToUTF8(env, jkey);
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58572 std::u16string value = base::android::ConvertJavaStringToUTF16(env, jvalue);
Scott Violetf4eec902019-04-04 21:20:34573 MapData* map_data =
574 MapData::Get(navigation_controller_->GetEntryAtIndex(index));
575 map_data->map()[key] = value;
mvanouwerkerk5b1519e2016-09-27 15:47:46576}
577
Jenna Himawana6d3fab72025-04-29 01:43:00578void NavigationControllerAndroid::CopyStateFrom(
579 JNIEnv* env,
580 jlong source_navigation_controller_ptr,
581 jboolean needs_reload) {
582 navigation_controller_->CopyStateFrom(
583 reinterpret_cast<NavigationControllerAndroid*>(
584 source_navigation_controller_ptr)
585 ->navigation_controller_,
586 needs_reload);
587}
588
[email protected]155c7f22013-12-09 17:07:18589} // namespace content