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