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
,
40 const JavaParamRef
<jobject
>& obj
,
41 const JavaParamRef
<jobject
>& java_web_contents
) {
42 WebContents
* web_contents
=
43 WebContents::FromJavaWebContents(java_web_contents
);
46 WebContentsObserverProxy
* native_observer
=
47 new WebContentsObserverProxy(env
, obj
, web_contents
);
48 return reinterpret_cast<intptr_t>(native_observer
);
51 void WebContentsObserverProxy::Destroy(JNIEnv
* env
, jobject obj
) {
55 void WebContentsObserverProxy::WebContentsDestroyed() {
56 JNIEnv
* env
= AttachCurrentThread();
57 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
58 // The java side will destroy |this|
59 Java_WebContentsObserverProxy_destroy(env
, obj
.obj());
62 void WebContentsObserverProxy::RenderViewReady() {
63 JNIEnv
* env
= AttachCurrentThread();
64 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
65 Java_WebContentsObserverProxy_renderViewReady(env
, obj
.obj());
68 void WebContentsObserverProxy::RenderProcessGone(
69 base::TerminationStatus termination_status
) {
70 JNIEnv
* env
= AttachCurrentThread();
71 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
72 jboolean was_oom_protected
=
73 termination_status
== base::TERMINATION_STATUS_OOM_PROTECTED
;
74 Java_WebContentsObserverProxy_renderProcessGone(env
, obj
.obj(),
78 void WebContentsObserverProxy::DidStartLoading() {
79 JNIEnv
* env
= AttachCurrentThread();
80 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
81 ScopedJavaLocalRef
<jstring
> jstring_url(
82 ConvertUTF8ToJavaString(env
, web_contents()->GetVisibleURL().spec()));
83 Java_WebContentsObserverProxy_didStartLoading(env
, obj
.obj(),
87 void WebContentsObserverProxy::DidStopLoading() {
88 JNIEnv
* env
= AttachCurrentThread();
89 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
90 ScopedJavaLocalRef
<jstring
> jstring_url(ConvertUTF8ToJavaString(
91 env
, web_contents()->GetLastCommittedURL().spec()));
92 Java_WebContentsObserverProxy_didStopLoading(env
, obj
.obj(),
96 void WebContentsObserverProxy::DidFailProvisionalLoad(
97 RenderFrameHost
* render_frame_host
,
98 const GURL
& validated_url
,
100 const base::string16
& error_description
,
101 bool was_ignored_by_handler
) {
102 DidFailLoadInternal(true, !render_frame_host
->GetParent(), error_code
,
103 error_description
, validated_url
, was_ignored_by_handler
);
106 void WebContentsObserverProxy::DidFailLoad(
107 RenderFrameHost
* render_frame_host
,
108 const GURL
& validated_url
,
110 const base::string16
& error_description
,
111 bool was_ignored_by_handler
) {
112 DidFailLoadInternal(false, !render_frame_host
->GetParent(), error_code
,
113 error_description
, validated_url
, was_ignored_by_handler
);
116 void WebContentsObserverProxy::DidNavigateMainFrame(
117 const LoadCommittedDetails
& details
,
118 const FrameNavigateParams
& params
) {
119 JNIEnv
* env
= AttachCurrentThread();
120 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
121 ScopedJavaLocalRef
<jstring
> jstring_url(
122 ConvertUTF8ToJavaString(env
, params
.url
.spec()));
123 ScopedJavaLocalRef
<jstring
> jstring_base_url(
124 ConvertUTF8ToJavaString(env
, params
.base_url
.spec()));
126 // See http://crbug.com/251330 for why it's determined this way.
127 url::Replacements
<char> replacements
;
128 replacements
.ClearRef();
129 bool urls_same_ignoring_fragment
=
130 params
.url
.ReplaceComponents(replacements
) ==
131 details
.previous_url
.ReplaceComponents(replacements
);
133 // is_fragment_navigation is indicative of the intent of this variable.
134 // However, there isn't sufficient information here to determine whether this
135 // is actually a fragment navigation, or a history API navigation to a URL
136 // that would also be valid for a fragment navigation.
137 bool is_fragment_navigation
=
138 urls_same_ignoring_fragment
&& details
.is_in_page
;
139 Java_WebContentsObserverProxy_didNavigateMainFrame(
140 env
, obj
.obj(), jstring_url
.obj(), jstring_base_url
.obj(),
141 details
.is_navigation_to_different_page(), is_fragment_navigation
,
142 details
.http_status_code
);
145 void WebContentsObserverProxy::DidNavigateAnyFrame(
146 RenderFrameHost
* render_frame_host
,
147 const LoadCommittedDetails
& details
,
148 const FrameNavigateParams
& params
) {
149 JNIEnv
* env
= AttachCurrentThread();
150 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
151 ScopedJavaLocalRef
<jstring
> jstring_url(
152 ConvertUTF8ToJavaString(env
, params
.url
.spec()));
153 ScopedJavaLocalRef
<jstring
> jstring_base_url(
154 ConvertUTF8ToJavaString(env
, params
.base_url
.spec()));
155 jboolean jboolean_is_reload
= ui::PageTransitionCoreTypeIs(
156 params
.transition
, ui::PAGE_TRANSITION_RELOAD
);
158 Java_WebContentsObserverProxy_didNavigateAnyFrame(
159 env
, obj
.obj(), jstring_url
.obj(), jstring_base_url
.obj(),
163 void WebContentsObserverProxy::DocumentAvailableInMainFrame() {
164 JNIEnv
* env
= AttachCurrentThread();
165 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
166 Java_WebContentsObserverProxy_documentAvailableInMainFrame(env
, obj
.obj());
169 void WebContentsObserverProxy::DidStartProvisionalLoadForFrame(
170 RenderFrameHost
* render_frame_host
,
171 const GURL
& validated_url
,
173 bool is_iframe_srcdoc
) {
174 JNIEnv
* env
= AttachCurrentThread();
175 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
176 ScopedJavaLocalRef
<jstring
> jstring_url(
177 ConvertUTF8ToJavaString(env
, validated_url
.spec()));
178 // TODO(dcheng): Does Java really need the parent frame ID? It doesn't appear
179 // to be used at all, and it just adds complexity here.
180 Java_WebContentsObserverProxy_didStartProvisionalLoadForFrame(
181 env
, obj
.obj(), render_frame_host
->GetRoutingID(),
182 render_frame_host
->GetParent()
183 ? render_frame_host
->GetParent()->GetRoutingID()
185 !render_frame_host
->GetParent(), jstring_url
.obj(), is_error_page
,
189 void WebContentsObserverProxy::DidCommitProvisionalLoadForFrame(
190 RenderFrameHost
* render_frame_host
,
192 ui::PageTransition transition_type
) {
193 JNIEnv
* env
= AttachCurrentThread();
194 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
195 ScopedJavaLocalRef
<jstring
> jstring_url(
196 ConvertUTF8ToJavaString(env
, url
.spec()));
197 Java_WebContentsObserverProxy_didCommitProvisionalLoadForFrame(
198 env
, obj
.obj(), render_frame_host
->GetRoutingID(),
199 !render_frame_host
->GetParent(), jstring_url
.obj(), transition_type
);
202 void WebContentsObserverProxy::DidFinishLoad(RenderFrameHost
* render_frame_host
,
203 const GURL
& validated_url
) {
204 JNIEnv
* env
= AttachCurrentThread();
205 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
207 std::string url_string
= validated_url
.spec();
208 NavigationEntry
* entry
=
209 web_contents()->GetController().GetLastCommittedEntry();
210 // Note that GetBaseURLForDataURL is only used by the Android WebView.
211 if (entry
&& !entry
->GetBaseURLForDataURL().is_empty())
212 url_string
= entry
->GetBaseURLForDataURL().possibly_invalid_spec();
214 ScopedJavaLocalRef
<jstring
> jstring_url(
215 ConvertUTF8ToJavaString(env
, url_string
));
216 Java_WebContentsObserverProxy_didFinishLoad(
217 env
, obj
.obj(), render_frame_host
->GetRoutingID(), jstring_url
.obj(),
218 !render_frame_host
->GetParent());
221 void WebContentsObserverProxy::DocumentLoadedInFrame(
222 RenderFrameHost
* render_frame_host
) {
223 JNIEnv
* env
= AttachCurrentThread();
224 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
225 Java_WebContentsObserverProxy_documentLoadedInFrame(
226 env
, obj
.obj(), render_frame_host
->GetRoutingID(),
227 !render_frame_host
->GetParent());
230 void WebContentsObserverProxy::NavigationEntryCommitted(
231 const LoadCommittedDetails
& load_details
) {
232 JNIEnv
* env
= AttachCurrentThread();
233 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
234 Java_WebContentsObserverProxy_navigationEntryCommitted(env
, obj
.obj());
237 void WebContentsObserverProxy::DidAttachInterstitialPage() {
238 JNIEnv
* env
= AttachCurrentThread();
239 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
240 Java_WebContentsObserverProxy_didAttachInterstitialPage(env
, obj
.obj());
243 void WebContentsObserverProxy::DidDetachInterstitialPage() {
244 JNIEnv
* env
= AttachCurrentThread();
245 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
246 Java_WebContentsObserverProxy_didDetachInterstitialPage(env
, obj
.obj());
249 void WebContentsObserverProxy::DidChangeThemeColor(SkColor color
) {
250 JNIEnv
* env
= AttachCurrentThread();
251 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
252 Java_WebContentsObserverProxy_didChangeThemeColor(env
, obj
.obj(), color
);
255 void WebContentsObserverProxy::DidFailLoadInternal(
256 bool is_provisional_load
,
259 const base::string16
& description
,
261 bool was_ignored_by_handler
) {
262 JNIEnv
* env
= AttachCurrentThread();
263 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
264 ScopedJavaLocalRef
<jstring
> jstring_error_description(
265 ConvertUTF16ToJavaString(env
, description
));
266 ScopedJavaLocalRef
<jstring
> jstring_url(
267 ConvertUTF8ToJavaString(env
, url
.spec()));
269 Java_WebContentsObserverProxy_didFailLoad(
270 env
, obj
.obj(), is_provisional_load
, is_main_frame
, error_code
,
271 jstring_error_description
.obj(), jstring_url
.obj(),
272 was_ignored_by_handler
);
275 void WebContentsObserverProxy::DidFirstVisuallyNonEmptyPaint() {
276 JNIEnv
* env
= AttachCurrentThread();
277 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
278 Java_WebContentsObserverProxy_didFirstVisuallyNonEmptyPaint(env
, obj
.obj());
281 void WebContentsObserverProxy::DidStartNavigationToPendingEntry(
283 NavigationController::ReloadType reload_type
) {
284 JNIEnv
* env
= AttachCurrentThread();
285 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
286 ScopedJavaLocalRef
<jstring
> jstring_url(
287 ConvertUTF8ToJavaString(env
, url
.spec()));
289 Java_WebContentsObserverProxy_didStartNavigationToPendingEntry(
290 env
, obj
.obj(), jstring_url
.obj());
293 void WebContentsObserverProxy::MediaSessionStateChanged(bool is_controllable
,
295 JNIEnv
* env
= AttachCurrentThread();
297 ScopedJavaLocalRef
<jobject
> obj(java_observer_
);
299 Java_WebContentsObserverProxy_mediaSessionStateChanged(
300 env
, obj
.obj(), is_controllable
, is_suspended
);
303 bool RegisterWebContentsObserverProxy(JNIEnv
* env
) {
304 return RegisterNativesImpl(env
);
306 } // namespace content