Upstream version 6.35.121.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     bool to_different_document) {
144   JNIEnv* env = AttachCurrentThread();
145   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
146   if (obj.is_null())
147     return;
148   bool has_stopped = source == NULL || !source->IsLoading();
149
150   if (has_stopped)
151     Java_WebContentsDelegateAndroid_onLoadStopped(env, obj.obj());
152   else
153     Java_WebContentsDelegateAndroid_onLoadStarted(env, obj.obj());
154 }
155
156 void WebContentsDelegateAndroid::LoadProgressChanged(WebContents* source,
157                                                      double progress) {
158   JNIEnv* env = AttachCurrentThread();
159   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
160   if (obj.is_null())
161     return;
162   Java_WebContentsDelegateAndroid_notifyLoadProgressChanged(
163       env,
164       obj.obj(),
165       progress);
166 }
167
168 void WebContentsDelegateAndroid::RendererUnresponsive(WebContents* source) {
169   JNIEnv* env = AttachCurrentThread();
170   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
171   if (obj.is_null())
172     return;
173   Java_WebContentsDelegateAndroid_rendererUnresponsive(env, obj.obj());
174 }
175
176 void WebContentsDelegateAndroid::RendererResponsive(WebContents* source) {
177   JNIEnv* env = AttachCurrentThread();
178   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
179   if (obj.is_null())
180     return;
181   Java_WebContentsDelegateAndroid_rendererResponsive(env, obj.obj());
182 }
183
184 void WebContentsDelegateAndroid::CloseContents(WebContents* source) {
185   JNIEnv* env = AttachCurrentThread();
186   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
187   if (obj.is_null())
188     return;
189   Java_WebContentsDelegateAndroid_closeContents(env, obj.obj());
190 }
191
192 void WebContentsDelegateAndroid::MoveContents(WebContents* source,
193                                               const gfx::Rect& pos) {
194   // Do nothing.
195 }
196
197 bool WebContentsDelegateAndroid::AddMessageToConsole(
198     WebContents* source,
199     int32 level,
200     const base::string16& message,
201     int32 line_no,
202     const base::string16& source_id) {
203   JNIEnv* env = AttachCurrentThread();
204   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
205   if (obj.is_null())
206     return WebContentsDelegate::AddMessageToConsole(source, level, message,
207                                                     line_no, source_id);
208   ScopedJavaLocalRef<jstring> jmessage(ConvertUTF16ToJavaString(env, message));
209   ScopedJavaLocalRef<jstring> jsource_id(
210       ConvertUTF16ToJavaString(env, source_id));
211   int jlevel = WEB_CONTENTS_DELEGATE_LOG_LEVEL_DEBUG;
212   switch (level) {
213     case logging::LOG_VERBOSE:
214       jlevel = WEB_CONTENTS_DELEGATE_LOG_LEVEL_DEBUG;
215       break;
216     case logging::LOG_INFO:
217       jlevel = WEB_CONTENTS_DELEGATE_LOG_LEVEL_LOG;
218       break;
219     case logging::LOG_WARNING:
220       jlevel = WEB_CONTENTS_DELEGATE_LOG_LEVEL_WARNING;
221       break;
222     case logging::LOG_ERROR:
223       jlevel = WEB_CONTENTS_DELEGATE_LOG_LEVEL_ERROR;
224       break;
225     default:
226       NOTREACHED();
227   }
228   return Java_WebContentsDelegateAndroid_addMessageToConsole(
229       env,
230       GetJavaDelegate(env).obj(),
231       jlevel,
232       jmessage.obj(),
233       line_no,
234       jsource_id.obj());
235 }
236
237 // This is either called from TabContents::DidNavigateMainFramePostCommit() with
238 // an empty GURL or responding to RenderViewHost::OnMsgUpateTargetURL(). In
239 // Chrome, the latter is not always called, especially not during history
240 // navigation. So we only handle the first case and pass the source TabContents'
241 // url to Java to update the UI.
242 void WebContentsDelegateAndroid::UpdateTargetURL(WebContents* source,
243                                                  int32 page_id,
244                                                  const GURL& url) {
245   if (!url.is_empty())
246     return;
247   JNIEnv* env = AttachCurrentThread();
248   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
249   if (obj.is_null())
250     return;
251   ScopedJavaLocalRef<jstring> java_url =
252       ConvertUTF8ToJavaString(env, source->GetURL().spec());
253   Java_WebContentsDelegateAndroid_onUpdateUrl(env,
254                                               obj.obj(),
255                                               java_url.obj());
256 }
257
258 void WebContentsDelegateAndroid::HandleKeyboardEvent(
259     WebContents* source,
260     const content::NativeWebKeyboardEvent& event) {
261   jobject key_event = event.os_event;
262   if (key_event) {
263     JNIEnv* env = AttachCurrentThread();
264     ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
265     if (obj.is_null())
266       return;
267     Java_WebContentsDelegateAndroid_handleKeyboardEvent(
268         env, obj.obj(), key_event);
269   }
270 }
271
272 bool WebContentsDelegateAndroid::TakeFocus(WebContents* source, bool reverse) {
273   JNIEnv* env = AttachCurrentThread();
274   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
275   if (obj.is_null())
276     return WebContentsDelegate::TakeFocus(source, reverse);
277   return Java_WebContentsDelegateAndroid_takeFocus(
278       env, obj.obj(), reverse);
279 }
280
281 void WebContentsDelegateAndroid::ShowRepostFormWarningDialog(
282     WebContents* source) {
283   JNIEnv* env = AttachCurrentThread();
284   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
285   if (obj.is_null())
286     return;
287   ScopedJavaLocalRef<jobject> content_view_core =
288       content::ContentViewCore::FromWebContents(source)->GetJavaObject();
289   if (content_view_core.is_null())
290     return;
291   Java_WebContentsDelegateAndroid_showRepostFormWarningDialog(env, obj.obj(),
292       content_view_core.obj());
293 }
294
295 void WebContentsDelegateAndroid::ToggleFullscreenModeForTab(
296     WebContents* web_contents,
297     bool enter_fullscreen) {
298   JNIEnv* env = AttachCurrentThread();
299   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
300   if (obj.is_null())
301     return;
302   Java_WebContentsDelegateAndroid_toggleFullscreenModeForTab(
303       env, obj.obj(), enter_fullscreen);
304 }
305
306 bool WebContentsDelegateAndroid::IsFullscreenForTabOrPending(
307     const WebContents* web_contents) const {
308   JNIEnv* env = AttachCurrentThread();
309   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
310   if (obj.is_null())
311     return false;
312   return Java_WebContentsDelegateAndroid_isFullscreenForTabOrPending(
313       env, obj.obj());
314 }
315
316 void WebContentsDelegateAndroid::ShowValidationMessage(
317     WebContents* web_contents,
318     const gfx::Rect& anchor_in_root_view,
319     const base::string16& main_text,
320     const base::string16& sub_text) {
321   RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
322   if (rwhv) {
323     validation_message_bubble_.reset(
324         new ValidationMessageBubbleAndroid(rwhv->GetRenderWidgetHost(),
325                                            anchor_in_root_view,
326                                            main_text,
327                                            sub_text));
328   }
329 }
330
331 void WebContentsDelegateAndroid::HideValidationMessage(
332     WebContents* web_contents) {
333   validation_message_bubble_.reset();
334 }
335
336 void WebContentsDelegateAndroid::MoveValidationMessage(
337     WebContents* web_contents,
338     const gfx::Rect& anchor_in_root_view) {
339   if (!validation_message_bubble_)
340     return;
341   RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
342   if (rwhv) {
343     validation_message_bubble_->SetPositionRelativeToAnchor(
344         rwhv->GetRenderWidgetHost(), anchor_in_root_view);
345   }
346 }
347 // ----------------------------------------------------------------------------
348 // Native JNI methods
349 // ----------------------------------------------------------------------------
350
351 // Register native methods
352
353 bool RegisterWebContentsDelegateAndroid(JNIEnv* env) {
354   return RegisterNativesImpl(env);
355 }
356
357 }  // namespace web_contents_delegate_android