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 using base::android::HasClass; 26 27 namespace content { 28 29 WebContentsObserverAndroid::WebContentsObserverAndroid( 30 JNIEnv* env, 31 jobject obj, 32 WebContents* web_contents) 33 : WebContentsObserver(web_contents), 34 weak_java_observer_(env, obj){ 35 } 36 37 WebContentsObserverAndroid::~WebContentsObserverAndroid() { 38 } 39 40 jint Init(JNIEnv* env, jobject obj, jint native_content_view_core) { 41 ContentViewCore* content_view_core = 42 reinterpret_cast<ContentViewCore*>(native_content_view_core); 43 WebContentsObserverAndroid* native_observer = new WebContentsObserverAndroid( 44 env, obj, content_view_core->GetWebContents()); 45 return reinterpret_cast<jint>(native_observer); 46 } 47 48 void WebContentsObserverAndroid::Destroy(JNIEnv* env, jobject obj) { 49 delete this; 50 } 51 52 void WebContentsObserverAndroid::WebContentsDestroyed( 53 WebContents* web_contents) { 54 JNIEnv* env = AttachCurrentThread(); 55 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 56 if (obj.is_null()) { 57 delete this; 58 } else { 59 // The java side will destroy |this| 60 Java_WebContentsObserverAndroid_detachFromWebContents(env, obj.obj()); 61 } 62 } 63 64 void WebContentsObserverAndroid::DidStartLoading( 65 RenderViewHost* render_view_host) { 66 JNIEnv* env = AttachCurrentThread(); 67 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 68 if (obj.is_null()) 69 return; 70 ScopedJavaLocalRef<jstring> jstring_url( 71 ConvertUTF8ToJavaString(env, web_contents()->GetURL().spec())); 72 Java_WebContentsObserverAndroid_didStartLoading( 73 env, obj.obj(), jstring_url.obj()); 74 } 75 76 void WebContentsObserverAndroid::DidStopLoading( 77 RenderViewHost* render_view_host) { 78 JNIEnv* env = AttachCurrentThread(); 79 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 80 if (obj.is_null()) 81 return; 82 83 std::string url_string; 84 NavigationEntry* entry = 85 web_contents()->GetController().GetLastCommittedEntry(); 86 // Not that GetBaseURLForDataURL is only used by the Android WebView 87 if (entry && !entry->GetBaseURLForDataURL().is_empty()) { 88 url_string = entry->GetBaseURLForDataURL().possibly_invalid_spec(); 89 } else { 90 url_string = web_contents()->GetURL().spec(); 91 } 92 93 ScopedJavaLocalRef<jstring> jstring_url( 94 ConvertUTF8ToJavaString(env, url_string)); 95 Java_WebContentsObserverAndroid_didStopLoading( 96 env, obj.obj(), jstring_url.obj()); 97 } 98 99 void WebContentsObserverAndroid::DidFailProvisionalLoad( 100 int64 frame_id, 101 bool is_main_frame, 102 const GURL& validated_url, 103 int error_code, 104 const string16& error_description, 105 RenderViewHost* render_view_host) { 106 DidFailLoadInternal( 107 true, is_main_frame, error_code, error_description, validated_url); 108 } 109 110 void WebContentsObserverAndroid::DidFailLoad( 111 int64 frame_id, 112 const GURL& validated_url, 113 bool is_main_frame, 114 int error_code, 115 const string16& error_description, 116 RenderViewHost* render_view_host) { 117 DidFailLoadInternal( 118 false, is_main_frame, error_code, error_description, validated_url); 119 } 120 121 void WebContentsObserverAndroid::DidNavigateMainFrame( 122 const LoadCommittedDetails& details, 123 const FrameNavigateParams& params) { 124 JNIEnv* env = AttachCurrentThread(); 125 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 126 if (obj.is_null()) 127 return; 128 ScopedJavaLocalRef<jstring> jstring_url( 129 ConvertUTF8ToJavaString(env, params.url.spec())); 130 ScopedJavaLocalRef<jstring> jstring_base_url( 131 ConvertUTF8ToJavaString(env, params.base_url.spec())); 132 Java_WebContentsObserverAndroid_didNavigateMainFrame( 133 env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(), 134 details.is_navigation_to_different_page()); 135 } 136 137 void WebContentsObserverAndroid::DidNavigateAnyFrame( 138 const LoadCommittedDetails& details, 139 const FrameNavigateParams& params) { 140 JNIEnv* env = AttachCurrentThread(); 141 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 142 if (obj.is_null()) 143 return; 144 ScopedJavaLocalRef<jstring> jstring_url( 145 ConvertUTF8ToJavaString(env, params.url.spec())); 146 ScopedJavaLocalRef<jstring> jstring_base_url( 147 ConvertUTF8ToJavaString(env, params.base_url.spec())); 148 jboolean jboolean_is_reload = 149 PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_RELOAD); 150 151 Java_WebContentsObserverAndroid_didNavigateAnyFrame( 152 env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(), 153 jboolean_is_reload); 154 } 155 156 void WebContentsObserverAndroid::DidStartProvisionalLoadForFrame( 157 int64 frame_id, 158 int64 parent_frame_id, 159 bool is_main_frame, 160 const GURL& validated_url, 161 bool is_error_page, 162 bool is_iframe_srcdoc, 163 RenderViewHost* render_view_host) { 164 JNIEnv* env = AttachCurrentThread(); 165 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 166 if (obj.is_null()) 167 return; 168 ScopedJavaLocalRef<jstring> jstring_url( 169 ConvertUTF8ToJavaString(env, validated_url.spec())); 170 Java_WebContentsObserverAndroid_didStartProvisionalLoadForFrame( 171 env, obj.obj(), frame_id, parent_frame_id, is_main_frame, 172 jstring_url.obj(), is_error_page, is_iframe_srcdoc); 173 } 174 175 void WebContentsObserverAndroid::DidCommitProvisionalLoadForFrame( 176 int64 frame_id, 177 bool is_main_frame, 178 const GURL& url, 179 PageTransition transition_type, 180 RenderViewHost* render_view_host) { 181 JNIEnv* env = AttachCurrentThread(); 182 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 183 if (obj.is_null()) 184 return; 185 ScopedJavaLocalRef<jstring> jstring_url( 186 ConvertUTF8ToJavaString(env, url.spec())); 187 Java_WebContentsObserverAndroid_didCommitProvisionalLoadForFrame( 188 env, obj.obj(), frame_id, is_main_frame, jstring_url.obj(), 189 transition_type); 190 } 191 192 void WebContentsObserverAndroid::DidFinishLoad( 193 int64 frame_id, 194 const GURL& validated_url, 195 bool is_main_frame, 196 RenderViewHost* render_view_host) { 197 JNIEnv* env = AttachCurrentThread(); 198 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 199 if (obj.is_null()) 200 return; 201 ScopedJavaLocalRef<jstring> jstring_url( 202 ConvertUTF8ToJavaString(env, validated_url.spec())); 203 Java_WebContentsObserverAndroid_didFinishLoad( 204 env, obj.obj(), frame_id, jstring_url.obj(), is_main_frame); 205 } 206 207 void WebContentsObserverAndroid::DidChangeVisibleSSLState() { 208 JNIEnv* env = AttachCurrentThread(); 209 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 210 if (obj.is_null()) 211 return; 212 Java_WebContentsObserverAndroid_didChangeVisibleSSLState(env, obj.obj()); 213 } 214 215 void WebContentsObserverAndroid::DidFailLoadInternal( 216 bool is_provisional_load, 217 bool is_main_frame, 218 int error_code, 219 const string16& description, 220 const GURL& url) { 221 JNIEnv* env = AttachCurrentThread(); 222 ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); 223 if (obj.is_null()) 224 return; 225 ScopedJavaLocalRef<jstring> jstring_error_description( 226 ConvertUTF16ToJavaString(env, description)); 227 ScopedJavaLocalRef<jstring> jstring_url( 228 ConvertUTF8ToJavaString(env, url.spec())); 229 230 Java_WebContentsObserverAndroid_didFailLoad( 231 env, obj.obj(), 232 is_provisional_load, 233 is_main_frame, 234 error_code, 235 jstring_error_description.obj(), jstring_url.obj()); 236 } 237 238 bool RegisterWebContentsObserverAndroid(JNIEnv* env) { 239 if (!HasClass(env, kWebContentsObserverAndroidClassPath)) { 240 DLOG(ERROR) << "Unable to find class WebContentsObserverAndroid!"; 241 return false; 242 } 243 return RegisterNativesImpl(env); 244 } 245 } // namespace content 246