[SyncFS] Build indexes from FileTracker entries on disk.
[chromium-blink-merge.git] / mojo / shell / dynamic_service_loader.cc
blob6f1fc80c78aad0e3ee7501fb04f0806df63c3036
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "mojo/shell/dynamic_service_loader.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "mojo/common/common_type_converters.h"
14 #include "mojo/common/data_pipe_utils.h"
15 #include "mojo/services/public/interfaces/network/url_loader.mojom.h"
16 #include "mojo/shell/context.h"
17 #include "mojo/shell/keep_alive.h"
18 #include "mojo/shell/switches.h"
19 #include "net/base/filename_util.h"
21 namespace mojo {
22 namespace shell {
23 namespace {
25 class Loader {
26 public:
27 explicit Loader(scoped_ptr<DynamicServiceRunner> runner)
28 : runner_(runner.Pass()) {
31 virtual void Start(const GURL& url,
32 ScopedMessagePipeHandle service_handle,
33 Context* context) = 0;
35 void StartService(const base::FilePath& path,
36 ScopedMessagePipeHandle service_handle,
37 bool path_is_valid) {
38 if (path_is_valid) {
39 runner_->Start(path, service_handle.Pass(),
40 base::Bind(&Loader::AppCompleted, base::Unretained(this)));
41 } else {
42 AppCompleted();
46 protected:
47 virtual ~Loader() {}
49 private:
50 void AppCompleted() {
51 delete this;
54 scoped_ptr<DynamicServiceRunner> runner_;
57 // For loading services via file:// URLs.
58 class LocalLoader : public Loader {
59 public:
60 explicit LocalLoader(scoped_ptr<DynamicServiceRunner> runner)
61 : Loader(runner.Pass()) {
64 virtual void Start(const GURL& url,
65 ScopedMessagePipeHandle service_handle,
66 Context* context) OVERRIDE {
67 base::FilePath path;
68 net::FileURLToFilePath(url, &path);
70 // TODO(darin): Check if the given file path exists.
72 // Complete asynchronously for consistency with NetworkServiceLoader.
73 base::MessageLoop::current()->PostTask(
74 FROM_HERE,
75 base::Bind(&Loader::StartService,
76 base::Unretained(this),
77 path,
78 base::Passed(&service_handle),
79 true));
83 // For loading services via the network stack.
84 class NetworkLoader : public Loader {
85 public:
86 explicit NetworkLoader(scoped_ptr<DynamicServiceRunner> runner,
87 NetworkService* network_service)
88 : Loader(runner.Pass()) {
89 network_service->CreateURLLoader(Get(&url_loader_));
92 virtual void Start(const GURL& url,
93 ScopedMessagePipeHandle service_handle,
94 Context* context) OVERRIDE {
95 service_handle_ = service_handle.Pass();
96 context_ = context;
98 URLRequestPtr request(URLRequest::New());
99 request->url = String::From(url);
100 request->auto_follow_redirects = true;
102 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
103 switches::kDisableCache)) {
104 request->bypass_cache = true;
107 url_loader_->Start(request.Pass(),
108 base::Bind(&NetworkLoader::OnReceivedResponse,
109 base::Unretained(this)));
112 private:
113 virtual ~NetworkLoader() {
114 if (!file_.empty())
115 base::DeleteFile(file_, false);
118 void OnReceivedResponse(URLResponsePtr response) {
119 if (response->error) {
120 LOG(ERROR) << "Error (" << response->error->code << ": "
121 << response->error->description << ") while fetching "
122 << response->url;
125 base::CreateTemporaryFile(&file_);
126 common::CopyToFile(response->body.Pass(),
127 file_,
128 context_->task_runners()->blocking_pool(),
129 base::Bind(&Loader::StartService,
130 base::Unretained(this),
131 file_,
132 base::Passed(&service_handle_)));
135 Context* context_;
136 NetworkServicePtr network_service_;
137 URLLoaderPtr url_loader_;
138 ScopedMessagePipeHandle service_handle_;
139 base::FilePath file_;
142 } // namespace
144 DynamicServiceLoader::DynamicServiceLoader(
145 Context* context,
146 scoped_ptr<DynamicServiceRunnerFactory> runner_factory)
147 : context_(context),
148 runner_factory_(runner_factory.Pass()) {
151 DynamicServiceLoader::~DynamicServiceLoader() {
154 void DynamicServiceLoader::LoadService(ServiceManager* manager,
155 const GURL& url,
156 ScopedMessagePipeHandle shell_handle) {
157 scoped_ptr<DynamicServiceRunner> runner = runner_factory_->Create(context_);
159 GURL resolved_url;
160 if (url.SchemeIs("mojo")) {
161 resolved_url = context_->mojo_url_resolver()->Resolve(url);
162 } else {
163 resolved_url = url;
166 Loader* loader;
167 if (resolved_url.SchemeIsFile()) {
168 loader = new LocalLoader(runner.Pass());
169 } else {
170 if (!network_service_.get()) {
171 context_->service_manager()->ConnectToService(
172 GURL("mojo:mojo_network_service"),
173 &network_service_);
175 loader = new NetworkLoader(runner.Pass(), network_service_.get());
177 loader->Start(resolved_url, shell_handle.Pass(), context_);
180 void DynamicServiceLoader::OnServiceError(ServiceManager* manager,
181 const GURL& url) {
182 // TODO(darin): What should we do about service errors? This implies that
183 // the app closed its handle to the service manager. Maybe we don't care?
186 } // namespace shell
187 } // namespace mojo