blob: 25123a214a94bd8e7140b2fe673c758f2e149c59 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/android/content_view_core.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view_android.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/user_agent.h"
#include "jni/ContentViewCoreImpl_jni.h"
#include "ui/android/window_android.h"
using base::android::AttachCurrentThread;
using base::android::JavaParamRef;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
namespace content {
namespace {
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewFromHost(
RenderViewHost* host) {
return static_cast<RenderWidgetHostViewAndroid*>(
host->GetWidget()->GetView());
}
} // namespace
ContentViewCore::ContentViewCore(JNIEnv* env,
const JavaRef<jobject>& obj,
WebContents* web_contents)
: WebContentsObserver(web_contents),
java_ref_(env, obj),
web_contents_(static_cast<WebContentsImpl*>(web_contents)) {
// Currently, the only use case we have for overriding a user agent involves
// spoofing a desktop Linux user agent for "Request desktop site".
// Automatically set it for all WebContents so that it is available when a
// NavigationEntry requires the user agent to be overridden.
const char kLinuxInfoStr[] = "X11; Linux x86_64";
std::string product = content::GetContentClient()->GetProduct();
std::string spoofed_ua =
BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
web_contents->SetUserAgentOverride(spoofed_ua, false);
}
ContentViewCore::~ContentViewCore() {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
java_ref_.reset();
if (!j_obj.is_null()) {
Java_ContentViewCoreImpl_onNativeContentViewCoreDestroyed(
env, j_obj, reinterpret_cast<intptr_t>(this));
}
}
void ContentViewCore::OnJavaContentViewCoreDestroyed(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
java_ref_.reset();
// Java peer has gone, ContentViewCore is not functional and waits to
// be destroyed with WebContents.
DCHECK(web_contents_);
}
void ContentViewCore::RenderViewReady() {
WebContentsViewAndroid* view =
static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
if (view->device_orientation() == 0)
return;
RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
if (rwhva)
rwhva->UpdateScreenInfo(GetViewAndroid());
web_contents_->OnScreenOrientationChange();
}
void ContentViewCore::WebContentsDestroyed() {
delete this;
}
void ContentViewCore::RenderViewHostChanged(RenderViewHost* old_host,
RenderViewHost* new_host) {
if (old_host) {
auto* view = GetRenderWidgetHostViewFromHost(old_host);
if (view)
view->UpdateNativeViewTree(nullptr);
view = GetRenderWidgetHostViewFromHost(new_host);
if (view)
view->UpdateNativeViewTree(GetViewAndroid());
}
SetFocusInternal(GetViewAndroid()->HasFocus());
}
RenderWidgetHostViewAndroid* ContentViewCore::GetRenderWidgetHostViewAndroid()
const {
RenderWidgetHostView* rwhv = NULL;
if (web_contents_) {
rwhv = web_contents_->GetRenderWidgetHostView();
if (web_contents_->ShowingInterstitialPage()) {
rwhv = web_contents_->GetInterstitialPage()
->GetMainFrame()
->GetRenderViewHost()
->GetWidget()
->GetView();
}
}
return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
}
ui::ViewAndroid* ContentViewCore::GetViewAndroid() const {
return web_contents_->GetView()->GetNativeView();
}
// ----------------------------------------------------------------------------
// Methods called from Java via JNI
// ----------------------------------------------------------------------------
void ContentViewCore::SetFocusInternal(bool focused) {
if (!GetRenderWidgetHostViewAndroid())
return;
if (focused)
GetRenderWidgetHostViewAndroid()->GotFocus();
else
GetRenderWidgetHostViewAndroid()->LostFocus();
}
// This is called for each ContentView.
jlong JNI_ContentViewCoreImpl_Init(JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& jweb_contents) {
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
WebContents::FromJavaWebContents(jweb_contents));
CHECK(web_contents)
<< "A ContentViewCore should be created with a valid WebContents.";
return reinterpret_cast<intptr_t>(
new ContentViewCore(env, obj, web_contents));
}
} // namespace content