blob: a96a9dd06c79ee11f8bc0579bd912649a08745ed [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2017 The Chromium Authors
Jinsuk Kima6490f82018-01-02 02:16:142// 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/android/javascript_injector.h"
6
Rupert Ben Wiserb7d1894f2025-04-02 19:13:157#include <vector>
8
Jinsuk Kima6490f82018-01-02 02:16:149#include "base/android/jni_string.h"
Gabriel Charette9f60dd12020-03-06 20:48:0410#include "base/memory/ptr_util.h"
Rupert Ben Wiser36b4404d2025-06-05 16:15:1911#include "components/origin_matcher/origin_matcher.h"
Jinsuk Kima6490f82018-01-02 02:16:1412#include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
Hiroki Nakagawac1e58012024-05-07 23:43:4113#include "content/browser/preloading/prerender/prerender_final_status.h"
14#include "content/browser/preloading/prerender/prerender_host_registry.h"
15#include "content/browser/web_contents/web_contents_impl.h"
Andrew Grieveecb885bb2024-05-29 18:14:1916
17// Must come after all headers that specialize FromJniType() / ToJniType().
Mohamed Heikalc09e1012019-06-21 14:47:2618#include "content/public/android/content_jni_headers/JavascriptInjectorImpl_jni.h"
Jinsuk Kima6490f82018-01-02 02:16:1419
20using base::android::AttachCurrentThread;
21using base::android::ConvertJavaStringToUTF8;
22using base::android::JavaParamRef;
23using base::android::ScopedJavaLocalRef;
24
25namespace content {
26
Jinsuk Kima6490f82018-01-02 02:16:1427JavascriptInjector::JavascriptInjector(
28 JNIEnv* env,
29 const base::android::JavaParamRef<jobject>& obj,
30 const base::android::JavaParamRef<jobject>& retained_objects,
31 WebContents* web_contents)
Dave Tapuskade1f720b2021-11-17 15:13:1032 : WebContentsUserData<JavascriptInjector>(*web_contents),
33 java_ref_(env, obj) {
Jinsuk Kima6490f82018-01-02 02:16:1434 java_bridge_dispatcher_host_ =
35 new GinJavaBridgeDispatcherHost(web_contents, retained_objects);
Jinsuk Kime376d0d2018-01-02 23:23:2136 web_contents->SetUserData(UserDataKey(), base::WrapUnique(this));
Jinsuk Kima6490f82018-01-02 02:16:1437}
38
39JavascriptInjector::~JavascriptInjector() {
40 JNIEnv* env = AttachCurrentThread();
41 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
42 if (j_obj.is_null())
43 return;
44 Java_JavascriptInjectorImpl_onDestroy(env, j_obj);
45}
46
47void JavascriptInjector::SetAllowInspection(JNIEnv* env,
Jinsuk Kima6490f82018-01-02 02:16:1448 jboolean allow) {
49 DCHECK(java_bridge_dispatcher_host_);
50 java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
51}
52
Rupert Ben Wiser36b4404d2025-06-05 16:15:1953void JavascriptInjector::AddInterface(
Jinsuk Kima6490f82018-01-02 02:16:1454 JNIEnv* env,
Jinsuk Kima6490f82018-01-02 02:16:1455 const JavaParamRef<jobject>& object,
56 const JavaParamRef<jstring>& name,
Rupert Ben Wiserb7d1894f2025-04-02 19:13:1557 const JavaParamRef<jclass>& safe_annotation_clazz,
Rupert Ben Wiser36b4404d2025-06-05 16:15:1958 origin_matcher::OriginMatcher matcher) {
Jinsuk Kima6490f82018-01-02 02:16:1459 DCHECK(java_bridge_dispatcher_host_);
Hiroki Nakagawac1e58012024-05-07 23:43:4160
Hiroki Nakagawac1e58012024-05-07 23:43:4161 // If a new js object is added or removed when a page is in BFCache or
62 // prerendered, the change won't apply after activating the page. To avoid
63 // this behavior difference when these features are involved vs not,
64 // evict all BFCached and prerendered pages so that we won't activate any
65 // pages that don't have this object modified.
Jiacheng Guo7117d5c9b2024-04-17 23:37:3166 // Same for RemoveInterface below.
Jiacheng Guo44cb9122024-06-07 14:56:4367 GetWebContents().GetController().GetBackForwardCache().Flush(
68 content::BackForwardCache::NotRestoredReason::
69 kWebViewJavaScriptObjectChanged);
Hiroki Nakagawac1e58012024-05-07 23:43:4170 GetWebContentsImpl().GetPrerenderHostRegistry()->CancelAllHosts(
71 PrerenderFinalStatus::kJavaScriptInterfaceAdded);
72
Jinsuk Kima6490f82018-01-02 02:16:1473 java_bridge_dispatcher_host_->AddNamedObject(
Rupert Ben Wiserb7d1894f2025-04-02 19:13:1574 ConvertJavaStringToUTF8(env, name), object, safe_annotation_clazz,
75 std::move(matcher));
Jinsuk Kima6490f82018-01-02 02:16:1476}
77
78void JavascriptInjector::RemoveInterface(JNIEnv* env,
Jinsuk Kima6490f82018-01-02 02:16:1479 const JavaParamRef<jstring>& name) {
80 DCHECK(java_bridge_dispatcher_host_);
Hiroki Nakagawac1e58012024-05-07 23:43:4181
Jiacheng Guo44cb9122024-06-07 14:56:4382 GetWebContents().GetController().GetBackForwardCache().Flush(
83 content::BackForwardCache::NotRestoredReason::
84 kWebViewJavaScriptObjectChanged);
Hiroki Nakagawac1e58012024-05-07 23:43:4185 GetWebContentsImpl().GetPrerenderHostRegistry()->CancelAllHosts(
86 PrerenderFinalStatus::kJavaScriptInterfaceRemoved);
87
Jinsuk Kima6490f82018-01-02 02:16:1488 java_bridge_dispatcher_host_->RemoveNamedObject(
89 ConvertJavaStringToUTF8(env, name));
90}
91
Hiroki Nakagawac1e58012024-05-07 23:43:4192WebContentsImpl& JavascriptInjector::GetWebContentsImpl() {
93 return static_cast<WebContentsImpl&>(GetWebContents());
94}
95
Jinsuk Kima6490f82018-01-02 02:16:1496jlong JNI_JavascriptInjectorImpl_Init(
97 JNIEnv* env,
98 const JavaParamRef<jobject>& obj,
99 const JavaParamRef<jobject>& jweb_contents,
100 const JavaParamRef<jobject>& retained_objects) {
101 auto* web_contents = WebContents::FromJavaWebContents(jweb_contents);
102 CHECK(web_contents) << "Should be created with a valid WebContents.";
103 DCHECK(!JavascriptInjector::FromWebContents(web_contents));
104
105 // Owned by |web_contents|.
106 auto* injector =
107 new JavascriptInjector(env, obj, retained_objects, web_contents);
108 return reinterpret_cast<intptr_t>(injector);
109}
110
Daniel Cheng383df852021-10-02 03:28:01111WEB_CONTENTS_USER_DATA_KEY_IMPL(JavascriptInjector);
François Doray4f51d5d2018-12-03 22:26:24112
Jinsuk Kima6490f82018-01-02 02:16:14113} // namespace content