Commit 0e46ffc8 authored by Takashi Toyoshima's avatar Takashi Toyoshima Committed by Commit Bot

BundledExchanges: Update SafeBundledExchangesParser interface

This class should hold the BundledExchangesParserFactory instance
so to keep the utility process alive. This fix leads a design change
to pass a service connector at constructor rather than other open
methods.

Also, this adds an error check to SafeBundledExchangesParser::OpenFile.
We could return a file open error and so on when
BundledExchangesReader::ReadMetadata is called.

Bug: 966753
Change-Id: I3174a88d0236f4afe0ebbad8348626800096b68d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1732518Reviewed-by: default avatarTsuyoshi Horo <horo@chromium.org>
Reviewed-by: default avatarKunihiko Sakamoto <ksakamoto@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Commit-Queue: Takashi Toyoshima <toyoshim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683923}
parent 232793b8
...@@ -137,7 +137,10 @@ class BundledExchangesReader::SharedFileDataSource final ...@@ -137,7 +137,10 @@ class BundledExchangesReader::SharedFileDataSource final
BundledExchangesReader::BundledExchangesReader( BundledExchangesReader::BundledExchangesReader(
const BundledExchangesSource& source) const BundledExchangesSource& source)
: file_(base::MakeRefCounted<SharedFile>(source.file_path)) {} : parser_(ServiceManagerConnection::GetForProcess()
? ServiceManagerConnection::GetForProcess()->GetConnector()
: nullptr),
file_(base::MakeRefCounted<SharedFile>(source.file_path)) {}
BundledExchangesReader::~BundledExchangesReader() { BundledExchangesReader::~BundledExchangesReader() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
...@@ -202,8 +205,7 @@ const GURL& BundledExchangesReader::GetStartURL() const { ...@@ -202,8 +205,7 @@ const GURL& BundledExchangesReader::GetStartURL() const {
} }
void BundledExchangesReader::SetBundledExchangesParserFactoryForTesting( void BundledExchangesReader::SetBundledExchangesParserFactoryForTesting(
std::unique_ptr<data_decoder::mojom::BundledExchangesParserFactory> mojo::Remote<data_decoder::mojom::BundledExchangesParserFactory> factory) {
factory) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
parser_.SetBundledExchangesParserFactoryForTesting(std::move(factory)); parser_.SetBundledExchangesParserFactoryForTesting(std::move(factory));
...@@ -211,15 +213,17 @@ void BundledExchangesReader::SetBundledExchangesParserFactoryForTesting( ...@@ -211,15 +213,17 @@ void BundledExchangesReader::SetBundledExchangesParserFactoryForTesting(
void BundledExchangesReader::ReadMetadataInternal(MetadataCallback callback, void BundledExchangesReader::ReadMetadataInternal(MetadataCallback callback,
base::File file) { base::File file) {
parser_.OpenFile( base::File::Error error = parser_.OpenFile(std::move(file));
ServiceManagerConnection::GetForProcess() if (base::File::FILE_OK != error) {
? ServiceManagerConnection::GetForProcess()->GetConnector() PostTask(FROM_HERE,
: nullptr, base::BindOnce(std::move(callback),
std::move(file)); data_decoder::mojom::BundleMetadataParseError::New(
base::File::ErrorToString(error))));
parser_.ParseMetadata( } else {
base::BindOnce(&BundledExchangesReader::OnMetadataParsed, parser_.ParseMetadata(
base::Unretained(this), std::move(callback))); base::BindOnce(&BundledExchangesReader::OnMetadataParsed,
base::Unretained(this), std::move(callback)));
}
} }
void BundledExchangesReader::OnMetadataParsed( void BundledExchangesReader::OnMetadataParsed(
......
...@@ -68,8 +68,7 @@ class CONTENT_EXPORT BundledExchangesReader final { ...@@ -68,8 +68,7 @@ class CONTENT_EXPORT BundledExchangesReader final {
const GURL& GetStartURL() const; const GURL& GetStartURL() const;
void SetBundledExchangesParserFactoryForTesting( void SetBundledExchangesParserFactoryForTesting(
std::unique_ptr<data_decoder::mojom::BundledExchangesParserFactory> mojo::Remote<data_decoder::mojom::BundledExchangesParserFactory> factory);
factory);
private: private:
// A simple wrapper class to share a single base::File instance among multiple // A simple wrapper class to share a single base::File instance among multiple
......
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
#include "base/test/scoped_task_environment.h" #include "base/test/scoped_task_environment.h"
#include "content/browser/web_package/bundled_exchanges_source.h" #include "content/browser/web_package/bundled_exchanges_source.h"
#include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/data_decoder/public/mojom/bundled_exchanges_parser.mojom.h" #include "services/data_decoder/public/mojom/bundled_exchanges_parser.mojom.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -133,7 +137,10 @@ class BundledExchangesReaderTest : public testing::Test { ...@@ -133,7 +137,10 @@ class BundledExchangesReaderTest : public testing::Test {
std::unique_ptr<MockParserFactory> factory = std::unique_ptr<MockParserFactory> factory =
std::make_unique<MockParserFactory>(); std::make_unique<MockParserFactory>();
factory_ = factory.get(); factory_ = factory.get();
reader_->SetBundledExchangesParserFactoryForTesting(std::move(factory)); mojo::Remote<data_decoder::mojom::BundledExchangesParserFactory> remote;
mojo::MakeSelfOwnedReceiver(std::move(factory),
remote.BindNewPipeAndPassReceiver());
reader_->SetBundledExchangesParserFactoryForTesting(std::move(remote));
} }
protected: protected:
......
...@@ -15,45 +15,42 @@ constexpr char kConnectionError[] = ...@@ -15,45 +15,42 @@ constexpr char kConnectionError[] =
"Cannot connect to the remote parser service"; "Cannot connect to the remote parser service";
} // namespace } // namespace
SafeBundledExchangesParser::SafeBundledExchangesParser() = default; SafeBundledExchangesParser::SafeBundledExchangesParser(
service_manager::Connector* connector) {
if (connector) {
connector->Connect(mojom::kServiceName,
factory_.BindNewPipeAndPassReceiver());
}
}
SafeBundledExchangesParser::~SafeBundledExchangesParser() = default; SafeBundledExchangesParser::~SafeBundledExchangesParser() = default;
void SafeBundledExchangesParser::OpenFile(service_manager::Connector* connector, base::File::Error SafeBundledExchangesParser::OpenFile(base::File file) {
base::File file) {
DCHECK(disconnected_); DCHECK(disconnected_);
if (factory_for_testing_) { DCHECK(factory_.is_connected());
factory_for_testing_->GetParserForFile(parser_.BindNewPipeAndPassReceiver(),
std::move(file));
} else {
mojo::Remote<mojom::BundledExchangesParserFactory> factory;
connector->Connect(mojom::kServiceName,
factory.BindNewPipeAndPassReceiver());
factory->GetParserForFile(parser_.BindNewPipeAndPassReceiver(), if (!file.IsValid())
std::move(file)); return file.error_details();
}
factory_->GetParserForFile(parser_.BindNewPipeAndPassReceiver(),
std::move(file));
parser_.set_disconnect_handler(base::BindOnce( parser_.set_disconnect_handler(base::BindOnce(
&SafeBundledExchangesParser::OnDisconnect, base::Unretained(this))); &SafeBundledExchangesParser::OnDisconnect, base::Unretained(this)));
disconnected_ = false; disconnected_ = false;
return base::File::FILE_OK;
} }
void SafeBundledExchangesParser::OpenDataSource( void SafeBundledExchangesParser::OpenDataSource(
service_manager::Connector* connector,
mojo::PendingRemote<mojom::BundleDataSource> data_source) { mojo::PendingRemote<mojom::BundleDataSource> data_source) {
DCHECK(disconnected_); DCHECK(disconnected_);
if (factory_for_testing_) { DCHECK(factory_.is_connected());
factory_for_testing_->GetParserForDataSource( factory_->GetParserForDataSource(parser_.BindNewPipeAndPassReceiver(),
parser_.BindNewPipeAndPassReceiver(), std::move(data_source)); std::move(data_source));
} else {
mojo::Remote<mojom::BundledExchangesParserFactory> factory;
connector->Connect(mojom::kServiceName,
factory.BindNewPipeAndPassReceiver());
factory->GetParserForDataSource(parser_.BindNewPipeAndPassReceiver(),
std::move(data_source));
}
parser_.set_disconnect_handler(base::BindOnce( parser_.set_disconnect_handler(base::BindOnce(
&SafeBundledExchangesParser::OnDisconnect, base::Unretained(this))); &SafeBundledExchangesParser::OnDisconnect, base::Unretained(this)));
disconnected_ = false; disconnected_ = false;
} }
...@@ -122,8 +119,8 @@ void SafeBundledExchangesParser::OnResponseParsed( ...@@ -122,8 +119,8 @@ void SafeBundledExchangesParser::OnResponseParsed(
} }
void SafeBundledExchangesParser::SetBundledExchangesParserFactoryForTesting( void SafeBundledExchangesParser::SetBundledExchangesParserFactoryForTesting(
std::unique_ptr<mojom::BundledExchangesParserFactory> factory) { mojo::Remote<mojom::BundledExchangesParserFactory> factory) {
factory_for_testing_ = std::move(factory); factory_ = std::move(factory);
} }
} // namespace data_decoder } // namespace data_decoder
...@@ -25,20 +25,18 @@ namespace data_decoder { ...@@ -25,20 +25,18 @@ namespace data_decoder {
// mojom::BundledExchangesParser service. // mojom::BundledExchangesParser service.
class SafeBundledExchangesParser { class SafeBundledExchangesParser {
public: public:
SafeBundledExchangesParser(); // |connector| can be null if SetBundledExchangesParserForTesting() will be
// called before calling Open*().
explicit SafeBundledExchangesParser(service_manager::Connector* connector);
// Remaining callbacks on flight will be dropped. // Remaining callbacks on flight will be dropped.
~SafeBundledExchangesParser(); ~SafeBundledExchangesParser();
// Binds |this| instance to the given |file| for subsequent parse calls. // Binds |this| instance to the given |file| for subsequent parse calls.
// |connector| can be null if SetBundledExchangesParserForTesting() was base::File::Error OpenFile(base::File file);
// called.
void OpenFile(service_manager::Connector* connector, base::File file);
// Binds |this| instance to the given |data_source| for subsequent parse // Binds |this| instance to the given |data_source| for subsequent parse
// calls. |connector| can be null if SetBundledExchangesParserForTesting() // calls.
// was called. void OpenDataSource(mojo::PendingRemote<mojom::BundleDataSource> data_source);
void OpenDataSource(service_manager::Connector* connector,
mojo::PendingRemote<mojom::BundleDataSource> data_source);
// Parses metadata. See mojom::BundledExchangesParser::ParseMetadata for // Parses metadata. See mojom::BundledExchangesParser::ParseMetadata for
// details. This method fails when it's called before the previous call // details. This method fails when it's called before the previous call
...@@ -56,7 +54,7 @@ class SafeBundledExchangesParser { ...@@ -56,7 +54,7 @@ class SafeBundledExchangesParser {
// Sets alternative BundledExchangesParserFactory that will be used to create // Sets alternative BundledExchangesParserFactory that will be used to create
// BundledExchangesParser for testing purpose. // BundledExchangesParser for testing purpose.
void SetBundledExchangesParserFactoryForTesting( void SetBundledExchangesParserFactoryForTesting(
std::unique_ptr<mojom::BundledExchangesParserFactory> factory); mojo::Remote<mojom::BundledExchangesParserFactory> factory);
private: private:
void OnDisconnect(); void OnDisconnect();
...@@ -66,14 +64,13 @@ class SafeBundledExchangesParser { ...@@ -66,14 +64,13 @@ class SafeBundledExchangesParser {
mojom::BundleResponsePtr response, mojom::BundleResponsePtr response,
mojom::BundleResponseParseErrorPtr error); mojom::BundleResponseParseErrorPtr error);
mojo::Remote<mojom::BundledExchangesParserFactory> factory_;
mojo::Remote<mojom::BundledExchangesParser> parser_; mojo::Remote<mojom::BundledExchangesParser> parser_;
mojom::BundledExchangesParser::ParseMetadataCallback metadata_callback_; mojom::BundledExchangesParser::ParseMetadataCallback metadata_callback_;
base::flat_map<size_t, mojom::BundledExchangesParser::ParseResponseCallback> base::flat_map<size_t, mojom::BundledExchangesParser::ParseResponseCallback>
response_callbacks_; response_callbacks_;
size_t response_callback_next_id_ = 0; size_t response_callback_next_id_ = 0;
bool disconnected_ = true; bool disconnected_ = true;
std::unique_ptr<mojom::BundledExchangesParserFactory> factory_for_testing_ =
nullptr;
DISALLOW_COPY_AND_ASSIGN(SafeBundledExchangesParser); DISALLOW_COPY_AND_ASSIGN(SafeBundledExchangesParser);
}; };
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/path_service.h" #include "base/path_service.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/scoped_task_environment.h" #include "base/test/scoped_task_environment.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/data_decoder/public/cpp/test_data_decoder_service.h" #include "services/data_decoder/public/cpp/test_data_decoder_service.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -65,7 +66,10 @@ class MockFactory final : public mojom::BundledExchangesParserFactory { ...@@ -65,7 +66,10 @@ class MockFactory final : public mojom::BundledExchangesParserFactory {
}; };
MockFactory() {} MockFactory() {}
MockParser* GetCreatedParser() { return parser_.get(); } MockParser* GetCreatedParser() {
base::RunLoop().RunUntilIdle();
return parser_.get();
}
void DeleteParser() { parser_.reset(); } void DeleteParser() { parser_.reset(); }
private: private:
...@@ -107,17 +111,26 @@ class SafeBundledExchangesParserTest : public testing::Test { ...@@ -107,17 +111,26 @@ class SafeBundledExchangesParserTest : public testing::Test {
public: public:
service_manager::Connector* GetConnector() { return service_.connector(); } service_manager::Connector* GetConnector() { return service_.connector(); }
MockFactory* InitializeMockFactory(SafeBundledExchangesParser* parser) {
std::unique_ptr<MockFactory> factory = std::make_unique<MockFactory>();
MockFactory* raw_factory = factory.get();
mojo::Remote<mojom::BundledExchangesParserFactory> remote;
mojo::MakeSelfOwnedReceiver(std::move(factory),
remote.BindNewPipeAndPassReceiver());
parser->SetBundledExchangesParserFactoryForTesting(std::move(remote));
return raw_factory;
}
private: private:
base::test::ScopedTaskEnvironment task_environment_; base::test::ScopedTaskEnvironment task_environment_;
TestDataDecoderService service_; TestDataDecoderService service_;
}; };
TEST_F(SafeBundledExchangesParserTest, ParseGoldenFile) { TEST_F(SafeBundledExchangesParserTest, ParseGoldenFile) {
SafeBundledExchangesParser parser; SafeBundledExchangesParser parser(GetConnector());
base::File test_file = base::File test_file =
OpenTestFile(base::FilePath(FILE_PATH_LITERAL("hello.wbn"))); OpenTestFile(base::FilePath(FILE_PATH_LITERAL("hello.wbn")));
ASSERT_EQ(base::File::FILE_OK, parser.OpenFile(std::move(test_file)));
parser.OpenFile(GetConnector(), std::move(test_file));
mojom::BundleMetadataPtr metadata_result; mojom::BundleMetadataPtr metadata_result;
{ {
...@@ -172,8 +185,13 @@ TEST_F(SafeBundledExchangesParserTest, ParseGoldenFile) { ...@@ -172,8 +185,13 @@ TEST_F(SafeBundledExchangesParserTest, ParseGoldenFile) {
EXPECT_EQ(index[3]->request_url, "https://test.example.org/script.js"); EXPECT_EQ(index[3]->request_url, "https://test.example.org/script.js");
} }
TEST_F(SafeBundledExchangesParserTest, OpenInvalidFile) {
SafeBundledExchangesParser parser(GetConnector());
EXPECT_EQ(base::File::FILE_ERROR_FAILED, parser.OpenFile(base::File()));
}
TEST_F(SafeBundledExchangesParserTest, CallWithoutOpen) { TEST_F(SafeBundledExchangesParserTest, CallWithoutOpen) {
SafeBundledExchangesParser parser; SafeBundledExchangesParser parser(GetConnector());
bool metadata_parsed = false; bool metadata_parsed = false;
parser.ParseMetadata(base::BindOnce( parser.ParseMetadata(base::BindOnce(
[](bool* metadata_parsed, mojom::BundleMetadataPtr metadata, [](bool* metadata_parsed, mojom::BundleMetadataPtr metadata,
...@@ -204,13 +222,13 @@ TEST_F(SafeBundledExchangesParserTest, CallWithoutOpen) { ...@@ -204,13 +222,13 @@ TEST_F(SafeBundledExchangesParserTest, CallWithoutOpen) {
} }
TEST_F(SafeBundledExchangesParserTest, UseMockFactory) { TEST_F(SafeBundledExchangesParserTest, UseMockFactory) {
SafeBundledExchangesParser parser; SafeBundledExchangesParser parser(GetConnector());
std::unique_ptr<MockFactory> factory = std::make_unique<MockFactory>(); MockFactory* raw_factory = InitializeMockFactory(&parser);
MockFactory* raw_factory = factory.get();
parser.SetBundledExchangesParserFactoryForTesting(std::move(factory));
EXPECT_FALSE(raw_factory->GetCreatedParser()); EXPECT_FALSE(raw_factory->GetCreatedParser());
parser.OpenFile(GetConnector(), base::File()); base::File test_file =
OpenTestFile(base::FilePath(FILE_PATH_LITERAL("hello.wbn")));
ASSERT_EQ(base::File::FILE_OK, parser.OpenFile(std::move(test_file)));
ASSERT_TRUE(raw_factory->GetCreatedParser()); ASSERT_TRUE(raw_factory->GetCreatedParser());
EXPECT_FALSE(raw_factory->GetCreatedParser()->IsParseMetadataCalled()); EXPECT_FALSE(raw_factory->GetCreatedParser()->IsParseMetadataCalled());
EXPECT_FALSE(raw_factory->GetCreatedParser()->IsParseResponseCalled()); EXPECT_FALSE(raw_factory->GetCreatedParser()->IsParseResponseCalled());
...@@ -227,15 +245,13 @@ TEST_F(SafeBundledExchangesParserTest, UseMockFactory) { ...@@ -227,15 +245,13 @@ TEST_F(SafeBundledExchangesParserTest, UseMockFactory) {
} }
TEST_F(SafeBundledExchangesParserTest, ConnectionError) { TEST_F(SafeBundledExchangesParserTest, ConnectionError) {
SafeBundledExchangesParser parser; SafeBundledExchangesParser parser(GetConnector());
std::unique_ptr<MockFactory> factory = std::make_unique<MockFactory>(); MockFactory* raw_factory = InitializeMockFactory(&parser);
MockFactory* raw_factory = factory.get();
parser.SetBundledExchangesParserFactoryForTesting(std::move(factory));
mojo::PendingRemote<mojom::BundleDataSource> remote_data_source; mojo::PendingRemote<mojom::BundleDataSource> remote_data_source;
auto data_source = std::make_unique<MockDataSource>( auto data_source = std::make_unique<MockDataSource>(
remote_data_source.InitWithNewPipeAndPassReceiver()); remote_data_source.InitWithNewPipeAndPassReceiver());
parser.OpenDataSource(GetConnector(), std::move(remote_data_source)); parser.OpenDataSource(std::move(remote_data_source));
ASSERT_TRUE(raw_factory->GetCreatedParser()); ASSERT_TRUE(raw_factory->GetCreatedParser());
base::RunLoop run_loop; base::RunLoop run_loop;
......
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