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.
4
5 #include "content/browser/android/web_contents_observer_android.h"
6
7 #include <string>
8
9 #include <jni.h>
10
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/android/content_view_core_impl.h"
15 #include "content/browser/renderer_host/render_widget_host_impl.h"
16 #include "content/browser/web_contents/web_contents_impl.h"
17 #include "content/public/browser/navigation_details.h"
18 #include "content/public/browser/navigation_entry.h"
19 #include "jni/WebContentsObserverAndroid_jni.h"
20
21 using base::android::AttachCurrentThread;
22 using base::android::ScopedJavaLocalRef;
23 using base::android::ConvertUTF8ToJavaString;
24 using base::android::ConvertUTF16ToJavaString;
25
26 namespace content {
27
WebContentsObserverAndroid(JNIEnv * env,jobject obj,WebContents * web_contents)28 WebContentsObserverAndroid::WebContentsObserverAndroid(
29 JNIEnv* env,
30 jobject obj,
31 WebContents* web_contents)
32 : WebContentsObserver(web_contents),
33 weak_java_observer_(env, obj){
34 }
35
~WebContentsObserverAndroid()36 WebContentsObserverAndroid::~WebContentsObserverAndroid() {
37 }
38
Init(JNIEnv * env,jobject obj,jlong native_content_view_core)39 jlong Init(JNIEnv* env, jobject obj, jlong native_content_view_core) {
40 ContentViewCore* content_view_core =
41 reinterpret_cast<ContentViewCore*>(native_content_view_core);
42 WebContentsObserverAndroid* native_observer = new WebContentsObserverAndroid(
43 env, obj, content_view_core->GetWebContents());
44 return reinterpret_cast<intptr_t>(native_observer);
45 }
46
Destroy(JNIEnv * env,jobject obj)47 void WebContentsObserverAndroid::Destroy(JNIEnv* env, jobject obj) {
48 delete this;
49 }
50
WebContentsDestroyed(WebContents * web_contents)51 void WebContentsObserverAndroid::WebContentsDestroyed(
52 WebContents* web_contents) {
53 JNIEnv* env = AttachCurrentThread();
54 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
55 if (obj.is_null()) {
56 delete this;
57 } else {
58 // The java side will destroy |this|
59 Java_WebContentsObserverAndroid_detachFromWebContents(env, obj.obj());
60 }
61 }
62
RenderProcessGone(base::TerminationStatus termination_status)63 void WebContentsObserverAndroid::RenderProcessGone(
64 base::TerminationStatus termination_status) {
65 JNIEnv* env = AttachCurrentThread();
66 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
67 if (obj.is_null())
68 return;
69 jboolean was_oom_protected =
70 termination_status == base::TERMINATION_STATUS_OOM_PROTECTED;
71 Java_WebContentsObserverAndroid_renderProcessGone(
72 env, obj.obj(), was_oom_protected);
73 }
74
DidStartLoading(RenderViewHost * render_view_host)75 void WebContentsObserverAndroid::DidStartLoading(
76 RenderViewHost* render_view_host) {
77 JNIEnv* env = AttachCurrentThread();
78 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
79 if (obj.is_null())
80 return;
81 ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString(
82 env, web_contents()->GetVisibleURL().spec()));
83 Java_WebContentsObserverAndroid_didStartLoading(
84 env, obj.obj(), jstring_url.obj());
85 }
86
DidStopLoading(RenderViewHost * render_view_host)87 void WebContentsObserverAndroid::DidStopLoading(
88 RenderViewHost* render_view_host) {
89 JNIEnv* env = AttachCurrentThread();
90 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
91 if (obj.is_null())
92 return;
93 ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString(
94 env, web_contents()->GetLastCommittedURL().spec()));
95 Java_WebContentsObserverAndroid_didStopLoading(
96 env, obj.obj(), jstring_url.obj());
97 }
98
DidFailProvisionalLoad(int64 frame_id,const base::string16 & frame_unique_name,bool is_main_frame,const GURL & validated_url,int error_code,const base::string16 & error_description,RenderViewHost * render_view_host)99 void WebContentsObserverAndroid::DidFailProvisionalLoad(
100 int64 frame_id,
101 const base::string16& frame_unique_name,
102 bool is_main_frame,
103 const GURL& validated_url,
104 int error_code,
105 const base::string16& error_description,
106 RenderViewHost* render_view_host) {
107 DidFailLoadInternal(
108 true, is_main_frame, error_code, error_description, validated_url);
109 }
110
DidFailLoad(int64 frame_id,const GURL & validated_url,bool is_main_frame,int error_code,const base::string16 & error_description,RenderViewHost * render_view_host)111 void WebContentsObserverAndroid::DidFailLoad(
112 int64 frame_id,
113 const GURL& validated_url,
114 bool is_main_frame,
115 int error_code,
116 const base::string16& error_description,
117 RenderViewHost* render_view_host) {
118 DidFailLoadInternal(
119 false, is_main_frame, error_code, error_description, validated_url);
120 }
121
DidNavigateMainFrame(const LoadCommittedDetails & details,const FrameNavigateParams & params)122 void WebContentsObserverAndroid::DidNavigateMainFrame(
123 const LoadCommittedDetails& details,
124 const FrameNavigateParams& params) {
125 JNIEnv* env = AttachCurrentThread();
126 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
127 if (obj.is_null())
128 return;
129 ScopedJavaLocalRef<jstring> jstring_url(
130 ConvertUTF8ToJavaString(env, params.url.spec()));
131 ScopedJavaLocalRef<jstring> jstring_base_url(
132 ConvertUTF8ToJavaString(env, params.base_url.spec()));
133 // See http://crbug.com/251330 for why it's determined this way.
134 bool in_page_navigation =
135 details.type == NAVIGATION_TYPE_IN_PAGE || details.is_in_page;
136 // TODO(mkosiba): delete once downstream rolls.
137 Java_WebContentsObserverAndroid_didNavigateMainFrameV_JLS_JLS_Z(
138 env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
139 details.is_navigation_to_different_page());
140 Java_WebContentsObserverAndroid_didNavigateMainFrameV_JLS_JLS_Z_Z(
141 env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
142 details.is_navigation_to_different_page(), in_page_navigation);
143 }
144
DidNavigateAnyFrame(const LoadCommittedDetails & details,const FrameNavigateParams & params)145 void WebContentsObserverAndroid::DidNavigateAnyFrame(
146 const LoadCommittedDetails& details,
147 const FrameNavigateParams& params) {
148 JNIEnv* env = AttachCurrentThread();
149 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
150 if (obj.is_null())
151 return;
152 ScopedJavaLocalRef<jstring> jstring_url(
153 ConvertUTF8ToJavaString(env, params.url.spec()));
154 ScopedJavaLocalRef<jstring> jstring_base_url(
155 ConvertUTF8ToJavaString(env, params.base_url.spec()));
156 jboolean jboolean_is_reload =
157 PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_RELOAD);
158
159 Java_WebContentsObserverAndroid_didNavigateAnyFrame(
160 env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
161 jboolean_is_reload);
162 }
163
DidStartProvisionalLoadForFrame(int64 frame_id,int64 parent_frame_id,bool is_main_frame,const GURL & validated_url,bool is_error_page,bool is_iframe_srcdoc,RenderViewHost * render_view_host)164 void WebContentsObserverAndroid::DidStartProvisionalLoadForFrame(
165 int64 frame_id,
166 int64 parent_frame_id,
167 bool is_main_frame,
168 const GURL& validated_url,
169 bool is_error_page,
170 bool is_iframe_srcdoc,
171 RenderViewHost* render_view_host) {
172 JNIEnv* env = AttachCurrentThread();
173 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
174 if (obj.is_null())
175 return;
176 ScopedJavaLocalRef<jstring> jstring_url(
177 ConvertUTF8ToJavaString(env, validated_url.spec()));
178 Java_WebContentsObserverAndroid_didStartProvisionalLoadForFrame(
179 env, obj.obj(), frame_id, parent_frame_id, is_main_frame,
180 jstring_url.obj(), is_error_page, is_iframe_srcdoc);
181 }
182
DidCommitProvisionalLoadForFrame(int64 frame_id,const base::string16 & frame_unique_name,bool is_main_frame,const GURL & url,PageTransition transition_type,RenderViewHost * render_view_host)183 void WebContentsObserverAndroid::DidCommitProvisionalLoadForFrame(
184 int64 frame_id,
185 const base::string16& frame_unique_name,
186 bool is_main_frame,
187 const GURL& url,
188 PageTransition transition_type,
189 RenderViewHost* render_view_host) {
190 JNIEnv* env = AttachCurrentThread();
191 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
192 if (obj.is_null())
193 return;
194 ScopedJavaLocalRef<jstring> jstring_url(
195 ConvertUTF8ToJavaString(env, url.spec()));
196 Java_WebContentsObserverAndroid_didCommitProvisionalLoadForFrame(
197 env, obj.obj(), frame_id, is_main_frame, jstring_url.obj(),
198 transition_type);
199 }
200
DidFinishLoad(int64 frame_id,const GURL & validated_url,bool is_main_frame,RenderViewHost * render_view_host)201 void WebContentsObserverAndroid::DidFinishLoad(
202 int64 frame_id,
203 const GURL& validated_url,
204 bool is_main_frame,
205 RenderViewHost* render_view_host) {
206 JNIEnv* env = AttachCurrentThread();
207 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
208 if (obj.is_null())
209 return;
210
211 std::string url_string = validated_url.spec();
212 NavigationEntry* entry =
213 web_contents()->GetController().GetLastCommittedEntry();
214 // Note that GetBaseURLForDataURL is only used by the Android WebView.
215 if (entry && !entry->GetBaseURLForDataURL().is_empty())
216 url_string = entry->GetBaseURLForDataURL().possibly_invalid_spec();
217
218 ScopedJavaLocalRef<jstring> jstring_url(
219 ConvertUTF8ToJavaString(env, url_string));
220 Java_WebContentsObserverAndroid_didFinishLoad(
221 env, obj.obj(), frame_id, jstring_url.obj(), is_main_frame);
222 }
223
NavigationEntryCommitted(const LoadCommittedDetails & load_details)224 void WebContentsObserverAndroid::NavigationEntryCommitted(
225 const LoadCommittedDetails& load_details) {
226 JNIEnv* env = AttachCurrentThread();
227 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
228 if (obj.is_null())
229 return;
230 Java_WebContentsObserverAndroid_navigationEntryCommitted(env, obj.obj());
231 }
232
DidChangeVisibleSSLState()233 void WebContentsObserverAndroid::DidChangeVisibleSSLState() {
234 JNIEnv* env = AttachCurrentThread();
235 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
236 if (obj.is_null())
237 return;
238 Java_WebContentsObserverAndroid_didChangeVisibleSSLState(env, obj.obj());
239 }
240
DidAttachInterstitialPage()241 void WebContentsObserverAndroid::DidAttachInterstitialPage() {
242 JNIEnv* env = AttachCurrentThread();
243 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
244 if (obj.is_null())
245 return;
246 Java_WebContentsObserverAndroid_didAttachInterstitialPage(env, obj.obj());
247 }
248
DidDetachInterstitialPage()249 void WebContentsObserverAndroid::DidDetachInterstitialPage() {
250 JNIEnv* env = AttachCurrentThread();
251 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
252 if (obj.is_null())
253 return;
254 Java_WebContentsObserverAndroid_didDetachInterstitialPage(env, obj.obj());
255 }
256
DidFailLoadInternal(bool is_provisional_load,bool is_main_frame,int error_code,const base::string16 & description,const GURL & url)257 void WebContentsObserverAndroid::DidFailLoadInternal(
258 bool is_provisional_load,
259 bool is_main_frame,
260 int error_code,
261 const base::string16& description,
262 const GURL& url) {
263 JNIEnv* env = AttachCurrentThread();
264 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
265 if (obj.is_null())
266 return;
267 ScopedJavaLocalRef<jstring> jstring_error_description(
268 ConvertUTF16ToJavaString(env, description));
269 ScopedJavaLocalRef<jstring> jstring_url(
270 ConvertUTF8ToJavaString(env, url.spec()));
271
272 Java_WebContentsObserverAndroid_didFailLoad(
273 env, obj.obj(),
274 is_provisional_load,
275 is_main_frame,
276 error_code,
277 jstring_error_description.obj(), jstring_url.obj());
278 }
279
RegisterWebContentsObserverAndroid(JNIEnv * env)280 bool RegisterWebContentsObserverAndroid(JNIEnv* env) {
281 return RegisterNativesImpl(env);
282 }
283 } // namespace content
284