Chromium Code Reviews| Index: content/browser/android/content_view_core_impl.cc |
| diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc |
| index 4e8d88fdfdfa8f5fc41359bc5a1f187cfadba4ee..fe55dba89f61b3fd854d219115f9486cb85f84a1 100644 |
| --- a/content/browser/android/content_view_core_impl.cc |
| +++ b/content/browser/android/content_view_core_impl.cc |
| @@ -29,6 +29,7 @@ |
| #include "content/public/browser/notification_types.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/content_client.h" |
| +#include "content/public/common/frame_navigate_params.h" |
| #include "content/public/common/page_transition_types.h" |
| #include "jni/ContentViewCore_jni.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" |
| @@ -44,6 +45,7 @@ using base::android::ConvertJavaStringToUTF16; |
| using base::android::ConvertJavaStringToUTF8; |
| using base::android::ConvertUTF16ToJavaString; |
| using base::android::ConvertUTF8ToJavaString; |
| +using base::android::CheckException; |
| using base::android::GetClass; |
| using base::android::HasField; |
| using base::android::JavaByteArrayToByteVector; |
| @@ -70,12 +72,134 @@ struct ContentViewCoreImpl::JavaObject { |
| }; |
| +// static |
| +ContentViewCore* ContentViewCore::FromWebContents(WebContents* web_contents) { |
| + return web_contents->GetContentNativeView(); |
| +} |
| + |
| +// static |
| ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env, |
| jobject obj) { |
| return reinterpret_cast<ContentViewCore*>( |
| env->GetIntField(obj, g_native_content_view)); |
| } |
| +class ContentViewCoreImpl::ContentViewWebContentsObserver |
| + : public WebContentsObserver { |
| + public: |
| + ContentViewWebContentsObserver(WebContents* web_contents, |
| + ContentViewCoreImpl* parent); |
| + virtual ~ContentViewWebContentsObserver(); |
| + |
| + private: |
| + // WebContentsObserver |
| + virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE; |
| + virtual void DidStartLoading(RenderViewHost* render_view_host) OVERRIDE; |
| + virtual void DidStartProvisionalLoadForFrame( |
| + int64 frame_id, |
| + bool is_main_frame, |
| + const GURL& validated_url, |
| + bool is_error_page, |
| + RenderViewHost* render_view_host) OVERRIDE; |
| + virtual void DidFailProvisionalLoad( |
| + int64 frame_id, |
| + bool is_main_frame, |
| + const GURL& validated_url, |
| + int error_code, |
| + const string16& error_description, |
| + RenderViewHost* render_view_host) OVERRIDE; |
| + virtual void DidFailLoad(int64 frame_id, |
| + const GURL& validated_url, |
| + bool is_main_frame, |
| + int error_code, |
| + const string16& error_description, |
| + RenderViewHost* render_view_host) OVERRIDE; |
| + virtual void DidFinishLoad(int64 frame_id, |
| + const GURL& validated_url, |
| + bool is_main_frame, |
| + RenderViewHost* render_view_host) OVERRIDE; |
| + virtual void DidNavigateMainFrame( |
| + const LoadCommittedDetails& details, |
| + const FrameNavigateParams& params) OVERRIDE; |
| + |
| + NotificationRegistrar registrar_; |
| + |
| + ContentViewCoreImpl* parent_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ContentViewWebContentsObserver); |
| +}; |
| + |
| +ContentViewCoreImpl::ContentViewWebContentsObserver:: |
| + ContentViewWebContentsObserver(WebContents* web_contents, |
| + ContentViewCoreImpl* parent) |
| + : WebContentsObserver(web_contents), |
| + parent_(parent) { |
| +} |
| + |
| +ContentViewCoreImpl::ContentViewWebContentsObserver:: |
| + ~ContentViewWebContentsObserver() { |
| +} |
| + |
| +void ContentViewCoreImpl::ContentViewWebContentsObserver:: |
| + WebContentsDestroyed(WebContents* web_contents) { |
| + parent_->DetachWebContents(web_contents); |
| +} |
| + |
| +void ContentViewCoreImpl::ContentViewWebContentsObserver::DidStartLoading( |
| + RenderViewHost* render_view_host) { |
| + parent_->DidStartLoading(); |
| +} |
| + |
| +void ContentViewCoreImpl::ContentViewWebContentsObserver:: |
| + DidStartProvisionalLoadForFrame(int64 frame_id, |
| + bool is_main_frame, |
| + const GURL& validated_url, |
| + bool is_error_page, |
| + RenderViewHost* render_view_host) { |
| + // Don't report status for page components like iframes to comply with legacy |
| + // WebView behavior. |
| + if (is_main_frame) |
| + parent_->OnPageStarted(validated_url); |
| +} |
| + |
| +void ContentViewCoreImpl::ContentViewWebContentsObserver:: |
| + DidFailProvisionalLoad(int64 frame_id, |
| + bool is_main_frame, |
| + const GURL& validated_url, |
| + int error_code, |
| + const string16& error_description, |
| + RenderViewHost* render_view_host) { |
| + // Don't report status for page components like iframes to comply with legacy |
| + // WebView behavior. |
| + if (is_main_frame) |
| + parent_->OnPageFailed(error_code, error_description, validated_url); |
| +} |
| + |
| +void ContentViewCoreImpl::ContentViewWebContentsObserver::DidFailLoad( |
| + int64 frame_id, const GURL& validated_url, bool is_main_frame, |
| + int error_code, const string16& error_description, |
| + RenderViewHost* render_view_host) { |
| + // This is reported only for legacy WebView compatibility. The browser only |
| + // needs to be notified of provisional load failures. |
| + if (is_main_frame) |
| + parent_->OnPageFailed(error_code, error_description, validated_url); |
| +} |
| + |
| +void ContentViewCoreImpl::ContentViewWebContentsObserver::DidFinishLoad( |
| + int64 frame_id, const GURL& validated_url, bool is_main_frame, |
| + RenderViewHost* render_view_host) { |
| + // Don't report status for page components like iframes to comply with legacy |
| + // WebView behavior. |
| + if (is_main_frame) |
| + parent_->OnPageFinished(validated_url); |
| +} |
| + |
| +void ContentViewCoreImpl::ContentViewWebContentsObserver:: |
| + DidNavigateMainFrame( |
| + const LoadCommittedDetails& details, |
| + const FrameNavigateParams& params) { |
| + parent_->OnDidCommitMainFrame(params.url, params.base_url); |
| +} |
| ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env, jobject obj, |
| bool hardware_accelerated, |
| @@ -119,6 +243,12 @@ ContentViewCoreImpl::~ContentViewCoreImpl() { |
| delete java_object_; |
| java_object_ = NULL; |
| java_ref_.reset(); |
| + |
| + if (owns_web_contents_) { |
| + delete web_contents_; |
| + } else { |
| + DetachWebContents(web_contents_); |
| + } |
| } |
| void ContentViewCoreImpl::Destroy(JNIEnv* env, jobject obj) { |
| @@ -133,6 +263,64 @@ void ContentViewCoreImpl::InitWebContents(WebContents* web_contents) { |
| static_cast<WebContentsViewAndroid*>(web_contents_->GetView())-> |
| SetContentViewCore(this); |
| + |
| + web_contents_observer_.reset( |
| + new ContentViewWebContentsObserver(web_contents_, this)); |
| +} |
| + |
| +void ContentViewCoreImpl::ReplaceWebContents( |
| + WebContents* old_web_contents, |
| + WebContents* new_web_contents) { |
| + DCHECK(old_web_contents == web_contents_); |
| + notification_registrar_.Remove(this, |
| + NOTIFICATION_RENDER_VIEW_HOST_CHANGED, |
| + Source<NavigationController>(&web_contents_->GetController())); |
| + |
| + // Since we only use the bottom portion of the prerender stack, we have |
| + // to take care of everything incl. showing the new view ourselves. |
| + old_web_contents->GetRenderWidgetHostView()->Hide(); |
| + |
| + // Note that we are not deleting web_contents_ irrespective of |
| + // owns_web_contents_: it's the caller responsibility to delete it. |
| + // Note also that we don't change owns_web_contents_, so we'll own the new |
| + // WebContents if we owned the old one. |
| + InitWebContents(new_web_contents); |
| + |
| + new_web_contents->GetRenderWidgetHostView()->Show(); |
| +} |
| + |
| +WebContents* ContentViewCoreImpl::AcquireWebContents() { |
| + DCHECK(owns_web_contents_); |
| + owns_web_contents_ = false; |
| + return web_contents_; |
| +} |
| + |
| +void ContentViewCoreImpl::DetachWebContents(WebContents* web_contents) { |
| + if (web_contents_) { |
| + DCHECK(web_contents_ == web_contents); |
| + |
| + static_cast<WebContentsViewAndroid*>( |
| + web_contents_->GetView())->SetContentViewCore( |
| + base::WeakPtr<ContentViewCoreImpl>()); |
| + |
| + // Terminate the renderer process if this is the last tab. |
| + // If there's no unload listener, FastShutdownForPageCount kills the |
| + // renderer process. Otherwise, we go with the slow path where renderer |
| + // process shuts down itself when ref count becomes 0. |
| + RenderProcessHost* process = web_contents_->GetRenderProcessHost(); |
| + process->FastShutdownForPageCount(1); |
| + |
| + web_contents_ = NULL; |
| + owns_web_contents_ = false; |
| + |
| + // NOTE: since it's possible that the web_contents_ pointer can be cleared |
| + // out, we should really be checking if it's NULL before each use. However, |
| + // this really shouldn't happen in practice - right now, it only happens |
| + // when a Tab is deleted (which deletes WebContents) but the |
| + // ContentViewCore associated with the Tab is not. This only occurs when |
| + // code is explicitly changed for some type of testing. Because of this, |
| + // references to web_contents_ are generally not guarded. |
| + } |
| } |
| void ContentViewCoreImpl::Observe(int type, |
| @@ -520,6 +708,7 @@ int ContentViewCoreImpl::GetNavigationHistory(JNIEnv* env, |
| Java_ContentViewCore_addToNavigationHistory(env, obj, context, j_url.obj(), |
| j_virtual_url.obj(), j_original_url.obj(), j_title.obj(), |
| j_bitmap.obj()); |
| + CheckException(env); |
|
Yaron
2012/09/20 04:13:53
Should be done automatically by jni-generator
|
| } |
| return controller.GetCurrentEntryIndex(); |
| @@ -578,6 +767,24 @@ void ContentViewCoreImpl::OnTabCrashed(const base::ProcessHandle handle) { |
| NOTIMPLEMENTED() << "not upstreamed yet"; |
| } |
| +// Called from UI thread |
| +void ContentViewCoreImpl::Invalidate() { |
| + JNIEnv* env = AttachCurrentThread(); |
| + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); |
| + if (obj.is_null()) |
| + return; |
| + Java_ContentViewCore_invalidate(env, obj.obj()); |
| +} |
| + |
| +// Called from non-UI thread |
| +void ContentViewCoreImpl::PostInvalidate() { |
| + JNIEnv* env = AttachCurrentThread(); |
| + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); |
| + if (obj.is_null()) |
| + return; |
| + Java_ContentViewCore_postInvalidate(env, obj.obj()); |
| +} |
| + |
| void ContentViewCoreImpl::ImeUpdateAdapter(int native_ime_adapter, |
| int text_input_type, |
| const std::string& text, |
| @@ -696,6 +903,43 @@ void ContentViewCoreImpl::DidStartLoading() { |
| Java_ContentViewCore_didStartLoading(env, j_obj.obj()); |
| } |
| +void ContentViewCoreImpl::OnPageStarted(const GURL& validated_url) { |
| + if (content_view_client_.get()) |
| + content_view_client_->OnPageStarted(validated_url); |
| + JNIEnv* env = AttachCurrentThread(); |
| + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); |
| + if (obj.is_null()) |
| + return; |
| + Java_ContentViewCore_onPageStarted(env, obj.obj()); |
| +} |
| + |
| +void ContentViewCoreImpl::OnPageFinished(const GURL& validated_url) { |
| + if (content_view_client_.get()) |
| + content_view_client_->OnPageFinished(validated_url); |
| + |
| + JNIEnv* env = AttachCurrentThread(); |
| + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); |
| + if (obj.is_null()) |
| + return; |
| + ScopedJavaLocalRef<jstring> jvalidated_url = |
| + ConvertUTF8ToJavaString(env, validated_url.spec()); |
| + Java_ContentViewCore_onPageFinished(env, obj.obj(), jvalidated_url.obj()); |
| +} |
| + |
| +void ContentViewCoreImpl::OnDidCommitMainFrame(const GURL& url, |
| + const GURL& base_url) { |
| + if (content_view_client_.get()) |
| + content_view_client_->OnDidCommitMainFrame(url, base_url); |
| +} |
| + |
| +void ContentViewCoreImpl::OnPageFailed(int error_code, |
| + const string16& description, |
| + const GURL& failing_url) { |
| + if (content_view_client_.get()) |
| + content_view_client_->OnReceivedError(error_code, description, failing_url); |
| + OnPageFinished(failing_url); |
| +} |
| + |
| void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) { |
| JNIEnv* env = AttachCurrentThread(); |
| ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); |