Commit d8e54a6f authored by Sophie Chang's avatar Sophie Chang Committed by Commit Bot

Add implementation for OptimizationGuideService

This validates the hints protobuf file and sends a notification when the hints have been validated and processed.

Bug: 777892
Change-Id: I72ca225a0d327f11849f0cd3f3198fe6c2abb06b
Reviewed-on: https://chromium-review.googlesource.com/753290
Commit-Queue: Sophie Chang <sophiechang@chromium.org>
Reviewed-by: default avatarColin Blundell <blundell@chromium.org>
Reviewed-by: default avatarSorin Jianu <sorin@chromium.org>
Reviewed-by: default avatarJoshua Pawlicki <waffles@chromium.org>
Reviewed-by: default avatarDoug Arnett <dougarnett@chromium.org>
Reviewed-by: default avatarRyan Sturm <ryansturm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#515218}
parent a30ce3f9
...@@ -89,10 +89,10 @@ void OptimizationHintsComponentInstallerPolicy::ComponentReady( ...@@ -89,10 +89,10 @@ void OptimizationHintsComponentInstallerPolicy::ComponentReady(
optimization_guide::OptimizationGuideService* optimization_guide_service = optimization_guide::OptimizationGuideService* optimization_guide_service =
g_browser_process->optimization_guide_service(); g_browser_process->optimization_guide_service();
if (optimization_guide_service) { if (optimization_guide_service) {
optimization_guide::UnindexedHintsInfo unindexed_hints_info( optimization_guide::ComponentInfo component_info(
version, version,
install_dir.Append(optimization_guide::kUnindexedHintsFileName)); install_dir.Append(optimization_guide::kUnindexedHintsFileName));
optimization_guide_service->ReadAndIndexHints(unindexed_hints_info); optimization_guide_service->ProcessHints(component_info);
} }
} }
...@@ -138,11 +138,9 @@ void RegisterOptimizationHintsComponent(ComponentUpdateService* cus, ...@@ -138,11 +138,9 @@ void RegisterOptimizationHintsComponent(ComponentUpdateService* cus,
if (!profile_prefs || !profile_prefs->GetBoolean(prefs::kDataSaverEnabled)) { if (!profile_prefs || !profile_prefs->GetBoolean(prefs::kDataSaverEnabled)) {
return; return;
} }
std::unique_ptr<ComponentInstallerPolicy> policy( auto installer = base::MakeRefCounted<ComponentInstaller>(
new OptimizationHintsComponentInstallerPolicy()); std::make_unique<OptimizationHintsComponentInstallerPolicy>());
// |cus| will take ownership of |installer| during installer->Register(cus). installer->Register(cus, base::OnceClosure());
ComponentInstaller* installer = new ComponentInstaller(std::move(policy));
installer->Register(cus, base::Closure());
} }
} // namespace component_updater } // namespace component_updater
...@@ -32,23 +32,22 @@ class TestOptimizationGuideService ...@@ -32,23 +32,22 @@ class TestOptimizationGuideService
: public optimization_guide::OptimizationGuideService { : public optimization_guide::OptimizationGuideService {
public: public:
TestOptimizationGuideService( TestOptimizationGuideService(
const scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner) const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_task_runner)
: optimization_guide::OptimizationGuideService(io_thread_task_runner) {} : optimization_guide::OptimizationGuideService(io_thread_task_runner) {}
~TestOptimizationGuideService() override {} ~TestOptimizationGuideService() override {}
using UnindexedHintsInfo = optimization_guide::UnindexedHintsInfo; void ProcessHints(
void ReadAndIndexHints( const optimization_guide::ComponentInfo& component_info) override {
const UnindexedHintsInfo& unindexed_hints_info) override { component_info_ =
unindexed_hints_info_ = std::make_unique<optimization_guide::ComponentInfo>(component_info);
base::MakeUnique<UnindexedHintsInfo>(unindexed_hints_info);
} }
UnindexedHintsInfo* unindexed_hints_info() const { optimization_guide::ComponentInfo* component_info() const {
return unindexed_hints_info_.get(); return component_info_.get();
} }
private: private:
std::unique_ptr<UnindexedHintsInfo> unindexed_hints_info_; std::unique_ptr<optimization_guide::ComponentInfo> component_info_;
DISALLOW_COPY_AND_ASSIGN(TestOptimizationGuideService); DISALLOW_COPY_AND_ASSIGN(TestOptimizationGuideService);
}; };
...@@ -204,7 +203,7 @@ TEST_F(OptimizationHintsComponentInstallerTest, NoRulesetFormatIgnored) { ...@@ -204,7 +203,7 @@ TEST_F(OptimizationHintsComponentInstallerTest, NoRulesetFormatIgnored) {
ASSERT_NO_FATAL_FAILURE(CreateTestOptimizationHints("some hints")); ASSERT_NO_FATAL_FAILURE(CreateTestOptimizationHints("some hints"));
ASSERT_NO_FATAL_FAILURE(LoadOptimizationHints(base::Version(""))); ASSERT_NO_FATAL_FAILURE(LoadOptimizationHints(base::Version("")));
EXPECT_EQ(nullptr, service()->unindexed_hints_info()); EXPECT_EQ(nullptr, service()->component_info());
} }
TEST_F(OptimizationHintsComponentInstallerTest, FutureRulesetFormatIgnored) { TEST_F(OptimizationHintsComponentInstallerTest, FutureRulesetFormatIgnored) {
...@@ -217,7 +216,7 @@ TEST_F(OptimizationHintsComponentInstallerTest, FutureRulesetFormatIgnored) { ...@@ -217,7 +216,7 @@ TEST_F(OptimizationHintsComponentInstallerTest, FutureRulesetFormatIgnored) {
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
LoadOptimizationHints(base::Version(future_ruleset_components))); LoadOptimizationHints(base::Version(future_ruleset_components)));
EXPECT_EQ(nullptr, service()->unindexed_hints_info()); EXPECT_EQ(nullptr, service()->component_info());
} }
TEST_F(OptimizationHintsComponentInstallerTest, LoadFileWithData) { TEST_F(OptimizationHintsComponentInstallerTest, LoadFileWithData) {
...@@ -227,13 +226,12 @@ TEST_F(OptimizationHintsComponentInstallerTest, LoadFileWithData) { ...@@ -227,13 +226,12 @@ TEST_F(OptimizationHintsComponentInstallerTest, LoadFileWithData) {
ASSERT_NO_FATAL_FAILURE(CreateTestOptimizationHints(expected_hints)); ASSERT_NO_FATAL_FAILURE(CreateTestOptimizationHints(expected_hints));
ASSERT_NO_FATAL_FAILURE(LoadOptimizationHints(ruleset_format_version())); ASSERT_NO_FATAL_FAILURE(LoadOptimizationHints(ruleset_format_version()));
auto* unindexed_hints_info = service()->unindexed_hints_info(); auto* component_info = service()->component_info();
EXPECT_NE(nullptr, unindexed_hints_info); EXPECT_NE(nullptr, component_info);
EXPECT_EQ(base::Version(kTestHintsVersion), EXPECT_EQ(base::Version(kTestHintsVersion), component_info->hints_version);
unindexed_hints_info->hints_version);
std::string actual_hints; std::string actual_hints;
ASSERT_TRUE( ASSERT_TRUE(
base::ReadFileToString(unindexed_hints_info->hints_path, &actual_hints)); base::ReadFileToString(component_info->hints_path, &actual_hints));
EXPECT_EQ(expected_hints, actual_hints); EXPECT_EQ(expected_hints, actual_hints);
} }
......
...@@ -202,6 +202,7 @@ test("components_unittests") { ...@@ -202,6 +202,7 @@ test("components_unittests") {
"//components/network_error_logging:unit_tests", "//components/network_error_logging:unit_tests",
"//components/network_hints/renderer:unit_tests", "//components/network_hints/renderer:unit_tests",
"//components/offline_pages:unit_tests", "//components/offline_pages:unit_tests",
"//components/optimization_guide:unit_tests",
"//components/password_manager/content/browser:unit_tests", "//components/password_manager/content/browser:unit_tests",
"//components/payments/content:unit_tests", "//components/payments/content:unit_tests",
"//components/payments/content/utility:unit_tests", "//components/payments/content/utility:unit_tests",
......
...@@ -8,9 +8,26 @@ static_library("optimization_guide") { ...@@ -8,9 +8,26 @@ static_library("optimization_guide") {
"optimization_guide_constants.h", "optimization_guide_constants.h",
"optimization_guide_service.cc", "optimization_guide_service.cc",
"optimization_guide_service.h", "optimization_guide_service.h",
"optimization_guide_service_observer.h",
] ]
deps = [ deps = [
"//base", "//base",
"//components/optimization_guide/proto:optimization_guide_proto",
]
}
source_set("unit_tests") {
testonly = true
sources = [
"optimization_guide_service_unittest.cc",
]
deps = [
":optimization_guide",
"//base",
"//base/test:test_support",
"//components/optimization_guide/proto:optimization_guide_proto",
"//testing/gtest",
] ]
} }
The optimization guide component contains code for processing server hints for
what optimizations to perform on a page load to improve data savings and/or
performance.
...@@ -7,44 +7,117 @@ ...@@ -7,44 +7,117 @@
#include <string> #include <string>
#include "base/bind.h" #include "base/bind.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/task_scheduler/post_task.h"
namespace optimization_guide { namespace optimization_guide {
UnindexedHintsInfo::UnindexedHintsInfo(const base::Version& hints_version, namespace {
const base::FilePath& hints_path)
// Version "0" corresponds to no processed version. By service conventions,
// we represent it as a dotted triple.
const char kNullVersion[] = "0.0.0";
} // namespace
ComponentInfo::ComponentInfo(const base::Version& hints_version,
const base::FilePath& hints_path)
: hints_version(hints_version), hints_path(hints_path) {} : hints_version(hints_version), hints_path(hints_path) {}
UnindexedHintsInfo::~UnindexedHintsInfo() {} ComponentInfo::~ComponentInfo() {}
OptimizationGuideService::OptimizationGuideService( OptimizationGuideService::OptimizationGuideService(
const scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner) const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_task_runner)
: background_task_runner_(base::CreateSequencedTaskRunnerWithTraits( : background_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND})), {base::MayBlock(), base::TaskPriority::BACKGROUND})),
io_thread_task_runner_(io_thread_task_runner) { io_thread_task_runner_(io_thread_task_runner),
latest_processed_version_(kNullVersion) {
DETACH_FROM_SEQUENCE(sequence_checker_); DETACH_FROM_SEQUENCE(sequence_checker_);
} }
OptimizationGuideService::~OptimizationGuideService() {} OptimizationGuideService::~OptimizationGuideService() {}
void OptimizationGuideService::ReadAndIndexHints( void OptimizationGuideService::SetLatestProcessedVersionForTesting(
const UnindexedHintsInfo& unindexed_hints_info) { const base::Version& version) {
latest_processed_version_ = version;
}
void OptimizationGuideService::AddObserver(
OptimizationGuideServiceObserver* observer) {
if (io_thread_task_runner_->BelongsToCurrentThread()) {
AddObserverOnIOThread(observer);
} else {
io_thread_task_runner_->PostTask(
FROM_HERE, base::Bind(&OptimizationGuideService::AddObserverOnIOThread,
base::Unretained(this), observer));
}
}
void OptimizationGuideService::AddObserverOnIOThread(
OptimizationGuideServiceObserver* observer) {
DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
observers_.AddObserver(observer);
}
void OptimizationGuideService::RemoveObserver(
OptimizationGuideServiceObserver* observer) {
if (io_thread_task_runner_->BelongsToCurrentThread()) {
RemoveObserverOnIOThread(observer);
} else {
io_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&OptimizationGuideService::RemoveObserverOnIOThread,
base::Unretained(this), observer));
}
}
void OptimizationGuideService::RemoveObserverOnIOThread(
OptimizationGuideServiceObserver* observer) {
DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
observers_.RemoveObserver(observer);
}
void OptimizationGuideService::ProcessHints(
const ComponentInfo& component_info) {
background_task_runner_->PostTask( background_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::Bind(&OptimizationGuideService::ReadAndIndexHintsInBackground, base::BindOnce(&OptimizationGuideService::ProcessHintsInBackground,
base::Unretained(this), unindexed_hints_info)); base::Unretained(this), component_info));
} }
void OptimizationGuideService::ReadAndIndexHintsInBackground( void OptimizationGuideService::ProcessHintsInBackground(
const UnindexedHintsInfo& unindexed_hints_info) { const ComponentInfo& component_info) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!unindexed_hints_info.hints_version.IsValid()) {
if (!component_info.hints_version.IsValid())
return; return;
} if (latest_processed_version_.CompareTo(component_info.hints_version) >= 0)
if (unindexed_hints_info.hints_path.empty()) { return;
if (component_info.hints_path.empty())
return;
std::string binary_pb;
if (!base::ReadFileToString(component_info.hints_path, &binary_pb))
return;
proto::Configuration new_config;
if (!new_config.ParseFromString(binary_pb)) {
DVLOG(1) << "Failed parsing proto";
return; return;
} }
// TODO(crbug.com/77892): Actually process hints here and dispatch indexed latest_processed_version_ = component_info.hints_version;
// hints to IO thread. io_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&OptimizationGuideService::DispatchHintsOnIOThread,
base::Unretained(this), new_config));
}
void OptimizationGuideService::DispatchHintsOnIOThread(
const proto::Configuration& config) {
DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
for (auto& observer : observers_)
observer.OnHintsProcessed(config);
} }
} // namespace optimization_guide } // namespace optimization_guide
...@@ -10,49 +10,64 @@ ...@@ -10,49 +10,64 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "base/version.h" #include "base/version.h"
#include "components/optimization_guide/optimization_guide_service_observer.h"
#include "components/optimization_guide/proto/hints.pb.h"
namespace optimization_guide { namespace optimization_guide {
// Encapsulates information about a version of optimization hints data received // Encapsulates information about a version of optimization hints data received
// from the components server. // from the components server.
struct UnindexedHintsInfo { struct ComponentInfo {
UnindexedHintsInfo(const base::Version& hints_version, ComponentInfo(const base::Version& hints_version,
const base::FilePath& hints_path); const base::FilePath& hints_path);
~UnindexedHintsInfo(); ~ComponentInfo();
// The version of the hints content. // The version of the hints content.
const base::Version hints_version; const base::Version hints_version;
// The path to the file containing the unindexed hints. // The path to the file containing the hints protobuf file.
const base::FilePath hints_path; const base::FilePath hints_path;
}; };
// Reads and indexes the hints downloaded from the Component Updater as part of // Processes the hints downloaded from the Component Updater as part of the
// the Optimization Hints component. // Optimization Hints component.
class OptimizationGuideService { class OptimizationGuideService {
public: public:
OptimizationGuideService( explicit OptimizationGuideService(
const scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner); const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_task_runner);
virtual ~OptimizationGuideService(); virtual ~OptimizationGuideService();
// Reads and indexes hints from the given unindexed hints, unless its void AddObserver(OptimizationGuideServiceObserver* observer);
// |hints_version| matches that of the most recently parsed version, in which void RemoveObserver(OptimizationGuideServiceObserver* observer);
// case it does nothing.
// Processes hints from the given unindexed hints, unless its |hints_version|
// matches that of the most recently parsed version, in which case it does
// nothing.
// //
// Virtual so it can be mocked out in tests. // Virtual so it can be mocked out in tests.
virtual void ReadAndIndexHints( virtual void ProcessHints(const ComponentInfo& component_info);
const UnindexedHintsInfo& unindexed_hints_info);
// Sets the latest processed version for testing.
void SetLatestProcessedVersionForTesting(const base::Version& version);
private: private:
// Always called as part of a background priority task. // Always called as part of a background priority task.
void ReadAndIndexHintsInBackground( void ProcessHintsInBackground(const ComponentInfo& component_info);
const UnindexedHintsInfo& unindexed_hints_info);
// Adds the observer on IO thread.
void AddObserverOnIOThread(OptimizationGuideServiceObserver* observer);
// Removes the observer on IO thread, if present.
void RemoveObserverOnIOThread(OptimizationGuideServiceObserver* observer);
// Dispatches hints to listeners on IO thread.
void DispatchHintsOnIOThread(const proto::Configuration& config);
// Runner for indexing tasks. // Runner for indexing tasks.
scoped_refptr<base::SequencedTaskRunner> background_task_runner_; scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
...@@ -61,6 +76,11 @@ class OptimizationGuideService { ...@@ -61,6 +76,11 @@ class OptimizationGuideService {
// Runner for IO Thread tasks. // Runner for IO Thread tasks.
scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
// Observers receiving notifications on hints being processed.
base::ObserverList<OptimizationGuideServiceObserver> observers_;
base::Version latest_processed_version_;
DISALLOW_COPY_AND_ASSIGN(OptimizationGuideService); DISALLOW_COPY_AND_ASSIGN(OptimizationGuideService);
}; };
......
// Copyright 2017 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_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_SERVICE_OBSERVER_H_
#define COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_SERVICE_OBSERVER_H_
#include "components/optimization_guide/proto/hints.pb.h"
namespace optimization_guide {
// Interface for objects that wish to be notified of changes in the Optimization
// Guide Service.
//
// All calls will be made on the IO thread.
class OptimizationGuideServiceObserver {
public:
// Called when the hints have been processed.
virtual void OnHintsProcessed(const proto::Configuration& config) = 0;
protected:
virtual ~OptimizationGuideServiceObserver() {}
};
} // namespace optimization_guide
#endif // COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_SERVICE_OBSERVER_H_
// Copyright 2017 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/optimization_guide/optimization_guide_service.h"
#include <memory>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "base/version.h"
#include "components/optimization_guide/optimization_guide_service_observer.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace optimization_guide {
const base::FilePath::CharType kFileName[] = FILE_PATH_LITERAL("somefile.pb");
class TestObserver : public OptimizationGuideServiceObserver {
public:
TestObserver() : received_notification_(false) {}
~TestObserver() override {}
void OnHintsProcessed(const proto::Configuration& config) override {
received_notification_ = true;
received_config_ = config;
}
bool received_notification() const { return received_notification_; }
proto::Configuration received_config() const { return received_config_; }
private:
bool received_notification_;
proto::Configuration received_config_;
DISALLOW_COPY_AND_ASSIGN(TestObserver);
};
class OptimizationGuideServiceTest : public testing::Test {
public:
OptimizationGuideServiceTest() {}
~OptimizationGuideServiceTest() override {}
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
optimization_guide_service_ = std::make_unique<OptimizationGuideService>(
scoped_task_environment_.GetMainThreadTaskRunner());
observer_ = std::make_unique<TestObserver>();
}
OptimizationGuideService* optimization_guide_service() {
return optimization_guide_service_.get();
}
TestObserver* observer() { return observer_.get(); }
void AddObserver() { optimization_guide_service_->AddObserver(observer()); }
void RemoveObserver() {
optimization_guide_service_->RemoveObserver(observer());
}
void UpdateHints(const base::Version& version,
const base::FilePath& filePath) {
ComponentInfo info(version, filePath);
optimization_guide_service_->ProcessHints(info);
}
void WriteConfigToFile(const base::FilePath& filePath,
const proto::Configuration& config) {
std::string serialized_config;
ASSERT_TRUE(config.SerializeToString(&serialized_config));
ASSERT_EQ(static_cast<int32_t>(serialized_config.length()),
base::WriteFile(filePath, serialized_config.data(),
serialized_config.length()));
}
base::FilePath temp_dir() const { return temp_dir_.GetPath(); }
protected:
void RunUntilIdle() {
scoped_task_environment_.RunUntilIdle();
base::RunLoop().RunUntilIdle();
}
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
base::ScopedTempDir temp_dir_;
std::unique_ptr<OptimizationGuideService> optimization_guide_service_;
std::unique_ptr<TestObserver> observer_;
DISALLOW_COPY_AND_ASSIGN(OptimizationGuideServiceTest);
};
TEST_F(OptimizationGuideServiceTest, ProcessHintsInvalidVersionIgnored) {
AddObserver();
UpdateHints(base::Version(""), base::FilePath(kFileName));
RunUntilIdle();
EXPECT_FALSE(observer()->received_notification());
}
TEST_F(OptimizationGuideServiceTest, ProcessHintsPastVersionIgnored) {
AddObserver();
optimization_guide_service()->SetLatestProcessedVersionForTesting(
base::Version("2.0.0"));
const base::FilePath filePath = temp_dir().Append(kFileName);
proto::Configuration config;
proto::Hint* hint = config.add_hints();
hint->set_key("google.com");
ASSERT_NO_FATAL_FAILURE(WriteConfigToFile(filePath, config));
UpdateHints(base::Version("1.0.0"), filePath);
RunUntilIdle();
EXPECT_FALSE(observer()->received_notification());
}
TEST_F(OptimizationGuideServiceTest, ProcessHintsSameVersionIgnored) {
AddObserver();
const base::Version version("1.0.0");
optimization_guide_service()->SetLatestProcessedVersionForTesting(version);
const base::FilePath filePath = temp_dir().Append(kFileName);
proto::Configuration config;
proto::Hint* hint = config.add_hints();
hint->set_key("google.com");
ASSERT_NO_FATAL_FAILURE(WriteConfigToFile(filePath, config));
UpdateHints(version, filePath);
RunUntilIdle();
EXPECT_FALSE(observer()->received_notification());
}
TEST_F(OptimizationGuideServiceTest, ProcessHintsEmptyFileNameIgnored) {
AddObserver();
UpdateHints(base::Version("1.0.0"), base::FilePath(FILE_PATH_LITERAL("")));
RunUntilIdle();
EXPECT_FALSE(observer()->received_notification());
}
TEST_F(OptimizationGuideServiceTest, ProcessHintsInvalidFileIgnored) {
AddObserver();
UpdateHints(base::Version("1.0.0"), base::FilePath(kFileName));
RunUntilIdle();
EXPECT_FALSE(observer()->received_notification());
}
TEST_F(OptimizationGuideServiceTest, ProcessHintsNotAConfigInFileIgnored) {
AddObserver();
const base::FilePath filePath = temp_dir().Append(kFileName);
ASSERT_EQ(static_cast<int32_t>(3), base::WriteFile(filePath, "boo", 3));
UpdateHints(base::Version("1.0.0"), filePath);
RunUntilIdle();
EXPECT_FALSE(observer()->received_notification());
}
TEST_F(OptimizationGuideServiceTest, ProcessHintsIssuesNotification) {
AddObserver();
const base::FilePath filePath = temp_dir().Append(kFileName);
proto::Configuration config;
proto::Hint* hint = config.add_hints();
hint->set_key("google.com");
ASSERT_NO_FATAL_FAILURE(WriteConfigToFile(filePath, config));
UpdateHints(base::Version("1.0.0"), filePath);
RunUntilIdle();
EXPECT_TRUE(observer()->received_notification());
proto::Configuration received_config = observer()->received_config();
ASSERT_EQ(1, received_config.hints_size());
ASSERT_EQ("google.com", received_config.hints()[0].key());
}
TEST_F(OptimizationGuideServiceTest,
UnregisteredObserverDoesNotReceiveNotification) {
// Add and remove observer to ensure that observer properly unregistered.
AddObserver();
RemoveObserver();
const base::FilePath filePath = temp_dir().Append(kFileName);
proto::Configuration config;
proto::Hint* hint = config.add_hints();
hint->set_key("google.com");
ASSERT_NO_FATAL_FAILURE(WriteConfigToFile(filePath, config));
UpdateHints(base::Version("1.0.0"), filePath);
RunUntilIdle();
EXPECT_FALSE(observer()->received_notification());
}
} // namespace optimization_guide
# Copyright 2017 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.
import("//third_party/protobuf/proto_library.gni")
proto_library("optimization_guide_proto") {
sources = [
"hints.proto",
]
}
// Copyright 2017 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.
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package optimization_guide.proto;
enum OptimizationType {
TYPE_UNSPECIFIED = 0;
// This optimization blocks Javascript on the page.
NOSCRIPT = 1;
}
// Presents semantics for how page load URLs should be matched.
enum KeyRepresentation {
REPRESENTATION_UNSPECIFIED = 0;
// The suffix to match in the hostname of a page load URL.
// Example: A host suffix of cnn.com would match pages with host
// sports.cnn.com, but not foocnn.com.
HOST_SUFFIX = 1;
}
message Optimization {
// The type of optimization the hint applies to.
optional OptimizationType optimization_type = 1;
}
message Hint {
// Describes the granularity of the key field.
optional KeyRepresentation key_representation = 1;
// The key that applies to this hint. The key_representation field describes
// the form in which this key takes. Guaranteed to be non-empty.
optional string key = 2;
// An unordered, non-empty set of optimizations that should be whitelisted for
// this hint.
repeated Optimization whitelisted_optimizations = 3;
}
message Configuration {
// An unordered list containing hints for key/optimization combinations.
// It is guaranteed that there will only be a single hint per key and key
// representation combination. These hints are intended to apply to a full
// page.
//
// Note, this list may contain multiple hints that apply to a page. For
// example, if there are hints for (HOST_SUFFIX,cnn.com) and
// (HOST_SUFFIX,sports.cnn.com), these may both apply to sports.cnn.com/foo.
// It is expected for the client to match a page to the hint with the
// finest granularity.
repeated Hint hints = 1;
}
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