Commit 47bd294d authored by Scott Violet's avatar Scott Violet Committed by Commit Bot

weblayer: adds fullscreen support

BUG=none
TEST=none

Change-Id: Id93a18c55d148eb9cf4f7fea9a53f2c4add63d6f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1861514
Commit-Queue: Scott Violet <sky@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706635}
parent ea3e8b05
...@@ -60,6 +60,7 @@ jumbo_static_library("weblayer_lib") { ...@@ -60,6 +60,7 @@ jumbo_static_library("weblayer_lib") {
"common/content_client_impl.h", "common/content_client_impl.h",
"public/browser_controller.h", "public/browser_controller.h",
"public/browser_observer.h", "public/browser_observer.h",
"public/fullscreen_delegate.h",
"public/main.h", "public/main.h",
"public/navigation.h", "public/navigation.h",
"public/navigation_controller.h", "public/navigation_controller.h",
...@@ -153,6 +154,8 @@ jumbo_static_library("weblayer_lib") { ...@@ -153,6 +154,8 @@ jumbo_static_library("weblayer_lib") {
"browser/browser_observer_proxy.h", "browser/browser_observer_proxy.h",
"browser/content_view_render_view.cc", "browser/content_view_render_view.cc",
"browser/content_view_render_view.h", "browser/content_view_render_view.h",
"browser/fullscreen_delegate_proxy.cc",
"browser/fullscreen_delegate_proxy.h",
"browser/top_controls_container_view.cc", "browser/top_controls_container_view.cc",
"browser/top_controls_container_view.h", "browser/top_controls_container_view.h",
] ]
......
...@@ -4,13 +4,16 @@ ...@@ -4,13 +4,16 @@
#include "weblayer/browser/browser_controller_impl.h" #include "weblayer/browser/browser_controller_impl.h"
#include "base/auto_reset.h"
#include "base/logging.h" #include "base/logging.h"
#include "content/public/browser/interstitial_page.h" #include "content/public/browser/interstitial_page.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/browser_controls_state.h" #include "content/public/common/browser_controls_state.h"
#include "weblayer/browser/navigation_controller_impl.h" #include "weblayer/browser/navigation_controller_impl.h"
#include "weblayer/browser/profile_impl.h" #include "weblayer/browser/profile_impl.h"
#include "weblayer/public/browser_observer.h" #include "weblayer/public/browser_observer.h"
#include "weblayer/public/fullscreen_delegate.h"
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
#include "ui/views/controls/webview/webview.h" #include "ui/views/controls/webview/webview.h"
...@@ -26,6 +29,14 @@ namespace weblayer { ...@@ -26,6 +29,14 @@ namespace weblayer {
namespace { namespace {
// Pointer value of this is used as a key in base::SupportsUserData for
// WebContents. Value of the key is an instance of |UserData|.
constexpr int kWebContentsUserDataKey = 0;
struct UserData : public base::SupportsUserData::Data {
BrowserControllerImpl* controller = nullptr;
};
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
BrowserController* g_last_browser_controller; BrowserController* g_last_browser_controller;
#endif #endif
...@@ -40,6 +51,9 @@ BrowserControllerImpl::BrowserControllerImpl(ProfileImpl* profile) ...@@ -40,6 +51,9 @@ BrowserControllerImpl::BrowserControllerImpl(ProfileImpl* profile)
content::WebContents::CreateParams create_params( content::WebContents::CreateParams create_params(
profile_->GetBrowserContext()); profile_->GetBrowserContext());
web_contents_ = content::WebContents::Create(create_params); web_contents_ = content::WebContents::Create(create_params);
std::unique_ptr<UserData> user_data = std::make_unique<UserData>();
user_data->controller = this;
web_contents_->SetUserData(&kWebContentsUserDataKey, std::move(user_data));
web_contents_->SetDelegate(this); web_contents_->SetDelegate(this);
Observe(web_contents_.get()); Observe(web_contents_.get());
...@@ -53,6 +67,36 @@ BrowserControllerImpl::~BrowserControllerImpl() { ...@@ -53,6 +67,36 @@ BrowserControllerImpl::~BrowserControllerImpl() {
web_contents_.reset(); web_contents_.reset();
} }
// static
BrowserControllerImpl* BrowserControllerImpl::FromWebContents(
content::WebContents* web_contents) {
return reinterpret_cast<UserData*>(
web_contents->GetUserData(&kWebContentsUserDataKey))
->controller;
}
void BrowserControllerImpl::SetFullscreenDelegate(
FullscreenDelegate* delegate) {
if (delegate == fullscreen_delegate_)
return;
const bool had_delegate = (fullscreen_delegate_ != nullptr);
const bool has_delegate = (delegate != nullptr);
// If currently fullscreen, and the delegate is being set to null, force an
// exit now (otherwise the delegate can't take us out of fullscreen).
if (is_fullscreen_ && fullscreen_delegate_ && had_delegate != has_delegate)
OnExitFullscreen();
fullscreen_delegate_ = delegate;
// Whether fullscreen is enabled depends upon whether there is a delegate. If
// having a delegate changed, then update the renderer (which is where
// fullscreen enabled is tracked).
content::RenderViewHost* host = web_contents_->GetRenderViewHost();
if (had_delegate != has_delegate && host)
host->OnWebkitPreferencesChanged();
}
void BrowserControllerImpl::AddObserver(BrowserObserver* observer) { void BrowserControllerImpl::AddObserver(BrowserObserver* observer) {
observers_.AddObserver(observer); observers_.AddObserver(observer);
} }
...@@ -134,6 +178,39 @@ bool BrowserControllerImpl::DoBrowserControlsShrinkRendererSize( ...@@ -134,6 +178,39 @@ bool BrowserControllerImpl::DoBrowserControlsShrinkRendererSize(
return true; return true;
} }
bool BrowserControllerImpl::EmbedsFullscreenWidget() {
return true;
}
void BrowserControllerImpl::EnterFullscreenModeForTab(
content::WebContents* web_contents,
const GURL& origin,
const blink::mojom::FullscreenOptions& options) {
// TODO: support |options|.
is_fullscreen_ = true;
auto exit_fullscreen_closure = base::BindOnce(
&BrowserControllerImpl::OnExitFullscreen, weak_ptr_factory_.GetWeakPtr());
base::AutoReset<bool> reset(&processing_enter_fullscreen_, true);
fullscreen_delegate_->EnterFullscreen(std::move(exit_fullscreen_closure));
}
void BrowserControllerImpl::ExitFullscreenModeForTab(
content::WebContents* web_contents) {
is_fullscreen_ = false;
fullscreen_delegate_->ExitFullscreen();
}
bool BrowserControllerImpl::IsFullscreenForTabOrPending(
const content::WebContents* web_contents) {
return is_fullscreen_;
}
blink::mojom::DisplayMode BrowserControllerImpl::GetDisplayMode(
const content::WebContents* web_contents) {
return is_fullscreen_ ? blink::mojom::DisplayMode::kFullscreen
: blink::mojom::DisplayMode::kBrowser;
}
void BrowserControllerImpl::DidFirstVisuallyNonEmptyPaint() { void BrowserControllerImpl::DidFirstVisuallyNonEmptyPaint() {
for (auto& observer : observers_) for (auto& observer : observers_)
observer.FirstContentfulPaint(); observer.FirstContentfulPaint();
...@@ -156,6 +233,15 @@ void BrowserControllerImpl::DidFinishNavigation( ...@@ -156,6 +233,15 @@ void BrowserControllerImpl::DidFinishNavigation(
#endif #endif
} }
void BrowserControllerImpl::OnExitFullscreen() {
// If |processing_enter_fullscreen_| is true, it means the callback is being
// called while processing EnterFullscreenModeForTab(). WebContents doesn't
// deal well with this. FATAL as Android generally doesn't run with DCHECKs.
LOG_IF(FATAL, !processing_enter_fullscreen_)
<< "exiting fullscreen while entering fullscreen is not supported";
web_contents_->ExitFullscreen(/* will_cause_resize */ false);
}
std::unique_ptr<BrowserController> BrowserController::Create(Profile* profile) { std::unique_ptr<BrowserController> BrowserController::Create(Profile* profile) {
return std::make_unique<BrowserControllerImpl>( return std::make_unique<BrowserControllerImpl>(
static_cast<ProfileImpl*>(profile)); static_cast<ProfileImpl*>(profile));
......
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
#ifndef WEBLAYER_BROWSER_BROWSER_CONTROLLER_IMPL_H_ #ifndef WEBLAYER_BROWSER_BROWSER_CONTROLLER_IMPL_H_
#define WEBLAYER_BROWSER_BROWSER_CONTROLLER_IMPL_H_ #define WEBLAYER_BROWSER_BROWSER_CONTROLLER_IMPL_H_
#include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_delegate.h"
...@@ -21,6 +24,7 @@ class WebContents; ...@@ -21,6 +24,7 @@ class WebContents;
} }
namespace weblayer { namespace weblayer {
class FullscreenDelegate;
class NavigationControllerImpl; class NavigationControllerImpl;
class ProfileImpl; class ProfileImpl;
...@@ -35,6 +39,11 @@ class BrowserControllerImpl : public BrowserController, ...@@ -35,6 +39,11 @@ class BrowserControllerImpl : public BrowserController,
explicit BrowserControllerImpl(ProfileImpl* profile); explicit BrowserControllerImpl(ProfileImpl* profile);
~BrowserControllerImpl() override; ~BrowserControllerImpl() override;
// Returns the BrowserControllerImpl from the specified WebContents, or null
// if BrowserControllerImpl was not created by a BrowserControllerImpl.
static BrowserControllerImpl* FromWebContents(
content::WebContents* web_contents);
content::WebContents* web_contents() const { return web_contents_.get(); } content::WebContents* web_contents() const { return web_contents_.get(); }
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
...@@ -47,8 +56,11 @@ class BrowserControllerImpl : public BrowserController, ...@@ -47,8 +56,11 @@ class BrowserControllerImpl : public BrowserController,
jlong native_top_controls_container_view); jlong native_top_controls_container_view);
#endif #endif
FullscreenDelegate* fullscreen_delegate() { return fullscreen_delegate_; }
private: private:
// BrowserController implementation: // BrowserController implementation:
void SetFullscreenDelegate(FullscreenDelegate* delegate) override;
void AddObserver(BrowserObserver* observer) override; void AddObserver(BrowserObserver* observer) override;
void RemoveObserver(BrowserObserver* observer) override; void RemoveObserver(BrowserObserver* observer) override;
NavigationController* GetNavigationController() override; NavigationController* GetNavigationController() override;
...@@ -66,12 +78,26 @@ class BrowserControllerImpl : public BrowserController, ...@@ -66,12 +78,26 @@ class BrowserControllerImpl : public BrowserController,
int GetTopControlsHeight() override; int GetTopControlsHeight() override;
bool DoBrowserControlsShrinkRendererSize( bool DoBrowserControlsShrinkRendererSize(
const content::WebContents* web_contents) override; const content::WebContents* web_contents) override;
bool EmbedsFullscreenWidget() override;
void EnterFullscreenModeForTab(
content::WebContents* web_contents,
const GURL& origin,
const blink::mojom::FullscreenOptions& options) override;
void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
bool IsFullscreenForTabOrPending(
const content::WebContents* web_contents) override;
blink::mojom::DisplayMode GetDisplayMode(
const content::WebContents* web_contents) override;
// content::WebContentsObserver implementation: // content::WebContentsObserver implementation:
void DidFirstVisuallyNonEmptyPaint() override; void DidFirstVisuallyNonEmptyPaint() override;
void DidFinishNavigation( void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override; content::NavigationHandle* navigation_handle) override;
// Called from closure supplied to delegate to exit fullscreen.
void OnExitFullscreen();
FullscreenDelegate* fullscreen_delegate_ = nullptr;
ProfileImpl* profile_; ProfileImpl* profile_;
std::unique_ptr<content::WebContents> web_contents_; std::unique_ptr<content::WebContents> web_contents_;
std::unique_ptr<NavigationControllerImpl> navigation_controller_; std::unique_ptr<NavigationControllerImpl> navigation_controller_;
...@@ -80,6 +106,12 @@ class BrowserControllerImpl : public BrowserController, ...@@ -80,6 +106,12 @@ class BrowserControllerImpl : public BrowserController,
TopControlsContainerView* top_controls_container_view_ = nullptr; TopControlsContainerView* top_controls_container_view_ = nullptr;
#endif #endif
bool is_fullscreen_ = false;
// Set to true doing EnterFullscreenModeForTab().
bool processing_enter_fullscreen_ = false;
base::WeakPtrFactory<BrowserControllerImpl> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(BrowserControllerImpl); DISALLOW_COPY_AND_ASSIGN(BrowserControllerImpl);
}; };
......
...@@ -17,14 +17,17 @@ ...@@ -17,14 +17,17 @@
#include "content/public/browser/network_service_instance.h" #include "content/public/browser/network_service_instance.h"
#include "content/public/common/service_names.mojom.h" #include "content/public/common/service_names.mojom.h"
#include "content/public/common/user_agent.h" #include "content/public/common/user_agent.h"
#include "content/public/common/web_preferences.h"
#include "services/network/network_service.h" #include "services/network/network_service.h"
#include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/network_service.mojom.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h" #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "url/gurl.h" #include "url/gurl.h"
#include "url/origin.h" #include "url/origin.h"
#include "weblayer/browser/browser_controller_impl.h"
#include "weblayer/browser/browser_main_parts_impl.h" #include "weblayer/browser/browser_main_parts_impl.h"
#include "weblayer/browser/weblayer_content_browser_overlay_manifest.h" #include "weblayer/browser/weblayer_content_browser_overlay_manifest.h"
#include "weblayer/public/fullscreen_delegate.h"
#include "weblayer/public/main.h" #include "weblayer/public/main.h"
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
...@@ -99,6 +102,19 @@ blink::UserAgentMetadata ContentBrowserClientImpl::GetUserAgentMetadata() { ...@@ -99,6 +102,19 @@ blink::UserAgentMetadata ContentBrowserClientImpl::GetUserAgentMetadata() {
return metadata; return metadata;
} }
void ContentBrowserClientImpl::OverrideWebkitPrefs(
content::RenderViewHost* render_view_host,
content::WebPreferences* prefs) {
content::WebContents* web_contents =
content::WebContents::FromRenderViewHost(render_view_host);
if (!web_contents)
return;
BrowserControllerImpl* browser_controller =
BrowserControllerImpl::FromWebContents(web_contents);
prefs->fullscreen_supported =
browser_controller && browser_controller->fullscreen_delegate();
}
mojo::Remote<network::mojom::NetworkContext> mojo::Remote<network::mojom::NetworkContext>
ContentBrowserClientImpl::CreateNetworkContext( ContentBrowserClientImpl::CreateNetworkContext(
content::BrowserContext* context, content::BrowserContext* context,
......
...@@ -35,6 +35,8 @@ class ContentBrowserClientImpl : public content::ContentBrowserClient { ...@@ -35,6 +35,8 @@ class ContentBrowserClientImpl : public content::ContentBrowserClient {
base::StringPiece name) override; base::StringPiece name) override;
std::string GetUserAgent() override; std::string GetUserAgent() override;
blink::UserAgentMetadata GetUserAgentMetadata() override; blink::UserAgentMetadata GetUserAgentMetadata() override;
void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
content::WebPreferences* prefs) override;
mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext( mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext(
content::BrowserContext* context, content::BrowserContext* context,
bool in_memory, bool in_memory,
......
// Copyright 2019 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 "weblayer/browser/fullscreen_delegate_proxy.h"
#include "base/android/jni_string.h"
#include "url/gurl.h"
#include "weblayer/browser/browser_controller_impl.h"
#include "weblayer/browser/java/jni/FullscreenDelegateProxy_jni.h"
using base::android::AttachCurrentThread;
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaLocalRef;
namespace weblayer {
FullscreenDelegateProxy::FullscreenDelegateProxy(
JNIEnv* env,
jobject obj,
BrowserController* browser_controller)
: browser_controller_(browser_controller), java_observer_(env, obj) {
browser_controller_->SetFullscreenDelegate(this);
}
FullscreenDelegateProxy::~FullscreenDelegateProxy() {
browser_controller_->SetFullscreenDelegate(nullptr);
}
void FullscreenDelegateProxy::EnterFullscreen(base::OnceClosure exit_closure) {
exit_fullscreen_closure_ = std::move(exit_closure);
Java_FullscreenDelegateProxy_enterFullscreen(AttachCurrentThread(),
java_observer_);
}
void FullscreenDelegateProxy::ExitFullscreen() {
Java_FullscreenDelegateProxy_exitFullscreen(AttachCurrentThread(),
java_observer_);
}
void FullscreenDelegateProxy::DoExitFullscreen(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& caller) {
if (exit_fullscreen_closure_)
std::move(exit_fullscreen_closure_).Run();
}
static jlong JNI_FullscreenDelegateProxy_CreateFullscreenDelegateProxy(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& proxy,
jlong browser_controller) {
return reinterpret_cast<jlong>(new FullscreenDelegateProxy(
env, proxy,
reinterpret_cast<BrowserControllerImpl*>(browser_controller)));
}
static void JNI_FullscreenDelegateProxy_DeleteFullscreenDelegateProxy(
JNIEnv* env,
jlong proxy) {
delete reinterpret_cast<FullscreenDelegateProxy*>(proxy);
}
} // namespace weblayer
// Copyright 2019 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.
#ifndef WEBLAYER_BROWSER_FULLSCREEN_DELEGATE_PROXY_H_
#define WEBLAYER_BROWSER_FULLSCREEN_DELEGATE_PROXY_H_
#include <jni.h>
#include "base/android/scoped_java_ref.h"
#include "base/callback.h"
#include "base/macros.h"
#include "weblayer/public/fullscreen_delegate.h"
namespace weblayer {
class BrowserController;
// FullscreenDelegateProxy forwards all FullscreenDelegate functions to the
// Java side. There is at most one FullscreenDelegateProxy per
// BrowserController.
class FullscreenDelegateProxy : public FullscreenDelegate {
public:
FullscreenDelegateProxy(JNIEnv* env,
jobject obj,
BrowserController* browser_controller);
~FullscreenDelegateProxy() override;
// FullscreenDelegate:
void EnterFullscreen(base::OnceClosure exit_closure) override;
void ExitFullscreen() override;
// Called from the Java side to exit fullscreen.
void DoExitFullscreen(JNIEnv* env,
const base::android::JavaParamRef<jobject>& caller);
private:
BrowserController* browser_controller_;
base::android::ScopedJavaGlobalRef<jobject> java_observer_;
base::OnceClosure exit_fullscreen_closure_;
DISALLOW_COPY_AND_ASSIGN(FullscreenDelegateProxy);
};
} // namespace weblayer
#endif // WEBLAYER_BROWSER_FULLSCREEN_DELEGATE_PROXY_H_
...@@ -18,6 +18,7 @@ android_library("java") { ...@@ -18,6 +18,7 @@ android_library("java") {
"org/chromium/weblayer_private/BrowserObserverProxy.java", "org/chromium/weblayer_private/BrowserObserverProxy.java",
"org/chromium/weblayer_private/ContentView.java", "org/chromium/weblayer_private/ContentView.java",
"org/chromium/weblayer_private/ContentViewRenderView.java", "org/chromium/weblayer_private/ContentViewRenderView.java",
"org/chromium/weblayer_private/FullscreenDelegateProxy.java",
"org/chromium/weblayer_private/NavigationControllerImpl.java", "org/chromium/weblayer_private/NavigationControllerImpl.java",
"org/chromium/weblayer_private/NavigationImpl.java", "org/chromium/weblayer_private/NavigationImpl.java",
"org/chromium/weblayer_private/ProfileImpl.java", "org/chromium/weblayer_private/ProfileImpl.java",
...@@ -44,6 +45,7 @@ generate_jni("jni") { ...@@ -44,6 +45,7 @@ generate_jni("jni") {
"org/chromium/weblayer_private/BrowserControllerImpl.java", "org/chromium/weblayer_private/BrowserControllerImpl.java",
"org/chromium/weblayer_private/BrowserObserverProxy.java", "org/chromium/weblayer_private/BrowserObserverProxy.java",
"org/chromium/weblayer_private/ContentViewRenderView.java", "org/chromium/weblayer_private/ContentViewRenderView.java",
"org/chromium/weblayer_private/FullscreenDelegateProxy.java",
"org/chromium/weblayer_private/NavigationControllerImpl.java", "org/chromium/weblayer_private/NavigationControllerImpl.java",
"org/chromium/weblayer_private/NavigationImpl.java", "org/chromium/weblayer_private/NavigationImpl.java",
"org/chromium/weblayer_private/ProfileImpl.java", "org/chromium/weblayer_private/ProfileImpl.java",
...@@ -71,6 +73,7 @@ android_aidl("aidl") { ...@@ -71,6 +73,7 @@ android_aidl("aidl") {
"org/chromium/weblayer_private/aidl/IBrowserFragmentController.aidl", "org/chromium/weblayer_private/aidl/IBrowserFragmentController.aidl",
"org/chromium/weblayer_private/aidl/IChildProcessService.aidl", "org/chromium/weblayer_private/aidl/IChildProcessService.aidl",
"org/chromium/weblayer_private/aidl/IClientNavigation.aidl", "org/chromium/weblayer_private/aidl/IClientNavigation.aidl",
"org/chromium/weblayer_private/aidl/IFullscreenDelegateClient.aidl",
"org/chromium/weblayer_private/aidl/INavigation.aidl", "org/chromium/weblayer_private/aidl/INavigation.aidl",
"org/chromium/weblayer_private/aidl/INavigationController.aidl", "org/chromium/weblayer_private/aidl/INavigationController.aidl",
"org/chromium/weblayer_private/aidl/INavigationControllerClient.aidl", "org/chromium/weblayer_private/aidl/INavigationControllerClient.aidl",
......
...@@ -21,6 +21,7 @@ import org.chromium.ui.base.ActivityWindowAndroid; ...@@ -21,6 +21,7 @@ import org.chromium.ui.base.ActivityWindowAndroid;
import org.chromium.ui.base.ViewAndroidDelegate; import org.chromium.ui.base.ViewAndroidDelegate;
import org.chromium.weblayer_private.aidl.IBrowserController; import org.chromium.weblayer_private.aidl.IBrowserController;
import org.chromium.weblayer_private.aidl.IBrowserControllerClient; import org.chromium.weblayer_private.aidl.IBrowserControllerClient;
import org.chromium.weblayer_private.aidl.IFullscreenDelegateClient;
import org.chromium.weblayer_private.aidl.INavigationControllerClient; import org.chromium.weblayer_private.aidl.INavigationControllerClient;
import org.chromium.weblayer_private.aidl.IObjectWrapper; import org.chromium.weblayer_private.aidl.IObjectWrapper;
import org.chromium.weblayer_private.aidl.ObjectWrapper; import org.chromium.weblayer_private.aidl.ObjectWrapper;
...@@ -42,6 +43,7 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -42,6 +43,7 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
private WebContents mWebContents; private WebContents mWebContents;
private BrowserObserverProxy mBrowserObserverProxy; private BrowserObserverProxy mBrowserObserverProxy;
private NavigationControllerImpl mNavigationController; private NavigationControllerImpl mNavigationController;
private FullscreenDelegateProxy mFullscreenDelegateProxy;
private static class InternalAccessDelegateImpl private static class InternalAccessDelegateImpl
implements ViewEventSink.InternalAccessDelegate { implements ViewEventSink.InternalAccessDelegate {
...@@ -127,13 +129,34 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -127,13 +129,34 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
mBrowserObserverProxy = new BrowserObserverProxy(mNativeBrowserController, client); mBrowserObserverProxy = new BrowserObserverProxy(mNativeBrowserController, client);
} }
@Override
public void setFullscreenDelegateClient(IFullscreenDelegateClient client) {
if (client != null) {
if (mFullscreenDelegateProxy == null) {
mFullscreenDelegateProxy =
new FullscreenDelegateProxy(mNativeBrowserController, client);
} else {
mFullscreenDelegateProxy.setClient(client);
}
} else if (mFullscreenDelegateProxy != null) {
mFullscreenDelegateProxy.destroy();
mFullscreenDelegateProxy = null;
}
}
public void destroy() { public void destroy() {
BrowserControllerImplJni.get().setTopControlsContainerView( BrowserControllerImplJni.get().setTopControlsContainerView(
mNativeBrowserController, BrowserControllerImpl.this, 0); mNativeBrowserController, BrowserControllerImpl.this, 0);
mTopControlsContainerView.destroy(); mTopControlsContainerView.destroy();
mContentViewRenderView.destroy(); mContentViewRenderView.destroy();
if (mBrowserObserverProxy != null) mBrowserObserverProxy.destroy(); if (mBrowserObserverProxy != null) {
mBrowserObserverProxy = null; mBrowserObserverProxy.destroy();
mBrowserObserverProxy = null;
}
if (mFullscreenDelegateProxy != null) {
mFullscreenDelegateProxy.destroy();
mFullscreenDelegateProxy = null;
}
mNavigationController = null; mNavigationController = null;
BrowserControllerImplJni.get().deleteBrowserController(mNativeBrowserController); BrowserControllerImplJni.get().deleteBrowserController(mNativeBrowserController);
mNativeBrowserController = 0; mNativeBrowserController = 0;
......
// Copyright 2019 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.
package org.chromium.weblayer_private;
import android.os.RemoteException;
import android.webkit.ValueCallback;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.weblayer_private.aidl.APICallException;
import org.chromium.weblayer_private.aidl.IFullscreenDelegateClient;
import org.chromium.weblayer_private.aidl.ObjectWrapper;
/**
* Owns the c++ FullscreenDelegateProxy class, which is responsible for forwarding all
* FullscreenDelegate delegate calls to this class, which in turn forwards to the
* FullscreenDelegateClient.
*/
@JNINamespace("weblayer")
public final class FullscreenDelegateProxy {
private long mNativeFullscreenDelegateProxy;
private IFullscreenDelegateClient mClient;
FullscreenDelegateProxy(long browserController, IFullscreenDelegateClient client) {
assert client != null;
mClient = client;
mNativeFullscreenDelegateProxy =
FullscreenDelegateProxyJni.get().createFullscreenDelegateProxy(
this, browserController);
}
public void setClient(IFullscreenDelegateClient client) {
assert client != null;
mClient = client;
}
public void destroy() {
FullscreenDelegateProxyJni.get().deleteFullscreenDelegateProxy(
mNativeFullscreenDelegateProxy);
mNativeFullscreenDelegateProxy = 0;
}
@CalledByNative
private void enterFullscreen() {
try {
ValueCallback<Void> exitFullscreenCallback = new ValueCallback<Void>() {
@Override
public void onReceiveValue(Void result) {
if (mNativeFullscreenDelegateProxy == 0) {
throw new IllegalStateException("Called after destroy()");
}
FullscreenDelegateProxyJni.get().doExitFullscreen(
mNativeFullscreenDelegateProxy, FullscreenDelegateProxy.this);
}
};
mClient.enterFullscreen(ObjectWrapper.wrap(exitFullscreenCallback));
} catch (RemoteException e) {
throw new APICallException(e);
}
}
@CalledByNative
private void exitFullscreen() {
try {
mClient.exitFullscreen();
} catch (RemoteException e) {
throw new APICallException(e);
}
}
@NativeMethods
interface Natives {
long createFullscreenDelegateProxy(FullscreenDelegateProxy proxy, long browserController);
void deleteFullscreenDelegateProxy(long proxy);
void doExitFullscreen(long nativeFullscreenDelegateProxy, FullscreenDelegateProxy proxy);
}
}
...@@ -12,6 +12,7 @@ import android.view.ViewGroup.LayoutParams; ...@@ -12,6 +12,7 @@ import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent; import android.view.ViewParent;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
...@@ -31,6 +32,8 @@ class TopControlsContainerView extends FrameLayout { ...@@ -31,6 +32,8 @@ class TopControlsContainerView extends FrameLayout {
// ID used with ViewResourceAdapter. // ID used with ViewResourceAdapter.
private static final int TOP_CONTROLS_ID = 1001; private static final int TOP_CONTROLS_ID = 1001;
private static final long SYSTEM_UI_VIEWPORT_UPDATE_DELAY_MS = 500;
private long mNativeTopControlsContainerView; private long mNativeTopControlsContainerView;
private ViewResourceAdapter mViewResourceAdapter; private ViewResourceAdapter mViewResourceAdapter;
...@@ -50,6 +53,11 @@ class TopControlsContainerView extends FrameLayout { ...@@ -50,6 +53,11 @@ class TopControlsContainerView extends FrameLayout {
// True if scrolling. // True if scrolling.
private boolean mInTopControlsScroll; private boolean mInTopControlsScroll;
private boolean mIsFullscreen;
// Used to delay processing fullscreen requests.
private Runnable mSystemUiFullscreenResizeRunnable;
// Used to delay updating the image for the layer. // Used to delay updating the image for the layer.
private final Runnable mRefreshResourceIdRunnable = () -> { private final Runnable mRefreshResourceIdRunnable = () -> {
if (mView == null) return; if (mView == null) return;
...@@ -76,7 +84,7 @@ class TopControlsContainerView extends FrameLayout { ...@@ -76,7 +84,7 @@ class TopControlsContainerView extends FrameLayout {
}); });
mNativeTopControlsContainerView = mNativeTopControlsContainerView =
TopControlsContainerViewJni.get().createTopControlsContainerView( TopControlsContainerViewJni.get().createTopControlsContainerView(
webContents, contentViewRenderView.getNativeHandle()); this, webContents, contentViewRenderView.getNativeHandle());
} }
public void destroy() { public void destroy() {
...@@ -117,6 +125,7 @@ class TopControlsContainerView extends FrameLayout { ...@@ -117,6 +125,7 @@ class TopControlsContainerView extends FrameLayout {
view.layout(0, 0, getWidth(), getHeight()); view.layout(0, 0, getWidth(), getHeight());
createAdapterAndLayer(); createAdapterAndLayer();
} }
if (mIsFullscreen) hideTopControls();
} }
public View getView() { public View getView() {
...@@ -128,6 +137,7 @@ class TopControlsContainerView extends FrameLayout { ...@@ -128,6 +137,7 @@ class TopControlsContainerView extends FrameLayout {
*/ */
public void onTopControlsChanged(int topControlsOffsetY, int topContentOffsetY) { public void onTopControlsChanged(int topControlsOffsetY, int topContentOffsetY) {
if (mView == null) return; if (mView == null) return;
if (mIsFullscreen) return;
if (topContentOffsetY == getHeight()) { if (topContentOffsetY == getHeight()) {
finishTopControlsScroll(topContentOffsetY); finishTopControlsScroll(topContentOffsetY);
return; return;
...@@ -225,10 +235,35 @@ class TopControlsContainerView extends FrameLayout { ...@@ -225,10 +235,35 @@ class TopControlsContainerView extends FrameLayout {
if (mView != null) mView.setVisibility(View.VISIBLE); if (mView != null) mView.setVisibility(View.VISIBLE);
} }
@CalledByNative
private void didToggleFullscreenModeForTab(final boolean isFullscreen) {
// Delay hiding until after the animation. This comes from Chrome code.
if (mSystemUiFullscreenResizeRunnable != null) {
getHandler().removeCallbacks(mSystemUiFullscreenResizeRunnable);
}
mSystemUiFullscreenResizeRunnable = () -> processFullscreenChanged(isFullscreen);
long delay = isFullscreen ? SYSTEM_UI_VIEWPORT_UPDATE_DELAY_MS : 0;
postDelayed(mSystemUiFullscreenResizeRunnable, delay);
}
private void processFullscreenChanged(boolean isFullscreen) {
mSystemUiFullscreenResizeRunnable = null;
if (mIsFullscreen == isFullscreen) return;
mIsFullscreen = isFullscreen;
if (mView == null) return;
if (mIsFullscreen) {
hideTopControls();
setTopControlsOffset(-mLastHeight, 0);
} else {
showTopControls();
setTopControlsOffset(0, mLastHeight);
}
}
@NativeMethods @NativeMethods
interface Natives { interface Natives {
long createTopControlsContainerView( long createTopControlsContainerView(TopControlsContainerView view, WebContents webContents,
WebContents webContents, long nativeContentViewRenderView); long nativeContentViewRenderView);
void deleteTopControlsContainerView( void deleteTopControlsContainerView(
long nativeTopControlsContainerView, TopControlsContainerView caller); long nativeTopControlsContainerView, TopControlsContainerView caller);
void createTopControlsLayer( void createTopControlsLayer(
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package org.chromium.weblayer_private.aidl; package org.chromium.weblayer_private.aidl;
import org.chromium.weblayer_private.aidl.IBrowserControllerClient; import org.chromium.weblayer_private.aidl.IBrowserControllerClient;
import org.chromium.weblayer_private.aidl.IFullscreenDelegateClient;
import org.chromium.weblayer_private.aidl.INavigationController; import org.chromium.weblayer_private.aidl.INavigationController;
import org.chromium.weblayer_private.aidl.INavigationControllerClient; import org.chromium.weblayer_private.aidl.INavigationControllerClient;
...@@ -12,4 +13,6 @@ interface IBrowserController { ...@@ -12,4 +13,6 @@ interface IBrowserController {
void setClient(in IBrowserControllerClient client) = 0; void setClient(in IBrowserControllerClient client) = 0;
INavigationController createNavigationController(in INavigationControllerClient client) = 1; INavigationController createNavigationController(in INavigationControllerClient client) = 1;
void setFullscreenDelegateClient(in IFullscreenDelegateClient client) = 2;
} }
// Copyright 2019 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.
package org.chromium.weblayer_private.aidl;
import org.chromium.weblayer_private.aidl.IObjectWrapper;
/**
* Used to forward FullscreenDelegate calls to the client.
*/
interface IFullscreenDelegateClient {
// exitFullscreenWrapper is a ValueCallback<Void> that when run exits
// fullscreen.
void enterFullscreen(in IObjectWrapper exitFullscreenWrapper) = 0;
void exitFullscreen() = 1;
}
...@@ -20,12 +20,15 @@ using base::android::AttachCurrentThread; ...@@ -20,12 +20,15 @@ using base::android::AttachCurrentThread;
namespace weblayer { namespace weblayer {
TopControlsContainerView::TopControlsContainerView( TopControlsContainerView::TopControlsContainerView(
const base::android::JavaParamRef<jobject>&
java_top_controls_container_view,
content::WebContents* web_contents, content::WebContents* web_contents,
ContentViewRenderView* content_view_render_view) ContentViewRenderView* content_view_render_view)
: content_view_render_view_(content_view_render_view), : java_top_controls_container_view_(java_top_controls_container_view),
web_contents_(web_contents) { content_view_render_view_(content_view_render_view) {
DCHECK(content_view_render_view_); DCHECK(content_view_render_view_);
DCHECK(web_contents_); DCHECK(web_contents);
Observe(web_contents);
} }
TopControlsContainerView::~TopControlsContainerView() = default; TopControlsContainerView::~TopControlsContainerView() = default;
...@@ -70,7 +73,7 @@ void TopControlsContainerView::SetTopControlsOffset( ...@@ -70,7 +73,7 @@ void TopControlsContainerView::SetTopControlsOffset(
int top_content_offset_y) { int top_content_offset_y) {
DCHECK(top_controls_layer_); DCHECK(top_controls_layer_);
top_controls_layer_->SetPosition(gfx::PointF(0, top_controls_offset_y)); top_controls_layer_->SetPosition(gfx::PointF(0, top_controls_offset_y));
web_contents_->GetNativeView()->GetLayer()->SetPosition( web_contents()->GetNativeView()->GetLayer()->SetPosition(
gfx::PointF(0, top_content_offset_y)); gfx::PointF(0, top_content_offset_y));
} }
...@@ -96,11 +99,22 @@ void TopControlsContainerView::UpdateTopControlsResource( ...@@ -96,11 +99,22 @@ void TopControlsContainerView::UpdateTopControlsResource(
top_controls_resource->ui_resource()->id()); top_controls_resource->ui_resource()->id());
} }
void TopControlsContainerView::DidToggleFullscreenModeForTab(
bool entered_fullscreen,
bool will_cause_resize) {
Java_TopControlsContainerView_didToggleFullscreenModeForTab(
AttachCurrentThread(), java_top_controls_container_view_,
entered_fullscreen);
}
static jlong JNI_TopControlsContainerView_CreateTopControlsContainerView( static jlong JNI_TopControlsContainerView_CreateTopControlsContainerView(
JNIEnv* env, JNIEnv* env,
const base::android::JavaParamRef<jobject>&
java_top_controls_container_view,
const base::android::JavaParamRef<jobject>& web_contents, const base::android::JavaParamRef<jobject>& web_contents,
jlong native_content_view_render_view) { jlong native_content_view_render_view) {
return reinterpret_cast<jlong>(new TopControlsContainerView( return reinterpret_cast<jlong>(new TopControlsContainerView(
java_top_controls_container_view,
content::WebContents::FromJavaWebContents(web_contents), content::WebContents::FromJavaWebContents(web_contents),
reinterpret_cast<ContentViewRenderView*>( reinterpret_cast<ContentViewRenderView*>(
native_content_view_render_view))); native_content_view_render_view)));
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/public/browser/web_contents_observer.h"
namespace cc { namespace cc {
class UIResourceLayer; class UIResourceLayer;
...@@ -25,11 +26,13 @@ class ContentViewRenderView; ...@@ -25,11 +26,13 @@ class ContentViewRenderView;
// Native side of TopControlsContainerView. Responsible for creating and // Native side of TopControlsContainerView. Responsible for creating and
// positioning the cc::Layer that contains an image of the contents of the // positioning the cc::Layer that contains an image of the contents of the
// top-control. // top-control.
class TopControlsContainerView { class TopControlsContainerView : public content::WebContentsObserver {
public: public:
TopControlsContainerView(content::WebContents* web_contents, TopControlsContainerView(const base::android::JavaParamRef<jobject>&
java_top_controls_container_view,
content::WebContents* web_contents,
ContentViewRenderView* content_view_render_view); ContentViewRenderView* content_view_render_view);
~TopControlsContainerView(); ~TopControlsContainerView() override;
// Height needed to display the top-control. // Height needed to display the top-control.
int GetTopControlsHeight(); int GetTopControlsHeight();
...@@ -69,8 +72,12 @@ class TopControlsContainerView { ...@@ -69,8 +72,12 @@ class TopControlsContainerView {
const base::android::JavaParamRef<jobject>& caller); const base::android::JavaParamRef<jobject>& caller);
private: private:
// WebContentsObserver:
void DidToggleFullscreenModeForTab(bool entered_fullscreen,
bool will_cause_resize) override;
base::android::ScopedJavaGlobalRef<jobject> java_top_controls_container_view_;
ContentViewRenderView* content_view_render_view_; ContentViewRenderView* content_view_render_view_;
content::WebContents* web_contents_;
int top_controls_resource_id_ = -1; int top_controls_resource_id_ = -1;
// Layer containing showing the image for the top-controls. This is a sibling // Layer containing showing the image for the top-controls. This is a sibling
......
...@@ -17,6 +17,7 @@ class WebView; ...@@ -17,6 +17,7 @@ class WebView;
namespace weblayer { namespace weblayer {
class BrowserObserver; class BrowserObserver;
class FullscreenDelegate;
class Profile; class Profile;
class NavigationController; class NavigationController;
...@@ -31,6 +32,10 @@ class BrowserController { ...@@ -31,6 +32,10 @@ class BrowserController {
virtual ~BrowserController() {} virtual ~BrowserController() {}
// Sets the FullscreenDelegate. Setting a non-null value implicitly enables
// fullscreen.
virtual void SetFullscreenDelegate(FullscreenDelegate* delegate) = 0;
virtual void AddObserver(BrowserObserver* observer) = 0; virtual void AddObserver(BrowserObserver* observer) = 0;
virtual void RemoveObserver(BrowserObserver* observer) = 0; virtual void RemoveObserver(BrowserObserver* observer) = 0;
......
// Copyright 2019 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.
#ifndef WEBLAYER_PUBLIC_FULLSCREEN_DELEGATE_H_
#define WEBLAYER_PUBLIC_FULLSCREEN_DELEGATE_H_
#include "base/callback_forward.h"
namespace weblayer {
class FullscreenDelegate {
public:
// Called when the page has requested to go fullscreen.
virtual void EnterFullscreen(base::OnceClosure exit_closure) = 0;
// Informs the delegate the page has exited fullscreen.
virtual void ExitFullscreen() = 0;
protected:
virtual ~FullscreenDelegate() {}
};
} // namespace weblayer
#endif // WEBLAYER_PUBLIC_FULLSCREEN_DELEGATE_H_
...@@ -27,6 +27,7 @@ template("weblayer_java") { ...@@ -27,6 +27,7 @@ template("weblayer_java") {
"org/chromium/weblayer/BrowserFragmentController.java", "org/chromium/weblayer/BrowserFragmentController.java",
"org/chromium/weblayer/BrowserObserver.java", "org/chromium/weblayer/BrowserObserver.java",
"org/chromium/weblayer/Callback.java", "org/chromium/weblayer/Callback.java",
"org/chromium/weblayer/FullscreenDelegate.java",
"org/chromium/weblayer/ListenableFuture.java", "org/chromium/weblayer/ListenableFuture.java",
"org/chromium/weblayer/ListenableResult.java", "org/chromium/weblayer/ListenableResult.java",
"org/chromium/weblayer/Navigation.java", "org/chromium/weblayer/Navigation.java",
......
...@@ -6,13 +6,18 @@ package org.chromium.weblayer; ...@@ -6,13 +6,18 @@ package org.chromium.weblayer;
import android.net.Uri; import android.net.Uri;
import android.os.RemoteException; import android.os.RemoteException;
import android.webkit.ValueCallback;
import org.chromium.weblayer_private.aidl.APICallException; import org.chromium.weblayer_private.aidl.APICallException;
import org.chromium.weblayer_private.aidl.IBrowserController; import org.chromium.weblayer_private.aidl.IBrowserController;
import org.chromium.weblayer_private.aidl.IBrowserControllerClient; import org.chromium.weblayer_private.aidl.IBrowserControllerClient;
import org.chromium.weblayer_private.aidl.IFullscreenDelegateClient;
import org.chromium.weblayer_private.aidl.IObjectWrapper;
import org.chromium.weblayer_private.aidl.ObjectWrapper;
public final class BrowserController { public final class BrowserController {
private final IBrowserController mImpl; private final IBrowserController mImpl;
private FullscreenDelegateClientImpl mFullscreenDelegateClient;
private final NavigationController mNavigationController; private final NavigationController mNavigationController;
private final ObserverList<BrowserObserver> mObservers; private final ObserverList<BrowserObserver> mObservers;
...@@ -28,6 +33,23 @@ public final class BrowserController { ...@@ -28,6 +33,23 @@ public final class BrowserController {
mNavigationController = NavigationController.create(mImpl); mNavigationController = NavigationController.create(mImpl);
} }
public void setFullscreenDelegate(FullscreenDelegate delegate) {
try {
if (delegate != null) {
mFullscreenDelegateClient = new FullscreenDelegateClientImpl(delegate);
mImpl.setFullscreenDelegateClient(mFullscreenDelegateClient);
} else {
mImpl.setFullscreenDelegateClient(null);
}
} catch (RemoteException e) {
throw new APICallException(e);
}
}
public FullscreenDelegate getFullscreenDelegate() {
return mFullscreenDelegateClient != null ? mFullscreenDelegateClient.getDelegate() : null;
}
@Override @Override
protected void finalize() { protected void finalize() {
// TODO(sky): figure out right assertion here if mProfile is non-null. // TODO(sky): figure out right assertion here if mProfile is non-null.
...@@ -72,4 +94,28 @@ public final class BrowserController { ...@@ -72,4 +94,28 @@ public final class BrowserController {
} }
} }
} }
private final class FullscreenDelegateClientImpl extends IFullscreenDelegateClient.Stub {
private FullscreenDelegate mDelegate;
/* package */ FullscreenDelegateClientImpl(FullscreenDelegate delegate) {
mDelegate = delegate;
}
public FullscreenDelegate getDelegate() {
return mDelegate;
}
@Override
public void enterFullscreen(IObjectWrapper exitFullscreenWrapper) {
ValueCallback<Void> exitFullscreenCallback = (ValueCallback<Void>) ObjectWrapper.unwrap(
exitFullscreenWrapper, ValueCallback.class);
mDelegate.enterFullscreen(() -> exitFullscreenCallback.onReceiveValue(null));
}
@Override
public void exitFullscreen() {
mDelegate.exitFullscreen();
}
}
} }
// Copyright 2019 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.
package org.chromium.weblayer;
/**
* Used to configure fullscreen related state. HTML fullscreen support is only enabled if a
* FullscreenDelegate is set.
*/
public abstract class FullscreenDelegate {
/**
* Called when the page has requested to go fullscreen. The delegate is responsible for
* putting the system into fullscreen mode. The delegate can exit out of fullscreen by
* running the supplied Runnable (calling exitFullscreenRunner.Run() results in calling
* exitFullscreen()).
*
* NOTE: the Runnable must not be used synchronously.
*/
public abstract void enterFullscreen(Runnable exitFullscreenRunner);
/**
* The page has exited fullscreen mode and the system should be moved out of fullscreen mode.
*/
public abstract void exitFullscreen();
}
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
<activity android:name="WebLayerShellActivity" <activity android:name="WebLayerShellActivity"
android:launchMode="singleTask" android:launchMode="singleTask"
android:theme="@android:style/Theme.Holo.Light.NoActionBar" android:theme="@android:style/Theme.Holo.Light.NoActionBar"
android:windowSoftInputMode="adjustPan|stateUnspecified"> android:windowSoftInputMode="adjustPan|stateUnspecified"
android:configChanges="orientation|screenSize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
......
...@@ -17,6 +17,7 @@ import android.view.KeyEvent; ...@@ -17,6 +17,7 @@ import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
...@@ -29,6 +30,7 @@ import org.chromium.weblayer.BrowserController; ...@@ -29,6 +30,7 @@ import org.chromium.weblayer.BrowserController;
import org.chromium.weblayer.BrowserFragment; import org.chromium.weblayer.BrowserFragment;
import org.chromium.weblayer.BrowserFragmentController; import org.chromium.weblayer.BrowserFragmentController;
import org.chromium.weblayer.BrowserObserver; import org.chromium.weblayer.BrowserObserver;
import org.chromium.weblayer.FullscreenDelegate;
import org.chromium.weblayer.NavigationController; import org.chromium.weblayer.NavigationController;
import org.chromium.weblayer.Profile; import org.chromium.weblayer.Profile;
import org.chromium.weblayer.UnsupportedVersionException; import org.chromium.weblayer.UnsupportedVersionException;
...@@ -130,6 +132,43 @@ public class WebLayerShellActivity extends FragmentActivity { ...@@ -130,6 +132,43 @@ public class WebLayerShellActivity extends FragmentActivity {
mFragment = getOrCreateBrowserFragment(savedInstanceState); mFragment = getOrCreateBrowserFragment(savedInstanceState);
mBrowserFragmentController = mFragment.getController(); mBrowserFragmentController = mFragment.getController();
mBrowserFragmentController.getBrowserController().setFullscreenDelegate(
new FullscreenDelegate() {
private int mSystemVisibilityToRestore;
@Override
public void enterFullscreen(Runnable exitFullscreenRunnable) {
// This comes from Chrome code to avoid an extra resize.
final WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
getWindow().setAttributes(attrs);
View decorView = getWindow().getDecorView();
// Caching the system ui visibility is ok for shell, but likely not ok for
// real code.
mSystemVisibilityToRestore = decorView.getSystemUiVisibility();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
| View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
@Override
public void exitFullscreen() {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(mSystemVisibilityToRestore);
final WindowManager.LayoutParams attrs = getWindow().getAttributes();
if ((attrs.flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
!= 0) {
attrs.flags &= ~WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
getWindow().setAttributes(attrs);
}
}
});
mProfile = mBrowserFragmentController.getProfile(); mProfile = mBrowserFragmentController.getProfile();
mBrowserFragmentController.setTopView(mTopContentsContainer); mBrowserFragmentController.setTopView(mTopContentsContainer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment