Commit 0efaa7ed authored by Scott Violet's avatar Scott Violet Committed by Commit Bot

weblayer: adds NewBrowserCallback

NewBrowserCallback is used from window.open (among other things). As
part of this BrowserFragmentController now has an API to get the list
of BrowserTabControllers and the ability to set a single active one.

BUG=none
TEST=testNewBrowser.testNewBrowser

Change-Id: I55702381c1adee4322a6fc660ce161bcc92c3dca
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1897487Reviewed-by: default avatarBo <boliu@chromium.org>
Commit-Queue: Scott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712828}
parent 1ebc8df2
...@@ -218,6 +218,8 @@ jumbo_static_library("weblayer_lib") { ...@@ -218,6 +218,8 @@ jumbo_static_library("weblayer_lib") {
"browser/download_callback_proxy.h", "browser/download_callback_proxy.h",
"browser/fullscreen_callback_proxy.cc", "browser/fullscreen_callback_proxy.cc",
"browser/fullscreen_callback_proxy.h", "browser/fullscreen_callback_proxy.h",
"browser/new_browser_callback_proxy.cc",
"browser/new_browser_callback_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",
] ]
......
...@@ -40,24 +40,24 @@ namespace weblayer { ...@@ -40,24 +40,24 @@ namespace weblayer {
namespace { namespace {
NewBrowserDisposition NewBrowserDispositionFromWindowDisposition( NewBrowserType NewBrowserTypeFromWindowDisposition(
WindowOpenDisposition disposition) { WindowOpenDisposition disposition) {
// WindowOpenDisposition has a *ton* of types, but the following are really // WindowOpenDisposition has a *ton* of types, but the following are really
// the only ones that should be hit for this code path. // the only ones that should be hit for this code path.
switch (disposition) { switch (disposition) {
case WindowOpenDisposition::NEW_FOREGROUND_TAB: case WindowOpenDisposition::NEW_FOREGROUND_TAB:
return NewBrowserDisposition::kForeground; return NewBrowserType::FOREGROUND_TAB;
case WindowOpenDisposition::NEW_BACKGROUND_TAB: case WindowOpenDisposition::NEW_BACKGROUND_TAB:
return NewBrowserDisposition::kBackground; return NewBrowserType::BACKGROUND_TAB;
case WindowOpenDisposition::NEW_POPUP: case WindowOpenDisposition::NEW_POPUP:
return NewBrowserDisposition::kNewPopup; return NewBrowserType::NEW_POPUP;
case WindowOpenDisposition::NEW_WINDOW: case WindowOpenDisposition::NEW_WINDOW:
return NewBrowserDisposition::kNewWindow; return NewBrowserType::NEW_WINDOW;
default: default:
// The set of allowed types are in // The set of allowed types are in
// ContentBrowserClientImpl::CanCreateWindow(). // ContentBrowserClientImpl::CanCreateWindow().
NOTREACHED(); NOTREACHED();
return NewBrowserDisposition::kForeground; return NewBrowserType::FOREGROUND_TAB;
} }
} }
...@@ -239,6 +239,14 @@ void BrowserControllerImpl::ExecuteScript( ...@@ -239,6 +239,14 @@ void BrowserControllerImpl::ExecuteScript(
base::BindOnce(&HandleJavaScriptResult, jcallback)); base::BindOnce(&HandleJavaScriptResult, jcallback));
} }
void BrowserControllerImpl::SetJavaImpl(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& impl) {
// This should only be called early on and only once.
DCHECK(!java_impl_);
java_impl_ = impl;
}
#endif #endif
content::WebContents* BrowserControllerImpl::OpenURLFromTab( content::WebContents* BrowserControllerImpl::OpenURLFromTab(
...@@ -282,7 +290,9 @@ void BrowserControllerImpl::RunFileChooser( ...@@ -282,7 +290,9 @@ void BrowserControllerImpl::RunFileChooser(
int BrowserControllerImpl::GetTopControlsHeight() { int BrowserControllerImpl::GetTopControlsHeight() {
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
return top_controls_container_view_->GetTopControlsHeight(); return top_controls_container_view_
? top_controls_container_view_->GetTopControlsHeight()
: 0;
#else #else
return 0; return 0;
#endif #endif
...@@ -345,8 +355,7 @@ void BrowserControllerImpl::AddNewContents( ...@@ -345,8 +355,7 @@ void BrowserControllerImpl::AddNewContents(
std::make_unique<BrowserControllerImpl>(profile_, std::make_unique<BrowserControllerImpl>(profile_,
std::move(new_contents)); std::move(new_contents));
new_browser_delegate_->OnNewBrowser( new_browser_delegate_->OnNewBrowser(
std::move(browser), std::move(browser), NewBrowserTypeFromWindowDisposition(disposition));
NewBrowserDispositionFromWindowDisposition(disposition));
} }
void BrowserControllerImpl::DidFinishNavigation( void BrowserControllerImpl::DidFinishNavigation(
......
...@@ -70,12 +70,13 @@ class BrowserControllerImpl : public BrowserController, ...@@ -70,12 +70,13 @@ class BrowserControllerImpl : public BrowserController,
const base::android::JavaParamRef<jstring>& script, const base::android::JavaParamRef<jstring>& script,
bool use_separate_isolate, bool use_separate_isolate,
const base::android::JavaParamRef<jobject>& callback); const base::android::JavaParamRef<jobject>& callback);
void SetJavaImpl(JNIEnv* env,
const base::android::JavaParamRef<jobject>& impl);
#endif #endif
DownloadDelegate* download_delegate() { return download_delegate_; } DownloadDelegate* download_delegate() { return download_delegate_; }
FullscreenDelegate* fullscreen_delegate() { return fullscreen_delegate_; } FullscreenDelegate* fullscreen_delegate() { return fullscreen_delegate_; }
private:
// BrowserController: // BrowserController:
void SetDownloadDelegate(DownloadDelegate* delegate) override; void SetDownloadDelegate(DownloadDelegate* delegate) override;
void SetFullscreenDelegate(FullscreenDelegate* delegate) override; void SetFullscreenDelegate(FullscreenDelegate* delegate) override;
...@@ -90,6 +91,7 @@ class BrowserControllerImpl : public BrowserController, ...@@ -90,6 +91,7 @@ class BrowserControllerImpl : public BrowserController,
void AttachToView(views::WebView* web_view) override; void AttachToView(views::WebView* web_view) override;
#endif #endif
private:
// content::WebContentsDelegate: // content::WebContentsDelegate:
content::WebContents* OpenURLFromTab( content::WebContents* OpenURLFromTab(
content::WebContents* source, content::WebContents* source,
......
...@@ -17,6 +17,7 @@ generate_locale_config_srcjar("weblayer_locale_config") { ...@@ -17,6 +17,7 @@ generate_locale_config_srcjar("weblayer_locale_config") {
java_cpp_enum("generated_enums") { java_cpp_enum("generated_enums") {
sources = [ sources = [
"//weblayer/public/new_browser_delegate.h",
"//weblayer/public/profile.h", "//weblayer/public/profile.h",
] ]
} }
...@@ -35,6 +36,7 @@ android_library("java") { ...@@ -35,6 +36,7 @@ android_library("java") {
"org/chromium/weblayer_private/FullscreenCallbackProxy.java", "org/chromium/weblayer_private/FullscreenCallbackProxy.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/NewBrowserCallbackProxy.java",
"org/chromium/weblayer_private/ProfileImpl.java", "org/chromium/weblayer_private/ProfileImpl.java",
"org/chromium/weblayer_private/FragmentAndroidPermissionDelegate.java", "org/chromium/weblayer_private/FragmentAndroidPermissionDelegate.java",
"org/chromium/weblayer_private/FragmentWindowAndroid.java", "org/chromium/weblayer_private/FragmentWindowAndroid.java",
...@@ -61,8 +63,8 @@ android_library("java") { ...@@ -61,8 +63,8 @@ android_library("java") {
"//ui/android:ui_java", "//ui/android:ui_java",
] ]
srcjar_deps = [ srcjar_deps = [
":weblayer_locale_config",
":generated_enums", ":generated_enums",
":weblayer_locale_config",
] ]
jar_excluded_patterns = [ "*/LocaleConfig.class" ] jar_excluded_patterns = [ "*/LocaleConfig.class" ]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
...@@ -81,6 +83,7 @@ generate_jni("jni") { ...@@ -81,6 +83,7 @@ generate_jni("jni") {
"org/chromium/weblayer_private/FullscreenCallbackProxy.java", "org/chromium/weblayer_private/FullscreenCallbackProxy.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/NewBrowserCallbackProxy.java",
"org/chromium/weblayer_private/ProfileImpl.java", "org/chromium/weblayer_private/ProfileImpl.java",
"org/chromium/weblayer_private/TopControlsContainerView.java", "org/chromium/weblayer_private/TopControlsContainerView.java",
] ]
...@@ -88,11 +91,12 @@ generate_jni("jni") { ...@@ -88,11 +91,12 @@ generate_jni("jni") {
android_library("client_java") { android_library("client_java") {
java_files = [ java_files = [
"org/chromium/weblayer_private/aidl/ObjectWrapper.java",
"org/chromium/weblayer_private/aidl/WebLayerVersion.java",
"org/chromium/weblayer_private/aidl/APICallException.java", "org/chromium/weblayer_private/aidl/APICallException.java",
"org/chromium/weblayer_private/aidl/BrowserFragmentArgs.java", "org/chromium/weblayer_private/aidl/BrowserFragmentArgs.java",
"org/chromium/weblayer_private/aidl/BrowsingDataType.java", "org/chromium/weblayer_private/aidl/BrowsingDataType.java",
"org/chromium/weblayer_private/aidl/NewBrowserType.java",
"org/chromium/weblayer_private/aidl/ObjectWrapper.java",
"org/chromium/weblayer_private/aidl/WebLayerVersion.java",
] ]
deps = [ deps = [
......
...@@ -29,6 +29,7 @@ import org.chromium.weblayer_private.aidl.ObjectWrapper; ...@@ -29,6 +29,7 @@ import org.chromium.weblayer_private.aidl.ObjectWrapper;
*/ */
@JNINamespace("weblayer") @JNINamespace("weblayer")
public final class BrowserControllerImpl extends IBrowserController.Stub { public final class BrowserControllerImpl extends IBrowserController.Stub {
private static int sNextId = 1;
private long mNativeBrowserController; private long mNativeBrowserController;
private ProfileImpl mProfile; private ProfileImpl mProfile;
...@@ -41,6 +42,9 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -41,6 +42,9 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
// BrowserFragmentControllerImpl this BrowserControllerImpl is in. This is only null during // BrowserFragmentControllerImpl this BrowserControllerImpl is in. This is only null during
// creation. // creation.
private BrowserFragmentControllerImpl mFragment; private BrowserFragmentControllerImpl mFragment;
private NewBrowserCallbackProxy mNewBrowserCallbackProxy;
private IBrowserControllerClient mClient;
private final int mId;
private static class InternalAccessDelegateImpl private static class InternalAccessDelegateImpl
implements ViewEventSink.InternalAccessDelegate { implements ViewEventSink.InternalAccessDelegate {
...@@ -64,9 +68,28 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -64,9 +68,28 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
} }
public BrowserControllerImpl(ProfileImpl profile, WindowAndroid windowAndroid) { public BrowserControllerImpl(ProfileImpl profile, WindowAndroid windowAndroid) {
mId = ++sNextId;
init(profile, windowAndroid,
BrowserControllerImplJni.get().createBrowserController(
profile.getNativeProfile(), this));
}
/**
* This constructor is called when the native side triggers creation of a BrowserControllerImpl
* (as happens with popups).
*/
public BrowserControllerImpl(
ProfileImpl profile, WindowAndroid windowAndroid, long nativeBrowserController) {
mId = ++sNextId;
BrowserControllerImplJni.get().setJavaImpl(
nativeBrowserController, BrowserControllerImpl.this);
init(profile, windowAndroid, nativeBrowserController);
}
private void init(
ProfileImpl profile, WindowAndroid windowAndroid, long nativeBrowserController) {
mProfile = profile; mProfile = profile;
mNativeBrowserController = BrowserControllerImplJni.get().createBrowserController( mNativeBrowserController = nativeBrowserController;
profile.getNativeProfile(), this);
mWebContents = BrowserControllerImplJni.get().getWebContents( mWebContents = BrowserControllerImplJni.get().getWebContents(
mNativeBrowserController, BrowserControllerImpl.this); mNativeBrowserController, BrowserControllerImpl.this);
mViewAndroidDelegate = new ViewAndroidDelegate(null) { mViewAndroidDelegate = new ViewAndroidDelegate(null) {
...@@ -82,6 +105,14 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -82,6 +105,14 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
windowAndroid, WebContents.createDefaultInternalsHolder()); windowAndroid, WebContents.createDefaultInternalsHolder());
} }
public ProfileImpl getProfile() {
return mProfile;
}
public IBrowserControllerClient getClient() {
return mClient;
}
/** /**
* Sets the BrowserFragmentControllerImpl this BrowserControllerImpl is contained in. * Sets the BrowserFragmentControllerImpl this BrowserControllerImpl is contained in.
*/ */
...@@ -95,6 +126,21 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -95,6 +126,21 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
return mFragment; return mFragment;
} }
@Override
public void setNewBrowsersEnabled(boolean enable) {
if (enable && mNewBrowserCallbackProxy == null) {
mNewBrowserCallbackProxy = new NewBrowserCallbackProxy(this);
} else if (!enable && mNewBrowserCallbackProxy != null) {
mNewBrowserCallbackProxy.destroy();
mNewBrowserCallbackProxy = null;
}
}
@Override
public int getId() {
return mId;
}
/** /**
* Called when this BrowserControllerImpl becomes the active BrowserControllerImpl. * Called when this BrowserControllerImpl becomes the active BrowserControllerImpl.
*/ */
...@@ -105,7 +151,6 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -105,7 +151,6 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
BrowserControllerImpl.this, topControlsContainerViewHandle); BrowserControllerImpl.this, topControlsContainerViewHandle);
mWebContents.onShow(); mWebContents.onShow();
} }
/** /**
* Called when this BrowserControllerImpl is no longer the active BrowserControllerImpl. * Called when this BrowserControllerImpl is no longer the active BrowserControllerImpl.
*/ */
...@@ -133,6 +178,7 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -133,6 +178,7 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
@Override @Override
public void setClient(IBrowserControllerClient client) { public void setClient(IBrowserControllerClient client) {
mClient = client;
mBrowserCallbackProxy = new BrowserCallbackProxy(mNativeBrowserController, client); mBrowserCallbackProxy = new BrowserCallbackProxy(mNativeBrowserController, client);
} }
...@@ -195,6 +241,10 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -195,6 +241,10 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
mFullscreenCallbackProxy.destroy(); mFullscreenCallbackProxy.destroy();
mFullscreenCallbackProxy = null; mFullscreenCallbackProxy = null;
} }
if (mNewBrowserCallbackProxy != null) {
mNewBrowserCallbackProxy.destroy();
mNewBrowserCallbackProxy = null;
}
mNavigationController = null; mNavigationController = null;
BrowserControllerImplJni.get().deleteBrowserController(mNativeBrowserController); BrowserControllerImplJni.get().deleteBrowserController(mNativeBrowserController);
mNativeBrowserController = 0; mNativeBrowserController = 0;
...@@ -208,7 +258,7 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -208,7 +258,7 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
/** /**
* Returns the BrowserFragmentViewController for this BrowserControllerImpl, but only if this * Returns the BrowserFragmentViewController for this BrowserControllerImpl, but only if this
* the active BrowserControllerImpl. * is the active BrowserControllerImpl.
*/ */
private BrowserFragmentViewController getViewController() { private BrowserFragmentViewController getViewController() {
return (mFragment.getActiveBrowserController() == this) ? mFragment.getViewController() return (mFragment.getActiveBrowserController() == this) ? mFragment.getViewController()
...@@ -218,6 +268,7 @@ public final class BrowserControllerImpl extends IBrowserController.Stub { ...@@ -218,6 +268,7 @@ public final class BrowserControllerImpl extends IBrowserController.Stub {
@NativeMethods @NativeMethods
interface Natives { interface Natives {
long createBrowserController(long profile, BrowserControllerImpl caller); long createBrowserController(long profile, BrowserControllerImpl caller);
void setJavaImpl(long nativeBrowserControllerImpl, BrowserControllerImpl impl);
void setTopControlsContainerView(long nativeBrowserControllerImpl, void setTopControlsContainerView(long nativeBrowserControllerImpl,
BrowserControllerImpl caller, long nativeTopControlsContainerView); BrowserControllerImpl caller, long nativeTopControlsContainerView);
void deleteBrowserController(long browserController); void deleteBrowserController(long browserController);
......
...@@ -19,6 +19,7 @@ import org.chromium.weblayer_private.aidl.IProfile; ...@@ -19,6 +19,7 @@ import org.chromium.weblayer_private.aidl.IProfile;
import org.chromium.weblayer_private.aidl.ObjectWrapper; import org.chromium.weblayer_private.aidl.ObjectWrapper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/** /**
* Implementation of {@link IBrowserFragmentController}. * Implementation of {@link IBrowserFragmentController}.
...@@ -79,11 +80,6 @@ public class BrowserFragmentControllerImpl extends IBrowserFragmentController.St ...@@ -79,11 +80,6 @@ public class BrowserFragmentControllerImpl extends IBrowserFragmentController.St
(ValueCallback<Boolean>) ObjectWrapper.unwrap(valueCallback, ValueCallback.class)); (ValueCallback<Boolean>) ObjectWrapper.unwrap(valueCallback, ValueCallback.class));
} }
@Override
public BrowserControllerImpl getBrowserController() {
return getViewController().getBrowserController();
}
public BrowserFragmentViewController getViewController() { public BrowserFragmentViewController getViewController() {
if (mViewController == null) { if (mViewController == null) {
throw new RuntimeException("Currently BrowserController requires Activity context, so " throw new RuntimeException("Currently BrowserController requires Activity context, so "
...@@ -121,7 +117,9 @@ public class BrowserFragmentControllerImpl extends IBrowserFragmentController.St ...@@ -121,7 +117,9 @@ public class BrowserFragmentControllerImpl extends IBrowserFragmentController.St
// destroyed, or switching to a different fragment. // destroyed, or switching to a different fragment.
} }
public boolean setActiveBrowserController(BrowserControllerImpl browser) { @Override
public boolean setActiveBrowserController(IBrowserController controller) {
BrowserControllerImpl browser = (BrowserControllerImpl) controller;
if (browser.getFragment() != this) return false; if (browser.getFragment() != this) return false;
mViewController.setActiveBrowserController(browser); mViewController.setActiveBrowserController(browser);
return true; return true;
...@@ -131,6 +129,16 @@ public class BrowserFragmentControllerImpl extends IBrowserFragmentController.St ...@@ -131,6 +129,16 @@ public class BrowserFragmentControllerImpl extends IBrowserFragmentController.St
return mViewController.getBrowserController(); return mViewController.getBrowserController();
} }
@Override
public List getBrowserControllers() {
return new ArrayList(mBrowsers);
}
@Override
public int getActiveBrowserControllerId() {
return getActiveBrowserController() != null ? getActiveBrowserController().getId() : 0;
}
public View getFragmentView() { public View getFragmentView() {
return getViewController().getView(); return getViewController().getView();
} }
......
...@@ -93,12 +93,16 @@ public final class BrowserFragmentViewController ...@@ -93,12 +93,16 @@ public final class BrowserFragmentViewController
mBrowserController = browserController; mBrowserController = browserController;
WebContents webContents = WebContents webContents =
mBrowserController != null ? mBrowserController.getWebContents() : null; mBrowserController != null ? mBrowserController.getWebContents() : null;
// Create the WebContentsGestureStateTracker before setting the WebContents on
// the views as they may call back to this class.
if (mBrowserController != null) {
mGestureStateTracker =
new WebContentsGestureStateTracker(mContentView, webContents, this);
}
mContentView.setWebContents(webContents); mContentView.setWebContents(webContents);
mContentViewRenderView.setWebContents(webContents); mContentViewRenderView.setWebContents(webContents);
mTopControlsContainerView.setWebContents(webContents); mTopControlsContainerView.setWebContents(webContents);
if (mBrowserController != null) { if (mBrowserController != null) {
mGestureStateTracker =
new WebContentsGestureStateTracker(mContentView, webContents, this);
mBrowserController.onDidGainActive(mTopControlsContainerView.getNativeHandle()); mBrowserController.onDidGainActive(mTopControlsContainerView.getNativeHandle());
mContentView.requestFocus(); mContentView.requestFocus();
} }
......
// 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 org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.weblayer_private.aidl.NewBrowserType;
/**
* Owns the c++ NewBrowserCallback class, which is responsible for forwarding all
* NewBrowserCallback calls to this class, which in turn forwards to the
* IBrowserFragmentControllerClient.
*/
@JNINamespace("weblayer")
public final class NewBrowserCallbackProxy {
private long mNativeNewBrowserCallbackProxy;
private final BrowserControllerImpl mBrowser;
public NewBrowserCallbackProxy(BrowserControllerImpl browser) {
mBrowser = browser;
mNativeNewBrowserCallbackProxy =
NewBrowserCallbackProxyJni.get().createNewBrowserCallbackProxy(
this, browser.getNativeBrowserController());
}
public void destroy() {
NewBrowserCallbackProxyJni.get().deleteNewBrowserCallbackProxy(
mNativeNewBrowserCallbackProxy);
mNativeNewBrowserCallbackProxy = 0;
}
@NewBrowserType
private static int implTypeToJavaType(@ImplNewBrowserType int type) {
switch (type) {
case ImplNewBrowserType.FOREGROUND_TAB:
return NewBrowserType.FOREGROUND_TAB;
case ImplNewBrowserType.BACKGROUND_TAB:
return NewBrowserType.BACKGROUND_TAB;
case ImplNewBrowserType.NEW_POPUP:
return NewBrowserType.NEW_POPUP;
case ImplNewBrowserType.NEW_WINDOW:
return NewBrowserType.NEW_WINDOW;
}
assert false;
return NewBrowserType.FOREGROUND_TAB;
}
@CalledByNative
public void onNewBrowser(long nativeBrowser, @ImplNewBrowserType int mode)
throws RemoteException {
// This class should only be created while the browser is attached to a fragment.
assert mBrowser.getFragment() != null;
BrowserControllerImpl browser = new BrowserControllerImpl(
mBrowser.getProfile(), mBrowser.getFragment().getWindowAndroid(), nativeBrowser);
mBrowser.getFragment().attachBrowserController(browser);
mBrowser.getClient().onNewBrowser(browser, implTypeToJavaType(mode));
}
@NativeMethods
interface Natives {
long createNewBrowserCallbackProxy(NewBrowserCallbackProxy proxy, long browserController);
void deleteNewBrowserCallbackProxy(long proxy);
}
}
...@@ -19,4 +19,11 @@ interface IBrowserController { ...@@ -19,4 +19,11 @@ interface IBrowserController {
void setFullscreenCallbackClient(in IFullscreenCallbackClient client) = 3; void setFullscreenCallbackClient(in IFullscreenCallbackClient client) = 3;
void executeScript(in String script, boolean useSeparateIsolate, in IObjectWrapper callback) = 4; void executeScript(in String script, boolean useSeparateIsolate, in IObjectWrapper callback) = 4;
void setNewBrowsersEnabled(in boolean enabled) = 5;
// Returns a unique identifier for this BrowserController. The id is *not* unique across
// restores. The id is intended for the client library to avoid creating duplicate client objects
// for the same IBrowserController.
int getId() = 6;
} }
...@@ -10,4 +10,6 @@ package org.chromium.weblayer_private.aidl; ...@@ -10,4 +10,6 @@ package org.chromium.weblayer_private.aidl;
*/ */
interface IBrowserControllerClient { interface IBrowserControllerClient {
void visibleUrlChanged(in String url) = 0; void visibleUrlChanged(in String url) = 0;
void onNewBrowser(in IBrowserController controller, in int mode) = 1;
} }
...@@ -7,13 +7,20 @@ package org.chromium.weblayer_private.aidl; ...@@ -7,13 +7,20 @@ package org.chromium.weblayer_private.aidl;
import org.chromium.weblayer_private.aidl.IBrowserController; import org.chromium.weblayer_private.aidl.IBrowserController;
import org.chromium.weblayer_private.aidl.IObjectWrapper; import org.chromium.weblayer_private.aidl.IObjectWrapper;
import java.util.List;
interface IBrowserFragmentController { interface IBrowserFragmentController {
IProfile getProfile() = 0; IProfile getProfile() = 0;
IBrowserController getBrowserController() = 1; void setTopView(in IObjectWrapper view) = 1;
void setTopView(IObjectWrapper view) = 3;
// |valueCallback| is a wrapped ValueCallback<Boolean> instead. The bool value in |valueCallback| // |valueCallback| is a wrapped ValueCallback<Boolean> instead. The bool value in |valueCallback|
// indicates is whether the request was successful. Request might fail if it is subsumed by a // indicates is whether the request was successful. Request might fail if it is subsumed by a
// following request, or if this object is destroyed. // following request, or if this object is destroyed.
void setSupportsEmbedding(in boolean enable, in IObjectWrapper valueCallback) = 4; void setSupportsEmbedding(in boolean enable, in IObjectWrapper valueCallback) = 2;
// Returns false if browserController is not attached to this fragment.
boolean setActiveBrowserController(in IBrowserController browserController) = 3;
int getActiveBrowserControllerId() = 4;
List getBrowserControllers() = 5;
} }
// 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 androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@IntDef({NewBrowserType.FOREGROUND_TAB, NewBrowserType.BACKGROUND_TAB, NewBrowserType.NEW_POPUP,
NewBrowserType.NEW_WINDOW})
@Retention(RetentionPolicy.SOURCE)
public @interface NewBrowserType {
int FOREGROUND_TAB = 0;
int BACKGROUND_TAB = 1;
int NEW_POPUP = 2;
int NEW_WINDOW = 3;
}
...@@ -9,4 +9,4 @@ package org.chromium.weblayer_private.aidl; ...@@ -9,4 +9,4 @@ package org.chromium.weblayer_private.aidl;
* *
* Whenever any AIDL file is changed, sVersionNumber must be incremented. * Whenever any AIDL file is changed, sVersionNumber must be incremented.
* */ * */
public final class WebLayerVersion { public static int sVersionNumber = 6; } public final class WebLayerVersion { public static final int sVersionNumber = 7; }
// 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/new_browser_callback_proxy.h"
#include "base/android/jni_string.h"
#include "url/gurl.h"
#include "weblayer/browser/browser_controller_impl.h"
#include "weblayer/browser/java/jni/NewBrowserCallbackProxy_jni.h"
using base::android::AttachCurrentThread;
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaLocalRef;
namespace weblayer {
NewBrowserCallbackProxy::NewBrowserCallbackProxy(
JNIEnv* env,
jobject obj,
BrowserControllerImpl* browser_controller)
: browser_controller_(browser_controller), java_impl_(env, obj) {
DCHECK(!browser_controller_->has_new_browser_delegate());
browser_controller_->SetNewBrowserDelegate(this);
}
NewBrowserCallbackProxy::~NewBrowserCallbackProxy() {
browser_controller_->SetNewBrowserDelegate(nullptr);
}
void NewBrowserCallbackProxy::OnNewBrowser(
std::unique_ptr<BrowserController> new_contents,
NewBrowserType type) {
JNIEnv* env = AttachCurrentThread();
// The Java side takes ownership of BrowserController.
Java_NewBrowserCallbackProxy_onNewBrowser(
env, java_impl_, reinterpret_cast<jlong>(new_contents.release()),
static_cast<int>(type));
}
static jlong JNI_NewBrowserCallbackProxy_CreateNewBrowserCallbackProxy(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& proxy,
jlong browser_controller) {
return reinterpret_cast<jlong>(new NewBrowserCallbackProxy(
env, proxy,
reinterpret_cast<BrowserControllerImpl*>(browser_controller)));
}
static void JNI_NewBrowserCallbackProxy_DeleteNewBrowserCallbackProxy(
JNIEnv* env,
jlong proxy) {
delete reinterpret_cast<NewBrowserCallbackProxy*>(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_NEW_BROWSER_CALLBACK_PROXY_H_
#define WEBLAYER_BROWSER_NEW_BROWSER_CALLBACK_PROXY_H_
#include <jni.h>
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "weblayer/public/new_browser_delegate.h"
namespace weblayer {
class BrowserControllerImpl;
// NewBrowserCallbackProxy forwards all NewBrowserDelegate functions to the Java
// side. There is one NewBrowserCallbackProxy per BrowserController.
class NewBrowserCallbackProxy : public NewBrowserDelegate {
public:
NewBrowserCallbackProxy(JNIEnv* env,
jobject obj,
BrowserControllerImpl* browser_controller);
~NewBrowserCallbackProxy() override;
// NewBrowserDelegate:
void OnNewBrowser(std::unique_ptr<BrowserController> new_contents,
NewBrowserType type) override;
private:
BrowserControllerImpl* browser_controller_;
base::android::ScopedJavaGlobalRef<jobject> java_impl_;
DISALLOW_COPY_AND_ASSIGN(NewBrowserCallbackProxy);
};
} // namespace weblayer
#endif // WEBLAYER_BROWSER_NEW_BROWSER_CALLBACK_PROXY_H_
...@@ -35,6 +35,8 @@ android_library("java") { ...@@ -35,6 +35,8 @@ android_library("java") {
"org/chromium/weblayer/NavigationCallback.java", "org/chromium/weblayer/NavigationCallback.java",
"org/chromium/weblayer/NavigationController.java", "org/chromium/weblayer/NavigationController.java",
"org/chromium/weblayer/Navigation.java", "org/chromium/weblayer/Navigation.java",
"org/chromium/weblayer/NewBrowserCallback.java",
"org/chromium/weblayer/NewBrowserType.java",
"org/chromium/weblayer/ObserverList.java", "org/chromium/weblayer/ObserverList.java",
"org/chromium/weblayer/Profile.java", "org/chromium/weblayer/Profile.java",
"org/chromium/weblayer/ThreadCheck.java", "org/chromium/weblayer/ThreadCheck.java",
......
...@@ -34,10 +34,14 @@ public final class BrowserController { ...@@ -34,10 +34,14 @@ public final class BrowserController {
private FullscreenCallbackClientImpl mFullscreenCallbackClient; private FullscreenCallbackClientImpl mFullscreenCallbackClient;
private final NavigationController mNavigationController; private final NavigationController mNavigationController;
private final ObserverList<BrowserCallback> mCallbacks; private final ObserverList<BrowserCallback> mCallbacks;
private BrowserFragmentController mBrowserFragmentController;
private DownloadCallbackClientImpl mDownloadCallbackClient; private DownloadCallbackClientImpl mDownloadCallbackClient;
private NewBrowserCallback mNewBrowserCallback;
BrowserController(IBrowserController impl) { BrowserController(
IBrowserController impl, BrowserFragmentController browserFragmentController) {
mImpl = impl; mImpl = impl;
mBrowserFragmentController = browserFragmentController;
try { try {
mImpl.setClient(new BrowserClientImpl()); mImpl.setClient(new BrowserClientImpl());
} catch (RemoteException e) { } catch (RemoteException e) {
...@@ -46,6 +50,12 @@ public final class BrowserController { ...@@ -46,6 +50,12 @@ public final class BrowserController {
mCallbacks = new ObserverList<BrowserCallback>(); mCallbacks = new ObserverList<BrowserCallback>();
mNavigationController = NavigationController.create(mImpl); mNavigationController = NavigationController.create(mImpl);
mBrowserFragmentController.registerBrowserController(this);
}
public BrowserFragmentController getBrowserFragmentController() {
ThreadCheck.ensureOnUiThread();
return mBrowserFragmentController;
} }
public void setDownloadCallback(@Nullable DownloadCallback callback) { public void setDownloadCallback(@Nullable DownloadCallback callback) {
...@@ -116,6 +126,16 @@ public final class BrowserController { ...@@ -116,6 +126,16 @@ public final class BrowserController {
} }
} }
public void setNewBrowserCallback(@Nullable NewBrowserCallback callback) {
ThreadCheck.ensureOnUiThread();
mNewBrowserCallback = callback;
try {
mImpl.setNewBrowsersEnabled(mNewBrowserCallback != null);
} catch (RemoteException e) {
throw new APICallException(e);
}
}
@Nullable @Nullable
public FullscreenCallback getFullscreenCallback() { public FullscreenCallback getFullscreenCallback() {
ThreadCheck.ensureOnUiThread(); ThreadCheck.ensureOnUiThread();
...@@ -150,6 +170,16 @@ public final class BrowserController { ...@@ -150,6 +170,16 @@ public final class BrowserController {
callback.visibleUrlChanged(uri); callback.visibleUrlChanged(uri);
} }
} }
@Override
public void onNewBrowser(IBrowserController browser, int mode) {
// This should only be hit if setNewBrowserCallback() has been called with a non-null
// value.
assert mNewBrowserCallback != null;
BrowserController browserController =
new BrowserController(browser, mBrowserFragmentController);
mNewBrowserCallback.onNewBrowser(browserController, mode);
}
} }
private static final class DownloadCallbackClientImpl extends IDownloadCallbackClient.Stub { private static final class DownloadCallbackClientImpl extends IDownloadCallbackClient.Stub {
......
...@@ -13,18 +13,53 @@ import androidx.annotation.NonNull; ...@@ -13,18 +13,53 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
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.IBrowserFragmentController; import org.chromium.weblayer_private.aidl.IBrowserFragmentController;
import org.chromium.weblayer_private.aidl.ObjectWrapper; import org.chromium.weblayer_private.aidl.ObjectWrapper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* Represents a browser fragment. Created from Profile. * BrowserFragmentController contains any number of BrowserControllers, with one active
* BrowserController. The active BrowserController is visible to the user, all other
* BrowserControllers are hidden.
*
* By default BrowserFragmentController has a single active BrowserController.
*/ */
public final class BrowserFragmentController { public final class BrowserFragmentController {
private final IBrowserFragmentController mImpl; private final IBrowserFragmentController mImpl;
private BrowserController mController; // Mapes from id (as returned from IBrowserController.getId() to BrowserController.
private final Map<Integer, BrowserController> mBrowserControllerMap;
BrowserFragmentController(IBrowserFragmentController impl) { BrowserFragmentController(IBrowserFragmentController impl) {
mImpl = impl; mImpl = impl;
mBrowserControllerMap = new HashMap<Integer, BrowserController>();
try {
for (Object browserController : impl.getBrowserControllers()) {
// getBrowserControllers() returns List<BrowserControllerImpl>, which isn't
// accessible from the client library.
IBrowserController iBrowserController =
IBrowserController.Stub.asInterface((android.os.IBinder) browserController);
// BrowserController's constructor calls registerBrowserController().
new BrowserController(iBrowserController, this);
}
} catch (RemoteException e) {
throw new APICallException(e);
}
}
// This is called when a new BrowserController is created.
void registerBrowserController(BrowserController browserController) {
try {
int id = browserController.getIBrowserController().getId();
assert !mBrowserControllerMap.containsKey(id);
mBrowserControllerMap.put(id, browserController);
} catch (RemoteException e) {
throw new APICallException(e);
}
} }
/** /**
...@@ -40,21 +75,67 @@ public final class BrowserFragmentController { ...@@ -40,21 +75,67 @@ public final class BrowserFragmentController {
} }
/** /**
* Returns the BrowserController associated with this BrowserFragmentController. * Sets the active (visible) BrowserController. Only one BrowserController is visible at a time.
* *
* @return The BrowserController. * @param browserController The BrowserController to make active.
*
* @throws IllegalStateException if {@link browserController} was not added to this
* BrowserFragmentController.
*
* @see #addBrowserController()
*/ */
@NonNull public void setActiveBrowserController(@NonNull BrowserController browserController) {
public BrowserController getBrowserController() {
ThreadCheck.ensureOnUiThread(); ThreadCheck.ensureOnUiThread();
if (mController == null) { try {
try { if (!mImpl.setActiveBrowserController(browserController.getIBrowserController())) {
mController = new BrowserController(mImpl.getBrowserController()); throw new IllegalStateException("attachBrowserController() must be called before "
} catch (RemoteException e) { + "setActiveBrowserController");
throw new APICallException(e);
} }
} catch (RemoteException e) {
throw new APICallException(e);
} }
return mController; }
/**
* Returns the active (visible) BrowserController associated with this
* BrowserFragmentController.
*
* @return The BrowserController.
*/
@Nullable
public BrowserController getActiveBrowserController() {
ThreadCheck.ensureOnUiThread();
try {
return mBrowserControllerMap.get(mImpl.getActiveBrowserControllerId());
} catch (RemoteException e) {
throw new APICallException(e);
}
}
/**
* Returns the set of BrowserControllers contained in this BrowserFragmentController.
*
* @return The BrowserControllers
*/
@NonNull
public List<BrowserController> getBrowserControllers() {
ThreadCheck.ensureOnUiThread();
return new ArrayList<BrowserController>(mBrowserControllerMap.values());
}
/**
* Disposes a BrowserController. If {@link browserController} is the active BrowserController,
* no BrowserController is made active. After this call {@link browserController} should not be
* used.
*
* @param browserController The BrowserController to dispose.
*
* @throws IllegalStateException is {@link browserController} is not in this
* BrowserFragmentController.
*/
public void disposeBrowserController(BrowserController browserController) {
ThreadCheck.ensureOnUiThread();
// TODO(sky): implement this.
} }
/** /**
......
// 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;
import androidx.annotation.NonNull;
/**
* Used for handling new browsers (such as occurs when window.open() is called). If this is not
* set, popups are disabled.
*/
public abstract class NewBrowserCallback {
public abstract void onNewBrowser(
@NonNull BrowserController browserController, @NewBrowserType int type);
}
// 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;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@IntDef({NewBrowserType.FOREGROUND_TAB, NewBrowserType.BACKGROUND_TAB, NewBrowserType.NEW_POPUP,
NewBrowserType.NEW_WINDOW})
@Retention(RetentionPolicy.SOURCE)
public @interface NewBrowserType {
/**
* The page requested a new browser to be shown active.
*/
int FOREGROUND_TAB = org.chromium.weblayer_private.aidl.NewBrowserType.FOREGROUND_TAB;
/**
* The page requested a new browser in the background. Generally, this is only encountered when
* keyboard modifiers are used.
*/
int BACKGROUND_TAB = org.chromium.weblayer_private.aidl.NewBrowserType.BACKGROUND_TAB;
/**
* The page requested the browser to open a new popup. A popup generally shows minimal ui
* affordances, such as no tabstrip. On a phone, this is generally the same as
* NEW_BROWSER_MODE_FOREGROUND_TAB.
*/
int NEW_POPUP = org.chromium.weblayer_private.aidl.NewBrowserType.NEW_POPUP;
/**
* The page requested the browser to open in a new window. On a phone, this is generally the
* same as NEW_BROWSER_MODE_FOREGROUND_TAB.
*/
int NEW_WINDOW = org.chromium.weblayer_private.aidl.NewBrowserType.NEW_WINDOW;
}
...@@ -11,19 +11,22 @@ namespace weblayer { ...@@ -11,19 +11,22 @@ namespace weblayer {
class BrowserController; class BrowserController;
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.weblayer_private
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: ImplNewBrowserType
// Corresponds to type of browser the page requested. // Corresponds to type of browser the page requested.
enum class NewBrowserDisposition { enum class NewBrowserType {
// The new browser should be opened in the foreground. // The new browser should be opened in the foreground.
kForeground, FOREGROUND_TAB = 0,
// The new browser should be opened in the foreground. // The new browser should be opened in the foreground.
kBackground, BACKGROUND_TAB,
// The page requested the browser be shown in a new window with minimal // The page requested the browser be shown in a new window with minimal
// browser UI. For example, no tabstrip. // browser UI. For example, no tabstrip.
kNewPopup, NEW_POPUP,
// The page requested the browser be shown in a new window. // The page requested the browser be shown in a new window.
kNewWindow, NEW_WINDOW,
}; };
// An interface that allows clients to handle requests for new browsers, or // An interface that allows clients to handle requests for new browsers, or
...@@ -31,7 +34,7 @@ enum class NewBrowserDisposition { ...@@ -31,7 +34,7 @@ enum class NewBrowserDisposition {
class NewBrowserDelegate { class NewBrowserDelegate {
public: public:
virtual void OnNewBrowser(std::unique_ptr<BrowserController> new_contents, virtual void OnNewBrowser(std::unique_ptr<BrowserController> new_contents,
NewBrowserDisposition disposition) = 0; NewBrowserType type) = 0;
protected: protected:
virtual ~NewBrowserDelegate() {} virtual ~NewBrowserDelegate() {}
......
...@@ -222,6 +222,7 @@ instrumentation_test_apk("weblayer_instrumentation_test_apk") { ...@@ -222,6 +222,7 @@ instrumentation_test_apk("weblayer_instrumentation_test_apk") {
"javatests/src/org/chromium/weblayer/test/InputTypesTest.java", "javatests/src/org/chromium/weblayer/test/InputTypesTest.java",
"javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java", "javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java",
"javatests/src/org/chromium/weblayer/test/NavigationTest.java", "javatests/src/org/chromium/weblayer/test/NavigationTest.java",
"javatests/src/org/chromium/weblayer/test/NewBrowserCallbackTest.java",
"javatests/src/org/chromium/weblayer/test/RenderingTest.java", "javatests/src/org/chromium/weblayer/test/RenderingTest.java",
"javatests/src/org/chromium/weblayer/test/ProfileTest.java", "javatests/src/org/chromium/weblayer/test/ProfileTest.java",
"javatests/src/org/chromium/weblayer/test/SmokeTest.java", "javatests/src/org/chromium/weblayer/test/SmokeTest.java",
......
...@@ -87,7 +87,7 @@ public class WebLayerBrowserTestsActivity extends NativeBrowserTestActivity { ...@@ -87,7 +87,7 @@ public class WebLayerBrowserTestsActivity extends NativeBrowserTestActivity {
mProfile = mBrowserFragmentController.getProfile(); mProfile = mBrowserFragmentController.getProfile();
mBrowserFragmentController.setTopView(topContentsContainer); mBrowserFragmentController.setTopView(topContentsContainer);
mBrowserController = mBrowserFragmentController.getBrowserController(); mBrowserController = mBrowserFragmentController.getActiveBrowserController();
mBrowserController.registerBrowserCallback(new BrowserCallback() { mBrowserController.registerBrowserCallback(new BrowserCallback() {
@Override @Override
public void visibleUrlChanged(Uri uri) { public void visibleUrlChanged(Uri uri) {
......
// 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.test;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.weblayer.BrowserController;
import org.chromium.weblayer.NewBrowserCallback;
import org.chromium.weblayer.shell.InstrumentationActivity;
/**
* Tests that NewBrowserCallback methods are invoked as expected.
*/
@RunWith(BaseJUnit4ClassRunner.class)
public class NewBrowserCallbackTest {
@Rule
public InstrumentationActivityTestRule mActivityTestRule =
new InstrumentationActivityTestRule();
private EmbeddedTestServer mTestServer;
private InstrumentationActivity mActivity;
private static class NewBrowserCallbackImpl extends NewBrowserCallback {
public int mNewBrowserCount;
private CallbackHelper mCallbackHelper = new CallbackHelper();
@Override
public void onNewBrowser(BrowserController browser, int mode) {
mCallbackHelper.notifyCalled();
browser.getBrowserFragmentController().setActiveBrowserController(browser);
}
public void waitForNewBrowser() {
try {
mCallbackHelper.waitForCallback(0);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@Before
public void setUp() {
mTestServer = new EmbeddedTestServer();
mTestServer.initializeNative(InstrumentationRegistry.getInstrumentation().getContext(),
EmbeddedTestServer.ServerHTTPSSetting.USE_HTTP);
mTestServer.addDefaultHandlers("weblayer/test/data");
Assert.assertTrue(mTestServer.start(0));
}
@After
public void tearDown() {
mTestServer.stopAndDestroyServer();
}
@Test
@SmallTest
public void testNewBrowser() {
String url = mTestServer.getURL("/new_browser.html");
mActivity = mActivityTestRule.launchShellWithUrl(url);
Assert.assertNotNull(mActivity);
NewBrowserCallbackImpl callback = new NewBrowserCallbackImpl();
BrowserController firstBrowserController =
TestThreadUtils.runOnUiThreadBlockingNoException(() -> {
BrowserController browserController =
mActivity.getBrowserFragmentController().getActiveBrowserController();
browserController.setNewBrowserCallback(callback);
return browserController;
});
EventUtils.simulateTouchCenterOfView(mActivity.getWindow().getDecorView());
callback.waitForNewBrowser();
TestThreadUtils.runOnUiThreadBlocking(() -> {
Assert.assertEquals(
2, mActivity.getBrowserFragmentController().getBrowserControllers().size());
BrowserController browserController =
mActivity.getBrowserFragmentController().getActiveBrowserController();
Assert.assertNotSame(firstBrowserController, browserController);
});
}
}
...@@ -59,7 +59,7 @@ public class TopControlsTest { ...@@ -59,7 +59,7 @@ public class TopControlsTest {
.commitNow(); .commitNow();
mBrowserFragmentController = BrowserFragmentController.fromFragment(fragment); mBrowserFragmentController = BrowserFragmentController.fromFragment(fragment);
mBrowserFragmentController.setTopView(new FrameLayout(activity)); mBrowserFragmentController.setTopView(new FrameLayout(activity));
mBrowserController = mBrowserFragmentController.getBrowserController(); mBrowserController = mBrowserFragmentController.getActiveBrowserController();
}); });
mActivityTestRule.navigateAndWait( mActivityTestRule.navigateAndWait(
......
...@@ -132,7 +132,7 @@ public class InstrumentationActivity extends FragmentActivity { ...@@ -132,7 +132,7 @@ public class InstrumentationActivity extends FragmentActivity {
mBrowserFragmentController.setTopView(mTopContentsContainer); mBrowserFragmentController.setTopView(mTopContentsContainer);
mBrowserController = mBrowserFragmentController.getBrowserController(); mBrowserController = mBrowserFragmentController.getActiveBrowserController();
mBrowserController.registerBrowserCallback(new BrowserCallback() { mBrowserController.registerBrowserCallback(new BrowserCallback() {
@Override @Override
public void visibleUrlChanged(Uri uri) { public void visibleUrlChanged(Uri uri) {
......
...@@ -125,7 +125,7 @@ public class WebLayerShellActivity extends FragmentActivity { ...@@ -125,7 +125,7 @@ public class WebLayerShellActivity extends FragmentActivity {
Fragment fragment = getOrCreateBrowserFragment(savedInstanceState); Fragment fragment = getOrCreateBrowserFragment(savedInstanceState);
mBrowserFragmentController = BrowserFragmentController.fromFragment(fragment); mBrowserFragmentController = BrowserFragmentController.fromFragment(fragment);
mBrowserFragmentController.getBrowserController().setFullscreenCallback( mBrowserFragmentController.getActiveBrowserController().setFullscreenCallback(
new FullscreenCallback() { new FullscreenCallback() {
private int mSystemVisibilityToRestore; private int mSystemVisibilityToRestore;
...@@ -166,7 +166,7 @@ public class WebLayerShellActivity extends FragmentActivity { ...@@ -166,7 +166,7 @@ public class WebLayerShellActivity extends FragmentActivity {
mBrowserFragmentController.setTopView(mTopContentsContainer); mBrowserFragmentController.setTopView(mTopContentsContainer);
mBrowserController = mBrowserFragmentController.getBrowserController(); mBrowserController = mBrowserFragmentController.getActiveBrowserController();
String startupUrl = getUrlFromIntent(getIntent()); String startupUrl = getUrlFromIntent(getIntent());
if (TextUtils.isEmpty(startupUrl)) { if (TextUtils.isEmpty(startupUrl)) {
startupUrl = "http://google.com"; startupUrl = "http://google.com";
...@@ -265,7 +265,8 @@ public class WebLayerShellActivity extends FragmentActivity { ...@@ -265,7 +265,8 @@ public class WebLayerShellActivity extends FragmentActivity {
public void onBackPressed() { public void onBackPressed() {
if (mBrowserFragmentController != null) { if (mBrowserFragmentController != null) {
NavigationController controller = NavigationController controller =
mBrowserFragmentController.getBrowserController().getNavigationController(); mBrowserFragmentController.getActiveBrowserController()
.getNavigationController();
if (controller.canGoBack()) { if (controller.canGoBack()) {
controller.goBack(); controller.goBack();
return; return;
......
<html>
<body>
<p id='x'>XXXX</p>
</body>
<script>
document.addEventListener('touchend',
function(e) {
window.open('about:blank', ''); }, false);
</script>
</html>
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