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/android/content_view_core_impl.h" 15 #include "content/browser/renderer_host/render_widget_host_impl.h" 16 #include "content/browser/web_contents/web_contents_impl.h" 17 #include "content/public/browser/navigation_details.h" 18 #include "content/public/browser/navigation_entry.h" 19 #include "jni/WebContentsObserverAndroid_jni.h" 20 21 using base::android::AttachCurrentThread; 22 using base::android::ScopedJavaLocalRef; 23 using base::android::ConvertUTF8ToJavaString; 24 using base::android::ConvertUTF16ToJavaString; 25 26 namespace content { 27 28 WebContentsObserverAndroid::WebContentsObserverAndroid( 29 JNIEnv* env, 30 jobject obj, 31 WebContents* web_contents) 32 : WebContentsObserver(web_contents), 33 weak_java_observer_(env, obj){ 34 } 35 36 WebContentsObserverAndroid::~WebContentsObserverAndroid() { 37 } 38 39 jlong Init(JNIEnv* env, jobject obj, jlong native_content_view_core) { 40 ContentViewCore* content_view_core = 41 reinterpret_cast<ContentViewCore*>(native_content_view_core); 42 WebContentsObserverAndroid* native_observer = new WebContentsObserverAndroid( 43 env, obj, content_view_core->GetWebContents()); 44 return reinterpret_cast<intptr_t>(native_observer); 45 } 46 47 void WebContentsObserverAndroid::Destroy(JNIEnv* env, jobject obj) { 48 delete this; 49 } 50 51 void WebContentsObserverAndroid::WebContentsDestroyed( 52 WebContents* web_contents) { 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 // See http://crbug.com/251330 for why it's determined this way. 134 bool in_page_navigation = 135 details.type == NAVIGATION_TYPE_IN_PAGE || details.is_in_page; 136 // TODO(mkosiba): delete once downstream rolls. 137 Java_WebContentsObserverAndroid_didNavigateMainFrameV_JLS_JLS_Z( 138 env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(), 139 details.is_navigation_to_different_page()); 140 Java_WebContentsObserverAndroid_didNavigateMainFrameV_JLS_JLS_Z_Z( 141 env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(), 142 details.is_navigation_to_different_page(), in_page_navigation); 143 } 144 145 void WebContentsObserverAndroid::DidNavigateAnyFrame( 146 const LoadCommittedDetails& details, 147 const FrameNavigateParams& params) { 148 JNIEnv* env = AttachCurrentThread(); 149 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 150 if (obj.is_null()) 151 return; 152 ScopedJavaLocalRef<jstring> jstring_url( 153 ConvertUTF8ToJavaString(env, params.url.spec())); 154 ScopedJavaLocalRef<jstring> jstring_base_url( 155 ConvertUTF8ToJavaString(env, params.base_url.spec())); 156 jboolean jboolean_is_reload = 157 PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_RELOAD); 158 159 Java_WebContentsObserverAndroid_didNavigateAnyFrame( 160 env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(), 161 jboolean_is_reload); 162 } 163 164 void WebContentsObserverAndroid::DidStartProvisionalLoadForFrame( 165 int64 frame_id, 166 int64 parent_frame_id, 167 bool is_main_frame, 168 const GURL& validated_url, 169 bool is_error_page, 170 bool is_iframe_srcdoc, 171 RenderViewHost* render_view_host) { 172 JNIEnv* env = AttachCurrentThread(); 173 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 174 if (obj.is_null()) 175 return; 176 ScopedJavaLocalRef<jstring> jstring_url( 177 ConvertUTF8ToJavaString(env, validated_url.spec())); 178 Java_WebContentsObserverAndroid_didStartProvisionalLoadForFrame( 179 env, obj.obj(), frame_id, parent_frame_id, is_main_frame, 180 jstring_url.obj(), is_error_page, is_iframe_srcdoc); 181 } 182 183 void WebContentsObserverAndroid::DidCommitProvisionalLoadForFrame( 184 int64 frame_id, 185 const base::string16& frame_unique_name, 186 bool is_main_frame, 187 const GURL& url, 188 PageTransition transition_type, 189 RenderViewHost* render_view_host) { 190 JNIEnv* env = AttachCurrentThread(); 191 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 192 if (obj.is_null()) 193 return; 194 ScopedJavaLocalRef<jstring> jstring_url( 195 ConvertUTF8ToJavaString(env, url.spec())); 196 Java_WebContentsObserverAndroid_didCommitProvisionalLoadForFrame( 197 env, obj.obj(), frame_id, is_main_frame, jstring_url.obj(), 198 transition_type); 199 } 200 201 void WebContentsObserverAndroid::DidFinishLoad( 202 int64 frame_id, 203 const GURL& validated_url, 204 bool is_main_frame, 205 RenderViewHost* render_view_host) { 206 JNIEnv* env = AttachCurrentThread(); 207 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 208 if (obj.is_null()) 209 return; 210 211 std::string url_string = validated_url.spec(); 212 NavigationEntry* entry = 213 web_contents()->GetController().GetLastCommittedEntry(); 214 // Note that GetBaseURLForDataURL is only used by the Android WebView. 215 if (entry && !entry->GetBaseURLForDataURL().is_empty()) 216 url_string = entry->GetBaseURLForDataURL().possibly_invalid_spec(); 217 218 ScopedJavaLocalRef<jstring> jstring_url( 219 ConvertUTF8ToJavaString(env, url_string)); 220 Java_WebContentsObserverAndroid_didFinishLoad( 221 env, obj.obj(), frame_id, jstring_url.obj(), is_main_frame); 222 } 223 224 void WebContentsObserverAndroid::NavigationEntryCommitted( 225 const LoadCommittedDetails& load_details) { 226 JNIEnv* env = AttachCurrentThread(); 227 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 228 if (obj.is_null()) 229 return; 230 Java_WebContentsObserverAndroid_navigationEntryCommitted(env, obj.obj()); 231 } 232 233 void WebContentsObserverAndroid::DidChangeVisibleSSLState() { 234 JNIEnv* env = AttachCurrentThread(); 235 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 236 if (obj.is_null()) 237 return; 238 Java_WebContentsObserverAndroid_didChangeVisibleSSLState(env, obj.obj()); 239 } 240 241 void WebContentsObserverAndroid::DidAttachInterstitialPage() { 242 JNIEnv* env = AttachCurrentThread(); 243 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 244 if (obj.is_null()) 245 return; 246 Java_WebContentsObserverAndroid_didAttachInterstitialPage(env, obj.obj()); 247 } 248 249 void WebContentsObserverAndroid::DidDetachInterstitialPage() { 250 JNIEnv* env = AttachCurrentThread(); 251 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 252 if (obj.is_null()) 253 return; 254 Java_WebContentsObserverAndroid_didDetachInterstitialPage(env, obj.obj()); 255 } 256 257 void WebContentsObserverAndroid::DidFailLoadInternal( 258 bool is_provisional_load, 259 bool is_main_frame, 260 int error_code, 261 const base::string16& description, 262 const GURL& url) { 263 JNIEnv* env = AttachCurrentThread(); 264 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 265 if (obj.is_null()) 266 return; 267 ScopedJavaLocalRef<jstring> jstring_error_description( 268 ConvertUTF16ToJavaString(env, description)); 269 ScopedJavaLocalRef<jstring> jstring_url( 270 ConvertUTF8ToJavaString(env, url.spec())); 271 272 Java_WebContentsObserverAndroid_didFailLoad( 273 env, obj.obj(), 274 is_provisional_load, 275 is_main_frame, 276 error_code, 277 jstring_error_description.obj(), jstring_url.obj()); 278 } 279 280 bool RegisterWebContentsObserverAndroid(JNIEnv* env) { 281 return RegisterNativesImpl(env); 282 } 283 } // namespace content 284