Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / content / browser / android / web_contents_observer_android.cc
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/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/WebContentsObserverAndroid_jni.h"
19
20 using base::android::AttachCurrentThread;
21 using base::android::ScopedJavaLocalRef;
22 using base::android::ConvertUTF8ToJavaString;
23 using base::android::ConvertUTF16ToJavaString;
24
25 namespace content {
26
27 WebContentsObserverAndroid::WebContentsObserverAndroid(
28     JNIEnv* env,
29     jobject obj,
30     WebContents* web_contents)
31     : WebContentsObserver(web_contents),
32       weak_java_observer_(env, obj){
33 }
34
35 WebContentsObserverAndroid::~WebContentsObserverAndroid() {
36 }
37
38 jlong Init(JNIEnv* env, jobject obj, jobject java_web_contents) {
39   content::WebContents* web_contents =
40         content::WebContents::FromJavaWebContents(java_web_contents);
41   CHECK(web_contents);
42
43   WebContentsObserverAndroid* native_observer = new WebContentsObserverAndroid(
44       env, obj, web_contents);
45   return reinterpret_cast<intptr_t>(native_observer);
46 }
47
48 void WebContentsObserverAndroid::Destroy(JNIEnv* env, jobject obj) {
49   delete this;
50 }
51
52 void WebContentsObserverAndroid::WebContentsDestroyed() {
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
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
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
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
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
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
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
134   // See http://crbug.com/251330 for why it's determined this way.
135   url::Replacements<char> replacements;
136   replacements.ClearRef();
137   bool urls_same_ignoring_fragment =
138       params.url.ReplaceComponents(replacements) ==
139       details.previous_url.ReplaceComponents(replacements);
140
141   // is_fragment_navigation is indicative of the intent of this variable.
142   // However, there isn't sufficient information here to determine whether this
143   // is actually a fragment navigation, or a history API navigation to a URL
144   // that would also be valid for a fragment navigation.
145   bool is_fragment_navigation = urls_same_ignoring_fragment &&
146       (details.type == NAVIGATION_TYPE_IN_PAGE || details.is_in_page);
147   Java_WebContentsObserverAndroid_didNavigateMainFrame(
148       env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
149       details.is_navigation_to_different_page(), is_fragment_navigation);
150 }
151
152 void WebContentsObserverAndroid::DidNavigateAnyFrame(
153     const LoadCommittedDetails& details,
154     const FrameNavigateParams& params) {
155   JNIEnv* env = AttachCurrentThread();
156   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
157   if (obj.is_null())
158     return;
159   ScopedJavaLocalRef<jstring> jstring_url(
160       ConvertUTF8ToJavaString(env, params.url.spec()));
161   ScopedJavaLocalRef<jstring> jstring_base_url(
162       ConvertUTF8ToJavaString(env, params.base_url.spec()));
163   jboolean jboolean_is_reload =
164       PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_RELOAD);
165
166   Java_WebContentsObserverAndroid_didNavigateAnyFrame(
167       env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
168       jboolean_is_reload);
169 }
170
171 void WebContentsObserverAndroid::DidStartProvisionalLoadForFrame(
172       int64 frame_id,
173       int64 parent_frame_id,
174       bool is_main_frame,
175       const GURL& validated_url,
176       bool is_error_page,
177       bool is_iframe_srcdoc,
178       RenderViewHost* render_view_host) {
179   JNIEnv* env = AttachCurrentThread();
180   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
181   if (obj.is_null())
182     return;
183   ScopedJavaLocalRef<jstring> jstring_url(
184       ConvertUTF8ToJavaString(env, validated_url.spec()));
185   Java_WebContentsObserverAndroid_didStartProvisionalLoadForFrame(
186       env, obj.obj(), frame_id, parent_frame_id, is_main_frame,
187       jstring_url.obj(), is_error_page, is_iframe_srcdoc);
188 }
189
190 void WebContentsObserverAndroid::DidCommitProvisionalLoadForFrame(
191       int64 frame_id,
192       const base::string16& frame_unique_name,
193       bool is_main_frame,
194       const GURL& url,
195       PageTransition transition_type,
196       RenderViewHost* render_view_host) {
197   JNIEnv* env = AttachCurrentThread();
198   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
199   if (obj.is_null())
200     return;
201   ScopedJavaLocalRef<jstring> jstring_url(
202       ConvertUTF8ToJavaString(env, url.spec()));
203   Java_WebContentsObserverAndroid_didCommitProvisionalLoadForFrame(
204       env, obj.obj(), frame_id, is_main_frame, jstring_url.obj(),
205       transition_type);
206 }
207
208 void WebContentsObserverAndroid::DidFinishLoad(
209     int64 frame_id,
210     const GURL& validated_url,
211     bool is_main_frame,
212     RenderViewHost* render_view_host) {
213   JNIEnv* env = AttachCurrentThread();
214   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
215   if (obj.is_null())
216     return;
217
218   std::string url_string = validated_url.spec();
219   NavigationEntry* entry =
220     web_contents()->GetController().GetLastCommittedEntry();
221   // Note that GetBaseURLForDataURL is only used by the Android WebView.
222   if (entry && !entry->GetBaseURLForDataURL().is_empty())
223     url_string = entry->GetBaseURLForDataURL().possibly_invalid_spec();
224
225   ScopedJavaLocalRef<jstring> jstring_url(
226       ConvertUTF8ToJavaString(env, url_string));
227   Java_WebContentsObserverAndroid_didFinishLoad(
228       env, obj.obj(), frame_id, jstring_url.obj(), is_main_frame);
229 }
230
231 void WebContentsObserverAndroid::DocumentLoadedInFrame(
232     int64 frame_id,
233     RenderViewHost* render_view_host) {
234   JNIEnv* env = AttachCurrentThread();
235   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
236   if (obj.is_null())
237     return;
238   Java_WebContentsObserverAndroid_documentLoadedInFrame(
239       env, obj.obj(), frame_id);
240 }
241
242 void WebContentsObserverAndroid::NavigationEntryCommitted(
243     const LoadCommittedDetails& load_details) {
244   JNIEnv* env = AttachCurrentThread();
245   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
246   if (obj.is_null())
247     return;
248   Java_WebContentsObserverAndroid_navigationEntryCommitted(env, obj.obj());
249 }
250
251 void WebContentsObserverAndroid::DidAttachInterstitialPage() {
252   JNIEnv* env = AttachCurrentThread();
253   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
254   if (obj.is_null())
255     return;
256   Java_WebContentsObserverAndroid_didAttachInterstitialPage(env, obj.obj());
257 }
258
259 void WebContentsObserverAndroid::DidDetachInterstitialPage() {
260   JNIEnv* env = AttachCurrentThread();
261   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
262   if (obj.is_null())
263     return;
264   Java_WebContentsObserverAndroid_didDetachInterstitialPage(env, obj.obj());
265 }
266
267 void WebContentsObserverAndroid::DidChangeThemeColor(SkColor color) {
268   JNIEnv* env = AttachCurrentThread();
269   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
270   if (obj.is_null())
271     return;
272   Java_WebContentsObserverAndroid_didChangeThemeColor(env, obj.obj(), color);
273 }
274
275 void WebContentsObserverAndroid::DidFailLoadInternal(
276     bool is_provisional_load,
277     bool is_main_frame,
278     int error_code,
279     const base::string16& description,
280     const GURL& url) {
281   JNIEnv* env = AttachCurrentThread();
282   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
283   if (obj.is_null())
284     return;
285   ScopedJavaLocalRef<jstring> jstring_error_description(
286       ConvertUTF16ToJavaString(env, description));
287   ScopedJavaLocalRef<jstring> jstring_url(
288       ConvertUTF8ToJavaString(env, url.spec()));
289
290   Java_WebContentsObserverAndroid_didFailLoad(
291       env, obj.obj(),
292       is_provisional_load,
293       is_main_frame,
294       error_code,
295       jstring_error_description.obj(), jstring_url.obj());
296 }
297
298 void WebContentsObserverAndroid::DidFirstVisuallyNonEmptyPaint() {
299   JNIEnv* env = AttachCurrentThread();
300   ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
301   if (obj.is_null())
302     return;
303   Java_WebContentsObserverAndroid_didFirstVisuallyNonEmptyPaint(
304       env, obj.obj());
305 }
306
307 bool RegisterWebContentsObserverAndroid(JNIEnv* env) {
308   return RegisterNativesImpl(env);
309 }
310 }  // namespace content