Home | History | Annotate | Download | only in android
      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