Commit a6e6a5e3 authored by Sebastien Marchand's avatar Sebastien Marchand Committed by Commit Bot

Set the TabLifecycleUnit state from its PageNode at creation

TabLifecycleUnit are only created once their WebContents gets added to the tab strip, which can lead to some inconsistencies for the PageNode properties mirrored in the TLCU class if they change before it happens.

Change-Id: I701b60195ec145d1dfd0febd5384bab2519cdef3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1898106
Commit-Queue: Sébastien Marchand <sebmarchand@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#713470}
parent 8c9688dc
......@@ -378,6 +378,15 @@ void TabLifecycleUnitSource::TabLifecycleUnit::SetRecentlyAudible(
recently_audible_time_ = NowTicks();
}
void TabLifecycleUnitSource::TabLifecycleUnit::SetInitialStateFromPageNodeData(
performance_manager::mojom::InterventionPolicy origin_trial_policy,
bool is_holding_weblock,
bool is_holding_indexeddb_lock) {
origin_trial_freeze_policy_ = origin_trial_policy;
is_holding_weblock_ = is_holding_weblock;
is_holding_indexeddb_lock_ = is_holding_indexeddb_lock;
}
void TabLifecycleUnitSource::TabLifecycleUnit::UpdateLifecycleState(
performance_manager::mojom::LifecycleState state) {
switch (state) {
......
......@@ -86,8 +86,15 @@ class TabLifecycleUnitSource::TabLifecycleUnit
// "recently audible" state of the tab changes.
void SetRecentlyAudible(bool recently_audible);
// Updates the tab's lifecycle state when changed outside the tab lifecycle
// unit.
// Set the initial state of this lifecycle unit with some data coming from the
// performance_manager Graph.
void SetInitialStateFromPageNodeData(
performance_manager::mojom::InterventionPolicy origin_trial_policy,
bool is_holding_weblock,
bool is_holding_indexeddb_lock);
// Updates the tab's lifecycle state when changed outside the tab
// lifecycle unit.
void UpdateLifecycleState(performance_manager::mojom::LifecycleState state);
// Updates the tab's origin trial freeze policy.
......@@ -123,6 +130,8 @@ class TabLifecycleUnitSource::TabLifecycleUnit
bool IsAutoDiscardable() const;
void SetAutoDiscardable(bool auto_discardable);
bool IsHoldingWebLockForTesting() { return is_holding_weblock_; }
protected:
friend class TabManagerTest;
......
......@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/resource_coordinator/discard_metrics_lifecycle_unit_observer.h"
#include "chrome/browser/resource_coordinator/lifecycle_unit_source_observer.h"
......@@ -23,7 +24,6 @@
#include "chrome/common/pref_names.h"
#include "components/performance_manager/performance_manager_impl.h"
#include "components/performance_manager/public/graph/page_node.h"
#include "components/performance_manager/public/web_contents_proxy.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_task_traits.h"
......@@ -318,6 +318,31 @@ void TabLifecycleUnitSource::OnTabInserted(TabStripModel* tab_strip_model,
lifecycle_unit->AddObserver(new DiscardMetricsLifecycleUnitObserver());
lifecycle_unit->AddObserver(new TracingLifecycleUnitObserver());
auto page_node =
performance_manager::PerformanceManager::GetPageNodeForWebContents(
contents);
auto task_runner =
base::CreateSingleThreadTaskRunner({base::CurrentThread()});
performance_manager::PerformanceManager::CallOnGraph(
FROM_HERE,
base::BindOnce(
[](base::WeakPtr<performance_manager::PageNode> page_node,
scoped_refptr<base::SingleThreadTaskRunner> runner,
performance_manager::Graph* graph) {
if (!page_node)
return;
runner->PostTask(
FROM_HERE,
base::BindOnce(
&TabLifecycleUnitSource::SetInitialStateFromPageNodeData,
page_node->GetContentsProxy(),
page_node->GetOriginTrialFreezePolicy(),
page_node->IsHoldingWebLock(),
page_node->IsHoldingIndexedDBLock()));
},
std::move(page_node), task_runner));
NotifyLifecycleUnitCreated(lifecycle_unit);
}
}
......@@ -414,6 +439,20 @@ void TabLifecycleUnitSource::OnLifecycleStateChanged(
lifecycle_unit->UpdateLifecycleState(state);
}
// static
void TabLifecycleUnitSource::SetInitialStateFromPageNodeData(
const performance_manager::WebContentsProxy& contents_proxy,
performance_manager::mojom::InterventionPolicy origin_trial_policy,
bool is_holding_weblock,
bool is_holding_indexeddb_lock) {
if (!contents_proxy.Get())
return;
TabLifecycleUnit* lifecycle_unit = GetTabLifecycleUnit(contents_proxy.Get());
DCHECK(lifecycle_unit);
lifecycle_unit->SetInitialStateFromPageNodeData(
origin_trial_policy, is_holding_weblock, is_holding_indexeddb_lock);
}
// static
void TabLifecycleUnitSource::OnOriginTrialFreezePolicyChanged(
content::WebContents* web_contents,
......
......@@ -16,6 +16,7 @@
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "components/performance_manager/public/mojom/coordination_unit.mojom.h"
#include "components/performance_manager/public/mojom/lifecycle.mojom.h"
#include "components/performance_manager/public/web_contents_proxy.h"
class PrefChangeRegistrar;
class PrefService;
......@@ -148,6 +149,14 @@ class TabLifecycleUnitSource : public BrowserListObserver,
void OnBrowserSetLastActive(Browser* browser) override;
void OnBrowserNoLongerActive(Browser* browser) override;
// Called when a TabLifecycleUnit is created to set some properties from
// the corresponding PageNode.
static void SetInitialStateFromPageNodeData(
const performance_manager::WebContentsProxy& contents_proxy,
performance_manager::mojom::InterventionPolicy origin_trial_policy,
bool is_holding_weblock,
bool is_holding_indexeddb_lock);
// This is called indirectly from the corresponding event on a PageNode in the
// performance_manager Graph.
static void OnLifecycleStateChanged(
......
......@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
......@@ -30,6 +31,9 @@
#include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "components/performance_manager/performance_manager_tab_helper.h"
#include "components/performance_manager/public/performance_manager.h"
#include "components/performance_manager/test_support/graph_impl.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/browser/navigation_controller.h"
......@@ -433,7 +437,6 @@ class TabLifecycleUnitSourceTest
std::unique_ptr<TabStripModel> tab_strip_model_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
private:
std::unique_ptr<content::WebContents> CreateAndNavigateWebContents() {
std::unique_ptr<content::WebContents> web_contents =
CreateTestWebContents();
......@@ -446,6 +449,7 @@ class TabLifecycleUnitSourceTest
return web_contents;
}
private:
TestTabStripModelDelegate tab_strip_model_delegate_;
DISALLOW_COPY_AND_ASSIGN(TabLifecycleUnitSourceTest);
......@@ -818,6 +822,49 @@ TEST_F(TabLifecycleUnitSourceTest, TabProactiveDiscardedByFrozenTimeout) {
::testing::Mock::VerifyAndClear(&tab_observer_);
}
TEST_F(TabLifecycleUnitSourceTest, AsyncInitialization) {
std::unique_ptr<content::WebContents> web_contents =
CreateAndNavigateWebContents();
content::WebContents* raw_web_contents = web_contents.get();
performance_manager::PerformanceManagerTabHelper::CreateForWebContents(
raw_web_contents);
auto page_node =
performance_manager::PerformanceManager::GetPageNodeForWebContents(
raw_web_contents);
// Set the |IsHoldingWebLock| property for the PageNode associated with
// |web_contents|.
base::RunLoop run_loop;
performance_manager::PerformanceManager::CallOnGraph(
FROM_HERE,
base::BindLambdaForTesting([&](performance_manager::Graph* unused) {
EXPECT_TRUE(page_node);
EXPECT_FALSE(page_node->IsHoldingWebLock());
auto* node_impl =
performance_manager::PageNodeImpl::FromNode(page_node.get());
node_impl->SetIsHoldingWebLockForTesting(true);
run_loop.Quit();
}));
run_loop.Run();
// Append the WebContents to the tab strip, this will cause the
// TabLifeCycleUnit to be created.
LifecycleUnit* unit = nullptr;
EXPECT_CALL(source_observer_, OnLifecycleUnitCreated(::testing::_))
.WillOnce(::testing::Invoke(
[&](LifecycleUnit* lifecycle_unit) { unit = lifecycle_unit; }));
tab_strip_model_->AppendWebContents(std::move(web_contents), true);
::testing::Mock::VerifyAndClear(&source_observer_);
EXPECT_TRUE(unit);
// Wait for the |IsHoldingWebLock| to be set in the TabLifeCycleUnit.
while (!static_cast<TabLifecycleUnitSource::TabLifecycleUnit*>(unit)
->IsHoldingWebLockForTesting()) {
task_environment()->RunUntilIdle();
}
}
namespace {
class MockOnPrefChanged {
......
......@@ -107,6 +107,10 @@ class PageNodeImpl
SetPageAlmostIdle(page_almost_idle);
}
void SetIsHoldingWebLockForTesting(bool is_holding_weblock) {
SetIsHoldingWebLock(is_holding_weblock);
}
base::WeakPtr<PageNodeImpl> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
......
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