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