Commit 9c6f36a7 authored by Sergey Ulanov's avatar Sergey Ulanov Committed by Commit Bot

[Fuchsia] Update webrunner to pass data directory to Context process.

Now the ContextProvider process passes data directory to the context
process as /web_context_data namespace. If the caller doesn't provide
dataDirectory then the ContextProvider start Context in incognito
mode by adding --incognito flag.

Bug: 852145
Change-Id: Id873d4334d59bac8781cb595ea836a0ace3434d4
Reviewed-on: https://chromium-review.googlesource.com/1149262Reviewed-by: default avatarWez <wez@chromium.org>
Commit-Queue: Wez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#579042}
parent 1dc120ad
......@@ -12,6 +12,7 @@
#include "services/network/public/cpp/network_switches.h"
#include "webrunner/browser/webrunner_net_log.h"
#include "webrunner/browser/webrunner_url_request_context_getter.h"
#include "webrunner/service/common.h"
namespace webrunner {
......@@ -52,10 +53,11 @@ std::unique_ptr<WebRunnerNetLog> CreateNetLog() {
return result;
}
WebRunnerBrowserContext::WebRunnerBrowserContext()
: net_log_(CreateNetLog()), resource_context_(new ResourceContext()) {
// TODO(sergeyu): Pass a valid path.
BrowserContext::Initialize(this, base::FilePath());
WebRunnerBrowserContext::WebRunnerBrowserContext(base::FilePath data_dir_path)
: data_dir_path_(std::move(data_dir_path)),
net_log_(CreateNetLog()),
resource_context_(new ResourceContext()) {
BrowserContext::Initialize(this, GetPath());
}
WebRunnerBrowserContext::~WebRunnerBrowserContext() {
......@@ -72,8 +74,7 @@ WebRunnerBrowserContext::CreateZoomLevelDelegate(
}
base::FilePath WebRunnerBrowserContext::GetPath() const {
NOTIMPLEMENTED();
return base::FilePath();
return data_dir_path_;
}
base::FilePath WebRunnerBrowserContext::GetCachePath() const {
......@@ -82,7 +83,7 @@ base::FilePath WebRunnerBrowserContext::GetCachePath() const {
}
bool WebRunnerBrowserContext::IsOffTheRecord() const {
return false;
return data_dir_path_.empty();
}
content::ResourceContext* WebRunnerBrowserContext::GetResourceContext() {
......
......@@ -5,6 +5,7 @@
#ifndef WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_
#define WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_
#include "base/files/file_path.h"
#include "base/macros.h"
#include "content/public/browser/browser_context.h"
......@@ -15,7 +16,7 @@ class WebRunnerURLRequestContextGetter;
class WebRunnerBrowserContext : public content::BrowserContext {
public:
WebRunnerBrowserContext();
explicit WebRunnerBrowserContext(base::FilePath data_dir_path);
~WebRunnerBrowserContext() override;
// BrowserContext implementation.
......@@ -53,6 +54,8 @@ class WebRunnerBrowserContext : public content::BrowserContext {
// Contains URLRequestContextGetter required for resource loading.
class ResourceContext;
const base::FilePath data_dir_path_;
std::unique_ptr<WebRunnerNetLog> net_log_;
scoped_refptr<WebRunnerURLRequestContextGetter> url_request_getter_;
std::unique_ptr<ResourceContext> resource_context_;
......
......@@ -4,9 +4,12 @@
#include "webrunner/browser/webrunner_browser_main_parts.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "webrunner/browser/context_impl.h"
#include "webrunner/browser/webrunner_browser_context.h"
#include "webrunner/browser/webrunner_screen.h"
#include "webrunner/service/common.h"
namespace webrunner {
......@@ -22,7 +25,8 @@ void WebRunnerBrowserMainParts::PreMainMessageLoopRun() {
display::Screen::SetScreenInstance(screen_.get());
DCHECK(!browser_context_);
browser_context_ = std::make_unique<WebRunnerBrowserContext>();
browser_context_ =
std::make_unique<WebRunnerBrowserContext>(GetWebContextDataDir());
fidl::InterfaceRequest<chromium::web::Context> context_request(
std::move(context_channel_));
......
......@@ -4,8 +4,26 @@
#include "webrunner/service/common.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
namespace webrunner {
constexpr const char kProcessTypeWebContext[] = "web-context";
constexpr char kIncognitoSwitch[] = "incognito";
constexpr char kWebContextDataPath[] = "/web_context_data";
base::FilePath GetWebContextDataDir() {
base::FilePath data_dir{kWebContextDataPath};
bool is_incognito =
base::CommandLine::ForCurrentProcess()->HasSwitch(kIncognitoSwitch);
CHECK_EQ(is_incognito, !base::DirectoryExists(data_dir));
if (is_incognito)
return base::FilePath();
return data_dir;
}
} // namespace webrunner
......@@ -7,13 +7,29 @@
#include <zircon/processargs.h>
namespace base {
class FilePath;
}
namespace webrunner {
// This file contains constants and functions shared between Context and
// ContextProvider processes.
// Handle ID for the Context interface request passed from ContextProvider to
// Context process.
constexpr uint32_t kContextRequestHandleId = PA_HND(PA_USER0, 0);
// Process type value used for the web::Context process. It is equivalent to
// the main browser process in chrome.
extern const char kProcessTypeWebContext[];
// Path to the direct used to store persistent data in context process.
extern const char kWebContextDataPath[];
// Switch passed to content process when running in incognito mode, i.e. when
// there is no kWebContextDataPath.
extern const char kIncognitoSwitch[];
// Returns data directory that should be used by this context process. Should
// not be called in ContextProvider. Empty path is returned if the context
// doesn't have storage dir.
base::FilePath GetWebContextDataDir();
} // namespace webrunner
......
......@@ -24,8 +24,8 @@ namespace webrunner {
namespace {
// Relaunches the current executable as a Context process.
base::Process LaunchContextProcess(const base::LaunchOptions& launch_options) {
base::CommandLine launch_command = *base::CommandLine::ForCurrentProcess();
base::Process LaunchContextProcess(base::CommandLine launch_command,
const base::LaunchOptions& launch_options) {
// TODO(crbug.com/867052): Remove this flag when GPU process works on Fuchsia.
launch_command.AppendSwitch(switches::kDisableGpu);
return base::LaunchProcess(launch_command, launch_options);
......@@ -48,26 +48,33 @@ void ContextProviderImpl::Create(
::fidl::InterfaceRequest<chromium::web::Context> context_request) {
DCHECK(context_request.is_valid());
if (params.dataDirectory) {
// TODO(https://crbug.com/850743): Implement this.
NOTIMPLEMENTED()
<< "Persistent data directory binding is not yet implemented.";
}
base::CommandLine launch_command = *base::CommandLine::ForCurrentProcess();
base::LaunchOptions launch_options;
launch_options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
// Transfer the ContextRequest handle to a well-known location in the child
// process' handle table.
base::LaunchOptions launch_options;
zx::channel context_handle(context_request.TakeChannel());
launch_options.handles_to_transfer.push_back(
{kContextRequestHandleId, context_handle.get()});
// Pass the data directory. If there is no data dir then --incognito flag is
// added instead.
if (params.dataDirectory) {
launch_options.paths_to_transfer.push_back(base::PathToTransfer{
base::FilePath(kWebContextDataPath), params.dataDirectory.release()});
} else {
launch_command.AppendSwitch(kIncognitoSwitch);
}
// Isolate the child Context processes by containing them within their own
// respective jobs.
zx::job job;
zx_status_t status = zx::job::create(*base::GetDefaultJob(), 0, &job);
ZX_CHECK(status == ZX_OK, status) << "zx_job_create";
ignore_result(launch_.Run(launch_options));
ignore_result(launch_.Run(std::move(launch_command), launch_options));
ignore_result(context_handle.release());
ignore_result(job.release());
}
......
......@@ -13,6 +13,7 @@
#include "webrunner/common/webrunner_export.h"
namespace base {
class CommandLine;
struct LaunchOptions;
class Process;
} // namespace base
......@@ -36,8 +37,9 @@ class WEBRUNNER_EXPORT ContextProviderImpl
override;
private:
using LaunchContextProcessCallback =
base::RepeatingCallback<base::Process(const base::LaunchOptions&)>;
using LaunchContextProcessCallback = base::RepeatingCallback<base::Process(
base::CommandLine command,
const base::LaunchOptions& options)>;
friend class ContextProviderImplTest;
......
......@@ -4,6 +4,7 @@
#include "webrunner/service/context_provider_impl.h"
#include <lib/fdio/util.h>
#include <lib/fidl/cpp/binding.h>
#include <zircon/processargs.h>
......@@ -15,6 +16,8 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/fuchsia/file_utils.h"
#include "base/message_loop/message_loop.h"
#include "base/test/multiprocess_test.h"
......@@ -25,6 +28,9 @@
namespace webrunner {
namespace {
constexpr char kTestDataFileIn[] = "DataFileIn";
constexpr char kTestDataFileOut[] = "DataFileOut";
class TestFrameObserver : public chromium::web::FrameObserver {
public:
void OnNavigationStateChanged(
......@@ -52,8 +58,8 @@ class TestFrameObserver : public chromium::web::FrameObserver {
class FakeContext : public chromium::web::Context {
public:
void CreateFrame(
::fidl::InterfaceHandle<chromium::web::FrameObserver> observer,
::fidl::InterfaceRequest<chromium::web::Frame> frame) override {
fidl::InterfaceHandle<chromium::web::FrameObserver> observer,
fidl::InterfaceRequest<chromium::web::Frame> frame) override {
chromium::web::NavigationStateChangeDetails details;
details.url_changed = true;
details.entry.url = "";
......@@ -64,6 +70,15 @@ class FakeContext : public chromium::web::Context {
MULTIPROCESS_TEST_MAIN(SpawnContextServer) {
base::MessageLoopForIO message_loop;
base::FilePath data_dir = GetWebContextDataDir();
if (!data_dir.empty()) {
EXPECT_TRUE(base::PathExists(data_dir.AppendASCII(kTestDataFileIn)));
auto out_file = data_dir.AppendASCII(kTestDataFileOut);
EXPECT_EQ(base::WriteFile(out_file, nullptr, 0), 0);
}
FakeContext fake_context;
zx::channel context_handle{zx_take_startup_handle(kContextRequestHandleId)};
CHECK(context_handle);
......@@ -96,15 +111,49 @@ class ContextProviderImplTest : public base::MultiProcessTest {
// Start a new child process whose main function is defined in
// MULTIPROCESSING_TEST_MAIN(SpawnContextServer).
base::Process LaunchProcess(const base::LaunchOptions& options) {
auto cmdline = base::GetMultiProcessTestChildBaseCommandLine();
cmdline.AppendSwitchASCII(switches::kTestChildProcess,
base::Process LaunchProcess(base::CommandLine command,
const base::LaunchOptions& options) {
command.AppendSwitchASCII(switches::kTestChildProcess,
"SpawnContextServer");
base::Process context_process = base::LaunchProcess(cmdline, options);
base::Process context_process = base::LaunchProcess(command, options);
EXPECT_TRUE(context_process.IsValid());
return context_process;
}
void CheckContext(fidl::InterfacePtr<chromium::web::Context>* context) {
// Call a Context method and wait for it to invoke an observer call.
base::RunLoop run_loop;
context->set_error_handler([&run_loop]() {
ADD_FAILURE();
run_loop.Quit();
});
TestFrameObserver frame_observer;
fidl::Binding<chromium::web::FrameObserver> frame_observer_binding(
&frame_observer);
frame_observer_binding.set_error_handler([&run_loop]() {
ADD_FAILURE();
run_loop.Quit();
});
frame_observer.SetNextChangeCallback(run_loop.QuitClosure());
chromium::web::FramePtr frame_ptr;
frame_ptr.set_error_handler([&run_loop]() {
ADD_FAILURE();
run_loop.Quit();
});
(*context)->CreateFrame(frame_observer_binding.NewBinding(),
frame_ptr.NewRequest());
run_loop.Run();
EXPECT_TRUE(frame_observer.last_change().url_changed ||
frame_observer.last_change().title_changed);
}
protected:
base::MessageLoopForIO message_loop_;
......@@ -121,19 +170,7 @@ TEST_F(ContextProviderImplTest, LaunchContext) {
chromium::web::CreateContextParams create_params;
provider_ptr_->Create(std::move(create_params), context.NewRequest());
// Call a Context method and wait for it to invoke an observer call.
TestFrameObserver frame_observer;
chromium::web::FramePtr frame_ptr;
fidl::Binding<chromium::web::FrameObserver> frame_observer_binding(
&frame_observer);
base::RunLoop run_loop;
frame_observer.SetNextChangeCallback(run_loop.QuitClosure());
context->CreateFrame(frame_observer_binding.NewBinding(),
frame_ptr.NewRequest());
run_loop.Run();
EXPECT_TRUE(frame_observer.last_change().url_changed ||
frame_observer.last_change().title_changed);
CheckContext(&context);
}
// Verify that there can be more than one connection to the provider.
......@@ -149,14 +186,44 @@ TEST_F(ContextProviderImplTest, MultipleClients) {
provider_2_ptr->Create(std::move(create_params), context.NewRequest());
TestFrameObserver frame_observer;
chromium::web::FramePtr frame_ptr;
fidl::Binding<chromium::web::FrameObserver> frame_observer_binding(
&frame_observer);
base::RunLoop run_loop;
frame_observer.SetNextChangeCallback(run_loop.QuitClosure());
chromium::web::FramePtr frame_ptr;
context->CreateFrame(frame_observer_binding.NewBinding(),
frame_ptr.NewRequest());
run_loop.Run();
}
TEST_F(ContextProviderImplTest, WithProfileDir) {
base::ScopedTempDir profile_temp_dir;
// Connect to a new context process.
fidl::InterfacePtr<chromium::web::Context> context;
chromium::web::CreateContextParams create_params;
// Setup data dir.
EXPECT_TRUE(profile_temp_dir.CreateUniqueTempDir());
ASSERT_EQ(
base::WriteFile(profile_temp_dir.GetPath().AppendASCII(kTestDataFileIn),
nullptr, 0),
0);
// Pass a handle data dir to the context.
create_params.dataDirectory.reset(
base::fuchsia::GetHandleFromFile(
base::File(profile_temp_dir.GetPath(),
base::File::FLAG_OPEN | base::File::FLAG_READ))
.release());
provider_ptr_->Create(std::move(create_params), context.NewRequest());
CheckContext(&context);
// Verify that the context process can write data to the out dir.
EXPECT_TRUE(base::PathExists(
profile_temp_dir.GetPath().AppendASCII(kTestDataFileOut)));
}
} // namespace webrunner
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