Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / components / web_contents_delegate_android / web_contents_delegate_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 "components/web_contents_delegate_android/web_contents_delegate_android.h"
6
7 #include <android/keycodes.h>
8
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_array.h"
11 #include "base/android/jni_string.h"
12 #include "components/web_contents_delegate_android/color_chooser_android.h"
13 #include "components/web_contents_delegate_android/validation_message_bubble_android.h"
14 #include "content/public/browser/android/content_view_core.h"
15 #include "content/public/browser/color_chooser.h"
16 #include "content/public/browser/invalidate_type.h"
17 #include "content/public/browser/native_web_keyboard_event.h"
18 #include "content/public/browser/page_navigator.h"
19 #include "content/public/browser/render_widget_host_view.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/common/page_transition_types.h"
22 #include "content/public/common/referrer.h"
23 #include "jni/WebContentsDelegateAndroid_jni.h"
24 #include "ui/base/window_open_disposition.h"
25 #include "ui/gfx/rect.h"
26 #include "url/gurl.h"
27
28 using base::android::AttachCurrentThread;
29 using base::android::ConvertUTF8ToJavaString;
30 using base::android::ConvertUTF16ToJavaString;
31 using base::android::ScopedJavaLocalRef;
32 using content::ColorChooser;
33 using content::RenderWidgetHostView;
34 using content::WebContents;
35 using content::WebContentsDelegate;
36
37 namespace web_contents_delegate_android {
38
39 WebContentsDelegateAndroid::WebContentsDelegateAndroid(JNIEnv* env, jobject obj)
40     : weak_java_delegate_(env, obj) {
41 }
42
43 WebContentsDelegateAndroid::~WebContentsDelegateAndroid() {
44 }
45
46 ScopedJavaLocalRef<jobject>
47 WebContentsDelegateAndroid::GetJavaDelegate(JNIEnv* env) const {
48   return weak_java_delegate_.get(env);
49 }
50
51 // ----------------------------------------------------------------------------
52 // WebContentsDelegate methods
53 // ----------------------------------------------------------------------------
54
55 ColorChooser* WebContentsDelegateAndroid::OpenColorChooser(
56       WebContents* source,
57       SkColor color,
58       const std::vector<content::ColorSuggestion>& suggestions)  {
59   return new ColorChooserAndroid(source, color, suggestions);
60 }
61
62 // OpenURLFromTab() will be called when we're performing a browser-intiated
63 // navigation. The most common scenario for this is opening new tabs (see
64 // RenderViewImpl::decidePolicyForNavigation for more details).
65 WebContents* WebContentsDelegateAndroid::OpenURLFromTab(
66     WebContents* source,
67     const content::OpenURLParams& params) {
68   const GURL& url = params.url;
69   WindowOpenDisposition disposition = params.disposition;
70   content::PageTransition transition(
71       PageTransitionFromInt(params.transition));
72
73   if (!source || (disposition != CURRENT_TAB &&
74                   disposition != NEW_FOREGROUND_TAB &&
75                   disposition != NEW_BACKGROUND_TAB &&
76                   disposition != OFF_THE_RECORD)) {
77     NOTIMPLEMENTED();
78     return NULL;
79   }
80
81   JNIEnv* env = AttachCurrentThread();
82   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
83   if (obj.is_null())
84     return WebContentsDelegate::OpenURLFromTab(source, params);
85
86   if (disposition == NEW_FOREGROUND_TAB ||
87       disposition == NEW_BACKGROUND_TAB ||
88       disposition == OFF_THE_RECORD) {
89     JNIEnv* env = AttachCurrentThread();
90     ScopedJavaLocalRef<jstring> java_url =
91         ConvertUTF8ToJavaString(env, url.spec());
92     ScopedJavaLocalRef<jstring> extra_headers =
93             ConvertUTF8ToJavaString(env, params.extra_headers);
94     ScopedJavaLocalRef<jbyteArray> post_data;
95     if (params.uses_post &&
96         params.browser_initiated_post_data.get() &&
97         params.browser_initiated_post_data.get()->size()) {
98       post_data = base::android::ToJavaByteArray(
99           env,
100           params.browser_initiated_post_data.get()->front_as<uint8>(),
101           params.browser_initiated_post_data.get()->size());
102     }
103     Java_WebContentsDelegateAndroid_openNewTab(env,
104                                                obj.obj(),
105                                                java_url.obj(),
106                                                extra_headers.obj(),
107                                                post_data.obj(),
108                                                disposition);
109     return NULL;
110   }
111
112   source->GetController().LoadURL(url, params.referrer, transition,
113                                   std::string());
114   return source;
115 }
116
117 void WebContentsDelegateAndroid::NavigationStateChanged(
118     const WebContents* source, unsigned changed_flags) {
119   JNIEnv* env = AttachCurrentThread();
120   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
121   if (obj.is_null())
122     return;
123   Java_WebContentsDelegateAndroid_navigationStateChanged(
124       env,
125       obj.obj(),
126       changed_flags);
127 }
128
129 void WebContentsDelegateAndroid::ActivateContents(WebContents* contents) {
130   JNIEnv* env = AttachCurrentThread();
131   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
132   if (obj.is_null())
133     return;
134   Java_WebContentsDelegateAndroid_activateContents(env, obj.obj());
135 }
136
137 void WebContentsDelegateAndroid::DeactivateContents(WebContents* contents) {
138   // On desktop the current window is deactivated here, bringing the next window
139   // to focus. Not implemented on Android.
140 }
141
142 void WebContentsDelegateAndroid::LoadingStateChanged(WebContents* source) {
143   JNIEnv* env = AttachCurrentThread();
144   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
145   if (obj.is_null())
146     return;
147   bool has_stopped = source == NULL || !source->IsLoading();
148
149   if (has_stopped)
150     Java_WebContentsDelegateAndroid_onLoadStopped(env, obj.obj());
151   else
152     Java_WebContentsDelegateAndroid_onLoadStarted(env, obj.obj());
153 }
154
155 void WebContentsDelegateAndroid::LoadProgressChanged(WebContents* source,
156                                                      double progress) {
157   JNIEnv* env = AttachCurrentThread();
158   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
159   if (obj.is_null())
160     return;
161   Java_WebContentsDelegateAndroid_notifyLoadProgressChanged(
162       env,
163       obj.obj(),
164       progress);
165 }
166
167 void WebContentsDelegateAndroid::RendererUnresponsive(WebContents* source) {
168   JNIEnv* env = AttachCurrentThread();
169   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
170   if (obj.is_null())
171     return;
172   Java_WebContentsDelegateAndroid_rendererUnresponsive(env, obj.obj());
173 }
174
175 void WebContentsDelegateAndroid::RendererResponsive(WebContents* source) {
176   JNIEnv* env = AttachCurrentThread();
177   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
178   if (obj.is_null())
179     return;
180   Java_WebContentsDelegateAndroid_rendererResponsive(env, obj.obj());
181 }
182
183 void WebContentsDelegateAndroid::CloseContents(WebContents* source) {
184   JNIEnv* env = AttachCurrentThread();
185   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
186   if (obj.is_null())
187     return;
188   Java_WebContentsDelegateAndroid_closeContents(env, obj.obj());
189 }
190
191 void WebContentsDelegateAndroid::MoveContents(WebContents* source,
192                                               const gfx::Rect& pos) {
193   // Do nothing.
194 }
195
196 bool WebContentsDelegateAndroid::AddMessageToConsole(
197     WebContents* source,
198     int32 level,
199     const base::string16& message,
200     int32 line_no,
201     const base::string16& source_id) {
202   JNIEnv* env = AttachCurrentThread();
203   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
204   if (obj.is_null())
205     return WebContentsDelegate::AddMessageToConsole(source, level, message,
206                                                     line_no, source_id);
207   ScopedJavaLocalRef<jstring> jmessage(ConvertUTF16ToJavaString(env, message));
208   ScopedJavaLocalRef<jstring> jsource_id(
209       ConvertUTF16ToJavaString(env, source_id));
210   int jlevel = WEB_CONTENTS_DELEGATE_LOG_LEVEL_DEBUG;
211   switch (level) {
212     case logging::LOG_VERBOSE:
213       jlevel = WEB_CONTENTS_DELEGATE_LOG_LEVEL_DEBUG;
214       break;
215     case logging::LOG_INFO:
216       jlevel = WEB_CONTENTS_DELEGATE_LOG_LEVEL_LOG;
217       break;
218     case logging::LOG_WARNING:
219       jlevel = WEB_CONTENTS_DELEGATE_LOG_LEVEL_WARNING;
220       break;
221     case logging::LOG_ERROR:
222       jlevel = WEB_CONTENTS_DELEGATE_LOG_LEVEL_ERROR;
223       break;
224     default:
225       NOTREACHED();
226   }
227   return Java_WebContentsDelegateAndroid_addMessageToConsole(
228       env,
229       GetJavaDelegate(env).obj(),
230       jlevel,
231       jmessage.obj(),
232       line_no,
233       jsource_id.obj());
234 }
235
236 // This is either called from TabContents::DidNavigateMainFramePostCommit() with
237 // an empty GURL or responding to RenderViewHost::OnMsgUpateTargetURL(). In
238 // Chrome, the latter is not always called, especially not during history
239 // navigation. So we only handle the first case and pass the source TabContents'
240 // url to Java to update the UI.
241 void WebContentsDelegateAndroid::UpdateTargetURL(WebContents* source,
242                                                  int32 page_id,
243                                                  const GURL& url) {
244   if (!url.is_empty())
245     return;
246   JNIEnv* env = AttachCurrentThread();
247   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
248   if (obj.is_null())
249     return;
250   ScopedJavaLocalRef<jstring> java_url =
251       ConvertUTF8ToJavaString(env, source->GetURL().spec());
252   Java_WebContentsDelegateAndroid_onUpdateUrl(env,
253                                               obj.obj(),
254                                               java_url.obj());
255 }
256
257 void WebContentsDelegateAndroid::HandleKeyboardEvent(
258     WebContents* source,
259     const content::NativeWebKeyboardEvent& event) {
260   jobject key_event = event.os_event;
261   if (key_event) {
262     JNIEnv* env = AttachCurrentThread();
263     ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
264     if (obj.is_null())
265       return;
266     Java_WebContentsDelegateAndroid_handleKeyboardEvent(
267         env, obj.obj(), key_event);
268   }
269 }
270
271 bool WebContentsDelegateAndroid::TakeFocus(WebContents* source, bool reverse) {
272   JNIEnv* env = AttachCurrentThread();
273   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
274   if (obj.is_null())
275     return WebContentsDelegate::TakeFocus(source, reverse);
276   return Java_WebContentsDelegateAndroid_takeFocus(
277       env, obj.obj(), reverse);
278 }
279
280 void WebContentsDelegateAndroid::ShowRepostFormWarningDialog(
281     WebContents* source) {
282   JNIEnv* env = AttachCurrentThread();
283   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
284   if (obj.is_null())
285     return;
286   ScopedJavaLocalRef<jobject> content_view_core =
287       content::ContentViewCore::FromWebContents(source)->GetJavaObject();
288   if (content_view_core.is_null())
289     return;
290   Java_WebContentsDelegateAndroid_showRepostFormWarningDialog(env, obj.obj(),
291       content_view_core.obj());
292 }
293
294 void WebContentsDelegateAndroid::ToggleFullscreenModeForTab(
295     WebContents* web_contents,
296     bool enter_fullscreen) {
297   JNIEnv* env = AttachCurrentThread();
298   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
299   if (obj.is_null())
300     return;
301   Java_WebContentsDelegateAndroid_toggleFullscreenModeForTab(
302       env, obj.obj(), enter_fullscreen);
303 }
304
305 bool WebContentsDelegateAndroid::IsFullscreenForTabOrPending(
306     const WebContents* web_contents) const {
307   JNIEnv* env = AttachCurrentThread();
308   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
309   if (obj.is_null())
310     return false;
311   return Java_WebContentsDelegateAndroid_isFullscreenForTabOrPending(
312       env, obj.obj());
313 }
314
315 void WebContentsDelegateAndroid::ShowValidationMessage(
316     WebContents* web_contents,
317     const gfx::Rect& anchor_in_root_view,
318     const base::string16& main_text,
319     const base::string16& sub_text) {
320   RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
321   if (rwhv) {
322     validation_message_bubble_.reset(
323         new ValidationMessageBubbleAndroid(rwhv->GetRenderWidgetHost(),
324                                            anchor_in_root_view,
325                                            main_text,
326                                            sub_text));
327   }
328 }
329
330 void WebContentsDelegateAndroid::HideValidationMessage(
331     WebContents* web_contents) {
332   validation_message_bubble_.reset();
333 }
334
335 void WebContentsDelegateAndroid::MoveValidationMessage(
336     WebContents* web_contents,
337     const gfx::Rect& anchor_in_root_view) {
338   if (!validation_message_bubble_)
339     return;
340   RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
341   if (rwhv) {
342     validation_message_bubble_->SetPositionRelativeToAnchor(
343         rwhv->GetRenderWidgetHost(), anchor_in_root_view);
344   }
345 }
346 // ----------------------------------------------------------------------------
347 // Native JNI methods
348 // ----------------------------------------------------------------------------
349
350 // Register native methods
351
352 bool RegisterWebContentsDelegateAndroid(JNIEnv* env) {
353   return RegisterNativesImpl(env);
354 }
355
356 }  // namespace web_contents_delegate_android