Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: mojo/shell/dynamic_service_loader.cc

Issue 423963004: First cut at "content handling" support in Mojo. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more gn Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mojo/shell/dynamic_service_loader.h ('k') | mojo/shell/dynamic_service_loader_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "mojo/shell/dynamic_service_loader.h" 5 #include "mojo/shell/dynamic_service_loader.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
13 #include "mojo/common/common_type_converters.h" 13 #include "mojo/common/common_type_converters.h"
14 #include "mojo/common/data_pipe_utils.h" 14 #include "mojo/common/data_pipe_utils.h"
15 #include "mojo/services/public/interfaces/network/url_loader.mojom.h" 15 #include "mojo/services/public/interfaces/network/url_loader.mojom.h"
16 #include "mojo/shell/context.h" 16 #include "mojo/shell/context.h"
17 #include "mojo/shell/keep_alive.h" 17 #include "mojo/shell/keep_alive.h"
18 #include "mojo/shell/switches.h" 18 #include "mojo/shell/switches.h"
19 #include "net/base/filename_util.h" 19 #include "net/base/filename_util.h"
20 20
21 namespace mojo { 21 namespace mojo {
22 namespace shell { 22 namespace shell {
23
23 namespace { 24 namespace {
24 25
25 class Loader { 26 void RunLibraryComplete(DynamicServiceRunner* runner,
26 public: 27 const base::FilePath& temp_file) {
27 explicit Loader(scoped_ptr<DynamicServiceRunner> runner) 28 delete runner;
28 : runner_(runner.Pass()) { 29 if (!temp_file.empty())
29 } 30 base::DeleteFile(temp_file, false);
30 31 }
31 virtual void Start(const GURL& url,
32 ScopedMessagePipeHandle service_handle,
33 Context* context) = 0;
34
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();
43 }
44 }
45
46 protected:
47 virtual ~Loader() {}
48
49 private:
50 void AppCompleted() {
51 delete this;
52 }
53
54 scoped_ptr<DynamicServiceRunner> runner_;
55 };
56
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()) {
62 }
63
64 virtual void Start(const GURL& url,
65 ScopedMessagePipeHandle service_handle,
66 Context* context) OVERRIDE {
67 base::FilePath path;
68 net::FileURLToFilePath(url, &path);
69
70 // Complete asynchronously for consistency with NetworkServiceLoader.
71 base::MessageLoop::current()->PostTask(
72 FROM_HERE,
73 base::Bind(&Loader::StartService,
74 base::Unretained(this),
75 path,
76 base::Passed(&service_handle),
77 base::PathExists(path)));
78 }
79 };
80
81 // For loading services via the network stack.
82 class NetworkLoader : public Loader {
83 public:
84 explicit NetworkLoader(scoped_ptr<DynamicServiceRunner> runner,
85 NetworkService* network_service)
86 : Loader(runner.Pass()) {
87 network_service->CreateURLLoader(Get(&url_loader_));
88 }
89
90 virtual void Start(const GURL& url,
91 ScopedMessagePipeHandle service_handle,
92 Context* context) OVERRIDE {
93 service_handle_ = service_handle.Pass();
94 context_ = context;
95
96 URLRequestPtr request(URLRequest::New());
97 request->url = String::From(url);
98 request->auto_follow_redirects = true;
99
100 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
101 switches::kDisableCache)) {
102 request->bypass_cache = true;
103 }
104
105 url_loader_->Start(request.Pass(),
106 base::Bind(&NetworkLoader::OnReceivedResponse,
107 base::Unretained(this)));
108 }
109
110 private:
111 virtual ~NetworkLoader() {
112 if (!file_.empty())
113 base::DeleteFile(file_, false);
114 }
115
116 void OnReceivedResponse(URLResponsePtr response) {
117 if (response->error) {
118 LOG(ERROR) << "Error (" << response->error->code << ": "
119 << response->error->description << ") while fetching "
120 << response->url;
121 }
122
123 base::CreateTemporaryFile(&file_);
124 common::CopyToFile(response->body.Pass(),
125 file_,
126 context_->task_runners()->blocking_pool(),
127 base::Bind(&Loader::StartService,
128 base::Unretained(this),
129 file_,
130 base::Passed(&service_handle_)));
131 }
132
133 Context* context_;
134 NetworkServicePtr network_service_;
135 URLLoaderPtr url_loader_;
136 ScopedMessagePipeHandle service_handle_;
137 base::FilePath file_;
138 };
139 32
140 } // namespace 33 } // namespace
141 34
142 DynamicServiceLoader::DynamicServiceLoader( 35 DynamicServiceLoader::DynamicServiceLoader(
143 Context* context, 36 Context* context,
144 scoped_ptr<DynamicServiceRunnerFactory> runner_factory) 37 scoped_ptr<DynamicServiceRunnerFactory> runner_factory)
145 : context_(context), 38 : context_(context),
146 runner_factory_(runner_factory.Pass()) { 39 runner_factory_(runner_factory.Pass()),
40 weak_ptr_factory_(this) {
147 } 41 }
148 42
149 DynamicServiceLoader::~DynamicServiceLoader() { 43 DynamicServiceLoader::~DynamicServiceLoader() {
150 } 44 }
151 45
152 void DynamicServiceLoader::LoadService(ServiceManager* manager, 46 void DynamicServiceLoader::RegisterContentHandler(
153 const GURL& url, 47 const std::string& mime_type,
154 ScopedMessagePipeHandle shell_handle) { 48 const GURL& content_handler_url) {
155 scoped_ptr<DynamicServiceRunner> runner = runner_factory_->Create(context_); 49 mime_type_to_url_[mime_type] = content_handler_url;
50 }
156 51
52 void DynamicServiceLoader::Load(ServiceManager* manager,
53 const GURL& url,
54 scoped_refptr<LoadCallbacks> callbacks) {
157 GURL resolved_url; 55 GURL resolved_url;
158 if (url.SchemeIs("mojo")) { 56 if (url.SchemeIs("mojo")) {
159 resolved_url = context_->mojo_url_resolver()->Resolve(url); 57 resolved_url = context_->mojo_url_resolver()->Resolve(url);
160 } else { 58 } else {
161 resolved_url = url; 59 resolved_url = url;
162 } 60 }
163 61
164 Loader* loader; 62 if (resolved_url.SchemeIsFile())
165 if (resolved_url.SchemeIsFile()) { 63 LoadLocalService(resolved_url, callbacks);
166 loader = new LocalLoader(runner.Pass()); 64 else
167 } else { 65 LoadNetworkService(resolved_url, callbacks);
168 if (!network_service_) { 66 }
169 context_->service_manager()->ConnectToService( 67
170 GURL("mojo:mojo_network_service"), 68 void DynamicServiceLoader::LoadLocalService(
171 &network_service_); 69 const GURL& resolved_url,
172 } 70 scoped_refptr<LoadCallbacks> callbacks) {
173 loader = new NetworkLoader(runner.Pass(), network_service_.get()); 71 base::FilePath path;
72 net::FileURLToFilePath(resolved_url, &path);
73 const bool kDeleteFileAfter = false;
74
75 // Async for consistency with network case.
76 base::MessageLoop::current()->PostTask(
77 FROM_HERE,
78 base::Bind(&DynamicServiceLoader::RunLibrary,
79 weak_ptr_factory_.GetWeakPtr(),
80 path,
81 callbacks,
82 kDeleteFileAfter,
83 base::PathExists(path)));
84 }
85
86 void DynamicServiceLoader::LoadNetworkService(
87 const GURL& resolved_url,
88 scoped_refptr<LoadCallbacks> callbacks) {
89 if (!network_service_) {
90 context_->service_manager()->ConnectToService(
91 GURL("mojo:mojo_network_service"),
92 &network_service_);
174 } 93 }
175 loader->Start(resolved_url, shell_handle.Pass(), context_); 94 if (!url_loader_)
95 network_service_->CreateURLLoader(Get(&url_loader_));
96
97 URLRequestPtr request(URLRequest::New());
98 request->url = String::From(resolved_url);
99 request->auto_follow_redirects = true;
100
101 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
102 switches::kDisableCache)) {
103 request->bypass_cache = true;
104 }
105
106 url_loader_->Start(
107 request.Pass(),
108 base::Bind(&DynamicServiceLoader::OnLoadNetworkServiceComplete,
109 weak_ptr_factory_.GetWeakPtr(),
110 callbacks));
111 }
112
113 void DynamicServiceLoader::OnLoadNetworkServiceComplete(
114 scoped_refptr<LoadCallbacks> callbacks, URLResponsePtr response) {
115 if (response->error) {
116 LOG(ERROR) << "Error (" << response->error->code << ": "
117 << response->error->description << ") while fetching "
118 << response->url;
119 }
120
121 MimeTypeToURLMap::iterator iter =
122 mime_type_to_url_.find(response->mime_type);
123 if (iter != mime_type_to_url_.end()) {
124 callbacks->LoadWithContentHandler(iter->second, response.Pass());
125 return;
126 }
127
128 base::FilePath file;
129 base::CreateTemporaryFile(&file);
130
131 const bool kDeleteFileAfter = true;
132 common::CopyToFile(response->body.Pass(),
133 file,
134 context_->task_runners()->blocking_pool(),
135 base::Bind(&DynamicServiceLoader::RunLibrary,
136 weak_ptr_factory_.GetWeakPtr(),
137 file,
138 callbacks,
139 kDeleteFileAfter));
140 }
141
142 void DynamicServiceLoader::RunLibrary(const base::FilePath& path,
143 scoped_refptr<LoadCallbacks> callbacks,
144 bool delete_file_after,
145 bool path_exists) {
146 // TODO(aa): We need to create a runner, even if we're not going to use it,
147 // because it getting destroyed is what causes shell to shut down. If we don't
148 // create this, in the case where shell never successfully creates even one
149 // app, then shell will never shut down, because no runners are ever
150 // destroyed.
151 scoped_ptr<DynamicServiceRunner> runner(runner_factory_->Create(context_));
152 if (!path_exists)
153 return;
154
155 ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
156 if (!shell_handle.is_valid())
157 return;
158
159 DynamicServiceRunner* runner_raw = runner.release();
160 runner_raw->Start(path,
161 shell_handle.Pass(),
162 base::Bind(&RunLibraryComplete,
163 base::Unretained(runner_raw),
164 delete_file_after ? path : base::FilePath()));
176 } 165 }
177 166
178 void DynamicServiceLoader::OnServiceError(ServiceManager* manager, 167 void DynamicServiceLoader::OnServiceError(ServiceManager* manager,
179 const GURL& url) { 168 const GURL& url) {
180 // TODO(darin): What should we do about service errors? This implies that 169 // TODO(darin): What should we do about service errors? This implies that
181 // the app closed its handle to the service manager. Maybe we don't care? 170 // the app closed its handle to the service manager. Maybe we don't care?
182 } 171 }
183 172
184 } // namespace shell 173 } // namespace shell
185 } // namespace mojo 174 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/shell/dynamic_service_loader.h ('k') | mojo/shell/dynamic_service_loader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698