blob: 135b018c1d8f08a703f2ebf9a6a5f2aad0a4d0b7 [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"
danakjc492bf82020-09-09 20:02:4418#include "content/browser/renderer_host/navigation_controller_impl.h"
19#include "content/browser/renderer_host/navigation_entry_impl.h"
Mohamed Heikalc09e1012019-06-21 14:47:2620#include "content/public/android/content_jni_headers/NavigationControllerImpl_jni.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
35using base::android::AttachCurrentThread;
ajith.v4502cc62014-09-05 17:41:3936using base::android::ConvertJavaStringToUTF16;
37using base::android::ConvertJavaStringToUTF8;
38using base::android::ConvertUTF16ToJavaString;
torne86560112016-08-04 15:59:0439using base::android::JavaParamRef;
torne660061cd2016-09-07 17:47:5440using base::android::JavaRef;
torne86560112016-08-04 15:59:0441using base::android::ScopedJavaLocalRef;
torne660061cd2016-09-07 17:47:5442
ajith.v4502cc62014-09-05 17:41:3943namespace {
44
Scott Violetf4eec902019-04-04 21:20:3445const char kMapDataKey[] = "map_data_key";
46
ajith.v4502cc62014-09-05 17:41:3947// static
Daniel Bratell7aacf952017-11-21 17:51:2548static base::android::ScopedJavaLocalRef<jobject>
49JNI_NavigationControllerImpl_CreateJavaNavigationEntry(
dtrainorb316e9272014-09-19 23:30:5550 JNIEnv* env,
51 content::NavigationEntry* entry,
52 int index) {
53 DCHECK(entry);
54
ajith.v4502cc62014-09-05 17:41:3955 // Get the details of the current entry
Yaron Friedman09b9c5972020-12-15 17:47:3956 ScopedJavaLocalRef<jobject> j_url(
57 url::GURLAndroid::FromNativeGURL(env, entry->GetURL()));
58 ScopedJavaLocalRef<jobject> j_virtual_url(
59 url::GURLAndroid::FromNativeGURL(env, entry->GetVirtualURL()));
60 ScopedJavaLocalRef<jobject> j_original_url(
61 url::GURLAndroid::FromNativeGURL(env, entry->GetOriginalRequestURL()));
ajith.v4502cc62014-09-05 17:41:3962 ScopedJavaLocalRef<jstring> j_title(
63 ConvertUTF16ToJavaString(env, entry->GetTitle()));
64 ScopedJavaLocalRef<jobject> j_bitmap;
65 const content::FaviconStatus& status = entry->GetFavicon();
Rulong Chen(陈汝龙)61e3cc822020-08-29 03:29:2566 if (status.valid && status.image.ToSkBitmap()->computeByteSize() > 0) {
danakj5cc14ce2020-11-10 22:00:4067 j_bitmap = gfx::ConvertToJavaBitmap(*status.image.ToSkBitmap(),
Rulong Chen(陈汝龙)61e3cc822020-08-29 03:29:2568 gfx::OomBehavior::kReturnNullOnOom);
69 }
Jeffrey Cohen23f8cd772019-03-19 17:17:2870 jlong j_timestamp = entry->GetTimestamp().ToJavaTime();
ajith.v4502cc62014-09-05 17:41:3971
dtrainorb316e9272014-09-19 23:30:5572 return content::Java_NavigationControllerImpl_createNavigationEntry(
Yaron Friedmanf381f132022-11-29 21:47:4073 env, index, j_url, j_virtual_url, j_original_url, j_title, j_bitmap,
74 entry->GetTransitionType(), j_timestamp, entry->IsInitialEntry());
ajith.v4502cc62014-09-05 17:41:3975}
76
Daniel Bratell7aacf952017-11-21 17:51:2577static void JNI_NavigationControllerImpl_AddNavigationEntryToHistory(
78 JNIEnv* env,
79 const JavaRef<jobject>& history,
80 content::NavigationEntry* entry,
81 int index) {
dtrainorb316e9272014-09-19 23:30:5582 content::Java_NavigationControllerImpl_addToNavigationHistory(
Daniel Bratell7aacf952017-11-21 17:51:2583 env, history,
84 JNI_NavigationControllerImpl_CreateJavaNavigationEntry(env, entry,
85 index));
dtrainorb316e9272014-09-19 23:30:5586}
87
Scott Violetf4eec902019-04-04 21:20:3488class MapData : public base::SupportsUserData::Data {
89 public:
90 MapData() = default;
Peter Boström828b9022021-09-21 02:28:4391
92 MapData(const MapData&) = delete;
93 MapData& operator=(const MapData&) = delete;
94
Scott Violetf4eec902019-04-04 21:20:3495 ~MapData() override = default;
96
97 static MapData* Get(content::NavigationEntry* entry) {
98 MapData* map_data = static_cast<MapData*>(entry->GetUserData(kMapDataKey));
99 if (map_data)
100 return map_data;
101 auto map_data_ptr = std::make_unique<MapData>();
102 map_data = map_data_ptr.get();
103 entry->SetUserData(kMapDataKey, std::move(map_data_ptr));
104 return map_data;
105 }
106
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58107 base::flat_map<std::string, std::u16string>& map() { return map_; }
Scott Violetf4eec902019-04-04 21:20:34108
109 // base::SupportsUserData::Data:
110 std::unique_ptr<Data> Clone() override {
111 std::unique_ptr<MapData> clone = std::make_unique<MapData>();
112 clone->map_ = map_;
113 return clone;
114 }
115
116 private:
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58117 base::flat_map<std::string, std::u16string> map_;
Scott Violetf4eec902019-04-04 21:20:34118};
119
ajith.v4502cc62014-09-05 17:41:39120} // namespace
[email protected]155c7f22013-12-09 17:07:18121
122namespace content {
123
[email protected]155c7f22013-12-09 17:07:18124NavigationControllerAndroid::NavigationControllerAndroid(
aelias5252baa2016-04-10 01:18:02125 NavigationControllerImpl* navigation_controller)
[email protected]155c7f22013-12-09 17:07:18126 : navigation_controller_(navigation_controller) {
127 JNIEnv* env = AttachCurrentThread();
Aran Gilman37d11632019-10-08 23:07:15128 obj_.Reset(env, Java_NavigationControllerImpl_create(
129 env, reinterpret_cast<intptr_t>(this))
130 .obj());
[email protected]155c7f22013-12-09 17:07:18131}
132
133NavigationControllerAndroid::~NavigationControllerAndroid() {
torne948f3662016-08-16 15:10:44134 Java_NavigationControllerImpl_destroy(AttachCurrentThread(), obj_);
[email protected]155c7f22013-12-09 17:07:18135}
136
137base::android::ScopedJavaLocalRef<jobject>
138NavigationControllerAndroid::GetJavaObject() {
139 return base::android::ScopedJavaLocalRef<jobject>(obj_);
140}
141
tornee1bfee92015-12-01 14:05:01142jboolean NavigationControllerAndroid::CanGoBack(
143 JNIEnv* env,
144 const JavaParamRef<jobject>& obj) {
[email protected]155c7f22013-12-09 17:07:18145 return navigation_controller_->CanGoBack();
146}
147
tornee1bfee92015-12-01 14:05:01148jboolean NavigationControllerAndroid::CanGoForward(
149 JNIEnv* env,
150 const JavaParamRef<jobject>& obj) {
[email protected]155c7f22013-12-09 17:07:18151 return navigation_controller_->CanGoForward();
152}
153
tornee1bfee92015-12-01 14:05:01154jboolean NavigationControllerAndroid::CanGoToOffset(
155 JNIEnv* env,
156 const JavaParamRef<jobject>& obj,
157 jint offset) {
WangHui74286d52021-03-31 16:17:15158 return navigation_controller_->CanGoToOffsetWithSkipping(offset);
[email protected]155c7f22013-12-09 17:07:18159}
160
tornee1bfee92015-12-01 14:05:01161void NavigationControllerAndroid::GoBack(JNIEnv* env,
162 const JavaParamRef<jobject>& obj) {
[email protected]155c7f22013-12-09 17:07:18163 navigation_controller_->GoBack();
164}
165
tornee1bfee92015-12-01 14:05:01166void NavigationControllerAndroid::GoForward(JNIEnv* env,
167 const JavaParamRef<jobject>& obj) {
[email protected]155c7f22013-12-09 17:07:18168 navigation_controller_->GoForward();
169}
170
171void NavigationControllerAndroid::GoToOffset(JNIEnv* env,
tornee1bfee92015-12-01 14:05:01172 const JavaParamRef<jobject>& obj,
[email protected]155c7f22013-12-09 17:07:18173 jint offset) {
WangHui74286d52021-03-31 16:17:15174 navigation_controller_->GoToOffsetWithSkipping(offset);
[email protected]155c7f22013-12-09 17:07:18175}
176
tornee1bfee92015-12-01 14:05:01177jboolean NavigationControllerAndroid::IsInitialNavigation(
178 JNIEnv* env,
179 const JavaParamRef<jobject>& obj) {
dfalcantara0d314d522015-01-05 22:56:43180 return navigation_controller_->IsInitialNavigation();
181}
182
tornee1bfee92015-12-01 14:05:01183void NavigationControllerAndroid::LoadIfNecessary(
184 JNIEnv* env,
185 const JavaParamRef<jobject>& obj) {
[email protected]6d3f32f2014-07-08 08:23:29186 navigation_controller_->LoadIfNecessary();
187}
188
tornee1bfee92015-12-01 14:05:01189void NavigationControllerAndroid::ContinuePendingReload(
190 JNIEnv* env,
191 const JavaParamRef<jobject>& obj) {
[email protected]6d3f32f2014-07-08 08:23:29192 navigation_controller_->ContinuePendingReload();
193}
194
195void NavigationControllerAndroid::Reload(JNIEnv* env,
tornee1bfee92015-12-01 14:05:01196 const JavaParamRef<jobject>& obj,
[email protected]6d3f32f2014-07-08 08:23:29197 jboolean check_for_repost) {
Rakina Zata Amnid605d462022-06-01 10:17:03198 SCOPED_CRASH_KEY_BOOL("nav_reentrancy_caller2", "Reload_check",
199 (bool)check_for_repost);
toyoshim6142d96f2016-12-19 09:07:25200 navigation_controller_->Reload(ReloadType::NORMAL, check_for_repost);
[email protected]6d3f32f2014-07-08 08:23:29201}
202
toyoshim7dad4b1182016-04-01 14:28:05203void NavigationControllerAndroid::ReloadBypassingCache(
[email protected]6d3f32f2014-07-08 08:23:29204 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01205 const JavaParamRef<jobject>& obj,
[email protected]6d3f32f2014-07-08 08:23:29206 jboolean check_for_repost) {
Rakina Zata Amnid605d462022-06-01 10:17:03207 SCOPED_CRASH_KEY_BOOL("nav_reentrancy_caller2", "ReloadB_check",
208 (bool)check_for_repost);
toyoshim6142d96f2016-12-19 09:07:25209 navigation_controller_->Reload(ReloadType::BYPASSING_CACHE, check_for_repost);
[email protected]6d3f32f2014-07-08 08:23:29210}
211
Matthew Carye7da4b12018-05-02 16:14:16212jboolean NavigationControllerAndroid::NeedsReload(
213 JNIEnv* env,
214 const JavaParamRef<jobject>& obj) {
215 return navigation_controller_->NeedsReload();
216}
217
218void NavigationControllerAndroid::SetNeedsReload(
tornee1bfee92015-12-01 14:05:01219 JNIEnv* env,
220 const JavaParamRef<jobject>& obj) {
[email protected]6d3f32f2014-07-08 08:23:29221 navigation_controller_->SetNeedsReload();
222}
223
tornee1bfee92015-12-01 14:05:01224void NavigationControllerAndroid::CancelPendingReload(
225 JNIEnv* env,
226 const JavaParamRef<jobject>& obj) {
[email protected]6d3f32f2014-07-08 08:23:29227 navigation_controller_->CancelPendingReload();
228}
229
tornee1bfee92015-12-01 14:05:01230void NavigationControllerAndroid::GoToNavigationIndex(
231 JNIEnv* env,
232 const JavaParamRef<jobject>& obj,
233 jint index) {
[email protected]155c7f22013-12-09 17:07:18234 navigation_controller_->GoToIndex(index);
235}
236
Pete Williamson1d87f4622022-10-18 19:36:43237base::android::ScopedJavaGlobalRef<jobject>
238NavigationControllerAndroid::LoadUrl(
lizebe8adeb82015-08-20 12:18:10239 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01240 const JavaParamRef<jobject>& obj,
241 const JavaParamRef<jstring>& url,
lizebe8adeb82015-08-20 12:18:10242 jint load_url_type,
243 jint transition_type,
tornee1bfee92015-12-01 14:05:01244 const JavaParamRef<jstring>& j_referrer_url,
lizebe8adeb82015-08-20 12:18:10245 jint referrer_policy,
246 jint ua_override_option,
tornee1bfee92015-12-01 14:05:01247 const JavaParamRef<jstring>& extra_headers,
lukasza477a5a22016-06-16 18:28:43248 const JavaParamRef<jobject>& j_post_data,
tornee1bfee92015-12-01 14:05:01249 const JavaParamRef<jstring>& base_url_for_data_url,
250 const JavaParamRef<jstring>& virtual_url_for_data_url,
mnaganovbf087422015-12-16 05:10:03251 const JavaParamRef<jstring>& data_url_as_string,
lizebe8adeb82015-08-20 12:18:10252 jboolean can_load_local_resources,
253 jboolean is_renderer_initiated,
Michael Thiessend3c9a032021-04-19 17:01:37254 jboolean should_replace_current_entry,
255 const JavaParamRef<jobject>& j_initiator_origin,
256 jboolean has_user_gesture,
257 jboolean should_clear_history_list,
Brandon Wyliea20e67ae2022-07-26 22:01:20258 jlong input_start,
259 jlong navigation_ui_data_ptr) {
ajith.v4502cc62014-09-05 17:41:39260 DCHECK(url);
261 NavigationController::LoadURLParams params(
262 GURL(ConvertJavaStringToUTF8(env, url)));
Brandon Wyliea20e67ae2022-07-26 22:01:20263 // Wrap the raw pointer in case on an early return.
264 std::unique_ptr<NavigationUIData> navigation_ui_data = base::WrapUnique(
265 reinterpret_cast<NavigationUIData*>(navigation_ui_data_ptr));
ajith.v4502cc62014-09-05 17:41:39266 params.load_type =
267 static_cast<NavigationController::LoadURLType>(load_url_type);
Sylvain Defresnec6ccc77d2014-09-19 10:19:35268 params.transition_type = ui::PageTransitionFromInt(transition_type);
ajith.v4502cc62014-09-05 17:41:39269 params.override_user_agent =
270 static_cast<NavigationController::UserAgentOverrideOption>(
271 ua_override_option);
272 params.can_load_local_resources = can_load_local_resources;
273 params.is_renderer_initiated = is_renderer_initiated;
lizebe8adeb82015-08-20 12:18:10274 params.should_replace_current_entry = should_replace_current_entry;
Michael Thiessend3c9a032021-04-19 17:01:37275 params.has_user_gesture = has_user_gesture;
276 params.should_clear_history_list = should_clear_history_list;
ajith.v4502cc62014-09-05 17:41:39277
278 if (extra_headers)
279 params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
280
John Abd-El-Maleka59411632018-01-10 20:08:28281 params.post_data = ExtractResourceRequestBodyFromJavaObject(env, j_post_data);
ajith.v4502cc62014-09-05 17:41:39282
283 if (base_url_for_data_url) {
284 params.base_url_for_data_url =
285 GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
286 }
287
288 if (virtual_url_for_data_url) {
289 params.virtual_url_for_data_url =
290 GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
291 }
292
mnaganovbf087422015-12-16 05:10:03293 if (data_url_as_string) {
Daniel Chengef9f4b72017-10-18 08:56:17294 // Treat |data_url_as_string| as if we were intending to put it into a GURL
295 // field. Note that kMaxURLChars is only enforced when serializing URLs
296 // for IPC.
297 GURL data_url = GURL(ConvertJavaStringToUTF8(env, data_url_as_string));
298 DCHECK(data_url.SchemeIs(url::kDataScheme));
mnaganovbf087422015-12-16 05:10:03299 DCHECK(params.url.SchemeIs(url::kDataScheme));
300#if DCHECK_IS_ON()
301 {
302 std::string mime_type, charset, data;
303 DCHECK(net::DataURL::Parse(params.url, &mime_type, &charset, &data));
304 DCHECK(data.empty());
305 }
Daniel Chengef9f4b72017-10-18 08:56:17306#endif
307 std::string s = data_url.spec();
Jongmok Kimc5491082022-10-19 09:17:59308 params.data_url_as_string =
309 base::MakeRefCounted<base::RefCountedString>(std::move(s));
mnaganovbf087422015-12-16 05:10:03310 }
311
ajith.v4502cc62014-09-05 17:41:39312 if (j_referrer_url) {
Lukasz Anforowicza192eb952019-10-15 19:22:22313 params.referrer =
314 Referrer(GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
315 Referrer::ConvertToPolicy(referrer_policy));
ajith.v4502cc62014-09-05 17:41:39316 }
317
Michael Thiessend3c9a032021-04-19 17:01:37318 if (j_initiator_origin) {
319 params.initiator_origin = url::Origin::FromJavaObject(j_initiator_origin);
320 }
321
322 if (input_start != 0)
323 params.input_start = base::TimeTicks::FromUptimeMillis(input_start);
324
Brandon Wyliea20e67ae2022-07-26 22:01:20325 params.navigation_ui_data = std::move(navigation_ui_data);
326
Pete Williamson1d87f4622022-10-18 19:36:43327 base::WeakPtr<NavigationHandle> handle =
328 navigation_controller_->LoadURLWithParams(params);
329
330 if (!handle) {
331 return nullptr;
332 }
333
334 return base::android::ScopedJavaGlobalRef<jobject>(
335 handle->GetJavaNavigationHandle());
ajith.v4502cc62014-09-05 17:41:39336}
337
tornee1bfee92015-12-01 14:05:01338void NavigationControllerAndroid::ClearHistory(
339 JNIEnv* env,
340 const JavaParamRef<jobject>& obj) {
ajith.v4502cc62014-09-05 17:41:39341 // TODO(creis): Do callers of this need to know if it fails?
342 if (navigation_controller_->CanPruneAllButLastCommitted())
343 navigation_controller_->PruneAllButLastCommitted();
344}
345
tornee1bfee92015-12-01 14:05:01346jint NavigationControllerAndroid::GetNavigationHistory(
347 JNIEnv* env,
348 const JavaParamRef<jobject>& obj,
349 const JavaParamRef<jobject>& history) {
ajith.v4502cc62014-09-05 17:41:39350 // Iterate through navigation entries to populate the list
351 int count = navigation_controller_->GetEntryCount();
352 for (int i = 0; i < count; ++i) {
Daniel Bratell7aacf952017-11-21 17:51:25353 JNI_NavigationControllerImpl_AddNavigationEntryToHistory(
dtrainorb316e9272014-09-19 23:30:55354 env, history, navigation_controller_->GetEntryAtIndex(i), i);
ajith.v4502cc62014-09-05 17:41:39355 }
356
357 return navigation_controller_->GetCurrentEntryIndex();
358}
359
360void NavigationControllerAndroid::GetDirectedNavigationHistory(
361 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01362 const JavaParamRef<jobject>& obj,
363 const JavaParamRef<jobject>& history,
ajith.v4502cc62014-09-05 17:41:39364 jboolean is_forward,
365 jint max_entries) {
366 // Iterate through navigation entries to populate the list
367 int count = navigation_controller_->GetEntryCount();
368 int num_added = 0;
369 int increment_value = is_forward ? 1 : -1;
370 for (int i = navigation_controller_->GetCurrentEntryIndex() + increment_value;
Aran Gilman37d11632019-10-08 23:07:15371 i >= 0 && i < count; i += increment_value) {
ajith.v4502cc62014-09-05 17:41:39372 if (num_added >= max_entries)
373 break;
374
Daniel Bratell7aacf952017-11-21 17:51:25375 JNI_NavigationControllerImpl_AddNavigationEntryToHistory(
dtrainorb316e9272014-09-19 23:30:55376 env, history, navigation_controller_->GetEntryAtIndex(i), i);
ajith.v4502cc62014-09-05 17:41:39377 num_added++;
378 }
379}
380
tornee1bfee92015-12-01 14:05:01381void NavigationControllerAndroid::ClearSslPreferences(
382 JNIEnv* env,
383 const JavaParamRef<jobject>& obj) {
Lukasz Anforowicza192eb952019-10-15 19:22:22384 SSLHostStateDelegate* delegate =
ajith.v4502cc62014-09-05 17:41:39385 navigation_controller_->GetBrowserContext()->GetSSLHostStateDelegate();
386 if (delegate)
danakj1606c572019-11-27 22:34:03387 delegate->Clear(base::NullCallback());
ajith.v4502cc62014-09-05 17:41:39388}
389
tornee1bfee92015-12-01 14:05:01390bool NavigationControllerAndroid::GetUseDesktopUserAgent(
391 JNIEnv* env,
392 const JavaParamRef<jobject>& obj) {
Mohamed Abdelhalim676259c2019-06-18 07:27:54393 NavigationEntry* entry = navigation_controller_->GetLastCommittedEntry();
ajith.v4502cc62014-09-05 17:41:39394 return entry && entry->GetIsOverridingUserAgent();
395}
396
397void NavigationControllerAndroid::SetUseDesktopUserAgent(
398 JNIEnv* env,
tornee1bfee92015-12-01 14:05:01399 const JavaParamRef<jobject>& obj,
ajith.v4502cc62014-09-05 17:41:39400 jboolean enabled,
Shu Yanga0b22212022-07-08 16:44:52401 jboolean reload_on_state_change,
402 jint source) {
Rakina Zata Amnid605d462022-06-01 10:17:03403 SCOPED_CRASH_KEY_BOOL("nav_reentrancy_caller2", "SetUA_enabled",
404 (bool)enabled);
ajith.v4502cc62014-09-05 17:41:39405 if (GetUseDesktopUserAgent(env, obj) == enabled)
406 return;
407
Rakina Zata Amni148dcad72022-06-08 14:53:50408 if (navigation_controller_->in_navigate_to_pending_entry() &&
409 reload_on_state_change) {
Shu Yanga0b22212022-07-08 16:44:52410 // Sometimes it's possible to call this function in response to a
Rakina Zata Amni148dcad72022-06-08 14:53:50411 // navigation to a pending entry. In this case, we should avoid triggering
412 // another navigation synchronously, as it will crash due to navigation
413 // re-entrancy checks. To do that, post a task to update the UA and
414 // reload asynchronously.
415 // TODO(https://crbug.com/1327907): Figure out the case that leads to this
416 // situation and avoid calling this function entirely in that case. For now,
417 // do a do a DumpWithoutCrashing so that we can investigate.
418 GetUIThreadTaskRunner({})->PostTask(
419 FROM_HERE,
420 base::BindOnce(
421 &NavigationControllerAndroid::SetUseDesktopUserAgentInternal,
422 weak_factory_.GetWeakPtr(), enabled, reload_on_state_change));
Shu Yanga0b22212022-07-08 16:44:52423 LOG(WARNING) << "NavigationControllerAndroid::SetUseDesktopUserAgent "
424 << "triggers re-entrant navigation, override: "
425 << (bool)enabled << ", source: " << (int)source;
426 SCOPED_CRASH_KEY_NUMBER("SetUseDesktopUserAgent", "caller", (int)source);
Rakina Zata Amni148dcad72022-06-08 14:53:50427 base::debug::DumpWithoutCrashing();
428 } else {
429 SetUseDesktopUserAgentInternal(enabled, reload_on_state_change);
430 }
431}
432
433void NavigationControllerAndroid::SetUseDesktopUserAgentInternal(
434 bool enabled,
435 bool reload_on_state_change) {
ajith.v4502cc62014-09-05 17:41:39436 // Make sure the navigation entry actually exists.
Mohamed Abdelhalim676259c2019-06-18 07:27:54437 NavigationEntry* entry = navigation_controller_->GetLastCommittedEntry();
Shu Yang31063532023-02-19 00:53:14438 // TODO(crbug.com/1414625): Early return for initial NavigationEntries as a
439 // workaround. Currently, doing a reload while on the initial NavigationEntry
440 // might result in committing an unrelated pending NavigationEntry and
441 // mistakenly marking that entry as an initial NavigationEntry. That will
442 // cause problems, such as the URL bar showing about:blank instead of the URL
443 // of the NavigationEntry. To prevent that happening in this case, skip
444 // reloading initial NavigationEntries entirely. This is a short-term fix,
445 // while we work on a long-term fix to no longer mistakenly mark the unrelated
446 // pending NavigationEntry as the initial NavigationEntry.
447 if (!entry || entry->IsInitialEntry()) {
ajith.v4502cc62014-09-05 17:41:39448 return;
Shu Yang31063532023-02-19 00:53:14449 }
ajith.v4502cc62014-09-05 17:41:39450
451 // Set the flag in the NavigationEntry.
452 entry->SetIsOverridingUserAgent(enabled);
aelias5252baa2016-04-10 01:18:02453 navigation_controller_->delegate()->UpdateOverridingUserAgent();
ajith.v4502cc62014-09-05 17:41:39454
455 // Send the override to the renderer.
456 if (reload_on_state_change) {
457 // Reloading the page will send the override down as part of the
458 // navigation IPC message.
yoichio4f7be0c2016-12-20 08:27:10459 navigation_controller_->Reload(ReloadType::ORIGINAL_REQUEST_URL, true);
ajith.v4502cc62014-09-05 17:41:39460 }
461}
462
dtrainorb316e9272014-09-19 23:30:55463base::android::ScopedJavaLocalRef<jobject>
dfalcantaraf5d7ff812015-01-16 22:58:03464NavigationControllerAndroid::GetEntryAtIndex(JNIEnv* env,
tornee1bfee92015-12-01 14:05:01465 const JavaParamRef<jobject>& obj,
dfalcantaraf5d7ff812015-01-16 22:58:03466 int index) {
467 if (index < 0 || index >= navigation_controller_->GetEntryCount())
468 return base::android::ScopedJavaLocalRef<jobject>();
469
Lukasz Anforowicza192eb952019-10-15 19:22:22470 NavigationEntry* entry = navigation_controller_->GetEntryAtIndex(index);
Daniel Bratell7aacf952017-11-21 17:51:25471 return JNI_NavigationControllerImpl_CreateJavaNavigationEntry(env, entry,
472 index);
dfalcantaraf5d7ff812015-01-16 22:58:03473}
474
475base::android::ScopedJavaLocalRef<jobject>
Ted Chocaa84a512019-04-23 19:15:40476NavigationControllerAndroid::GetVisibleEntry(JNIEnv* env,
477 const JavaParamRef<jobject>& obj) {
Lukasz Anforowicza192eb952019-10-15 19:22:22478 NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
Ted Chocaa84a512019-04-23 19:15:40479
480 if (!entry)
481 return base::android::ScopedJavaLocalRef<jobject>();
482
483 return JNI_NavigationControllerImpl_CreateJavaNavigationEntry(env, entry,
484 /*index=*/-1);
485}
486
487base::android::ScopedJavaLocalRef<jobject>
tornee1bfee92015-12-01 14:05:01488NavigationControllerAndroid::GetPendingEntry(JNIEnv* env,
489 const JavaParamRef<jobject>& obj) {
Lukasz Anforowicza192eb952019-10-15 19:22:22490 NavigationEntry* entry = navigation_controller_->GetPendingEntry();
dtrainorb316e9272014-09-19 23:30:55491
492 if (!entry)
493 return base::android::ScopedJavaLocalRef<jobject>();
494
Daniel Bratell7aacf952017-11-21 17:51:25495 return JNI_NavigationControllerImpl_CreateJavaNavigationEntry(
dtrainorb316e9272014-09-19 23:30:55496 env, entry, navigation_controller_->GetPendingEntryIndex());
497}
498
tornee1bfee92015-12-01 14:05:01499jint NavigationControllerAndroid::GetLastCommittedEntryIndex(
500 JNIEnv* env,
501 const JavaParamRef<jobject>& obj) {
jaekyun45bc8c52014-11-03 01:00:21502 return navigation_controller_->GetLastCommittedEntryIndex();
503}
504
tornee1bfee92015-12-01 14:05:01505jboolean NavigationControllerAndroid::RemoveEntryAtIndex(
506 JNIEnv* env,
507 const JavaParamRef<jobject>& obj,
508 jint index) {
jaekyun45bc8c52014-11-03 01:00:21509 return navigation_controller_->RemoveEntryAtIndex(index);
510}
511
Michael Thiessen9b14d512019-09-23 21:19:47512void NavigationControllerAndroid::PruneForwardEntries(
513 JNIEnv* env,
514 const JavaParamRef<jobject>& obj) {
515 return navigation_controller_->PruneForwardEntries();
516}
517
mvanouwerkerk5b1519e2016-09-27 15:47:46518ScopedJavaLocalRef<jstring> NavigationControllerAndroid::GetEntryExtraData(
519 JNIEnv* env,
520 const JavaParamRef<jobject>& obj,
521 jint index,
522 const JavaParamRef<jstring>& jkey) {
523 if (index < 0 || index >= navigation_controller_->GetEntryCount())
524 return ScopedJavaLocalRef<jstring>();
525
526 std::string key = base::android::ConvertJavaStringToUTF8(env, jkey);
Scott Violetf4eec902019-04-04 21:20:34527 MapData* map_data =
528 MapData::Get(navigation_controller_->GetEntryAtIndex(index));
529 auto iter = map_data->map().find(key);
530 return ConvertUTF16ToJavaString(
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58531 env, iter == map_data->map().end() ? std::u16string() : iter->second);
mvanouwerkerk5b1519e2016-09-27 15:47:46532}
533
534void NavigationControllerAndroid::SetEntryExtraData(
535 JNIEnv* env,
536 const JavaParamRef<jobject>& obj,
537 jint index,
538 const JavaParamRef<jstring>& jkey,
539 const JavaParamRef<jstring>& jvalue) {
540 if (index < 0 || index >= navigation_controller_->GetEntryCount())
541 return;
542
543 std::string key = base::android::ConvertJavaStringToUTF8(env, jkey);
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58544 std::u16string value = base::android::ConvertJavaStringToUTF16(env, jvalue);
Scott Violetf4eec902019-04-04 21:20:34545 MapData* map_data =
546 MapData::Get(navigation_controller_->GetEntryAtIndex(index));
547 map_data->map()[key] = value;
mvanouwerkerk5b1519e2016-09-27 15:47:46548}
549
Shivani Sharmaa5637cf2019-02-13 17:20:48550jboolean NavigationControllerAndroid::IsEntryMarkedToBeSkipped(
551 JNIEnv* env,
552 const base::android::JavaParamRef<jobject>& obj,
553 jint index) {
554 return navigation_controller_->IsEntryMarkedToBeSkipped(index);
555}
556
[email protected]155c7f22013-12-09 17:07:18557} // namespace content