1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/android/web_contents_observer_proxy.h"
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "base/android/scoped_java_ref.h"
12 #include "content/browser/renderer_host/render_widget_host_impl.h"
13 #include "content/browser/web_contents/web_contents_impl.h"
14 #include "content/public/browser/navigation_details.h"
15 #include "content/public/browser/navigation_entry.h"
16 #include "jni/WebContentsObserverProxy_jni.h"
18 using base::android::AttachCurrentThread
;
19 using base::android::ScopedJavaLocalRef
;
20 using base::android::ConvertUTF8ToJavaString
;
21 using base::android::ConvertUTF16ToJavaString
;
25 // TODO(dcheng): File a bug. This class incorrectly passes just a frame ID,
26 // which is not sufficient to identify a frame (since frame IDs are scoped per
27 // render process, and so may collide).
28 WebContentsObserverProxy::WebContentsObserverProxy(JNIEnv
* env
,
30 WebContents
* web_contents
)
31 : WebContentsObserver(web_contents
) {
33 java_observer_
.Reset(env
, obj
);
36 WebContentsObserverProxy::~WebContentsObserverProxy() {
39 jlong
Init(JNIEnv
* env
, jobject obj
, jobject java_web_contents
) {
40 WebContents
* web_contents
=
41 WebContents::FromJavaWebContents(java_web_contents
);
44 WebContentsObserverProxy
* native_observer
=
45 new WebContentsObserverProxy(env
, obj
, web_contents
);
46 return reinterpret_cast<intptr_t>(native_observer
);
49 void WebContentsObserverProxy::Destroy(JNIEnv
* env
, jobject obj
) {
53 void WebContentsObserverProxy::WebContentsDestroyed() {
54 JNIEnv
* env
= AttachCurrentThread();
55 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
56 // The java side will destroy |this|
57 Java_WebContentsObserverProxy_destroy(env
, obj
.obj());
60 void WebContentsObserverProxy::RenderViewReady() {
61 JNIEnv
* env
= AttachCurrentThread();
62 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
63 Java_WebContentsObserverProxy_renderViewReady(env
, obj
.obj());
66 void WebContentsObserverProxy::RenderProcessGone(
67 base::TerminationStatus termination_status
) {
68 JNIEnv
* env
= AttachCurrentThread();
69 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
70 jboolean was_oom_protected
=
71 termination_status
== base::TERMINATION_STATUS_OOM_PROTECTED
;
72 Java_WebContentsObserverProxy_renderProcessGone(env
, obj
.obj(),
76 void WebContentsObserverProxy::DidStartLoading() {
77 JNIEnv
* env
= AttachCurrentThread();
78 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
79 ScopedJavaLocalRef
<jstring
> jstring_url(
80 ConvertUTF8ToJavaString(env
, web_contents()->GetVisibleURL().spec()));
81 Java_WebContentsObserverProxy_didStartLoading(env
, obj
.obj(),
85 void WebContentsObserverProxy::DidStopLoading() {
86 JNIEnv
* env
= AttachCurrentThread();
87 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
88 ScopedJavaLocalRef
<jstring
> jstring_url(ConvertUTF8ToJavaString(
89 env
, web_contents()->GetLastCommittedURL().spec()));
90 Java_WebContentsObserverProxy_didStopLoading(env
, obj
.obj(),
94 void WebContentsObserverProxy::DidFailProvisionalLoad(
95 RenderFrameHost
* render_frame_host
,
96 const GURL
& validated_url
,
98 const base::string16
& error_description
,
99 bool was_ignored_by_handler
) {
100 DidFailLoadInternal(true, !render_frame_host
->GetParent(), error_code
,
101 error_description
, validated_url
, was_ignored_by_handler
);
104 void WebContentsObserverProxy::DidFailLoad(
105 RenderFrameHost
* render_frame_host
,
106 const GURL
& validated_url
,
108 const base::string16
& error_description
,
109 bool was_ignored_by_handler
) {
110 DidFailLoadInternal(false, !render_frame_host
->GetParent(), error_code
,
111 error_description
, validated_url
, was_ignored_by_handler
);
114 void WebContentsObserverProxy::DidNavigateMainFrame(
115 const LoadCommittedDetails
& details
,
116 const FrameNavigateParams
& params
) {
117 JNIEnv
* env
= AttachCurrentThread();
118 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
119 ScopedJavaLocalRef
<jstring
> jstring_url(
120 ConvertUTF8ToJavaString(env
, params
.url
.spec()));
121 ScopedJavaLocalRef
<jstring
> jstring_base_url(
122 ConvertUTF8ToJavaString(env
, params
.base_url
.spec()));
124 // See http://crbug.com/251330 for why it's determined this way.
125 url::Replacements
<char> replacements
;
126 replacements
.ClearRef();
127 bool urls_same_ignoring_fragment
=
128 params
.url
.ReplaceComponents(replacements
) ==
129 details
.previous_url
.ReplaceComponents(replacements
);
131 // is_fragment_navigation is indicative of the intent of this variable.
132 // However, there isn't sufficient information here to determine whether this
133 // is actually a fragment navigation, or a history API navigation to a URL
134 // that would also be valid for a fragment navigation.
135 bool is_fragment_navigation
=
136 urls_same_ignoring_fragment
&& details
.is_in_page
;
137 Java_WebContentsObserverProxy_didNavigateMainFrame(
138 env
, obj
.obj(), jstring_url
.obj(), jstring_base_url
.obj(),
139 details
.is_navigation_to_different_page(), is_fragment_navigation
,
140 details
.http_status_code
);
143 void WebContentsObserverProxy::DidNavigateAnyFrame(
144 RenderFrameHost
* render_frame_host
,
145 const LoadCommittedDetails
& details
,
146 const FrameNavigateParams
& params
) {
147 JNIEnv
* env
= AttachCurrentThread();
148 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
149 ScopedJavaLocalRef
<jstring
> jstring_url(
150 ConvertUTF8ToJavaString(env
, params
.url
.spec()));
151 ScopedJavaLocalRef
<jstring
> jstring_base_url(
152 ConvertUTF8ToJavaString(env
, params
.base_url
.spec()));
153 jboolean jboolean_is_reload
= ui::PageTransitionCoreTypeIs(
154 params
.transition
, ui::PAGE_TRANSITION_RELOAD
);
156 Java_WebContentsObserverProxy_didNavigateAnyFrame(
157 env
, obj
.obj(), jstring_url
.obj(), jstring_base_url
.obj(),
161 void WebContentsObserverProxy::DocumentAvailableInMainFrame() {
162 JNIEnv
* env
= AttachCurrentThread();
163 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
164 Java_WebContentsObserverProxy_documentAvailableInMainFrame(env
, obj
.obj());
167 void WebContentsObserverProxy::DidStartProvisionalLoadForFrame(
168 RenderFrameHost
* render_frame_host
,
169 const GURL
& validated_url
,
171 bool is_iframe_srcdoc
) {
172 JNIEnv
* env
= AttachCurrentThread();
173 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
174 ScopedJavaLocalRef
<jstring
> jstring_url(
175 ConvertUTF8ToJavaString(env
, validated_url
.spec()));
176 // TODO(dcheng): Does Java really need the parent frame ID? It doesn't appear
177 // to be used at all, and it just adds complexity here.
178 Java_WebContentsObserverProxy_didStartProvisionalLoadForFrame(
179 env
, obj
.obj(), render_frame_host
->GetRoutingID(),
180 render_frame_host
->GetParent()
181 ? render_frame_host
->GetParent()->GetRoutingID()
183 !render_frame_host
->GetParent(), jstring_url
.obj(), is_error_page
,
187 void WebContentsObserverProxy::DidCommitProvisionalLoadForFrame(
188 RenderFrameHost
* render_frame_host
,
190 ui::PageTransition transition_type
) {
191 JNIEnv
* env
= AttachCurrentThread();
192 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
193 ScopedJavaLocalRef
<jstring
> jstring_url(
194 ConvertUTF8ToJavaString(env
, url
.spec()));
195 Java_WebContentsObserverProxy_didCommitProvisionalLoadForFrame(
196 env
, obj
.obj(), render_frame_host
->GetRoutingID(),
197 !render_frame_host
->GetParent(), jstring_url
.obj(), transition_type
);
200 void WebContentsObserverProxy::DidFinishLoad(RenderFrameHost
* render_frame_host
,
201 const GURL
& validated_url
) {
202 JNIEnv
* env
= AttachCurrentThread();
203 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
205 std::string url_string
= validated_url
.spec();
206 NavigationEntry
* entry
=
207 web_contents()->GetController().GetLastCommittedEntry();
208 // Note that GetBaseURLForDataURL is only used by the Android WebView.
209 if (entry
&& !entry
->GetBaseURLForDataURL().is_empty())
210 url_string
= entry
->GetBaseURLForDataURL().possibly_invalid_spec();
212 ScopedJavaLocalRef
<jstring
> jstring_url(
213 ConvertUTF8ToJavaString(env
, url_string
));
214 Java_WebContentsObserverProxy_didFinishLoad(
215 env
, obj
.obj(), render_frame_host
->GetRoutingID(), jstring_url
.obj(),
216 !render_frame_host
->GetParent());
219 void WebContentsObserverProxy::DocumentLoadedInFrame(
220 RenderFrameHost
* render_frame_host
) {
221 JNIEnv
* env
= AttachCurrentThread();
222 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
223 Java_WebContentsObserverProxy_documentLoadedInFrame(
224 env
, obj
.obj(), render_frame_host
->GetRoutingID());
227 void WebContentsObserverProxy::NavigationEntryCommitted(
228 const LoadCommittedDetails
& load_details
) {
229 JNIEnv
* env
= AttachCurrentThread();
230 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
231 Java_WebContentsObserverProxy_navigationEntryCommitted(env
, obj
.obj());
234 void WebContentsObserverProxy::DidAttachInterstitialPage() {
235 JNIEnv
* env
= AttachCurrentThread();
236 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
237 Java_WebContentsObserverProxy_didAttachInterstitialPage(env
, obj
.obj());
240 void WebContentsObserverProxy::DidDetachInterstitialPage() {
241 JNIEnv
* env
= AttachCurrentThread();
242 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
243 Java_WebContentsObserverProxy_didDetachInterstitialPage(env
, obj
.obj());
246 void WebContentsObserverProxy::DidChangeThemeColor(SkColor color
) {
247 JNIEnv
* env
= AttachCurrentThread();
248 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
249 Java_WebContentsObserverProxy_didChangeThemeColor(env
, obj
.obj(), color
);
252 void WebContentsObserverProxy::DidFailLoadInternal(
253 bool is_provisional_load
,
256 const base::string16
& description
,
258 bool was_ignored_by_handler
) {
259 JNIEnv
* env
= AttachCurrentThread();
260 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
261 ScopedJavaLocalRef
<jstring
> jstring_error_description(
262 ConvertUTF16ToJavaString(env
, description
));
263 ScopedJavaLocalRef
<jstring
> jstring_url(
264 ConvertUTF8ToJavaString(env
, url
.spec()));
266 Java_WebContentsObserverProxy_didFailLoad(
267 env
, obj
.obj(), is_provisional_load
, is_main_frame
, error_code
,
268 jstring_error_description
.obj(), jstring_url
.obj(),
269 was_ignored_by_handler
);
272 void WebContentsObserverProxy::DidFirstVisuallyNonEmptyPaint() {
273 JNIEnv
* env
= AttachCurrentThread();
274 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
275 Java_WebContentsObserverProxy_didFirstVisuallyNonEmptyPaint(env
, obj
.obj());
278 void WebContentsObserverProxy::DidStartNavigationToPendingEntry(
280 NavigationController::ReloadType reload_type
) {
281 JNIEnv
* env
= AttachCurrentThread();
282 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
283 ScopedJavaLocalRef
<jstring
> jstring_url(
284 ConvertUTF8ToJavaString(env
, url
.spec()));
286 Java_WebContentsObserverProxy_didStartNavigationToPendingEntry(
287 env
, obj
.obj(), jstring_url
.obj());
290 void WebContentsObserverProxy::MediaSessionStateChanged(bool is_controllable
,
292 JNIEnv
* env
= AttachCurrentThread();
294 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
296 Java_WebContentsObserverProxy_mediaSessionStateChanged(
297 env
, obj
.obj(), is_controllable
, is_suspended
);
300 bool RegisterWebContentsObserverProxy(JNIEnv
* env
) {
301 return RegisterNativesImpl(env
);
303 } // namespace content