Skip to content

Commit

Permalink
base for the PageLiveStateDecorator class
Browse files Browse the repository at this point in the history
Change-Id: I7a645b839bb2a09f24929001b8f8017069b6216f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1903955
Commit-Queue: Sébastien Marchand <sebmarchand@chromium.org>
Reviewed-by: François Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#716417}
  • Loading branch information
sebmarchand authored and Commit Bot committed Nov 19, 2019
1 parent 8360e2e commit d8ff76c
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 0 deletions.
3 changes: 3 additions & 0 deletions components/performance_manager/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

static_library("performance_manager") {
sources = [
"decorators/page_live_state_decorator.cc",
"frame_priority/boosting_vote_aggregator.cc",
"frame_priority/frame_priority.cc",
"frame_priority/max_vote_aggregator.cc",
Expand Down Expand Up @@ -48,6 +49,7 @@ static_library("performance_manager") {
"performance_manager_tab_helper.h",
"process_node_source.cc",
"process_node_source.h",
"public/decorators/page_live_state_decorator.h",
"public/frame_priority/boosting_vote_aggregator.h",
"public/frame_priority/frame_priority.h",
"public/frame_priority/max_vote_aggregator.h",
Expand Down Expand Up @@ -89,6 +91,7 @@ source_set("unit_tests") {
testonly = true

sources = [
"decorators/page_live_state_decorator_unittest.cc",
"frame_priority/boosting_vote_aggregator_unittest.cc",
"frame_priority/frame_priority_unittest.cc",
"frame_priority/max_vote_aggregator_unittest.cc",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// 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 "components/performance_manager/public/decorators/page_live_state_decorator.h"

#include "components/performance_manager/graph/node_attached_data_impl.h"
#include "components/performance_manager/graph/page_node_impl.h"
#include "components/performance_manager/public/performance_manager.h"
#include "content/public/browser/browser_thread.h"

namespace performance_manager {

namespace {

// Private implementation of the node attached data. This keeps the complexity
// out of the header file.
class PageLiveStateDataImpl
: public PageLiveStateDecorator::Data,
public NodeAttachedDataImpl<PageLiveStateDataImpl> {
public:
struct Traits : public NodeAttachedDataInMap<PageNodeImpl> {};
~PageLiveStateDataImpl() override = default;
PageLiveStateDataImpl(const PageLiveStateDataImpl& other) = delete;
PageLiveStateDataImpl& operator=(const PageLiveStateDataImpl&) = delete;

// PageLiveStateDecorator::Data:
bool IsAttachedToUSB() const override { return is_attached_to_usb_; }

void set_is_attached_to_usb(bool is_attached_to_usb) {
is_attached_to_usb_ = is_attached_to_usb;
}

private:
// Make the impl our friend so it can access the constructor and any
// storage providers.
friend class ::performance_manager::NodeAttachedDataImpl<
PageLiveStateDataImpl>;

explicit PageLiveStateDataImpl(const PageNodeImpl* page_node) {}

bool is_attached_to_usb_ = false;
};

// Helper function to set a property in PageLiveStateDataImpl. This does the
// WebContents -> PageNode translation.
// This can only be called from the UI thread.
template <typename T>
void SetPropertyForWebContents(
content::WebContents* contents,
void (PageLiveStateDataImpl::*setter_function)(T),
T value) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
PerformanceManager::CallOnGraph(
FROM_HERE, base::BindOnce(
[](base::WeakPtr<PageNode> node,
void (PageLiveStateDataImpl::*setter_function)(T),
T value, Graph* graph) {
if (node) {
auto* data = PageLiveStateDataImpl::GetOrCreate(
PageNodeImpl::FromNode(node.get()));
DCHECK(data);
(data->*setter_function)(value);
}
},
PerformanceManager::GetPageNodeForWebContents(contents),
setter_function, value));
}

} // namespace

// static
void PageLiveStateDecorator::OnWebContentsAttachedToUSBChange(
content::WebContents* contents,
bool is_attached_to_usb) {
SetPropertyForWebContents(contents,
&PageLiveStateDataImpl::set_is_attached_to_usb,
is_attached_to_usb);
}

PageLiveStateDecorator::Data::Data() = default;
PageLiveStateDecorator::Data::~Data() = default;

PageLiveStateDecorator::Data*
PageLiveStateDecorator::Data::GetOrCreateForTesting(PageNode* page_node) {
return PageLiveStateDataImpl::GetOrCreate(PageNodeImpl::FromNode(page_node));
}

} // namespace performance_manager
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// 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 "components/performance_manager/public/decorators/page_live_state_decorator.h"

#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "components/performance_manager/performance_manager_test_harness.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace performance_manager {

namespace {

// Helper function that allows testing that a PageLiveStateDecorator::Data
// property has the expected value. This function should be called from the main
// thread and be passed the WebContents pointer associated with the PageNode to
// check.
template <typename T>
void TestPropertyOnPMSequence(content::WebContents* contents,
T (PageLiveStateDecorator::Data::*getter)() const,
T expected_value) {
base::RunLoop run_loop;
auto quit_closure = run_loop.QuitClosure();

base::WeakPtr<PageNode> node =
PerformanceManager::GetPageNodeForWebContents(contents);

PerformanceManager::CallOnGraph(
FROM_HERE, base::BindLambdaForTesting([&](Graph* unused) {
EXPECT_TRUE(node);
auto* data =
PageLiveStateDecorator::Data::GetOrCreateForTesting(node.get());
EXPECT_TRUE(data);
EXPECT_EQ((data->*getter)(), expected_value);
std::move(quit_closure).Run();
}));
run_loop.Run();
}

} // namespace

class PageLiveStateDecoratorTest : public PerformanceManagerTestHarness {
protected:
PageLiveStateDecoratorTest() = default;
~PageLiveStateDecoratorTest() override = default;
PageLiveStateDecoratorTest(const PageLiveStateDecoratorTest& other) = delete;
PageLiveStateDecoratorTest& operator=(const PageLiveStateDecoratorTest&) =
delete;
};

TEST_F(PageLiveStateDecoratorTest, OnWebContentsAttachedToUSBChange) {
auto contents = CreateTestWebContents();
auto* contents_raw = contents.get();
SetContents(std::move(contents));

// By default the page shouldn't be connected to a USB device.
TestPropertyOnPMSequence(
contents_raw, &PageLiveStateDecorator::Data::IsAttachedToUSB, false);

// Pretend that it attached to a USB device and make sure that the PageNode
// data get updated.
PageLiveStateDecorator::OnWebContentsAttachedToUSBChange(contents_raw, true);
TestPropertyOnPMSequence(
contents_raw, &PageLiveStateDecorator::Data::IsAttachedToUSB, true);

// Switch back to the default state.
PageLiveStateDecorator::OnWebContentsAttachedToUSBChange(contents_raw, false);
TestPropertyOnPMSequence(
contents_raw, &PageLiveStateDecorator::Data::IsAttachedToUSB, false);

DeleteContents();
}

} // namespace performance_manager
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_PAGE_LIVE_STATE_DECORATOR_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_PAGE_LIVE_STATE_DECORATOR_H_

namespace content {
class WebContents;
} // namespace content

namespace performance_manager {

class PageNode;

// Used to record some live state information about the PageNode.
// All the functions that take a WebContents* as a parameter should only be
// called from the UI thread, the event will be forwarded to the corresponding
// PageNode on the Performance Manager's sequence.
class PageLiveStateDecorator {
public:
class Data;

// This object should only be used via its static methods.
PageLiveStateDecorator() = delete;
~PageLiveStateDecorator() = delete;
PageLiveStateDecorator(const PageLiveStateDecorator& other) = delete;
PageLiveStateDecorator& operator=(const PageLiveStateDecorator&) = delete;

// The following functions should only be called from the UI thread:

// Should be called whenever a WebContents gets connected or disconnected to
// a USB device.
// TODO(sebmarchand|olivierli): Call this from USBTabHelper.
static void OnWebContentsAttachedToUSBChange(content::WebContents* contents,
bool is_attached_to_usb);
};

class PageLiveStateDecorator::Data {
public:
Data();
virtual ~Data();
Data(const Data& other) = delete;
Data& operator=(const Data&) = delete;

virtual bool IsAttachedToUSB() const = 0;

static Data* GetOrCreateForTesting(PageNode* page_node);
};

} // namespace performance_manager

#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_PAGE_LIVE_STATE_DECORATOR_H_

0 comments on commit d8ff76c

Please sign in to comment.