Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / android / web_contents_observer_android.cc
blob8b2fdd35df8af2d0439d259ced67cdc8eca15346
1 // Copyright (c) 2012 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_android.h"
7 #include <string>
9 #include <jni.h>
11 #include "base/android/jni_android.h"
12 #include "base/android/jni_string.h"
13 #include "base/android/scoped_java_ref.h"
14 #include "content/browser/renderer_host/render_widget_host_impl.h"
15 #include "content/browser/web_contents/web_contents_impl.h"
16 #include "content/public/browser/navigation_details.h"
17 #include "content/public/browser/navigation_entry.h"
18 #include "jni/WebContentsObserver_jni.h"
20 using base::android::AttachCurrentThread;
21 using base::android::ScopedJavaLocalRef;
22 using base::android::ConvertUTF8ToJavaString;
23 using base::android::ConvertUTF16ToJavaString;
25 namespace content {
27 // TODO(dcheng): File a bug. This class incorrectly passes just a frame ID,
28 // which is not sufficient to identify a frame (since frame IDs are scoped per
29 // render process, and so may collide).
30 WebContentsObserverAndroid::WebContentsObserverAndroid(
31 JNIEnv* env,
32 jobject obj,
33 WebContents* web_contents)
34 : WebContentsObserver(web_contents),
35 weak_java_observer_(env, obj){
38 WebContentsObserverAndroid::~WebContentsObserverAndroid() {
41 jlong Init(JNIEnv* env, jobject obj, jobject java_web_contents) {
42 WebContents* web_contents =
43 WebContents::FromJavaWebContents(java_web_contents);
44 CHECK(web_contents);
46 WebContentsObserverAndroid* native_observer = new WebContentsObserverAndroid(
47 env, obj, web_contents);
48 return reinterpret_cast<intptr_t>(native_observer);
51 void WebContentsObserverAndroid::Destroy(JNIEnv* env, jobject obj) {
52 delete this;
55 void WebContentsObserverAndroid::WebContentsDestroyed() {
56 JNIEnv* env = AttachCurrentThread();
57 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
58 if (obj.is_null()) {
59 delete this;
60 } else {
61 // The java side will destroy |this|
62 Java_WebContentsObserver_detachFromWebContents(env, obj.obj());
66 void WebContentsObserverAndroid::RenderViewReady() {
67 JNIEnv* env = AttachCurrentThread();
68 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
69 if (obj.is_null())
70 return;
71 Java_WebContentsObserver_renderViewReady(env, obj.obj());
74 void WebContentsObserverAndroid::RenderProcessGone(
75 base::TerminationStatus termination_status) {
76 JNIEnv* env = AttachCurrentThread();
77 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
78 if (obj.is_null())
79 return;
80 jboolean was_oom_protected =
81 termination_status == base::TERMINATION_STATUS_OOM_PROTECTED;
82 Java_WebContentsObserver_renderProcessGone(
83 env, obj.obj(), was_oom_protected);
86 void WebContentsObserverAndroid::DidStartLoading(
87 RenderViewHost* render_view_host) {
88 JNIEnv* env = AttachCurrentThread();
89 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
90 if (obj.is_null())
91 return;
92 ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString(
93 env, web_contents()->GetVisibleURL().spec()));
94 Java_WebContentsObserver_didStartLoading(
95 env, obj.obj(), jstring_url.obj());
98 void WebContentsObserverAndroid::DidStopLoading(
99 RenderViewHost* render_view_host) {
100 JNIEnv* env = AttachCurrentThread();
101 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
102 if (obj.is_null())
103 return;
104 ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString(
105 env, web_contents()->GetLastCommittedURL().spec()));
106 Java_WebContentsObserver_didStopLoading(
107 env, obj.obj(), jstring_url.obj());
110 void WebContentsObserverAndroid::DidFailProvisionalLoad(
111 RenderFrameHost* render_frame_host,
112 const GURL& validated_url,
113 int error_code,
114 const base::string16& error_description) {
115 DidFailLoadInternal(true,
116 !render_frame_host->GetParent(),
117 error_code,
118 error_description,
119 validated_url);
122 void WebContentsObserverAndroid::DidFailLoad(
123 RenderFrameHost* render_frame_host,
124 const GURL& validated_url,
125 int error_code,
126 const base::string16& error_description) {
127 DidFailLoadInternal(false,
128 !render_frame_host->GetParent(),
129 error_code,
130 error_description,
131 validated_url);
134 void WebContentsObserverAndroid::DidNavigateMainFrame(
135 const LoadCommittedDetails& details,
136 const FrameNavigateParams& params) {
137 JNIEnv* env = AttachCurrentThread();
138 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
139 if (obj.is_null())
140 return;
141 ScopedJavaLocalRef<jstring> jstring_url(
142 ConvertUTF8ToJavaString(env, params.url.spec()));
143 ScopedJavaLocalRef<jstring> jstring_base_url(
144 ConvertUTF8ToJavaString(env, params.base_url.spec()));
146 // See http://crbug.com/251330 for why it's determined this way.
147 url::Replacements<char> replacements;
148 replacements.ClearRef();
149 bool urls_same_ignoring_fragment =
150 params.url.ReplaceComponents(replacements) ==
151 details.previous_url.ReplaceComponents(replacements);
153 // is_fragment_navigation is indicative of the intent of this variable.
154 // However, there isn't sufficient information here to determine whether this
155 // is actually a fragment navigation, or a history API navigation to a URL
156 // that would also be valid for a fragment navigation.
157 bool is_fragment_navigation = urls_same_ignoring_fragment &&
158 (details.type == NAVIGATION_TYPE_IN_PAGE || details.is_in_page);
159 Java_WebContentsObserver_didNavigateMainFrame(
160 env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
161 details.is_navigation_to_different_page(), is_fragment_navigation,
162 details.http_status_code);
165 void WebContentsObserverAndroid::DidNavigateAnyFrame(
166 RenderFrameHost* render_frame_host,
167 const LoadCommittedDetails& details,
168 const FrameNavigateParams& params) {
169 JNIEnv* env = AttachCurrentThread();
170 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
171 if (obj.is_null())
172 return;
173 ScopedJavaLocalRef<jstring> jstring_url(
174 ConvertUTF8ToJavaString(env, params.url.spec()));
175 ScopedJavaLocalRef<jstring> jstring_base_url(
176 ConvertUTF8ToJavaString(env, params.base_url.spec()));
177 jboolean jboolean_is_reload = ui::PageTransitionCoreTypeIs(
178 params.transition, ui::PAGE_TRANSITION_RELOAD);
180 Java_WebContentsObserver_didNavigateAnyFrame(
181 env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
182 jboolean_is_reload);
185 void WebContentsObserverAndroid::DocumentAvailableInMainFrame() {
186 JNIEnv* env = AttachCurrentThread();
187 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
188 if (obj.is_null())
189 return;
190 Java_WebContentsObserver_documentAvailableInMainFrame(env, obj.obj());
193 void WebContentsObserverAndroid::DidStartProvisionalLoadForFrame(
194 RenderFrameHost* render_frame_host,
195 const GURL& validated_url,
196 bool is_error_page,
197 bool is_iframe_srcdoc) {
198 JNIEnv* env = AttachCurrentThread();
199 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
200 if (obj.is_null())
201 return;
202 ScopedJavaLocalRef<jstring> jstring_url(
203 ConvertUTF8ToJavaString(env, validated_url.spec()));
204 // TODO(dcheng): Does Java really need the parent frame ID? It doesn't appear
205 // to be used at all, and it just adds complexity here.
206 Java_WebContentsObserver_didStartProvisionalLoadForFrame(
207 env,
208 obj.obj(),
209 render_frame_host->GetRoutingID(),
210 render_frame_host->GetParent()
211 ? render_frame_host->GetParent()->GetRoutingID()
212 : -1,
213 !render_frame_host->GetParent(),
214 jstring_url.obj(),
215 is_error_page,
216 is_iframe_srcdoc);
219 void WebContentsObserverAndroid::DidCommitProvisionalLoadForFrame(
220 RenderFrameHost* render_frame_host,
221 const GURL& url,
222 ui::PageTransition transition_type) {
223 JNIEnv* env = AttachCurrentThread();
224 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
225 if (obj.is_null())
226 return;
227 ScopedJavaLocalRef<jstring> jstring_url(
228 ConvertUTF8ToJavaString(env, url.spec()));
229 Java_WebContentsObserver_didCommitProvisionalLoadForFrame(
230 env,
231 obj.obj(),
232 render_frame_host->GetRoutingID(),
233 !render_frame_host->GetParent(),
234 jstring_url.obj(),
235 transition_type);
238 void WebContentsObserverAndroid::DidFinishLoad(
239 RenderFrameHost* render_frame_host,
240 const GURL& validated_url) {
241 JNIEnv* env = AttachCurrentThread();
242 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
243 if (obj.is_null())
244 return;
246 std::string url_string = validated_url.spec();
247 NavigationEntry* entry =
248 web_contents()->GetController().GetLastCommittedEntry();
249 // Note that GetBaseURLForDataURL is only used by the Android WebView.
250 if (entry && !entry->GetBaseURLForDataURL().is_empty())
251 url_string = entry->GetBaseURLForDataURL().possibly_invalid_spec();
253 ScopedJavaLocalRef<jstring> jstring_url(
254 ConvertUTF8ToJavaString(env, url_string));
255 Java_WebContentsObserver_didFinishLoad(
256 env,
257 obj.obj(),
258 render_frame_host->GetRoutingID(),
259 jstring_url.obj(),
260 !render_frame_host->GetParent());
263 void WebContentsObserverAndroid::DocumentLoadedInFrame(
264 RenderFrameHost* render_frame_host) {
265 JNIEnv* env = AttachCurrentThread();
266 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
267 if (obj.is_null())
268 return;
269 Java_WebContentsObserver_documentLoadedInFrame(
270 env, obj.obj(), render_frame_host->GetRoutingID());
273 void WebContentsObserverAndroid::NavigationEntryCommitted(
274 const LoadCommittedDetails& load_details) {
275 JNIEnv* env = AttachCurrentThread();
276 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
277 if (obj.is_null())
278 return;
279 Java_WebContentsObserver_navigationEntryCommitted(env, obj.obj());
282 void WebContentsObserverAndroid::DidAttachInterstitialPage() {
283 JNIEnv* env = AttachCurrentThread();
284 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
285 if (obj.is_null())
286 return;
287 Java_WebContentsObserver_didAttachInterstitialPage(env, obj.obj());
290 void WebContentsObserverAndroid::DidDetachInterstitialPage() {
291 JNIEnv* env = AttachCurrentThread();
292 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
293 if (obj.is_null())
294 return;
295 Java_WebContentsObserver_didDetachInterstitialPage(env, obj.obj());
298 void WebContentsObserverAndroid::DidChangeThemeColor(SkColor color) {
299 JNIEnv* env = AttachCurrentThread();
300 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
301 if (obj.is_null())
302 return;
303 Java_WebContentsObserver_didChangeThemeColor(env, obj.obj(), color);
306 void WebContentsObserverAndroid::DidFailLoadInternal(
307 bool is_provisional_load,
308 bool is_main_frame,
309 int error_code,
310 const base::string16& description,
311 const GURL& url) {
312 JNIEnv* env = AttachCurrentThread();
313 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
314 if (obj.is_null())
315 return;
316 ScopedJavaLocalRef<jstring> jstring_error_description(
317 ConvertUTF16ToJavaString(env, description));
318 ScopedJavaLocalRef<jstring> jstring_url(
319 ConvertUTF8ToJavaString(env, url.spec()));
321 Java_WebContentsObserver_didFailLoad(
322 env, obj.obj(),
323 is_provisional_load,
324 is_main_frame,
325 error_code,
326 jstring_error_description.obj(), jstring_url.obj());
329 void WebContentsObserverAndroid::DidFirstVisuallyNonEmptyPaint() {
330 JNIEnv* env = AttachCurrentThread();
331 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
332 if (obj.is_null())
333 return;
334 Java_WebContentsObserver_didFirstVisuallyNonEmptyPaint(
335 env, obj.obj());
338 bool RegisterWebContentsObserverAndroid(JNIEnv* env) {
339 return RegisterNativesImpl(env);
341 } // namespace content