[M87 merge] weblayer: adds API to know if Browser is restoring and when done
This way embedders have API to know when they can take action
based on whether restore has completed.
BUG=1135278
TEST=covered by tests
(cherry picked from commit 3692e6bb068eed1929257e170110f39fd03a774c)
Change-Id: I72d804a86d8c4eeafdc3b72bbcf16875a78eb477
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2451550
Commit-Queue: Scott Violet <[email protected]>
Reviewed-by: Clark DuVall <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#814450}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2454639
Reviewed-by: Scott Violet <[email protected]>
Cr-Commit-Position: refs/branch-heads/4280@{#78}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn
index 370eaff..09224152d 100644
--- a/weblayer/BUILD.gn
+++ b/weblayer/BUILD.gn
@@ -310,6 +310,7 @@
"public/browser.cc",
"public/browser.h",
"public/browser_observer.h",
+ "public/browser_restore_observer.h",
"public/common/switches.cc",
"public/common/switches.h",
"public/cookie_manager.h",
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java
index 2cfb648..85bd6968 100644
--- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java
+++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java
@@ -18,11 +18,14 @@
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
+import org.chromium.weblayer.Browser;
+import org.chromium.weblayer.BrowserRestoreCallback;
import org.chromium.weblayer.Navigation;
import org.chromium.weblayer.NavigationCallback;
import org.chromium.weblayer.NavigationController;
import org.chromium.weblayer.Profile;
import org.chromium.weblayer.Tab;
+import org.chromium.weblayer.WebLayer;
import org.chromium.weblayer.shell.InstrumentationActivity;
import java.util.HashMap;
@@ -44,6 +47,16 @@
() -> mActivityTestRule.getActivity().getTab());
}
+ private boolean isRestoringPreviousState() {
+ return TestThreadUtils.runOnUiThreadBlockingNoException(
+ () -> mActivityTestRule.getActivity().getBrowser().isRestoringPreviousState());
+ }
+
+ private int getSupportedMajorVersion() {
+ return TestThreadUtils.runOnUiThreadBlockingNoException(
+ () -> WebLayer.getSupportedMajorVersion(mActivityTestRule.getActivity()));
+ }
+
@Test
@SmallTest
public void successfullyLoadsUrlAfterRecreation() {
@@ -126,12 +139,18 @@
extras.putString(InstrumentationActivity.EXTRA_PERSISTENCE_ID, "x");
final String url = mActivityTestRule.getTestDataURL("simple_page.html");
mActivityTestRule.launchShellWithUrl(url, extras);
+ if (getSupportedMajorVersion() >= 88) {
+ Assert.assertFalse(isRestoringPreviousState());
+ }
mActivityTestRule.recreateActivity();
Tab tab = getTab();
Assert.assertNotNull(tab);
waitForTabToFinishRestore(tab, url);
+ if (getSupportedMajorVersion() >= 88) {
+ Assert.assertFalse(isRestoringPreviousState());
+ }
}
@Test
@@ -200,7 +219,7 @@
Map<String, String> initialData = new HashMap<>();
initialData.put("foo", "bar");
- restoresTabData(extras, initialData);
+ restoreTabData(extras, initialData);
}
@Test
@@ -209,10 +228,10 @@
public void restoreTabDataAfterRecreate() throws Throwable {
Map<String, String> initialData = new HashMap<>();
initialData.put("foo", "bar");
- restoresTabData(new Bundle(), initialData);
+ restoreTabData(new Bundle(), initialData);
}
- private void restoresTabData(Bundle extras, Map<String, String> initialData) {
+ private void restoreTabData(Bundle extras, Map<String, String> initialData) {
String url = mActivityTestRule.getTestDataURL("simple_page.html");
mActivityTestRule.launchShellWithUrl(url, extras);
@@ -282,4 +301,46 @@
});
helper.waitForCallback(callCount, 1);
}
+
+ @Test
+ @SmallTest
+ @MinWebLayerVersion(88)
+ public void restoreUsingOnRestoreCompleted() throws Throwable {
+ final String persistenceId = "x";
+ Bundle extras = new Bundle();
+ extras.putString(InstrumentationActivity.EXTRA_PERSISTENCE_ID, persistenceId);
+ CallbackHelper callbackHelper = new CallbackHelper();
+ InstrumentationActivity.registerOnCreatedCallback(
+ new InstrumentationActivity.OnCreatedCallback() {
+ private int mBrowserCreateCount;
+ @Override
+ public void onCreated(Browser browser) {
+ if (mBrowserCreateCount == 0) {
+ // Initial creation.
+ mBrowserCreateCount = 1;
+ // isRestoringPreviousState() is true for the initial creation as
+ // persistence code has to check disk, which is async.
+ Assert.assertTrue(browser.isRestoringPreviousState());
+ } else if (mBrowserCreateCount == 1) {
+ // The activity was recreated.
+ mBrowserCreateCount = 2;
+ Assert.assertTrue(browser.isRestoringPreviousState());
+ browser.registerBrowserRestoreCallback(new BrowserRestoreCallback() {
+ @Override
+ public void onRestoreCompleted() {
+ Assert.assertFalse(browser.isRestoringPreviousState());
+ callbackHelper.notifyCalled();
+ }
+ });
+ } else {
+ Assert.fail("Unexpected phase");
+ }
+ }
+ });
+ final String url = mActivityTestRule.getTestDataURL("simple_page.html");
+ mActivityTestRule.launchShellWithUrl(url, extras);
+
+ mActivityTestRule.recreateActivity();
+ callbackHelper.waitForFirst();
+ }
}
diff --git a/weblayer/browser/browser_impl.cc b/weblayer/browser/browser_impl.cc
index 4bf9dca0..11cdb81c 100644
--- a/weblayer/browser/browser_impl.cc
+++ b/weblayer/browser/browser_impl.cc
@@ -24,6 +24,7 @@
#include "weblayer/browser/tab_impl.h"
#include "weblayer/common/weblayer_paths.h"
#include "weblayer/public/browser_observer.h"
+#include "weblayer/public/browser_restore_observer.h"
#if defined(OS_ANDROID)
#include "base/android/callback_android.h"
@@ -329,6 +330,14 @@
return CreateTab(nullptr);
}
+void BrowserImpl::OnRestoreCompleted() {
+ for (BrowserRestoreObserver& obs : browser_restore_observers_)
+ obs.OnRestoreCompleted();
+#if defined(OS_ANDROID)
+ Java_BrowserImpl_onRestoreCompleted(AttachCurrentThread(), java_impl_);
+#endif
+}
+
void BrowserImpl::PrepareForShutdown() {
browser_persister_.reset();
}
@@ -342,6 +351,10 @@
return GetMinimalPersistenceState(0);
}
+bool BrowserImpl::IsRestoringPreviousState() {
+ return browser_persister_ && browser_persister_->is_restore_in_progress();
+}
+
void BrowserImpl::AddObserver(BrowserObserver* observer) {
browser_observers_.AddObserver(observer);
}
@@ -350,6 +363,15 @@
browser_observers_.RemoveObserver(observer);
}
+void BrowserImpl::AddBrowserRestoreObserver(BrowserRestoreObserver* observer) {
+ browser_restore_observers_.AddObserver(observer);
+}
+
+void BrowserImpl::RemoveBrowserRestoreObserver(
+ BrowserRestoreObserver* observer) {
+ browser_restore_observers_.RemoveObserver(observer);
+}
+
void BrowserImpl::VisibleSecurityStateOfActiveTabChanged() {
if (visible_security_state_changed_callback_for_tests_)
std::move(visible_security_state_changed_callback_for_tests_).Run();
diff --git a/weblayer/browser/browser_impl.h b/weblayer/browser/browser_impl.h
index 00b4b67..b8ed0b6 100644
--- a/weblayer/browser/browser_impl.h
+++ b/weblayer/browser/browser_impl.h
@@ -57,6 +57,9 @@
const std::string& guid);
TabImpl* CreateTab(std::unique_ptr<content::WebContents> web_contents);
+ // Called from BrowserPersister when restore has completed.
+ void OnRestoreCompleted();
+
#if defined(OS_ANDROID)
bool CompositorHasSurface();
@@ -83,6 +86,9 @@
void OnFragmentStart(JNIEnv* env);
void OnFragmentResume(JNIEnv* env);
void OnFragmentPause(JNIEnv* env);
+ bool IsRestoringPreviousState(JNIEnv* env) {
+ return IsRestoringPreviousState();
+ }
bool fragment_resumed() { return fragment_resumed_; }
#endif
@@ -118,8 +124,11 @@
void PrepareForShutdown() override;
std::string GetPersistenceId() override;
std::vector<uint8_t> GetMinimalPersistenceState() override;
+ bool IsRestoringPreviousState() override;
void AddObserver(BrowserObserver* observer) override;
void RemoveObserver(BrowserObserver* observer) override;
+ void AddBrowserRestoreObserver(BrowserRestoreObserver* observer) override;
+ void RemoveBrowserRestoreObserver(BrowserRestoreObserver* observer) override;
void VisibleSecurityStateOfActiveTabChanged() override;
private:
@@ -149,6 +158,7 @@
base::android::ScopedJavaGlobalRef<jobject> java_impl_;
#endif
base::ObserverList<BrowserObserver> browser_observers_;
+ base::ObserverList<BrowserRestoreObserver> browser_restore_observers_;
ProfileImpl* const profile_;
std::vector<std::unique_ptr<Tab>> tabs_;
TabImpl* active_tab_ = nullptr;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
index 4bdd8bac..c357e62 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
@@ -471,6 +471,16 @@
return mUrlBarController;
}
+ @Override
+ public boolean isRestoringPreviousState() {
+ return BrowserImplJni.get().isRestoringPreviousState(mNativeBrowser);
+ }
+
+ @CalledByNative
+ private void onRestoreCompleted() throws RemoteException {
+ if (WebLayerFactoryImpl.getClientMajorVersion() >= 87) mClient.onRestoreCompleted();
+ }
+
public View getFragmentView() {
return getViewController().getView();
}
@@ -617,5 +627,6 @@
void onFragmentStart(long nativeBrowserImpl);
void onFragmentResume(long nativeBrowserImpl);
void onFragmentPause(long nativeBrowserImpl);
+ boolean isRestoringPreviousState(long nativeBrowserImpl);
}
}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl
index 4759677..485e4b45 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl
+++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl
@@ -40,4 +40,7 @@
void setTopViewAndScrollingBehavior(in IObjectWrapper view, in int minHeight,
in boolean onlyExpandControlsAtPageTop,
in boolean animate) = 12;
+
+ // Added in 87.
+ boolean isRestoringPreviousState() = 14;
}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowserClient.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowserClient.aidl
index e3b08c2..6c7eff7 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowserClient.aidl
+++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowserClient.aidl
@@ -14,4 +14,5 @@
// Added in 87.
IRemoteFragment createMediaRouteDialogFragment() = 3;
+ void onRestoreCompleted() = 5;
}
diff --git a/weblayer/browser/persistence/browser_persister.cc b/weblayer/browser/persistence/browser_persister.cc
index 61ea0b1d..8e2c342 100644
--- a/weblayer/browser/persistence/browser_persister.cc
+++ b/weblayer/browser/persistence/browser_persister.cc
@@ -277,6 +277,9 @@
ScheduleRebuildOnNextSave();
RestoreBrowserState(browser_, std::move(commands));
+
+ is_restore_in_progress_ = false;
+ browser_->OnRestoreCompleted();
}
void BrowserPersister::BuildCommandsForTab(TabImpl* tab, int index_in_browser) {
diff --git a/weblayer/browser/persistence/browser_persister.h b/weblayer/browser/persistence/browser_persister.h
index d4578eea..34183dd 100644
--- a/weblayer/browser/persistence/browser_persister.h
+++ b/weblayer/browser/persistence/browser_persister.h
@@ -53,6 +53,8 @@
~BrowserPersister() override;
+ bool is_restore_in_progress() const { return is_restore_in_progress_; }
+
void SaveIfNecessary();
// Returns the key used to encrypt the file. Empty if not encrypted.
@@ -139,6 +141,9 @@
&TabImpl::RemoveDataObserver>
data_observer_{this};
+ // True while asynchronously reading the state to restore.
+ bool is_restore_in_progress_ = true;
+
base::WeakPtrFactory<BrowserPersister> weak_factory_{this};
};
diff --git a/weblayer/browser/persistence/browser_persister_browsertest.cc b/weblayer/browser/persistence/browser_persister_browsertest.cc
index a8eeec2..7a7572ca 100644
--- a/weblayer/browser/persistence/browser_persister_browsertest.cc
+++ b/weblayer/browser/persistence/browser_persister_browsertest.cc
@@ -24,6 +24,7 @@
#include "weblayer/browser/profile_impl.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/common/weblayer_paths.h"
+#include "weblayer/public/browser_restore_observer.h"
#include "weblayer/public/navigation.h"
#include "weblayer/public/navigation_controller.h"
#include "weblayer/public/navigation_observer.h"
@@ -47,34 +48,12 @@
namespace {
using testing::UnorderedElementsAre;
-class BrowserObserverImpl : public BrowserObserver {
- public:
- static void WaitForNewTab(Browser* browser) {
- BrowserObserverImpl observer(browser);
- observer.Wait();
- }
-
- private:
- explicit BrowserObserverImpl(Browser* browser) : browser_(browser) {
- browser_->AddObserver(this);
- }
- ~BrowserObserverImpl() override { browser_->RemoveObserver(this); }
-
- void Wait() { run_loop_.Run(); }
-
- // BrowserObserver:
- void OnTabAdded(Tab* tab) override { run_loop_.Quit(); }
-
- Browser* browser_;
- base::RunLoop run_loop_;
-};
-
-class BrowserNavigationObserverImpl : public BrowserObserver,
+class BrowserNavigationObserverImpl : public BrowserRestoreObserver,
public NavigationObserver {
public:
static void WaitForNewTabToCompleteNavigation(Browser* browser,
const GURL& url,
- int tab_to_wait_for = 1) {
+ size_t tab_to_wait_for = 0) {
BrowserNavigationObserverImpl observer(browser, url, tab_to_wait_for);
observer.Wait();
}
@@ -82,9 +61,9 @@
private:
BrowserNavigationObserverImpl(Browser* browser,
const GURL& url,
- int tab_to_wait_for)
+ size_t tab_to_wait_for)
: browser_(browser), url_(url), tab_to_wait_for_(tab_to_wait_for) {
- browser_->AddObserver(this);
+ browser_->AddBrowserRestoreObserver(this);
}
~BrowserNavigationObserverImpl() override {
tab_->GetNavigationController()->RemoveObserver(this);
@@ -98,20 +77,19 @@
run_loop_.Quit();
}
- // BrowserObserver:
- void OnTabAdded(Tab* tab) override {
- if (--tab_to_wait_for_ != 0)
- return;
-
- browser_->RemoveObserver(this);
- tab_ = tab;
+ // BrowserRestoreObserver:
+ void OnRestoreCompleted() override {
+ browser_->RemoveBrowserRestoreObserver(this);
+ ASSERT_LT(tab_to_wait_for_, browser_->GetTabs().size());
+ ASSERT_EQ(nullptr, tab_);
+ tab_ = browser_->GetTabs()[tab_to_wait_for_];
tab_->GetNavigationController()->AddObserver(this);
}
Browser* browser_;
const GURL& url_;
Tab* tab_ = nullptr;
- int tab_to_wait_for_;
+ const size_t tab_to_wait_for_;
std::unique_ptr<TestNavigationObserver> navigation_observer_;
base::RunLoop run_loop_;
};
@@ -146,6 +124,7 @@
std::unique_ptr<BrowserImpl> browser = CreateBrowser(GetProfile(), "x");
Tab* tab = browser->CreateTab();
+ EXPECT_TRUE(browser->IsRestoringPreviousState());
const GURL url = embedded_test_server()->GetURL("/simple_page.html");
NavigateAndWaitForCompletion(url, tab);
ShutdownBrowserPersisterAndWait(browser.get());
@@ -155,6 +134,7 @@
browser = CreateBrowser(GetProfile(), "x");
// Should be no tabs while waiting for restore.
EXPECT_TRUE(browser->GetTabs().empty());
+ EXPECT_TRUE(browser->IsRestoringPreviousState());
// Wait for the restore and navigation to complete.
BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
browser.get(), url);
@@ -164,6 +144,7 @@
EXPECT_EQ(1, browser->GetTabs()[0]
->GetNavigationController()
->GetNavigationListSize());
+ EXPECT_FALSE(browser->IsRestoringPreviousState());
}
IN_PROC_BROWSER_TEST_F(BrowserPersisterTest, RestoresGuid) {
@@ -276,7 +257,7 @@
// Wait for the restore and navigation to complete. This waits for the
// second tab as that was the active one.
BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
- browser.get(), url2, 2);
+ browser.get(), url2, 1);
ASSERT_EQ(2u, browser->GetTabs().size()) << "iteration " << i;
// The first tab shouldn't have loaded yet, as it's not active.
@@ -331,7 +312,7 @@
// Restore the browsers.
browser1 = CreateBrowser(GetProfile(), "x");
BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
- browser1.get(), url1, 1);
+ browser1.get(), url1);
ASSERT_EQ(1u, browser1->GetTabs().size());
EXPECT_EQ(1, browser1->GetTabs()[0]
->GetNavigationController()
@@ -339,7 +320,7 @@
browser2 = CreateBrowser(GetProfile(), "y");
BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation(
- browser2.get(), url2, 2);
+ browser2.get(), url2, 1);
ASSERT_EQ(2u, browser2->GetTabs().size());
EXPECT_EQ(1, browser2->GetTabs()[1]
->GetNavigationController()
diff --git a/weblayer/public/browser.h b/weblayer/public/browser.h
index 8932998..02b1f97e 100644
--- a/weblayer/public/browser.h
+++ b/weblayer/public/browser.h
@@ -14,6 +14,7 @@
namespace weblayer {
class BrowserObserver;
+class BrowserRestoreObserver;
class Profile;
class Tab;
@@ -68,9 +69,18 @@
// lightweight restore when full persistence is not desirable.
virtual std::vector<uint8_t> GetMinimalPersistenceState() = 0;
+ // Returns true if this Browser is in the process of restoring the previous
+ // state. That is, PersistenceInfo was supplied to the constructor and
+ // the state is asynchronously being loaded.
+ virtual bool IsRestoringPreviousState() = 0;
+
virtual void AddObserver(BrowserObserver* observer) = 0;
virtual void RemoveObserver(BrowserObserver* observer) = 0;
+ virtual void AddBrowserRestoreObserver(BrowserRestoreObserver* observer) = 0;
+ virtual void RemoveBrowserRestoreObserver(
+ BrowserRestoreObserver* observer) = 0;
+
virtual void VisibleSecurityStateOfActiveTabChanged() = 0;
};
diff --git a/weblayer/public/browser_restore_observer.h b/weblayer/public/browser_restore_observer.h
new file mode 100644
index 0000000..8f85de8
--- /dev/null
+++ b/weblayer/public/browser_restore_observer.h
@@ -0,0 +1,25 @@
+// 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_PUBLIC_BROWSER_RESTORE_OBSERVER_H_
+#define WEBLAYER_PUBLIC_BROWSER_RESTORE_OBSERVER_H_
+
+#include "base/observer_list.h"
+
+namespace weblayer {
+
+// Used for observing events related to restoring the previous state of a
+// Browser.
+class BrowserRestoreObserver : public base::CheckedObserver {
+ public:
+ // Called when the Browser has completed restoring the previous state.
+ virtual void OnRestoreCompleted() {}
+
+ protected:
+ ~BrowserRestoreObserver() override = default;
+};
+
+} // namespace weblayer
+
+#endif // WEBLAYER_PUBLIC_BROWSER_RESTORE_OBSERVER_H_
diff --git a/weblayer/public/java/BUILD.gn b/weblayer/public/java/BUILD.gn
index 93818eb1..fbbb25a 100644
--- a/weblayer/public/java/BUILD.gn
+++ b/weblayer/public/java/BUILD.gn
@@ -38,6 +38,7 @@
"org/chromium/weblayer/BroadcastReceiver.java",
"org/chromium/weblayer/Browser.java",
"org/chromium/weblayer/BrowserFragment.java",
+ "org/chromium/weblayer/BrowserRestoreCallback.java",
"org/chromium/weblayer/BrowsingDataType.java",
"org/chromium/weblayer/Callback.java",
"org/chromium/weblayer/CaptureScreenShotCallback.java",
diff --git a/weblayer/public/java/org/chromium/weblayer/Browser.java b/weblayer/public/java/org/chromium/weblayer/Browser.java
index d568ed02..f8a02de 100644
--- a/weblayer/public/java/org/chromium/weblayer/Browser.java
+++ b/weblayer/public/java/org/chromium/weblayer/Browser.java
@@ -35,17 +35,21 @@
private final ObserverList<TabListCallback> mTabListCallbacks;
private final UrlBarController mUrlBarController;
+ private final ObserverList<BrowserRestoreCallback> mBrowserRestoreCallbacks;
+
// Constructor for test mocking.
protected Browser() {
mImpl = null;
mTabListCallbacks = null;
mUrlBarController = null;
+ mBrowserRestoreCallbacks = null;
}
Browser(IBrowser impl, BrowserFragment fragment) {
mImpl = impl;
mFragment = fragment;
mTabListCallbacks = new ObserverList<TabListCallback>();
+ mBrowserRestoreCallbacks = new ObserverList<BrowserRestoreCallback>();
try {
mImpl.setClient(new BrowserClientImpl());
@@ -209,6 +213,58 @@
}
/**
+ * Returns true if this Browser is in the process of restoring the previous state.
+ *
+ * @param True if restoring previous state.
+ *
+ * @since 87
+ */
+ public boolean isRestoringPreviousState() {
+ ThreadCheck.ensureOnUiThread();
+ if (WebLayer.getSupportedMajorVersionInternal() < 87) {
+ throw new UnsupportedOperationException();
+ }
+ throwIfDestroyed();
+ try {
+ return mImpl.isRestoringPreviousState();
+ } catch (RemoteException e) {
+ throw new APICallException(e);
+ }
+ }
+
+ /**
+ * Adds a BrowserRestoreCallback.
+ *
+ * @param callback The BrowserRestoreCallback.
+ *
+ * @since 87
+ */
+ public void registerBrowserRestoreCallback(@NonNull BrowserRestoreCallback callback) {
+ ThreadCheck.ensureOnUiThread();
+ if (WebLayer.getSupportedMajorVersionInternal() < 87) {
+ throw new UnsupportedOperationException();
+ }
+ throwIfDestroyed();
+ mBrowserRestoreCallbacks.addObserver(callback);
+ }
+
+ /**
+ * Removes a BrowserRestoreCallback.
+ *
+ * @param callback The BrowserRestoreCallback.
+ *
+ * @since 87
+ */
+ public void unregisterBrowserRestoreCallback(@NonNull BrowserRestoreCallback callback) {
+ ThreadCheck.ensureOnUiThread();
+ if (WebLayer.getSupportedMajorVersionInternal() < 87) {
+ throw new UnsupportedOperationException();
+ }
+ throwIfDestroyed();
+ mBrowserRestoreCallbacks.removeObserver(callback);
+ }
+
+ /**
* Sets the View shown at the top of the browser. A value of null removes the view. The
* top-view is typically used to show the uri. The top-view scrolls with the page.
*
@@ -396,5 +452,12 @@
StrictModeWorkaround.apply();
return MediaRouteDialogFragment.create(mFragment);
}
+
+ @Override
+ public void onRestoreCompleted() {
+ for (BrowserRestoreCallback callback : mBrowserRestoreCallbacks) {
+ callback.onRestoreCompleted();
+ }
+ }
}
}
diff --git a/weblayer/public/java/org/chromium/weblayer/BrowserRestoreCallback.java b/weblayer/public/java/org/chromium/weblayer/BrowserRestoreCallback.java
new file mode 100644
index 0000000..7ecb0a1
--- /dev/null
+++ b/weblayer/public/java/org/chromium/weblayer/BrowserRestoreCallback.java
@@ -0,0 +1,17 @@
+// 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;
+
+/**
+ * An interface for observing events related to restoring the previous state of a Browser.
+ *
+ * @since 88
+ */
+public abstract class BrowserRestoreCallback {
+ /**
+ * Called when WebLayer has finished restoring the previous state.
+ */
+ public void onRestoreCompleted() {}
+}
diff --git a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java
index decb817..4dd633cc 100644
--- a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java
+++ b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java
@@ -58,6 +58,8 @@
// that show Page Info UI on its TextView.
public static final String EXTRA_URLBAR_TEXT_CLICKABLE = "EXTRA_URLBAR_TEXT_CLICKABLE";
+ private static OnCreatedCallback sOnCreatedCallback;
+
private Profile mProfile;
private Fragment mFragment;
private Browser mBrowser;
@@ -85,6 +87,25 @@
return false;
}
+ /**
+ * Use this callback for tests that need to be notified synchronously when the Browser has been
+ * created.
+ */
+ public static interface OnCreatedCallback {
+ // Notification that a Browser was created.
+ // This is called on the UI thread.
+ public void onCreated(Browser browser);
+ }
+
+ // Registers a callback that is notified on the UI thread when a Browser is created.
+ public static void registerOnCreatedCallback(OnCreatedCallback callback) {
+ sOnCreatedCallback = callback;
+ // Ideally |callback| would be registered in the Intent, but that isn't possible as to do so
+ // |callback| would have to be a Parceable (which doesn't make sense). As at this time each
+ // test runs in its own process a static is used, if multiple tests were to run in the same
+ // binary, then some state would need to be put in the intent.
+ }
+
public Tab getTab() {
return mTab;
}
@@ -292,6 +313,12 @@
setTabCallbacks(mBrowser.getActiveTab());
setTab(mBrowser.getActiveTab());
}
+
+ if (sOnCreatedCallback != null) {
+ sOnCreatedCallback.onCreated(mBrowser);
+ // Don't reset |sOnCreatedCallback| as it's needed for tests that exercise activity
+ // recreation.
+ }
}
private void setTabCallbacks(Tab tab) {