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 @@ ...@@ -12,6 +12,7 @@
#include "services/network/public/cpp/network_switches.h" #include "services/network/public/cpp/network_switches.h"
#include "webrunner/browser/webrunner_net_log.h" #include "webrunner/browser/webrunner_net_log.h"
#include "webrunner/browser/webrunner_url_request_context_getter.h" #include "webrunner/browser/webrunner_url_request_context_getter.h"
#include "webrunner/service/common.h"
namespace webrunner { namespace webrunner {
...@@ -52,10 +53,11 @@ std::unique_ptr<WebRunnerNetLog> CreateNetLog() { ...@@ -52,10 +53,11 @@ std::unique_ptr<WebRunnerNetLog> CreateNetLog() {
return result; return result;
} }
WebRunnerBrowserContext::WebRunnerBrowserContext() WebRunnerBrowserContext::WebRunnerBrowserContext(base::FilePath data_dir_path)
: net_log_(CreateNetLog()), resource_context_(new ResourceContext()) { : data_dir_path_(std::move(data_dir_path)),
// TODO(sergeyu): Pass a valid path. net_log_(CreateNetLog()),
BrowserContext::Initialize(this, base::FilePath()); resource_context_(new ResourceContext()) {
BrowserContext::Initialize(this, GetPath());
} }
WebRunnerBrowserContext::~WebRunnerBrowserContext() { WebRunnerBrowserContext::~WebRunnerBrowserContext() {
...@@ -72,8 +74,7 @@ WebRunnerBrowserContext::CreateZoomLevelDelegate( ...@@ -72,8 +74,7 @@ WebRunnerBrowserContext::CreateZoomLevelDelegate(
} }
base::FilePath WebRunnerBrowserContext::GetPath() const { base::FilePath WebRunnerBrowserContext::GetPath() const {
NOTIMPLEMENTED(); return data_dir_path_;
return base::FilePath();
} }
base::FilePath WebRunnerBrowserContext::GetCachePath() const { base::FilePath WebRunnerBrowserContext::GetCachePath() const {
...@@ -82,7 +83,7 @@ base::FilePath WebRunnerBrowserContext::GetCachePath() const { ...@@ -82,7 +83,7 @@ base::FilePath WebRunnerBrowserContext::GetCachePath() const {
} }
bool WebRunnerBrowserContext::IsOffTheRecord() const { bool WebRunnerBrowserContext::IsOffTheRecord() const {
return false; return data_dir_path_.empty();
} }
content::ResourceContext* WebRunnerBrowserContext::GetResourceContext() { content::ResourceContext* WebRunnerBrowserContext::GetResourceContext() {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_ #ifndef WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_
#define WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_ #define WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_
#include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
...@@ -15,7 +16,7 @@ class WebRunnerURLRequestContextGetter; ...@@ -15,7 +16,7 @@ class WebRunnerURLRequestContextGetter;
class WebRunnerBrowserContext : public content::BrowserContext { class WebRunnerBrowserContext : public content::BrowserContext {
public: public:
WebRunnerBrowserContext(); explicit WebRunnerBrowserContext(base::FilePath data_dir_path);
~WebRunnerBrowserContext() override; ~WebRunnerBrowserContext() override;
// BrowserContext implementation. // BrowserContext implementation.
...@@ -53,6 +54,8 @@ class WebRunnerBrowserContext : public content::BrowserContext { ...@@ -53,6 +54,8 @@ class WebRunnerBrowserContext : public content::BrowserContext {
// Contains URLRequestContextGetter required for resource loading. // Contains URLRequestContextGetter required for resource loading.
class ResourceContext; class ResourceContext;
const base::FilePath data_dir_path_;
std::unique_ptr<WebRunnerNetLog> net_log_; std::unique_ptr<WebRunnerNetLog> net_log_;
scoped_refptr<WebRunnerURLRequestContextGetter> url_request_getter_; scoped_refptr<WebRunnerURLRequestContextGetter> url_request_getter_;
std::unique_ptr<ResourceContext> resource_context_; std::unique_ptr<ResourceContext> resource_context_;
......
...@@ -4,9 +4,12 @@ ...@@ -4,9 +4,12 @@
#include "webrunner/browser/webrunner_browser_main_parts.h" #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/context_impl.h"
#include "webrunner/browser/webrunner_browser_context.h" #include "webrunner/browser/webrunner_browser_context.h"
#include "webrunner/browser/webrunner_screen.h" #include "webrunner/browser/webrunner_screen.h"
#include "webrunner/service/common.h"
namespace webrunner { namespace webrunner {
...@@ -22,7 +25,8 @@ void WebRunnerBrowserMainParts::PreMainMessageLoopRun() { ...@@ -22,7 +25,8 @@ void WebRunnerBrowserMainParts::PreMainMessageLoopRun() {
display::Screen::SetScreenInstance(screen_.get()); display::Screen::SetScreenInstance(screen_.get());
DCHECK(!browser_context_); DCHECK(!browser_context_);
browser_context_ = std::make_unique<WebRunnerBrowserContext>(); browser_context_ =
std::make_unique<WebRunnerBrowserContext>(GetWebContextDataDir());
fidl::InterfaceRequest<chromium::web::Context> context_request( fidl::InterfaceRequest<chromium::web::Context> context_request(
std::move(context_channel_)); std::move(context_channel_));
......
...@@ -4,8 +4,26 @@ ...@@ -4,8 +4,26 @@
#include "webrunner/service/common.h" #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 { 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 } // namespace webrunner
...@@ -7,13 +7,29 @@ ...@@ -7,13 +7,29 @@
#include <zircon/processargs.h> #include <zircon/processargs.h>
namespace base {
class FilePath;
}
namespace webrunner { 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); constexpr uint32_t kContextRequestHandleId = PA_HND(PA_USER0, 0);
// Process type value used for the web::Context process. It is equivalent to // Path to the direct used to store persistent data in context process.
// the main browser process in chrome. extern const char kWebContextDataPath[];
extern const char kProcessTypeWebContext[];
// 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 } // namespace webrunner
......
...@@ -24,8 +24,8 @@ namespace webrunner { ...@@ -24,8 +24,8 @@ namespace webrunner {
namespace { namespace {
// Relaunches the current executable as a Context process. // Relaunches the current executable as a Context process.
base::Process LaunchContextProcess(const base::LaunchOptions& launch_options) { base::Process LaunchContextProcess(base::CommandLine launch_command,
base::CommandLine launch_command = *base::CommandLine::ForCurrentProcess(); const base::LaunchOptions& launch_options) {
// TODO(crbug.com/867052): Remove this flag when GPU process works on Fuchsia. // TODO(crbug.com/867052): Remove this flag when GPU process works on Fuchsia.
launch_command.AppendSwitch(switches::kDisableGpu); launch_command.AppendSwitch(switches::kDisableGpu);
return base::LaunchProcess(launch_command, launch_options); return base::LaunchProcess(launch_command, launch_options);
...@@ -48,26 +48,33 @@ void ContextProviderImpl::Create( ...@@ -48,26 +48,33 @@ void ContextProviderImpl::Create(
::fidl::InterfaceRequest<chromium::web::Context> context_request) { ::fidl::InterfaceRequest<chromium::web::Context> context_request) {
DCHECK(context_request.is_valid()); DCHECK(context_request.is_valid());
if (params.dataDirectory) { base::CommandLine launch_command = *base::CommandLine::ForCurrentProcess();
// TODO(https://crbug.com/850743): Implement this.
NOTIMPLEMENTED() base::LaunchOptions launch_options;
<< "Persistent data directory binding is not yet implemented."; launch_options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
}
// Transfer the ContextRequest handle to a well-known location in the child // Transfer the ContextRequest handle to a well-known location in the child
// process' handle table. // process' handle table.
base::LaunchOptions launch_options;
zx::channel context_handle(context_request.TakeChannel()); zx::channel context_handle(context_request.TakeChannel());
launch_options.handles_to_transfer.push_back( launch_options.handles_to_transfer.push_back(
{kContextRequestHandleId, context_handle.get()}); {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 // Isolate the child Context processes by containing them within their own
// respective jobs. // respective jobs.
zx::job job; zx::job job;
zx_status_t status = zx::job::create(*base::GetDefaultJob(), 0, &job); zx_status_t status = zx::job::create(*base::GetDefaultJob(), 0, &job);
ZX_CHECK(status == ZX_OK, status) << "zx_job_create"; 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(context_handle.release());
ignore_result(job.release()); ignore_result(job.release());
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "webrunner/common/webrunner_export.h" #include "webrunner/common/webrunner_export.h"
namespace base { namespace base {
class CommandLine;
struct LaunchOptions; struct LaunchOptions;
class Process; class Process;
} // namespace base } // namespace base
...@@ -36,8 +37,9 @@ class WEBRUNNER_EXPORT ContextProviderImpl ...@@ -36,8 +37,9 @@ class WEBRUNNER_EXPORT ContextProviderImpl
override; override;
private: private:
using LaunchContextProcessCallback = using LaunchContextProcessCallback = base::RepeatingCallback<base::Process(
base::RepeatingCallback<base::Process(const base::LaunchOptions&)>; base::CommandLine command,
const base::LaunchOptions& options)>;
friend class ContextProviderImplTest; friend class ContextProviderImplTest;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "webrunner/service/context_provider_impl.h" #include "webrunner/service/context_provider_impl.h"
#include <lib/fdio/util.h>
#include <lib/fidl/cpp/binding.h> #include <lib/fidl/cpp/binding.h>
#include <zircon/processargs.h> #include <zircon/processargs.h>
...@@ -15,6 +16,8 @@ ...@@ -15,6 +16,8 @@
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/files/file.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/fuchsia/file_utils.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/test/multiprocess_test.h" #include "base/test/multiprocess_test.h"
...@@ -25,6 +28,9 @@ ...@@ -25,6 +28,9 @@
namespace webrunner { namespace webrunner {
namespace { namespace {
constexpr char kTestDataFileIn[] = "DataFileIn";
constexpr char kTestDataFileOut[] = "DataFileOut";
class TestFrameObserver : public chromium::web::FrameObserver { class TestFrameObserver : public chromium::web::FrameObserver {
public: public:
void OnNavigationStateChanged( void OnNavigationStateChanged(
...@@ -52,8 +58,8 @@ class TestFrameObserver : public chromium::web::FrameObserver { ...@@ -52,8 +58,8 @@ class TestFrameObserver : public chromium::web::FrameObserver {
class FakeContext : public chromium::web::Context { class FakeContext : public chromium::web::Context {
public: public:
void CreateFrame( void CreateFrame(
::fidl::InterfaceHandle<chromium::web::FrameObserver> observer, fidl::InterfaceHandle<chromium::web::FrameObserver> observer,
::fidl::InterfaceRequest<chromium::web::Frame> frame) override { fidl::InterfaceRequest<chromium::web::Frame> frame) override {
chromium::web::NavigationStateChangeDetails details; chromium::web::NavigationStateChangeDetails details;
details.url_changed = true; details.url_changed = true;
details.entry.url = ""; details.entry.url = "";
...@@ -64,6 +70,15 @@ class FakeContext : public chromium::web::Context { ...@@ -64,6 +70,15 @@ class FakeContext : public chromium::web::Context {
MULTIPROCESS_TEST_MAIN(SpawnContextServer) { MULTIPROCESS_TEST_MAIN(SpawnContextServer) {
base::MessageLoopForIO message_loop; 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; FakeContext fake_context;
zx::channel context_handle{zx_take_startup_handle(kContextRequestHandleId)}; zx::channel context_handle{zx_take_startup_handle(kContextRequestHandleId)};
CHECK(context_handle); CHECK(context_handle);
...@@ -96,15 +111,49 @@ class ContextProviderImplTest : public base::MultiProcessTest { ...@@ -96,15 +111,49 @@ class ContextProviderImplTest : public base::MultiProcessTest {
// Start a new child process whose main function is defined in // Start a new child process whose main function is defined in
// MULTIPROCESSING_TEST_MAIN(SpawnContextServer). // MULTIPROCESSING_TEST_MAIN(SpawnContextServer).
base::Process LaunchProcess(const base::LaunchOptions& options) { base::Process LaunchProcess(base::CommandLine command,
auto cmdline = base::GetMultiProcessTestChildBaseCommandLine(); const base::LaunchOptions& options) {
cmdline.AppendSwitchASCII(switches::kTestChildProcess, command.AppendSwitchASCII(switches::kTestChildProcess,
"SpawnContextServer"); "SpawnContextServer");
base::Process context_process = base::LaunchProcess(cmdline, options); base::Process context_process = base::LaunchProcess(command, options);
EXPECT_TRUE(context_process.IsValid()); EXPECT_TRUE(context_process.IsValid());
return context_process; 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: protected:
base::MessageLoopForIO message_loop_; base::MessageLoopForIO message_loop_;
...@@ -121,19 +170,7 @@ TEST_F(ContextProviderImplTest, LaunchContext) { ...@@ -121,19 +170,7 @@ TEST_F(ContextProviderImplTest, LaunchContext) {
chromium::web::CreateContextParams create_params; chromium::web::CreateContextParams create_params;
provider_ptr_->Create(std::move(create_params), context.NewRequest()); provider_ptr_->Create(std::move(create_params), context.NewRequest());
// Call a Context method and wait for it to invoke an observer call. CheckContext(&context);
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);
} }
// Verify that there can be more than one connection to the provider. // Verify that there can be more than one connection to the provider.
...@@ -149,14 +186,44 @@ TEST_F(ContextProviderImplTest, MultipleClients) { ...@@ -149,14 +186,44 @@ TEST_F(ContextProviderImplTest, MultipleClients) {
provider_2_ptr->Create(std::move(create_params), context.NewRequest()); provider_2_ptr->Create(std::move(create_params), context.NewRequest());
TestFrameObserver frame_observer; TestFrameObserver frame_observer;
chromium::web::FramePtr frame_ptr;
fidl::Binding<chromium::web::FrameObserver> frame_observer_binding( fidl::Binding<chromium::web::FrameObserver> frame_observer_binding(
&frame_observer); &frame_observer);
base::RunLoop run_loop; base::RunLoop run_loop;
frame_observer.SetNextChangeCallback(run_loop.QuitClosure()); frame_observer.SetNextChangeCallback(run_loop.QuitClosure());
chromium::web::FramePtr frame_ptr;
context->CreateFrame(frame_observer_binding.NewBinding(), context->CreateFrame(frame_observer_binding.NewBinding(),
frame_ptr.NewRequest()); frame_ptr.NewRequest());
run_loop.Run(); 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 } // 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