[go: nahoru, domu]

Reland "Add weblayer browser_tests APK so we can run the tests on Android."

This is a reland of aaa2ec5c4603bfe5e423b8e3a49025c5fe75bd9f with fix from patchset 1 to 2 due to conflict with r702520.

Original change's description:
> Add weblayer browser_tests APK so we can run the tests on Android.
>
> The Shell C++ class isn't used on Android (unlike in content_shell) because we want to consume WebLayer there using the idiomatic Java API. At the same time, we want to write browser tests the same way for all platforms. So fake this by creating a Shell that reuses the existing BrowserController class that was created by Java.
>
> Change-Id: I946957f39eb79cff2e84c8abda56eed98b28d0a0
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1815884
> Reviewed-by: Clark DuVall <cduvall@chromium.org>
> Commit-Queue: John Abd-El-Malek <jam@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#702563}

TBR=cduvall@chromium.org

Change-Id: I425b7b15d9f742a25a5b7c9dd306067ca29e551b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1838953
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
Commit-Queue: John Abd-El-Malek <jam@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702657}
diff --git a/BUILD.gn b/BUILD.gn
index 0a5bcd64..f52daa3c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -195,12 +195,10 @@
   }
 
   if (is_win || (is_linux && !is_chromeos) || is_android) {
-    deps += [ "//weblayer/shell:weblayer_shell" ]
-  }
-
-  # TODO: enable this on Android.
-  if (is_win || (is_linux && !is_chromeos)) {
-    deps += [ "//weblayer/test:weblayer_browsertests" ]
+    deps += [
+      "//weblayer/shell:weblayer_shell",
+      "//weblayer/test:weblayer_browsertests",
+    ]
   }
 
   if (!is_ios && !is_android) {
diff --git a/build/android/pylib/constants/__init__.py b/build/android/pylib/constants/__init__.py
index aff42e3..5daecb6 100644
--- a/build/android/pylib/constants/__init__.py
+++ b/build/android/pylib/constants/__init__.py
@@ -79,6 +79,11 @@
     chrome.PackageInfo('org.chromium.webview_ui_test',
                        'org.chromium.webview_ui_test.WebViewUiTestActivity',
                        'webview-command-line', None),
+    'weblayer_browsertests':
+    chrome.PackageInfo(
+        'org.chromium.weblayer_browsertests_apk',
+        'org.chromium.weblayer_browsertests_apk.WebLayerBrowserTestsActivity',
+        'chrome-native-tests-command-line', None),
 })
 
 
diff --git a/testing/android/native_test/BUILD.gn b/testing/android/native_test/BUILD.gn
index e938a4d9..b6ee7181 100644
--- a/testing/android/native_test/BUILD.gn
+++ b/testing/android/native_test/BUILD.gn
@@ -61,6 +61,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//testing/android/reporter:reporter_java",
+    "//third_party/android_deps:android_support_v4_java",
   ]
   java_files = [
     "java/src/org/chromium/native_test/NativeBrowserTest.java",
diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java
index 0e3f245f..437cd8c2 100644
--- a/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java
+++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java
@@ -4,15 +4,15 @@
 
 package org.chromium.native_test;
 
-import android.app.Activity;
 import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
 
 import java.io.File;
 
 /**
  * An {@link android.app.Activity} for running native browser tests.
  */
-public abstract class NativeBrowserTestActivity extends Activity {
+public abstract class NativeBrowserTestActivity extends FragmentActivity {
     private static final String TAG = "cr_NativeTest";
 
     private NativeTest mTest = new NativeTest();
diff --git a/weblayer/browser/browser_controller_impl.cc b/weblayer/browser/browser_controller_impl.cc
index 05613da..3b8ddc7 100644
--- a/weblayer/browser/browser_controller_impl.cc
+++ b/weblayer/browser/browser_controller_impl.cc
@@ -24,8 +24,19 @@
 
 namespace weblayer {
 
+namespace {
+
+#if defined(OS_ANDROID)
+BrowserController* g_last_browser_controller;
+#endif
+
+}  // namespace
+
 BrowserControllerImpl::BrowserControllerImpl(ProfileImpl* profile)
     : profile_(profile) {
+#if defined(OS_ANDROID)
+  g_last_browser_controller = this;
+#endif
   content::WebContents::CreateParams create_params(
       profile_->GetBrowserContext());
   web_contents_ = content::WebContents::Create(create_params);
@@ -150,4 +161,10 @@
       static_cast<ProfileImpl*>(profile));
 }
 
+#if defined(OS_ANDROID)
+BrowserController* BrowserController::GetLastControllerForTesting() {
+  return g_last_browser_controller;
+}
+#endif
+
 }  // namespace weblayer
diff --git a/weblayer/public/browser_controller.h b/weblayer/public/browser_controller.h
index f66bc54..eab6012 100644
--- a/weblayer/public/browser_controller.h
+++ b/weblayer/public/browser_controller.h
@@ -25,6 +25,10 @@
  public:
   static std::unique_ptr<BrowserController> Create(Profile* profile);
 
+#if defined(OS_ANDROID)
+  static BrowserController* GetLastControllerForTesting();
+#endif
+
   virtual ~BrowserController() {}
 
   virtual void AddObserver(BrowserObserver* observer) = 0;
diff --git a/weblayer/shell/BUILD.gn b/weblayer/shell/BUILD.gn
index ad6f90de..e8117814 100644
--- a/weblayer/shell/BUILD.gn
+++ b/weblayer/shell/BUILD.gn
@@ -27,6 +27,7 @@
     "app/shell_main_params.h",
     "browser/shell.cc",
     "browser/shell.h",
+    "browser/shell_android.cc",
     "common/shell_switches.cc",
     "common/shell_switches.h",
   ]
diff --git a/weblayer/shell/android/browsertests_apk/AndroidManifest.xml b/weblayer/shell/android/browsertests_apk/AndroidManifest.xml
new file mode 100644
index 0000000..1097073
--- /dev/null
+++ b/weblayer/shell/android/browsertests_apk/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.chromium.weblayer_browsertests_apk">
+
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.CAMERA"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
+    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+    <uses-permission android:name="android.permission.VIBRATE"/>
+    <uses-permission android:name="android.permission.WAKE_LOCK"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+    <application android:name="WebLayerBrowserTestsApplication" android:label="WebLayerBrowserTests">
+        <activity android:name="WebLayerBrowserTestsActivity"
+                  android:launchMode="singleTask"
+                  android:theme="@android:style/Theme.Holo.Light.NoActionBar"
+                  android:configChanges="orientation|keyboardHidden|keyboard|screenSize"
+                  android:windowSoftInputMode="adjustPan|stateUnspecified">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+
+        <meta-data android:name="org.chromium.weblayer.WebLayerPackage"
+                   android:value="org.chromium.weblayer_browsertests_apk"/>
+    </application>
+
+    <instrumentation android:name="org.chromium.native_test.NativeTestInstrumentationTestRunner"
+            android:label="WebLayerBrowserTests"
+            android:targetPackage="org.chromium.weblayer_browsertests_apk"
+            chromium-junit3="true"/>
+</manifest>
diff --git a/weblayer/shell/android/browsertests_apk/DEPS b/weblayer/shell/android/browsertests_apk/DEPS
new file mode 100644
index 0000000..00e43bef
--- /dev/null
+++ b/weblayer/shell/android/browsertests_apk/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+  "+content/public/android",
+  "+content/public/app",
+  "+content/public/test",
+  "+ui/android",
+]
diff --git a/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsActivity.java b/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsActivity.java
new file mode 100644
index 0000000..dcb69e2
--- /dev/null
+++ b/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsActivity.java
@@ -0,0 +1,112 @@
+// 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_browsertests_apk;
+
+import android.net.Uri;
+import android.support.v4.app.FragmentTransaction;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+
+import org.chromium.base.library_loader.LibraryProcessType;
+import org.chromium.base.test.util.UrlUtils;
+import org.chromium.content_public.browser.BrowserStartupController;
+import org.chromium.native_test.NativeBrowserTest;
+import org.chromium.native_test.NativeBrowserTestActivity;
+import org.chromium.weblayer.BrowserController;
+import org.chromium.weblayer.BrowserFragmentController;
+import org.chromium.weblayer.BrowserObserver;
+import org.chromium.weblayer.ListenableFuture;
+import org.chromium.weblayer.Profile;
+import org.chromium.weblayer.WebLayer;
+
+import java.io.File;
+
+/** An Activity base class for running browser tests against WebLayerShell. */
+public class WebLayerBrowserTestsActivity extends NativeBrowserTestActivity {
+    private static final String TAG = "cr.native_test";
+
+    private WebLayer mWebLayer;
+    private Profile mProfile;
+    private BrowserFragmentController mBrowserFragmentController;
+    private BrowserController mBrowserController;
+    private EditText mUrlView;
+    private View mMainView;
+
+    @Override
+    protected void onDestroy() {
+        if (mProfile != null) mProfile.destroy();
+        if (mBrowserFragmentController != null) mBrowserFragmentController.destroy();
+        super.onDestroy();
+    }
+
+    @Override
+    protected void initializeBrowserProcess() {
+        BrowserStartupController.get(LibraryProcessType.PROCESS_WEBLAYER)
+                .setContentMainCallbackForTests(() -> {
+                    // This jumps into C++ to set up and run the test harness. The test harness runs
+                    // ContentMain()-equivalent code, and then waits for javaStartupTasksComplete()
+                    // to be called.
+                    runTests();
+                });
+
+        try {
+            ListenableFuture<WebLayer> future = WebLayer.create(getApplication());
+            future.addCallback((WebLayer webLayer) -> {
+                mWebLayer = webLayer;
+                createShell();
+            });
+        } catch (Exception e) {
+            throw new RuntimeException("failed loading WebLayer", e);
+        }
+
+        NativeBrowserTest.javaStartupTasksComplete();
+    }
+
+    protected void createShell() {
+        LinearLayout mainView = new LinearLayout(this);
+        int viewId = View.generateViewId();
+        mainView.setId(viewId);
+        mMainView = mainView;
+        setContentView(mainView);
+
+        mUrlView = new EditText(this);
+        mUrlView.setId(View.generateViewId());
+        // The background of the top-view must be opaque, otherwise it bleeds through to the
+        // cc::Layer that mirrors the contents of the top-view.
+        mUrlView.setBackgroundColor(0xFFa9a9a9);
+
+        RelativeLayout topContentsContainer = new RelativeLayout(this);
+        topContentsContainer.addView(mUrlView,
+                new RelativeLayout.LayoutParams(
+                        LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+
+        mProfile = mWebLayer.createProfile(null);
+
+        mBrowserFragmentController = mProfile.createBrowserFragmentController(this);
+
+        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+        transaction.add(viewId, mBrowserFragmentController.getFragment());
+        transaction.commit();
+
+        mBrowserFragmentController.setTopView(topContentsContainer);
+
+        mBrowserController = mBrowserFragmentController.getBrowserController();
+        mBrowserController.addObserver(new BrowserObserver() {
+            @Override
+            public void visibleUrlChanged(Uri uri) {
+                mUrlView.setText(uri.toString());
+            }
+        });
+    }
+
+    @Override
+    protected File getPrivateDataDirectory() {
+        return new File(UrlUtils.getIsolatedTestRoot(),
+                WebLayerBrowserTestsApplication.PRIVATE_DATA_DIRECTORY_SUFFIX);
+    }
+}
diff --git a/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsApplication.java b/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsApplication.java
new file mode 100644
index 0000000..f2e52a2
--- /dev/null
+++ b/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsApplication.java
@@ -0,0 +1,29 @@
+// 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_browsertests_apk;
+
+import android.content.Context;
+
+import org.chromium.base.PathUtils;
+import org.chromium.native_test.NativeBrowserTestApplication;
+import org.chromium.ui.base.ResourceBundle;
+
+/**
+ * A basic weblayer_public.browser.tests {@link android.app.Application}.
+ */
+public class WebLayerBrowserTestsApplication extends NativeBrowserTestApplication {
+    static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "weblayer_shell";
+
+    @Override
+    protected void attachBaseContext(Context base) {
+        super.attachBaseContext(base);
+
+        if (isBrowserProcess()) {
+            // Test-only stuff, see also NativeUnitTest.java.
+            PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
+            ResourceBundle.setNoAvailableLocalePaks();
+        }
+    }
+}
diff --git a/weblayer/shell/android/browsertests_apk/weblayer_browser_tests_jni_onload.cc b/weblayer/shell/android/browsertests_apk/weblayer_browser_tests_jni_onload.cc
new file mode 100644
index 0000000..7a14e5e
--- /dev/null
+++ b/weblayer/shell/android/browsertests_apk/weblayer_browser_tests_jni_onload.cc
@@ -0,0 +1,34 @@
+// 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 <memory>
+
+#include "base/android/jni_android.h"
+#include "base/android/library_loader/library_loader_hooks.h"
+#include "base/bind.h"
+#include "base/message_loop/message_pump.h"
+#include "content/public/app/content_jni_onload.h"
+#include "content/public/app/content_main.h"
+#include "content/public/test/nested_message_pump_android.h"
+#include "testing/android/native_test/native_test_launcher.h"
+#include "weblayer/app/content_main_delegate_impl.h"
+#include "weblayer/shell/app/shell_main_params.h"
+
+// This is called by the VM when the shared library is first loaded.
+JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+  base::android::InitVM(vm);
+  if (!content::android::OnJNIOnLoadInit())
+    return -1;
+
+  // This needs to be done before base::TestSuite::Initialize() is called,
+  // as it also tries to set MessagePumpForUIFactory.
+  base::MessagePump::OverrideMessagePumpForUIFactory(
+      []() -> std::unique_ptr<base::MessagePump> {
+        return std::make_unique<content::NestedMessagePumpAndroid>();
+      });
+
+  content::SetContentMainDelegate(
+      new weblayer::ContentMainDelegateImpl(weblayer::CreateMainParams()));
+  return JNI_VERSION_1_4;
+}
diff --git a/weblayer/shell/browser/shell.cc b/weblayer/shell/browser/shell.cc
index 78279a5d..5fab8e4 100644
--- a/weblayer/shell/browser/shell.cc
+++ b/weblayer/shell/browser/shell.cc
@@ -32,11 +32,13 @@
 Shell::Shell(std::unique_ptr<BrowserController> browser_controller)
     : browser_controller_(std::move(browser_controller)), window_(nullptr) {
   windows_.push_back(this);
-  browser_controller_->AddObserver(this);
+  if (browser_controller_)
+    browser_controller_->AddObserver(this);
 }
 
 Shell::~Shell() {
-  browser_controller_->RemoveObserver(this);
+  if (browser_controller_)
+    browser_controller_->RemoveObserver(this);
   PlatformCleanUp();
 
   for (size_t i = 0; i < windows_.size(); ++i) {
@@ -89,6 +91,15 @@
   *g_quit_main_message_loop = std::move(quit_closure);
 }
 
+BrowserController* Shell::browser_controller() {
+#if defined(OS_ANDROID)
+  // TODO(jam): this won't work if we need more than one Shell in a test.
+  return BrowserController::GetLastControllerForTesting();
+#else
+  return browser_controller_.get();
+#endif
+}
+
 void Shell::Initialize() {
   PlatformInitialize(GetShellDefaultSize());
 }
@@ -122,7 +133,11 @@
 Shell* Shell::CreateNewWindow(weblayer::Profile* web_profile,
                               const GURL& url,
                               const gfx::Size& initial_size) {
+#if defined(OS_ANDROID)
+  std::unique_ptr<BrowserController> browser_controller;
+#else
   auto browser_controller = BrowserController::Create(web_profile);
+#endif
 
   Shell* shell = CreateShell(std::move(browser_controller),
                              AdjustWindowSize(initial_size));
@@ -132,24 +147,24 @@
 }
 
 void Shell::LoadURL(const GURL& url) {
-  browser_controller_->GetNavigationController()->Navigate(url);
+  browser_controller()->GetNavigationController()->Navigate(url);
 }
 
 void Shell::GoBackOrForward(int offset) {
   if (offset == -1)
-    browser_controller_->GetNavigationController()->GoBack();
+    browser_controller()->GetNavigationController()->GoBack();
   else if (offset == 1)
-    browser_controller_->GetNavigationController()->GoForward();
+    browser_controller()->GetNavigationController()->GoForward();
 }
 
 void Shell::Reload() {
-  browser_controller_->GetNavigationController()->Reload();
+  browser_controller()->GetNavigationController()->Reload();
 }
 
 void Shell::ReloadBypassingCache() {}
 
 void Shell::Stop() {
-  browser_controller_->GetNavigationController()->Stop();
+  browser_controller()->GetNavigationController()->Stop();
 }
 
 gfx::Size Shell::GetShellDefaultSize() {
diff --git a/weblayer/shell/browser/shell.h b/weblayer/shell/browser/shell.h
index 49e0c9f..3b36bba 100644
--- a/weblayer/shell/browser/shell.h
+++ b/weblayer/shell/browser/shell.h
@@ -38,6 +38,9 @@
 
 // This represents one window of the Web Shell, i.e. all the UI including
 // buttons and url bar, as well as the web content area.
+// On desktop this is used for the demo Shell application and also
+// weblayer_browsertests. On Android this is only used for
+// weblayer_browsertests.
 class Shell : public BrowserObserver {
  public:
   ~Shell() override;
@@ -67,7 +70,7 @@
   // instance is destroyed.
   static void SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure);
 
-  BrowserController* browser_controller() { return browser_controller_.get(); }
+  BrowserController* browser_controller();
 
   gfx::NativeWindow window() { return window_; }
 
diff --git a/weblayer/shell/browser/shell_android.cc b/weblayer/shell/browser/shell_android.cc
new file mode 100644
index 0000000..f4b5a0c8
--- /dev/null
+++ b/weblayer/shell/browser/shell_android.cc
@@ -0,0 +1,33 @@
+// 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/shell/browser/shell.h"
+
+namespace weblayer {
+
+// Shell is only used on Android for weblayer_browsertests. So no need to
+// implement these methods.
+void Shell::PlatformInitialize(const gfx::Size& default_window_size) {}
+
+void Shell::PlatformExit() {}
+
+void Shell::PlatformCleanUp() {}
+
+void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) {}
+
+void Shell::PlatformSetAddressBarURL(const GURL& url) {}
+
+void Shell::PlatformSetLoadProgress(double progress) {}
+
+void Shell::PlatformCreateWindow(int width, int height) {}
+
+void Shell::PlatformSetContents() {}
+
+void Shell::PlatformResizeSubViews() {}
+
+void Shell::Close() {}
+
+void Shell::PlatformSetTitle(const base::string16& title) {}
+
+}  // namespace weblayer
diff --git a/weblayer/test/BUILD.gn b/weblayer/test/BUILD.gn
index 739026e..f0b855c 100644
--- a/weblayer/test/BUILD.gn
+++ b/weblayer/test/BUILD.gn
@@ -8,6 +8,60 @@
 import("//tools/grit/grit_rule.gni")
 import("//tools/v8_context_snapshot/v8_context_snapshot.gni")
 
+if (is_android) {
+  import("//build/config/android/rules.gni")
+
+  weblayer_browsertests_manifest =
+      "${target_gen_dir}/weblayer_browsertests_manifest/AndroidManifest.xml"
+
+  jinja_template("weblayer_browsertests_manifest") {
+    testonly = true
+    input = "//weblayer/shell/android/browsertests_apk/AndroidManifest.xml"
+    output = weblayer_browsertests_manifest
+  }
+
+  android_library("weblayer_browsertests_java") {
+    testonly = true
+    java_files = [
+      "../shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsActivity.java",
+      "../shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsApplication.java",
+    ]
+    deps = [
+      ":weblayer_browsertests_manifest",
+      "//base:base_java",
+      "//base:base_java_test_support",
+      "//content/public/android:content_java",
+      "//content/public/test/android:content_java_test_support",
+      "//testing/android/native_test:native_test_java",
+      "//third_party/android_deps:android_support_v4_java",
+      "//third_party/android_deps:com_android_support_support_compat_java",
+      "//ui/android:ui_java",
+      "//weblayer/public/java",
+    ]
+
+    android_manifest_for_lint = weblayer_browsertests_manifest
+  }
+}
+
+if (is_android) {
+  android_assets("weblayer_test_assets") {
+    testonly = true
+    sources = [
+      "$root_out_dir/weblayer.pak",
+    ]
+    disable_compression = true
+    deps = [
+      "//third_party/icu:icu_assets",
+      "//weblayer/shell:pak",
+    ]
+    if (use_v8_context_snapshot) {
+      deps += [ "//tools/v8_context_snapshot:v8_context_snapshot_assets" ]
+    } else {
+      deps += [ "//v8:v8_external_startup_data_assets" ]
+    }
+  }
+}
+
 test("weblayer_browsertests") {
   data = [
     "$root_out_dir/weblayer_shell.pak",
@@ -44,4 +98,28 @@
     "weblayer_browser_test_utils.cc",
     "weblayer_browser_test_utils.h",
   ]
+
+  if (is_android) {
+    sources += [
+      "../shell/android/browsertests_apk/weblayer_browser_tests_jni_onload.cc",
+    ]
+    deps += [
+      ":weblayer_browsertests_java",
+      ":weblayer_test_assets",
+      "//content/public/test/android:android_test_message_pump_support_java",
+      "//content/test:android_test_message_pump_support",
+      "//content/test:android_test_message_pump_support",
+      "//services/tracing:test_utils",
+      "//testing/android/native_test:native_test_support",
+      "//ui/android:android",
+      "//ui/touch_selection:touch_selection",
+
+      # Needed for WebLayerImpl.
+      "//weblayer/browser/java",
+    ]
+    android_manifest =
+        "${target_gen_dir}/weblayer_browsertests_manifest/AndroidManifest.xml"
+    android_manifest_dep = ":weblayer_browsertests_manifest"
+    use_default_launcher = false
+  }
 }