summaryrefslogtreecommitdiff
path: root/chromium/weblayer/shell
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/weblayer/shell
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/weblayer/shell')
-rw-r--r--chromium/weblayer/shell/android/BUILD.gn2
-rw-r--r--chromium/weblayer/shell/android/browsertests_apk/metrics_browsertest.cc93
-rw-r--r--chromium/weblayer/shell/android/browsertests_apk/metrics_test_helper.cc61
-rw-r--r--chromium/weblayer/shell/android/browsertests_apk/metrics_test_helper.h36
-rw-r--r--chromium/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsActivity.java19
-rw-r--r--chromium/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_private/MetricsTestHelper.java25
-rw-r--r--chromium/weblayer/shell/android/shell_apk/AndroidManifest.xml3
-rw-r--r--chromium/weblayer/shell/android/shell_apk/res/layout/shell_browser_controls.xml1
-rw-r--r--chromium/weblayer/shell/android/shell_apk/res/menu/app_menu.xml2
-rw-r--r--chromium/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/WebLayerShellActivity.java40
-rw-r--r--chromium/weblayer/shell/app/shell_main_params.cc22
-rw-r--r--chromium/weblayer/shell/browser/shell.cc72
-rw-r--r--chromium/weblayer/shell/browser/shell.h16
-rw-r--r--chromium/weblayer/shell/browser/shell_views.cc32
-rw-r--r--chromium/weblayer/shell/common/shell_switches.cc3
-rw-r--r--chromium/weblayer/shell/common/shell_switches.h2
16 files changed, 332 insertions, 97 deletions
diff --git a/chromium/weblayer/shell/android/BUILD.gn b/chromium/weblayer/shell/android/BUILD.gn
index bc3a270505f..5a6d1f7ff78 100644
--- a/chromium/weblayer/shell/android/BUILD.gn
+++ b/chromium/weblayer/shell/android/BUILD.gn
@@ -203,7 +203,7 @@ android_apk("weblayer_support_apk") {
rebase_path("$root_gen_dir/CHROME_VERSION.json", root_build_dir)
native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)"
- shared_libraries = [ "//weblayer:libweblayer" ]
+ shared_libraries = [ "//weblayer:libweblayer_test" ]
}
python_library("weblayer_shell_wpt") {
diff --git a/chromium/weblayer/shell/android/browsertests_apk/metrics_browsertest.cc b/chromium/weblayer/shell/android/browsertests_apk/metrics_browsertest.cc
index 30ff1b25e2c..a4f0af9ae89 100644
--- a/chromium/weblayer/shell/android/browsertests_apk/metrics_browsertest.cc
+++ b/chromium/weblayer/shell/android/browsertests_apk/metrics_browsertest.cc
@@ -4,33 +4,51 @@
#include <deque>
-#include "base/android/jni_android.h"
#include "base/command_line.h"
+#include "base/metrics/metrics_hashes.h"
+#include "base/metrics/statistics_recorder.h"
#include "base/no_destructor.h"
#include "base/test/bind_test_util.h"
+#include "components/metrics/log_decoder.h"
+#include "components/metrics/metrics_log_uploader.h"
#include "components/metrics/metrics_switches.h"
+#include "content/public/test/browser_test_utils.h"
#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
#include "weblayer/browser/android/metrics/weblayer_metrics_service_client.h"
#include "weblayer/browser/profile_impl.h"
#include "weblayer/public/navigation_controller.h"
#include "weblayer/public/profile.h"
#include "weblayer/public/tab.h"
+#include "weblayer/shell/android/browsertests_apk/metrics_test_helper.h"
#include "weblayer/shell/browser/shell.h"
#include "weblayer/test/weblayer_browser_test.h"
-#include "weblayer/test/weblayer_browsertests_jni/MetricsTestHelper_jni.h"
+#include "weblayer/test/weblayer_browser_test_utils.h"
namespace weblayer {
+namespace {
+
+bool HasHistogramWithHash(const metrics::ChromeUserMetricsExtension& uma_log,
+ uint64_t hash) {
+ for (int i = 0; i < uma_log.histogram_event_size(); ++i) {
+ if (uma_log.histogram_event(i).name_hash() == hash) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
class MetricsBrowserTest : public WebLayerBrowserTest {
public:
void SetUp() override {
- instance_ = this;
-
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitch(metrics::switches::kForceEnableMetricsReporting);
- Java_MetricsTestHelper_installTestGmsBridge(
- base::android::AttachCurrentThread(), HasUserConsent());
+ InstallTestGmsBridge(HasUserConsent(),
+ base::BindRepeating(&MetricsBrowserTest::OnLogMetrics,
+ base::Unretained(this)));
WebLayerMetricsServiceClient::GetInstance()->SetFastStartupForTesting(true);
WebLayerMetricsServiceClient::GetInstance()->SetUploadIntervalForTesting(
base::TimeDelta::FromMilliseconds(10));
@@ -38,20 +56,17 @@ class MetricsBrowserTest : public WebLayerBrowserTest {
}
void TearDown() override {
- Java_MetricsTestHelper_removeTestGmsBridge(
- base::android::AttachCurrentThread());
- instance_ = nullptr;
+ RemoveTestGmsBridge();
WebLayerBrowserTest::TearDown();
}
- static void OnLogMetrics(const metrics::ChromeUserMetricsExtension& metric) {
- if (!instance_)
- return;
- instance_->metrics_logs_.push_back(metric);
- std::move(instance_->on_new_log_).Run();
+ void OnLogMetrics(metrics::ChromeUserMetricsExtension metric) {
+ metrics_logs_.push_back(metric);
+ if (on_new_log_)
+ std::move(on_new_log_).Run();
}
- metrics::ChromeUserMetricsExtension waitForNextMetricsLog() {
+ metrics::ChromeUserMetricsExtension WaitForNextMetricsLog() {
if (metrics_logs_.empty()) {
base::RunLoop run_loop;
on_new_log_ = run_loop.QuitClosure();
@@ -71,23 +86,10 @@ class MetricsBrowserTest : public WebLayerBrowserTest {
std::unique_ptr<Profile> profile_;
std::deque<metrics::ChromeUserMetricsExtension> metrics_logs_;
base::OnceClosure on_new_log_;
- static MetricsBrowserTest* instance_;
};
-MetricsBrowserTest* MetricsBrowserTest::instance_ = nullptr;
-
-void JNI_MetricsTestHelper_OnLogMetrics(
- JNIEnv* env,
- const base::android::JavaParamRef<jbyteArray>& data) {
- metrics::ChromeUserMetricsExtension proto;
- jbyte* src_bytes = env->GetByteArrayElements(data, nullptr);
- proto.ParseFromArray(src_bytes, env->GetArrayLength(data.obj()));
- env->ReleaseByteArrayElements(data, src_bytes, JNI_ABORT);
- MetricsBrowserTest::OnLogMetrics(proto);
-}
-
IN_PROC_BROWSER_TEST_F(MetricsBrowserTest, ProtoHasExpectedFields) {
- metrics::ChromeUserMetricsExtension log = waitForNextMetricsLog();
+ metrics::ChromeUserMetricsExtension log = WaitForNextMetricsLog();
EXPECT_EQ(metrics::ChromeUserMetricsExtension::ANDROID_WEBLAYER,
log.product());
EXPECT_TRUE(log.has_client_id());
@@ -118,7 +120,7 @@ IN_PROC_BROWSER_TEST_F(MetricsBrowserTest, ProtoHasExpectedFields) {
}
IN_PROC_BROWSER_TEST_F(MetricsBrowserTest, PageLoadsEnableMultipleUploads) {
- waitForNextMetricsLog();
+ WaitForNextMetricsLog();
// At this point, the MetricsService should be asleep, and should not have
// created any more metrics logs.
@@ -133,7 +135,7 @@ IN_PROC_BROWSER_TEST_F(MetricsBrowserTest, PageLoadsEnableMultipleUploads) {
// This may take slightly longer than UPLOAD_INTERVAL_MS, due to the time
// spent processing the metrics log, but should be well within the timeout
// (unless something is broken).
- waitForNextMetricsLog();
+ WaitForNextMetricsLog();
// If we get here, we got a second metrics log (and the test may pass). If
// there was no second metrics log, then the above call will check fail with a
@@ -143,6 +145,35 @@ IN_PROC_BROWSER_TEST_F(MetricsBrowserTest, PageLoadsEnableMultipleUploads) {
// might potentially have a third metrics log in the queue.
}
+IN_PROC_BROWSER_TEST_F(MetricsBrowserTest, RendererHistograms) {
+ base::HistogramTester histogram_tester;
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ NavigateAndWaitForCompletion(
+ embedded_test_server()->GetURL("/simple_page.html"), shell());
+
+ uint64_t hash = base::HashMetricName("Android.SeccompStatus.RendererSandbox");
+
+ bool collect_final_metrics_for_log_called = false;
+
+ WebLayerMetricsServiceClient::GetInstance()
+ ->SetCollectFinalMetricsForLogClosureForTesting(
+ base::BindLambdaForTesting(
+ [&]() { collect_final_metrics_for_log_called = true; }));
+
+ // Not every WaitForNextMetricsLog call will end up calling
+ // MetricsServiceClient::CollectFinalMetricsForLog since there may already be
+ // staged logs to send (see ReportingService::SendNextLog). Since we need to
+ // wait for CollectFinalMetricsForLog to be run after the navigate call above,
+ // keep calling WaitForNextMetricsLog until CollectFinalMetricsForLog is
+ // called.
+ metrics::ChromeUserMetricsExtension uma_log;
+ while (!collect_final_metrics_for_log_called)
+ uma_log = WaitForNextMetricsLog();
+
+ ASSERT_TRUE(HasHistogramWithHash(uma_log, hash));
+}
+
class MetricsBrowserTestWithUserOptOut : public MetricsBrowserTest {
bool HasUserConsent() override { return false; }
};
diff --git a/chromium/weblayer/shell/android/browsertests_apk/metrics_test_helper.cc b/chromium/weblayer/shell/android/browsertests_apk/metrics_test_helper.cc
new file mode 100644
index 00000000000..5b78584f5a1
--- /dev/null
+++ b/chromium/weblayer/shell/android/browsertests_apk/metrics_test_helper.cc
@@ -0,0 +1,61 @@
+// Copyright 2020 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/android/browsertests_apk/metrics_test_helper.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/no_destructor.h"
+#include "weblayer/test/weblayer_browsertests_jni/MetricsTestHelper_jni.h"
+
+namespace weblayer {
+
+namespace {
+
+OnLogsMetricsCallback& GetOnLogMetricsCallback() {
+ static base::NoDestructor<OnLogsMetricsCallback> s_callback;
+ return *s_callback;
+}
+
+} // namespace
+
+void InstallTestGmsBridge(bool has_user_consent,
+ const OnLogsMetricsCallback on_log_metrics) {
+ GetOnLogMetricsCallback() = on_log_metrics;
+ Java_MetricsTestHelper_installTestGmsBridge(
+ base::android::AttachCurrentThread(), has_user_consent);
+}
+
+void RemoveTestGmsBridge() {
+ Java_MetricsTestHelper_removeTestGmsBridge(
+ base::android::AttachCurrentThread());
+ GetOnLogMetricsCallback().Reset();
+}
+
+void CreateProfile(const std::string& name) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_MetricsTestHelper_createProfile(
+ env, base::android::ConvertUTF8ToJavaString(env, name));
+}
+void DestroyProfile(const std::string& name) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_MetricsTestHelper_destroyProfile(
+ env, base::android::ConvertUTF8ToJavaString(env, name));
+}
+
+void JNI_MetricsTestHelper_OnLogMetrics(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jbyteArray>& data) {
+ auto& callback = GetOnLogMetricsCallback();
+ if (!callback)
+ return;
+
+ metrics::ChromeUserMetricsExtension proto;
+ jbyte* src_bytes = env->GetByteArrayElements(data, nullptr);
+ proto.ParseFromArray(src_bytes, env->GetArrayLength(data.obj()));
+ env->ReleaseByteArrayElements(data, src_bytes, JNI_ABORT);
+ callback.Run(proto);
+}
+
+} // namespace weblayer
diff --git a/chromium/weblayer/shell/android/browsertests_apk/metrics_test_helper.h b/chromium/weblayer/shell/android/browsertests_apk/metrics_test_helper.h
new file mode 100644
index 00000000000..6c54134cbcc
--- /dev/null
+++ b/chromium/weblayer/shell/android/browsertests_apk/metrics_test_helper.h
@@ -0,0 +1,36 @@
+// Copyright 2020 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_SHELL_ANDROID_BROWSERTESTS_APK_METRICS_TEST_HELPER_H_
+#define WEBLAYER_SHELL_ANDROID_BROWSERTESTS_APK_METRICS_TEST_HELPER_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
+
+namespace weblayer {
+
+// Various utilities to bridge to Java code for metrics related tests.
+
+using OnLogsMetricsCallback =
+ base::RepeatingCallback<void(metrics::ChromeUserMetricsExtension)>;
+
+// Call this in the SetUp() test harness method to install the test
+// GmsBridge and to set the metrics user consent state.
+void InstallTestGmsBridge(
+ bool has_user_consent,
+ const OnLogsMetricsCallback on_log_metrics = OnLogsMetricsCallback());
+
+// Call this in the TearDown() test harness method to remove the GmsBridge.
+void RemoveTestGmsBridge();
+
+// See Profile::Create()'s comments for the semantics of |name|.
+void CreateProfile(const std::string& name);
+
+void DestroyProfile(const std::string& name);
+
+} // namespace weblayer
+
+#endif // WEBLAYER_SHELL_ANDROID_BROWSERTESTS_APK_METRICS_TEST_HELPER_H_
diff --git a/chromium/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsActivity.java b/chromium/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsActivity.java
index 4837ddac429..ecc26c1f6ca 100644
--- a/chromium/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsActivity.java
+++ b/chromium/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_browsertests_apk/WebLayerBrowserTestsActivity.java
@@ -14,11 +14,14 @@ import android.widget.RelativeLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
+import org.chromium.base.CommandLine;
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.Browser;
+import org.chromium.weblayer.NewTabCallback;
+import org.chromium.weblayer.NewTabType;
import org.chromium.weblayer.Profile;
import org.chromium.weblayer.Tab;
import org.chromium.weblayer.TabCallback;
@@ -50,12 +53,13 @@ public class WebLayerBrowserTestsActivity extends NativeBrowserTestActivity {
WebLayer.loadAsync(getApplication(), webLayer -> {
mWebLayer = webLayer;
createShell();
+
+ NativeBrowserTest.javaStartupTasksComplete();
});
} catch (Exception e) {
throw new RuntimeException("failed loading WebLayer", e);
}
- NativeBrowserTest.javaStartupTasksComplete();
}
protected void createShell() {
@@ -76,7 +80,10 @@ public class WebLayerBrowserTestsActivity extends NativeBrowserTestActivity {
new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
- Fragment fragment = WebLayer.createBrowserFragment("BrowserTestProfile");
+ CommandLine commandLine = CommandLine.getInstance();
+ String path = (commandLine.hasSwitch("start-in-incognito")) ? null : "BrowserTestProfile";
+
+ Fragment fragment = WebLayer.createBrowserFragment(path);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(viewId, fragment);
@@ -93,6 +100,14 @@ public class WebLayerBrowserTestsActivity extends NativeBrowserTestActivity {
mUrlView.setText(uri.toString());
}
});
+ // Set a new tab callback to make sure popups are added.
+ mTab.setNewTabCallback(new NewTabCallback() {
+ @Override
+ public void onNewTab(Tab tab, @NewTabType int type) {}
+
+ @Override
+ public void onCloseTab() {}
+ });
}
@Override
diff --git a/chromium/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_private/MetricsTestHelper.java b/chromium/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_private/MetricsTestHelper.java
index 41affaaf8ab..c89b0e38793 100644
--- a/chromium/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_private/MetricsTestHelper.java
+++ b/chromium/weblayer/shell/android/browsertests_apk/src/org/chromium/weblayer_private/MetricsTestHelper.java
@@ -4,11 +4,16 @@
package org.chromium.weblayer_private;
+import android.content.Context;
+import android.text.TextUtils;
+
import org.chromium.base.Callback;
+import org.chromium.base.ContextUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
+import org.chromium.weblayer.WebLayer;
/**
* Helper for metrics_browsertest.cc
@@ -50,6 +55,26 @@ class MetricsTestHelper {
}
@CalledByNative
+ private static void createProfile(String name) {
+ Context appContext = ContextUtils.getApplicationContext();
+ WebLayer weblayer = WebLayer.loadSync(appContext);
+
+ String nameOrNull = null;
+ if (!TextUtils.isEmpty(name)) nameOrNull = name;
+ weblayer.getProfile(nameOrNull);
+ }
+
+ @CalledByNative
+ private static void destroyProfile(String name) {
+ Context appContext = ContextUtils.getApplicationContext();
+ WebLayer weblayer = WebLayer.loadSync(appContext);
+
+ String nameOrNull = null;
+ if (!TextUtils.isEmpty(name)) nameOrNull = name;
+ weblayer.getProfile(nameOrNull).destroy();
+ }
+
+ @CalledByNative
private static void removeTestGmsBridge() {
GmsBridge.injectInstance(null);
}
diff --git a/chromium/weblayer/shell/android/shell_apk/AndroidManifest.xml b/chromium/weblayer/shell/android/shell_apk/AndroidManifest.xml
index fabe6849287..83ab34ddbd4 100644
--- a/chromium/weblayer/shell/android/shell_apk/AndroidManifest.xml
+++ b/chromium/weblayer/shell/android/shell_apk/AndroidManifest.xml
@@ -9,7 +9,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.chromium.weblayer.shell">
- <application android:label="WebLayer shell">
+ <application android:label="WebLayer shell"
+ android:supportsRtl="true">
<activity android:name="WebLayerShellActivity"
android:launchMode="singleTask"
android:theme="@style/ShellTheme"
diff --git a/chromium/weblayer/shell/android/shell_apk/res/layout/shell_browser_controls.xml b/chromium/weblayer/shell/android/shell_apk/res/layout/shell_browser_controls.xml
index a07648248cc..f0f01f50784 100644
--- a/chromium/weblayer/shell/android/shell_apk/res/layout/shell_browser_controls.xml
+++ b/chromium/weblayer/shell/android/shell_apk/res/layout/shell_browser_controls.xml
@@ -28,6 +28,7 @@
android:imeOptions="actionGo"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:importantForAutofill="no"
android:textSize="15sp"/>
<View
diff --git a/chromium/weblayer/shell/android/shell_apk/res/menu/app_menu.xml b/chromium/weblayer/shell/android/shell_apk/res/menu/app_menu.xml
index 02821be9b0f..2d6ff129de0 100644
--- a/chromium/weblayer/shell/android/shell_apk/res/menu/app_menu.xml
+++ b/chromium/weblayer/shell/android/shell_apk/res/menu/app_menu.xml
@@ -17,4 +17,6 @@
android:title="Bottom view" />
<item android:id="@+id/site_settings_menu_id"
android:title="Site Settings" />
+ <item android:id="@+id/translate_menu_id"
+ android:title="Translate" />
</menu>
diff --git a/chromium/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/WebLayerShellActivity.java b/chromium/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/WebLayerShellActivity.java
index bb67a110ab9..fa140357af6 100644
--- a/chromium/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/WebLayerShellActivity.java
+++ b/chromium/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/WebLayerShellActivity.java
@@ -4,6 +4,7 @@
package org.chromium.weblayer.shell;
+import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@@ -19,6 +20,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
+import android.webkit.URLUtil;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
@@ -32,6 +34,7 @@ import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
+import org.chromium.base.CommandLine;
import org.chromium.base.IntentUtils;
import org.chromium.weblayer.Browser;
import org.chromium.weblayer.ContextMenuParams;
@@ -43,6 +46,7 @@ import org.chromium.weblayer.NavigationController;
import org.chromium.weblayer.NewTabCallback;
import org.chromium.weblayer.NewTabType;
import org.chromium.weblayer.Profile;
+import org.chromium.weblayer.SettingType;
import org.chromium.weblayer.SiteSettingsActivity;
import org.chromium.weblayer.Tab;
import org.chromium.weblayer.TabCallback;
@@ -58,7 +62,7 @@ import java.util.List;
* Activity for managing the Demo Shell.
*/
public class WebLayerShellActivity extends FragmentActivity {
- private static final String PROFILE_NAME = "DefaultProfile";
+ private static final String NON_INCOGNITO_PROFILE_NAME = "DefaultProfile";
private static class ContextMenuCreator
implements View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener {
@@ -133,6 +137,7 @@ public class WebLayerShellActivity extends FragmentActivity {
private List<Tab> mPreviousTabList = new ArrayList<>();
private Runnable mExitFullscreenRunnable;
private View mBottomView;
+ private boolean mInIncognitoMode;
@Override
protected void onCreate(final Bundle savedInstanceState) {
@@ -173,6 +178,9 @@ public class WebLayerShellActivity extends FragmentActivity {
popup.getMenuInflater().inflate(R.menu.app_menu, popup.getMenu());
MenuItem bottomMenuItem = popup.getMenu().findItem(R.id.toggle_bottom_view_id);
bottomMenuItem.setChecked(mBottomView != null);
+ popup.getMenu()
+ .findItem(R.id.translate_menu_id)
+ .setVisible(mBrowser.getActiveTab().canTranslate());
popup.setOnMenuItemClickListener(item -> {
if (item.getItemId() == R.id.reload_menu_id) {
mBrowser.getActiveTab().getNavigationController().reload();
@@ -205,12 +213,20 @@ public class WebLayerShellActivity extends FragmentActivity {
}
if (item.getItemId() == R.id.site_settings_menu_id) {
- Intent intent =
- SiteSettingsActivity.createIntentForCategoryList(this, PROFILE_NAME);
+ // TODO(crbug.com/1083233): Figure out the right long-term behavior here.
+ if (mInIncognitoMode) return true;
+
+ Intent intent = SiteSettingsActivity.createIntentForCategoryList(
+ this, NON_INCOGNITO_PROFILE_NAME);
IntentUtils.safeStartActivity(this, intent);
return true;
}
+ if (item.getItemId() == R.id.translate_menu_id) {
+ mBrowser.getActiveTab().showTranslateUi();
+ return true;
+ }
+
return false;
});
popup.show();
@@ -254,6 +270,7 @@ public class WebLayerShellActivity extends FragmentActivity {
fragment.setRetainInstance(true);
mBrowser = Browser.fromFragment(fragment);
mProfile = mBrowser.getProfile();
+ mProfile.setBooleanSetting(SettingType.UKM_ENABLED, true);
setTabCallbacks(mBrowser.getActiveTab(), fragment);
mBrowser.setTopView(mTopContentsContainer);
@@ -287,7 +304,7 @@ public class WebLayerShellActivity extends FragmentActivity {
return;
}
String startupUrl = getUrlFromIntent(getIntent());
- if (TextUtils.isEmpty(startupUrl)) {
+ if (TextUtils.isEmpty(startupUrl) || !URLUtil.isValidUrl(startupUrl)) {
startupUrl = "https://google.com";
}
loadUrl(startupUrl);
@@ -380,10 +397,10 @@ public class WebLayerShellActivity extends FragmentActivity {
public void bringTabToFront() {
tab.getBrowser().setActiveTab(tab);
- Context context = WebLayerShellActivity.this;
- Intent intent = new Intent(context, WebLayerShellActivity.class);
+ Activity activity = WebLayerShellActivity.this;
+ Intent intent = new Intent(activity, WebLayerShellActivity.class);
intent.setAction(Intent.ACTION_MAIN);
- context.getApplicationContext().startActivity(intent);
+ activity.startActivity(intent);
}
});
tab.getNavigationController().registerNavigationCallback(new NavigationCallback() {
@@ -427,7 +444,14 @@ public class WebLayerShellActivity extends FragmentActivity {
}
}
- Fragment fragment = WebLayer.createBrowserFragment(PROFILE_NAME);
+ if (CommandLine.isInitialized()
+ && CommandLine.getInstance().hasSwitch("start-in-incognito")) {
+ mInIncognitoMode = true;
+ }
+
+ String profileName = mInIncognitoMode ? null : NON_INCOGNITO_PROFILE_NAME;
+
+ Fragment fragment = WebLayer.createBrowserFragment(profileName);
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(mMainViewId, fragment);
diff --git a/chromium/weblayer/shell/app/shell_main_params.cc b/chromium/weblayer/shell/app/shell_main_params.cc
index 36e58d734ae..9ece1e23cda 100644
--- a/chromium/weblayer/shell/app/shell_main_params.cc
+++ b/chromium/weblayer/shell/app/shell_main_params.cc
@@ -49,29 +49,45 @@ GURL GetStartupURL() {
class MainDelegateImpl : public MainDelegate {
public:
void PreMainMessageLoopRun() override {
+ // On Android the Profile is created and owned in Java via an
+ // embedder-specific call to WebLayer.createBrowserFragment().
+#if !defined(OS_ANDROID)
InitializeProfile();
+#endif
Shell::Initialize();
+#if defined(OS_ANDROID)
+ Shell::CreateNewWindow(GetStartupURL(), gfx::Size());
+#else
Shell::CreateNewWindow(profile_.get(), GetStartupURL(), gfx::Size());
+#endif
}
- void PostMainMessageLoopRun() override { DestroyProfile(); }
+ void PostMainMessageLoopRun() override {
+#if !defined(OS_ANDROID)
+ DestroyProfile();
+#endif
+ }
void SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure) override {
Shell::SetMainMessageLoopQuitClosure(std::move(quit_closure));
}
private:
+#if !defined(OS_ANDROID)
void InitializeProfile() {
- profile_ = Profile::Create("web_shell");
+ auto* command_line = base::CommandLine::ForCurrentProcess();
+ std::string profile_name =
+ command_line->HasSwitch(switches::kStartInIncognito) ? "" : "web_shell";
- // TODO: create an incognito profile as well.
+ profile_ = Profile::Create(profile_name);
}
void DestroyProfile() { profile_.reset(); }
std::unique_ptr<Profile> profile_;
+#endif
};
} // namespace
diff --git a/chromium/weblayer/shell/browser/shell.cc b/chromium/weblayer/shell/browser/shell.cc
index 5f3c69dad3f..58adffab13d 100644
--- a/chromium/weblayer/shell/browser/shell.cc
+++ b/chromium/weblayer/shell/browser/shell.cc
@@ -16,6 +16,8 @@
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "url/gurl.h"
+#include "weblayer/browser/browser_impl.h"
+#include "weblayer/browser/browser_list.h"
#include "weblayer/browser/profile_impl.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/public/navigation_controller.h"
@@ -30,26 +32,26 @@ const int kDefaultTestWindowHeightDip = 700;
std::vector<Shell*> Shell::windows_;
-Shell::Shell(std::unique_ptr<Tab> tab)
- : tab_(std::move(tab)), window_(nullptr) {
+Shell::Shell(std::unique_ptr<Browser> browser)
+ : browser_(std::move(browser)), window_(nullptr) {
windows_.push_back(this);
- if (tab_) {
- tab_->AddObserver(this);
- tab_->GetNavigationController()->AddObserver(this);
+ if (tab()) {
+ tab()->AddObserver(this);
+ tab()->GetNavigationController()->AddObserver(this);
#if !defined(OS_ANDROID) // Android does this in Java.
// TODO: how will tests work with this on android? can we get to the
// concrete type?
- static_cast<TabImpl*>(tab_.get())->profile()->SetDownloadDelegate(this);
+ static_cast<TabImpl*>(tab())->profile()->SetDownloadDelegate(this);
#endif
}
}
Shell::~Shell() {
- if (tab_) {
- tab_->GetNavigationController()->RemoveObserver(this);
- tab_->RemoveObserver(this);
+ if (tab()) {
+ tab()->GetNavigationController()->RemoveObserver(this);
+ tab()->RemoveObserver(this);
}
PlatformCleanUp();
@@ -63,17 +65,19 @@ Shell::~Shell() {
// Always destroy WebContents before calling PlatformExit(). WebContents
// destruction sequence may depend on the resources destroyed in
// PlatformExit() (e.g. the display::Screen singleton).
- tab_.reset();
+ browser_.reset();
if (windows_.empty()) {
+ PlatformExit();
+
if (*g_quit_main_message_loop)
std::move(*g_quit_main_message_loop).Run();
}
}
-Shell* Shell::CreateShell(std::unique_ptr<Tab> tab,
+Shell* Shell::CreateShell(std::unique_ptr<Browser> browser,
const gfx::Size& initial_size) {
- Shell* shell = new Shell(std::move(tab));
+ Shell* shell = new Shell(std::move(browser));
shell->PlatformCreateWindow(initial_size.width(), initial_size.height());
shell->PlatformSetContents();
@@ -90,13 +94,6 @@ void Shell::CloseAllWindows() {
// Pump the message loop to allow window teardown tasks to run.
base::RunLoop().RunUntilIdle();
-
- // If there were no windows open then the message loop quit closure will
- // not have been run.
- if (*g_quit_main_message_loop)
- std::move(*g_quit_main_message_loop).Run();
-
- PlatformExit();
}
void Shell::SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure) {
@@ -104,11 +101,21 @@ void Shell::SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure) {
}
Tab* Shell::tab() {
+ if (!browser())
+ return nullptr;
+ CHECK(!browser()->GetTabs().empty());
+ return browser()->GetTabs()[0];
+}
+
+Browser* Shell::browser() {
#if defined(OS_ANDROID)
// TODO(jam): this won't work if we need more than one Shell in a test.
- return Tab::GetLastTabForTesting();
+ const auto& browsers = BrowserList::GetInstance()->browsers();
+ if (browsers.empty())
+ return nullptr;
+ return *(browsers.begin());
#else
- return tab_.get();
+ return browser_.get();
#endif
}
@@ -121,7 +128,8 @@ void Shell::DisplayedUrlChanged(const GURL& url) {
}
void Shell::LoadStateChanged(bool is_loading, bool to_different_document) {
- NavigationController* navigation_controller = tab_->GetNavigationController();
+ NavigationController* navigation_controller =
+ tab()->GetNavigationController();
PlatformEnableUIControl(STOP_BUTTON, is_loading && to_different_document);
@@ -158,16 +166,26 @@ gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
return GetShellDefaultSize();
}
+#if defined(OS_ANDROID)
+Shell* Shell::CreateNewWindow(const GURL& url, const gfx::Size& initial_size) {
+ // On Android, the browser is owned by the Java side.
+ return CreateNewWindowWithBrowser(nullptr, url, initial_size);
+}
+#else
Shell* Shell::CreateNewWindow(Profile* web_profile,
const GURL& url,
const gfx::Size& initial_size) {
-#if defined(OS_ANDROID)
- std::unique_ptr<Tab> tab;
-#else
- auto tab = Tab::Create(web_profile);
+ auto browser = Browser::Create(web_profile, nullptr);
+ browser->CreateTab();
+ return CreateNewWindowWithBrowser(std::move(browser), url, initial_size);
+}
#endif
- Shell* shell = CreateShell(std::move(tab), AdjustWindowSize(initial_size));
+Shell* Shell::CreateNewWindowWithBrowser(std::unique_ptr<Browser> browser,
+ const GURL& url,
+ const gfx::Size& initial_size) {
+ Shell* shell =
+ CreateShell(std::move(browser), AdjustWindowSize(initial_size));
if (!url.is_empty())
shell->LoadURL(url);
return shell;
diff --git a/chromium/weblayer/shell/browser/shell.h b/chromium/weblayer/shell/browser/shell.h
index 78f48accb9f..5664d767ba3 100644
--- a/chromium/weblayer/shell/browser/shell.h
+++ b/chromium/weblayer/shell/browser/shell.h
@@ -35,6 +35,7 @@ class WMState;
class GURL;
namespace weblayer {
+class Browser;
class Profile;
class Tab;
@@ -56,9 +57,13 @@ class Shell : public TabObserver,
// Do one time initialization at application startup.
static void Initialize();
+#if defined(OS_ANDROID)
+ static Shell* CreateNewWindow(const GURL& url, const gfx::Size& initial_size);
+#else
static Shell* CreateNewWindow(Profile* web_profile,
const GURL& url,
const gfx::Size& initial_size);
+#endif
// Returns the currently open windows.
static std::vector<Shell*>& windows() { return windows_; }
@@ -72,6 +77,7 @@ class Shell : public TabObserver,
static void SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure);
Tab* tab();
+ Browser* browser();
gfx::NativeWindow window() { return window_; }
@@ -80,7 +86,11 @@ class Shell : public TabObserver,
private:
enum UIControl { BACK_BUTTON, FORWARD_BUTTON, STOP_BUTTON };
- explicit Shell(std::unique_ptr<Tab> tab);
+ static Shell* CreateNewWindowWithBrowser(std::unique_ptr<Browser> browser,
+ const GURL& url,
+ const gfx::Size& initial_size);
+
+ explicit Shell(std::unique_ptr<Browser> browser);
// TabObserver implementation:
void DisplayedUrlChanged(const GURL& url) override;
@@ -102,7 +112,7 @@ class Shell : public TabObserver,
AllowDownloadCallback callback) override;
// Helper to create a new Shell.
- static Shell* CreateShell(std::unique_ptr<Tab> tab,
+ static Shell* CreateShell(std::unique_ptr<Browser> browser,
const gfx::Size& initial_size);
// Helper for one time initialization of application
@@ -141,7 +151,7 @@ class Shell : public TabObserver,
// Set the title of shell window
void PlatformSetTitle(const base::string16& title);
- std::unique_ptr<Tab> tab_;
+ std::unique_ptr<Browser> browser_;
gfx::NativeWindow window_;
diff --git a/chromium/weblayer/shell/browser/shell_views.cc b/chromium/weblayer/shell/browser/shell_views.cc
index cc442c555b1..ed799835e8f 100644
--- a/chromium/weblayer/shell/browser/shell_views.cc
+++ b/chromium/weblayer/shell/browser/shell_views.cc
@@ -6,6 +6,8 @@
#include <stddef.h>
+#include <memory>
+
#include "base/command_line.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -52,7 +54,10 @@ class ShellWindowDelegateView : public views::WidgetDelegateView,
public:
enum UIControl { BACK_BUTTON, FORWARD_BUTTON, STOP_BUTTON };
- ShellWindowDelegateView(Shell* shell) : shell_(shell) {}
+ explicit ShellWindowDelegateView(Shell* shell) : shell_(shell) {
+ SetHasWindowSizeControls(true);
+ InitShellWindow();
+ }
~ShellWindowDelegateView() override {}
@@ -192,11 +197,11 @@ class ShellWindowDelegateView : public views::WidgetDelegateView,
}
layout->AddPaddingRow(0, 5);
-
- InitAccelerators();
}
void InitAccelerators() {
+ // This function must be called when part of the widget hierarchy.
+ DCHECK(GetWidget());
static const ui::KeyboardCode keys[] = {ui::VKEY_F5, ui::VKEY_BROWSER_BACK,
ui::VKEY_BROWSER_FORWARD};
for (size_t i = 0; i < base::size(keys); ++i) {
@@ -239,16 +244,7 @@ class ShellWindowDelegateView : public views::WidgetDelegateView,
}
// Overridden from WidgetDelegateView
- bool CanResize() const override { return true; }
- bool CanMaximize() const override { return true; }
- bool CanMinimize() const override { return true; }
base::string16 GetWindowTitle() const override { return title_; }
- void WindowClosing() override {
- if (shell_) {
- delete shell_;
- shell_ = nullptr;
- }
- }
// Overridden from View
gfx::Size GetMinimumSize() const override {
@@ -256,12 +252,7 @@ class ShellWindowDelegateView : public views::WidgetDelegateView,
// (preferred) size.
return gfx::Size();
}
- void ViewHierarchyChanged(
- const views::ViewHierarchyChangedDetails& details) override {
- if (details.is_add && details.child == this) {
- InitShellWindow();
- }
- }
+ void AddedToWidget() override { InitAccelerators(); }
// Overridden from AcceleratorTarget:
bool AcceleratorPressed(const ui::Accelerator& accelerator) override {
@@ -281,8 +272,7 @@ class ShellWindowDelegateView : public views::WidgetDelegateView,
}
private:
- // Hold a reference of Shell for deleting it when the window is closing
- Shell* shell_;
+ std::unique_ptr<Shell> shell_;
// Window title
base::string16 title_;
@@ -382,7 +372,7 @@ void Shell::PlatformSetContents() {
views::WidgetDelegate* widget_delegate = window_widget_->widget_delegate();
ShellWindowDelegateView* delegate_view =
static_cast<ShellWindowDelegateView*>(widget_delegate);
- delegate_view->AttachTab(tab_.get(), content_size_);
+ delegate_view->AttachTab(tab(), content_size_);
window_->GetHost()->Show();
window_widget_->Show();
}
diff --git a/chromium/weblayer/shell/common/shell_switches.cc b/chromium/weblayer/shell/common/shell_switches.cc
index e70106da503..fa058d07acf 100644
--- a/chromium/weblayer/shell/common/shell_switches.cc
+++ b/chromium/weblayer/shell/common/shell_switches.cc
@@ -10,5 +10,8 @@ namespace switches {
// Stops new Shell objects from navigating to a default url.
const char kNoInitialNavigation[] = "no-initial-navigation";
+// Starts the shell with the profile in incognito mode.
+const char kStartInIncognito[] = "start-in-incognito";
+
} // namespace switches
} // namespace weblayer
diff --git a/chromium/weblayer/shell/common/shell_switches.h b/chromium/weblayer/shell/common/shell_switches.h
index 3219f68433b..dfbb5b0e7df 100644
--- a/chromium/weblayer/shell/common/shell_switches.h
+++ b/chromium/weblayer/shell/common/shell_switches.h
@@ -10,6 +10,8 @@ namespace switches {
extern const char kNoInitialNavigation[];
+extern const char kStartInIncognito[];
+
} // namespace switches
} // namespace weblayer