blob: c47592b410c7d30d29c334371627a2af2b632a0e [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(
Andrew Grieve9f9cac42025-07-22 20:06:28132 env, reinterpret_cast<intptr_t>(this)));
[email protected]155c7f22013-12-09 17:07:18133}
134
135NavigationControllerAndroid::~NavigationControllerAndroid() {
torne948f3662016-08-16 15:10:44136 Java_NavigationControllerImpl_destroy(AttachCurrentThread(), obj_);
[email protected]155c7f22013-12-09 17:07:18137}
138
139base::android::ScopedJavaLocalRef<jobject>
140NavigationControllerAndroid::GetJavaObject() {
141 return base::android::ScopedJavaLocalRef<jobject>(obj_);
142}
143
Andrew Grieveab2c9152025-07-02 19:53:13144jboolean NavigationControllerAndroid::CanGoBack(JNIEnv* env) {
[email protected]155c7f22013-12-09 17:07:18145 return navigation_controller_->CanGoBack();
146}
147
Andrew Grieveab2c9152025-07-02 19:53:13148jboolean NavigationControllerAndroid::CanGoForward(JNIEnv* env) {
[email protected]155c7f22013-12-09 17:07:18149 return navigation_controller_->CanGoForward();
150}
151
Andrew Grieveab2c9152025-07-02 19:53:13152jboolean NavigationControllerAndroid::CanGoToOffset(JNIEnv* env, jint offset) {
WangHui74286d52021-03-31 16:17:15153 return navigation_controller_->CanGoToOffsetWithSkipping(offset);
[email protected]155c7f22013-12-09 17:07:18154}
155
Andrew Grieveab2c9152025-07-02 19:53:13156void NavigationControllerAndroid::GoBack(JNIEnv* env) {
[email protected]155c7f22013-12-09 17:07:18157 navigation_controller_->GoBack();
158}
159
Andrew Grieveab2c9152025-07-02 19:53:13160void NavigationControllerAndroid::GoForward(JNIEnv* env) {
[email protected]155c7f22013-12-09 17:07:18161 navigation_controller_->GoForward();
162}
163
164void NavigationControllerAndroid::GoToOffset(JNIEnv* env,
[email protected]155c7f22013-12-09 17:07:18165 jint offset) {
WangHui74286d52021-03-31 16:17:15166 navigation_controller_->GoToOffsetWithSkipping(offset);
[email protected]155c7f22013-12-09 17:07:18167}
168
Andrew Grieveab2c9152025-07-02 19:53:13169jboolean NavigationControllerAndroid::IsInitialNavigation(JNIEnv* env) {
dfalcantara0d314d522015-01-05 22:56:43170 return navigation_controller_->IsInitialNavigation();
171}
172
Andrew Grieveab2c9152025-07-02 19:53:13173void NavigationControllerAndroid::LoadIfNecessary(JNIEnv* env) {
[email protected]6d3f32f2014-07-08 08:23:29174 navigation_controller_->LoadIfNecessary();
175}
176
Andrew Grieveab2c9152025-07-02 19:53:13177void NavigationControllerAndroid::ContinuePendingReload(JNIEnv* env) {
[email protected]6d3f32f2014-07-08 08:23:29178 navigation_controller_->ContinuePendingReload();
179}
180
181void NavigationControllerAndroid::Reload(JNIEnv* env,
[email protected]6d3f32f2014-07-08 08:23:29182 jboolean check_for_repost) {
Rakina Zata Amnid605d462022-06-01 10:17:03183 SCOPED_CRASH_KEY_BOOL("nav_reentrancy_caller2", "Reload_check",
184 (bool)check_for_repost);
toyoshim6142d96f2016-12-19 09:07:25185 navigation_controller_->Reload(ReloadType::NORMAL, check_for_repost);
[email protected]6d3f32f2014-07-08 08:23:29186}
187
toyoshim7dad4b1182016-04-01 14:28:05188void NavigationControllerAndroid::ReloadBypassingCache(
[email protected]6d3f32f2014-07-08 08:23:29189 JNIEnv* env,
[email protected]6d3f32f2014-07-08 08:23:29190 jboolean check_for_repost) {
Rakina Zata Amnid605d462022-06-01 10:17:03191 SCOPED_CRASH_KEY_BOOL("nav_reentrancy_caller2", "ReloadB_check",
192 (bool)check_for_repost);
toyoshim6142d96f2016-12-19 09:07:25193 navigation_controller_->Reload(ReloadType::BYPASSING_CACHE, check_for_repost);
[email protected]6d3f32f2014-07-08 08:23:29194}
195
Andrew Grieveab2c9152025-07-02 19:53:13196jboolean NavigationControllerAndroid::NeedsReload(JNIEnv* env) {
Matthew Carye7da4b12018-05-02 16:14:16197 return navigation_controller_->NeedsReload();
198}
199
Andrew Grieveab2c9152025-07-02 19:53:13200void NavigationControllerAndroid::SetNeedsReload(JNIEnv* env) {
[email protected]6d3f32f2014-07-08 08:23:29201 navigation_controller_->SetNeedsReload();
202}
203
Andrew Grieveab2c9152025-07-02 19:53:13204void NavigationControllerAndroid::CancelPendingReload(JNIEnv* env) {
[email protected]6d3f32f2014-07-08 08:23:29205 navigation_controller_->CancelPendingReload();
206}
207
Andrew Grieveab2c9152025-07-02 19:53:13208void NavigationControllerAndroid::GoToNavigationIndex(JNIEnv* env, jint index) {
[email protected]155c7f22013-12-09 17:07:18209 navigation_controller_->GoToIndex(index);
210}
211
Torne (Richard Coles)d07c794b2023-11-21 23:55:49212base::android::ScopedJavaLocalRef<jobject> NavigationControllerAndroid::LoadUrl(
lizebe8adeb82015-08-20 12:18:10213 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01214 const JavaParamRef<jstring>& url,
lizebe8adeb82015-08-20 12:18:10215 jint load_url_type,
216 jint transition_type,
tornee1bfee92015-12-01 14:05:01217 const JavaParamRef<jstring>& j_referrer_url,
lizebe8adeb82015-08-20 12:18:10218 jint referrer_policy,
219 jint ua_override_option,
tornee1bfee92015-12-01 14:05:01220 const JavaParamRef<jstring>& extra_headers,
lukasza477a5a22016-06-16 18:28:43221 const JavaParamRef<jobject>& j_post_data,
tornee1bfee92015-12-01 14:05:01222 const JavaParamRef<jstring>& base_url_for_data_url,
Shu Yang112ad492024-07-25 17:11:54223 const JavaParamRef<jstring>& virtual_url_for_special_cases,
mnaganovbf087422015-12-16 05:10:03224 const JavaParamRef<jstring>& data_url_as_string,
lizebe8adeb82015-08-20 12:18:10225 jboolean can_load_local_resources,
226 jboolean is_renderer_initiated,
Michael Thiessend3c9a032021-04-19 17:01:37227 jboolean should_replace_current_entry,
228 const JavaParamRef<jobject>& j_initiator_origin,
229 jboolean has_user_gesture,
230 jboolean should_clear_history_list,
Liam Brady767b85e2023-07-05 16:59:59231 const base::android::JavaParamRef<jobject>& j_additional_navigation_params,
Brandon Wyliea20e67ae2022-07-26 22:01:20232 jlong input_start,
Min Qin76ab3dd2024-02-07 21:23:50233 jlong navigation_ui_data_ptr,
234 jboolean is_pdf) {
ajith.v4502cc62014-09-05 17:41:39235 DCHECK(url);
236 NavigationController::LoadURLParams params(
237 GURL(ConvertJavaStringToUTF8(env, url)));
Brandon Wyliea20e67ae2022-07-26 22:01:20238 // Wrap the raw pointer in case on an early return.
239 std::unique_ptr<NavigationUIData> navigation_ui_data = base::WrapUnique(
240 reinterpret_cast<NavigationUIData*>(navigation_ui_data_ptr));
ajith.v4502cc62014-09-05 17:41:39241 params.load_type =
242 static_cast<NavigationController::LoadURLType>(load_url_type);
Sylvain Defresnec6ccc77d2014-09-19 10:19:35243 params.transition_type = ui::PageTransitionFromInt(transition_type);
ajith.v4502cc62014-09-05 17:41:39244 params.override_user_agent =
245 static_cast<NavigationController::UserAgentOverrideOption>(
246 ua_override_option);
247 params.can_load_local_resources = can_load_local_resources;
248 params.is_renderer_initiated = is_renderer_initiated;
lizebe8adeb82015-08-20 12:18:10249 params.should_replace_current_entry = should_replace_current_entry;
Michael Thiessend3c9a032021-04-19 17:01:37250 params.has_user_gesture = has_user_gesture;
251 params.should_clear_history_list = should_clear_history_list;
Min Qin76ab3dd2024-02-07 21:23:50252 params.is_pdf = is_pdf;
ajith.v4502cc62014-09-05 17:41:39253
Liam Brady767b85e2023-07-05 16:59:59254 if (j_additional_navigation_params) {
John Delaney43de85fd62023-05-24 17:31:39255 params.initiator_frame_token =
Liam Brady767b85e2023-07-05 16:59:59256 GetInitiatorFrameTokenFromJavaAdditionalNavigationParams(
257 env, j_additional_navigation_params);
John Delaney43de85fd62023-05-24 17:31:39258 params.initiator_process_id =
Liam Brady767b85e2023-07-05 16:59:59259 GetInitiatorProcessIdFromJavaAdditionalNavigationParams(
260 env, j_additional_navigation_params);
261
262 // If the attribution src token exists, then an impression exists with this
263 // navigation.
264 if (GetAttributionSrcTokenFromJavaAdditionalNavigationParams(
265 env, j_additional_navigation_params)
266 .has_value()) {
267 blink::Impression impression;
268 impression.attribution_src_token =
269 GetAttributionSrcTokenFromJavaAdditionalNavigationParams(
270 env, j_additional_navigation_params)
271 .value();
Liam Brady767b85e2023-07-05 16:59:59272 params.impression = impression;
273 }
John Delaney43de85fd62023-05-24 17:31:39274 }
275
ajith.v4502cc62014-09-05 17:41:39276 if (extra_headers)
277 params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
278
John Abd-El-Maleka59411632018-01-10 20:08:28279 params.post_data = ExtractResourceRequestBodyFromJavaObject(env, j_post_data);
ajith.v4502cc62014-09-05 17:41:39280
281 if (base_url_for_data_url) {
282 params.base_url_for_data_url =
283 GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
284 }
285
Shu Yang112ad492024-07-25 17:11:54286 if (virtual_url_for_special_cases) {
287 params.virtual_url_for_special_cases =
288 GURL(ConvertJavaStringToUTF8(env, virtual_url_for_special_cases));
ajith.v4502cc62014-09-05 17:41:39289 }
290
mnaganovbf087422015-12-16 05:10:03291 if (data_url_as_string) {
Daniel Chengef9f4b72017-10-18 08:56:17292 // Treat |data_url_as_string| as if we were intending to put it into a GURL
293 // field. Note that kMaxURLChars is only enforced when serializing URLs
294 // for IPC.
295 GURL data_url = GURL(ConvertJavaStringToUTF8(env, data_url_as_string));
296 DCHECK(data_url.SchemeIs(url::kDataScheme));
mnaganovbf087422015-12-16 05:10:03297 DCHECK(params.url.SchemeIs(url::kDataScheme));
298#if DCHECK_IS_ON()
299 {
300 std::string mime_type, charset, data;
301 DCHECK(net::DataURL::Parse(params.url, &mime_type, &charset, &data));
302 DCHECK(data.empty());
303 }
Daniel Chengef9f4b72017-10-18 08:56:17304#endif
305 std::string s = data_url.spec();
Jongmok Kimc5491082022-10-19 09:17:59306 params.data_url_as_string =
307 base::MakeRefCounted<base::RefCountedString>(std::move(s));
mnaganovbf087422015-12-16 05:10:03308 }
309
ajith.v4502cc62014-09-05 17:41:39310 if (j_referrer_url) {
Lukasz Anforowicza192eb952019-10-15 19:22:22311 params.referrer =
312 Referrer(GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
313 Referrer::ConvertToPolicy(referrer_policy));
ajith.v4502cc62014-09-05 17:41:39314 }
315
Michael Thiessend3c9a032021-04-19 17:01:37316 if (j_initiator_origin) {
Andrew Grieve6a37bcd2024-09-26 21:47:44317 params.initiator_origin =
318 url::Origin::FromJavaObject(env, j_initiator_origin);
Michael Thiessend3c9a032021-04-19 17:01:37319 }
320
321 if (input_start != 0)
322 params.input_start = base::TimeTicks::FromUptimeMillis(input_start);
323
Brandon Wyliea20e67ae2022-07-26 22:01:20324 params.navigation_ui_data = std::move(navigation_ui_data);
325
Pete Williamson1d87f4622022-10-18 19:36:43326 base::WeakPtr<NavigationHandle> handle =
327 navigation_controller_->LoadURLWithParams(params);
328
329 if (!handle) {
330 return nullptr;
331 }
332
Torne (Richard Coles)d07c794b2023-11-21 23:55:49333 return base::android::ScopedJavaLocalRef<jobject>(
Pete Williamson1d87f4622022-10-18 19:36:43334 handle->GetJavaNavigationHandle());
ajith.v4502cc62014-09-05 17:41:39335}
336
Andrew Grieveab2c9152025-07-02 19:53:13337void NavigationControllerAndroid::ClearHistory(JNIEnv* env) {
ajith.v4502cc62014-09-05 17:41:39338 // TODO(creis): Do callers of this need to know if it fails?
339 if (navigation_controller_->CanPruneAllButLastCommitted())
340 navigation_controller_->PruneAllButLastCommitted();
341}
342
tornee1bfee92015-12-01 14:05:01343jint NavigationControllerAndroid::GetNavigationHistory(
344 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01345 const JavaParamRef<jobject>& history) {
ajith.v4502cc62014-09-05 17:41:39346 // Iterate through navigation entries to populate the list
347 int count = navigation_controller_->GetEntryCount();
348 for (int i = 0; i < count; ++i) {
Daniel Bratell7aacf952017-11-21 17:51:25349 JNI_NavigationControllerImpl_AddNavigationEntryToHistory(
dtrainorb316e9272014-09-19 23:30:55350 env, history, navigation_controller_->GetEntryAtIndex(i), i);
ajith.v4502cc62014-09-05 17:41:39351 }
352
353 return navigation_controller_->GetCurrentEntryIndex();
354}
355
356void NavigationControllerAndroid::GetDirectedNavigationHistory(
357 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01358 const JavaParamRef<jobject>& history,
ajith.v4502cc62014-09-05 17:41:39359 jboolean is_forward,
360 jint max_entries) {
361 // Iterate through navigation entries to populate the list
362 int count = navigation_controller_->GetEntryCount();
363 int num_added = 0;
364 int increment_value = is_forward ? 1 : -1;
365 for (int i = navigation_controller_->GetCurrentEntryIndex() + increment_value;
Aran Gilman37d11632019-10-08 23:07:15366 i >= 0 && i < count; i += increment_value) {
ajith.v4502cc62014-09-05 17:41:39367 if (num_added >= max_entries)
368 break;
369
Daniel Bratell7aacf952017-11-21 17:51:25370 JNI_NavigationControllerImpl_AddNavigationEntryToHistory(
dtrainorb316e9272014-09-19 23:30:55371 env, history, navigation_controller_->GetEntryAtIndex(i), i);
ajith.v4502cc62014-09-05 17:41:39372 num_added++;
373 }
374}
375
Andrew Grieveab2c9152025-07-02 19:53:13376void NavigationControllerAndroid::ClearSslPreferences(JNIEnv* env) {
Lukasz Anforowicza192eb952019-10-15 19:22:22377 SSLHostStateDelegate* delegate =
ajith.v4502cc62014-09-05 17:41:39378 navigation_controller_->GetBrowserContext()->GetSSLHostStateDelegate();
379 if (delegate)
danakj1606c572019-11-27 22:34:03380 delegate->Clear(base::NullCallback());
ajith.v4502cc62014-09-05 17:41:39381}
382
Andrew Grieveab2c9152025-07-02 19:53:13383bool NavigationControllerAndroid::GetUseDesktopUserAgent(JNIEnv* env) {
Mohamed Abdelhalim676259c2019-06-18 07:27:54384 NavigationEntry* entry = navigation_controller_->GetLastCommittedEntry();
ajith.v4502cc62014-09-05 17:41:39385 return entry && entry->GetIsOverridingUserAgent();
386}
387
388void NavigationControllerAndroid::SetUseDesktopUserAgent(
389 JNIEnv* env,
ajith.v4502cc62014-09-05 17:41:39390 jboolean enabled,
Shu Yanga0b22212022-07-08 16:44:52391 jboolean reload_on_state_change,
392 jint source) {
Rakina Zata Amnid605d462022-06-01 10:17:03393 SCOPED_CRASH_KEY_BOOL("nav_reentrancy_caller2", "SetUA_enabled",
394 (bool)enabled);
Andrew Grieveab2c9152025-07-02 19:53:13395 if (GetUseDesktopUserAgent(env) == enabled) {
ajith.v4502cc62014-09-05 17:41:39396 return;
Andrew Grieveab2c9152025-07-02 19:53:13397 }
ajith.v4502cc62014-09-05 17:41:39398
Rakina Zata Amni148dcad72022-06-08 14:53:50399 if (navigation_controller_->in_navigate_to_pending_entry() &&
400 reload_on_state_change) {
Shu Yanga0b22212022-07-08 16:44:52401 // Sometimes it's possible to call this function in response to a
Rakina Zata Amni148dcad72022-06-08 14:53:50402 // navigation to a pending entry. In this case, we should avoid triggering
403 // another navigation synchronously, as it will crash due to navigation
404 // re-entrancy checks. To do that, post a task to update the UA and
405 // reload asynchronously.
Alison Gale770f3fc2024-04-27 00:39:58406 // TODO(crbug.com/40841494): Figure out the case that leads to this
Rakina Zata Amni148dcad72022-06-08 14:53:50407 // situation and avoid calling this function entirely in that case. For now,
408 // do a do a DumpWithoutCrashing so that we can investigate.
409 GetUIThreadTaskRunner({})->PostTask(
410 FROM_HERE,
411 base::BindOnce(
412 &NavigationControllerAndroid::SetUseDesktopUserAgentInternal,
413 weak_factory_.GetWeakPtr(), enabled, reload_on_state_change));
Shu Yanga0b22212022-07-08 16:44:52414 LOG(WARNING) << "NavigationControllerAndroid::SetUseDesktopUserAgent "
415 << "triggers re-entrant navigation, override: "
416 << (bool)enabled << ", source: " << (int)source;
417 SCOPED_CRASH_KEY_NUMBER("SetUseDesktopUserAgent", "caller", (int)source);
Rakina Zata Amni148dcad72022-06-08 14:53:50418 base::debug::DumpWithoutCrashing();
419 } else {
420 SetUseDesktopUserAgentInternal(enabled, reload_on_state_change);
421 }
422}
423
424void NavigationControllerAndroid::SetUseDesktopUserAgentInternal(
425 bool enabled,
426 bool reload_on_state_change) {
ajith.v4502cc62014-09-05 17:41:39427 // Make sure the navigation entry actually exists.
Mohamed Abdelhalim676259c2019-06-18 07:27:54428 NavigationEntry* entry = navigation_controller_->GetLastCommittedEntry();
Alison Gale81f4f2c72024-04-22 19:33:31429 // TODO(crbug.com/40063008): Early return for initial NavigationEntries as a
Shu Yang31063532023-02-19 00:53:14430 // workaround. Currently, doing a reload while on the initial NavigationEntry
431 // might result in committing an unrelated pending NavigationEntry and
432 // mistakenly marking that entry as an initial NavigationEntry. That will
433 // cause problems, such as the URL bar showing about:blank instead of the URL
434 // of the NavigationEntry. To prevent that happening in this case, skip
435 // reloading initial NavigationEntries entirely. This is a short-term fix,
436 // while we work on a long-term fix to no longer mistakenly mark the unrelated
437 // pending NavigationEntry as the initial NavigationEntry.
438 if (!entry || entry->IsInitialEntry()) {
ajith.v4502cc62014-09-05 17:41:39439 return;
Shu Yang31063532023-02-19 00:53:14440 }
ajith.v4502cc62014-09-05 17:41:39441
442 // Set the flag in the NavigationEntry.
443 entry->SetIsOverridingUserAgent(enabled);
aelias5252baa2016-04-10 01:18:02444 navigation_controller_->delegate()->UpdateOverridingUserAgent();
ajith.v4502cc62014-09-05 17:41:39445
446 // Send the override to the renderer.
447 if (reload_on_state_change) {
448 // Reloading the page will send the override down as part of the
449 // navigation IPC message.
Charlie Reis4c53a962023-06-21 23:17:53450 navigation_controller_->LoadOriginalRequestURL();
ajith.v4502cc62014-09-05 17:41:39451 }
452}
453
dtrainorb316e9272014-09-19 23:30:55454base::android::ScopedJavaLocalRef<jobject>
dfalcantaraf5d7ff812015-01-16 22:58:03455NavigationControllerAndroid::GetEntryAtIndex(JNIEnv* env,
dfalcantaraf5d7ff812015-01-16 22:58:03456 int index) {
457 if (index < 0 || index >= navigation_controller_->GetEntryCount())
458 return base::android::ScopedJavaLocalRef<jobject>();
459
Lukasz Anforowicza192eb952019-10-15 19:22:22460 NavigationEntry* entry = navigation_controller_->GetEntryAtIndex(index);
Daniel Bratell7aacf952017-11-21 17:51:25461 return JNI_NavigationControllerImpl_CreateJavaNavigationEntry(env, entry,
462 index);
dfalcantaraf5d7ff812015-01-16 22:58:03463}
464
465base::android::ScopedJavaLocalRef<jobject>
Andrew Grieveab2c9152025-07-02 19:53:13466NavigationControllerAndroid::GetVisibleEntry(JNIEnv* env) {
Lukasz Anforowicza192eb952019-10-15 19:22:22467 NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
Ted Chocaa84a512019-04-23 19:15:40468
469 if (!entry)
470 return base::android::ScopedJavaLocalRef<jobject>();
471
472 return JNI_NavigationControllerImpl_CreateJavaNavigationEntry(env, entry,
473 /*index=*/-1);
474}
475
476base::android::ScopedJavaLocalRef<jobject>
Andrew Grieveab2c9152025-07-02 19:53:13477NavigationControllerAndroid::GetPendingEntry(JNIEnv* env) {
Lukasz Anforowicza192eb952019-10-15 19:22:22478 NavigationEntry* entry = navigation_controller_->GetPendingEntry();
dtrainorb316e9272014-09-19 23:30:55479
480 if (!entry)
481 return base::android::ScopedJavaLocalRef<jobject>();
482
Daniel Bratell7aacf952017-11-21 17:51:25483 return JNI_NavigationControllerImpl_CreateJavaNavigationEntry(
dtrainorb316e9272014-09-19 23:30:55484 env, entry, navigation_controller_->GetPendingEntryIndex());
485}
486
Andrew Grieveab2c9152025-07-02 19:53:13487jint NavigationControllerAndroid::GetLastCommittedEntryIndex(JNIEnv* env) {
jaekyun45bc8c52014-11-03 01:00:21488 return navigation_controller_->GetLastCommittedEntryIndex();
489}
490
Andrew Grieveab2c9152025-07-02 19:53:13491jboolean NavigationControllerAndroid::RemoveEntryAtIndex(JNIEnv* env,
492 jint index) {
jaekyun45bc8c52014-11-03 01:00:21493 return navigation_controller_->RemoveEntryAtIndex(index);
494}
495
Andrew Grieveab2c9152025-07-02 19:53:13496void NavigationControllerAndroid::PruneForwardEntries(JNIEnv* env) {
Michael Thiessen9b14d512019-09-23 21:19:47497 return navigation_controller_->PruneForwardEntries();
498}
499
mvanouwerkerk5b1519e2016-09-27 15:47:46500ScopedJavaLocalRef<jstring> NavigationControllerAndroid::GetEntryExtraData(
501 JNIEnv* env,
mvanouwerkerk5b1519e2016-09-27 15:47:46502 jint index,
503 const JavaParamRef<jstring>& jkey) {
504 if (index < 0 || index >= navigation_controller_->GetEntryCount())
505 return ScopedJavaLocalRef<jstring>();
506
507 std::string key = base::android::ConvertJavaStringToUTF8(env, jkey);
Scott Violetf4eec902019-04-04 21:20:34508 MapData* map_data =
509 MapData::Get(navigation_controller_->GetEntryAtIndex(index));
510 auto iter = map_data->map().find(key);
511 return ConvertUTF16ToJavaString(
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58512 env, iter == map_data->map().end() ? std::u16string() : iter->second);
mvanouwerkerk5b1519e2016-09-27 15:47:46513}
514
515void NavigationControllerAndroid::SetEntryExtraData(
516 JNIEnv* env,
mvanouwerkerk5b1519e2016-09-27 15:47:46517 jint index,
518 const JavaParamRef<jstring>& jkey,
519 const JavaParamRef<jstring>& jvalue) {
520 if (index < 0 || index >= navigation_controller_->GetEntryCount())
521 return;
522
523 std::string key = base::android::ConvertJavaStringToUTF8(env, jkey);
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58524 std::u16string value = base::android::ConvertJavaStringToUTF16(env, jvalue);
Scott Violetf4eec902019-04-04 21:20:34525 MapData* map_data =
526 MapData::Get(navigation_controller_->GetEntryAtIndex(index));
527 map_data->map()[key] = value;
mvanouwerkerk5b1519e2016-09-27 15:47:46528}
529
Jenna Himawana6d3fab72025-04-29 01:43:00530void NavigationControllerAndroid::CopyStateFrom(
531 JNIEnv* env,
532 jlong source_navigation_controller_ptr,
533 jboolean needs_reload) {
534 navigation_controller_->CopyStateFrom(
535 reinterpret_cast<NavigationControllerAndroid*>(
536 source_navigation_controller_ptr)
537 ->navigation_controller_,
538 needs_reload);
539}
540
[email protected]155c7f22013-12-09 17:07:18541} // namespace content