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

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

Issue 323593002: Mojo: Use network service to load non-local Mojo Apps. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 6 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/in_process_dynamic_service_runner.h » ('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/location.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/data_pipe_utils.h"
14 #include "mojo/services/public/interfaces/network/url_loader.mojom.h"
8 #include "mojo/shell/context.h" 15 #include "mojo/shell/context.h"
9 #include "mojo/shell/keep_alive.h" 16 #include "mojo/shell/keep_alive.h"
17 #include "mojo/shell/switches.h"
18 #include "net/base/filename_util.h"
10 19
11 namespace mojo { 20 namespace mojo {
12 namespace shell { 21 namespace shell {
13
14 namespace { 22 namespace {
15 23
16 std::string MakeSharedLibraryName(const std::string& file_name) { 24 class Loader {
17 #if defined(OS_WIN) 25 public:
18 return file_name + ".dll"; 26 explicit Loader(scoped_ptr<DynamicServiceRunner> runner)
19 #elif defined(OS_LINUX) 27 : runner_(runner.Pass()) {
20 return "lib" + file_name + ".so"; 28 }
21 #elif defined(OS_MACOSX)
22 return "lib" + file_name + ".dylib";
23 #else
24 NOTREACHED() << "dynamic loading of services not supported";
25 return std::string();
26 #endif
27 }
28 29
29 } // namespace 30 virtual void Start(const GURL& url,
31 ScopedMessagePipeHandle service_handle,
32 Context* context) = 0;
30 33
31 class DynamicServiceLoader::LoadContext : public mojo::shell::Loader::Delegate { 34 void StartService(const base::FilePath& path,
35 ScopedMessagePipeHandle service_handle,
36 bool path_is_valid) {
37 if (path_is_valid) {
38 runner_->Start(path, service_handle.Pass(),
39 base::Bind(&Loader::AppCompleted, base::Unretained(this)));
40 } else {
41 AppCompleted();
42 }
43 }
44
45 protected:
46 virtual ~Loader() {}
47
48 private:
49 void AppCompleted() {
50 delete this;
51 }
52
53 scoped_ptr<DynamicServiceRunner> runner_;
54 };
55
56 // For loading services via file:// URLs.
57 class LocalLoader : public Loader {
32 public: 58 public:
33 LoadContext(DynamicServiceLoader* loader, 59 explicit LocalLoader(scoped_ptr<DynamicServiceRunner> runner)
34 const GURL& url, 60 : Loader(runner.Pass()) {
35 ScopedMessagePipeHandle service_handle, 61 }
36 scoped_ptr<DynamicServiceRunner> runner)
37 : loader_(loader),
38 url_(url),
39 service_handle_(service_handle.Pass()),
40 runner_(runner.Pass()),
41 keep_alive_(loader->context_) {
42 GURL url_to_load;
43 62
44 if (url.SchemeIs("mojo")) { 63 virtual void Start(const GURL& url,
45 std::string lib = MakeSharedLibraryName(url.ExtractFileName()); 64 ScopedMessagePipeHandle service_handle,
46 url_to_load = GURL(loader->context_->mojo_origin() + "/" + lib); 65 Context* context) OVERRIDE {
47 } else { 66 base::FilePath path;
48 url_to_load = url; 67 net::FileURLToFilePath(url, &path);
68
69 // TODO(darin): Check if the given file path exists.
70
71 // Complete asynchronously for consistency with NetworkServiceLoader.
72 base::MessageLoop::current()->PostTask(
73 FROM_HERE,
74 base::Bind(&Loader::StartService,
75 base::Unretained(this),
76 path,
77 base::Passed(&service_handle),
78 true));
79 }
80 };
81
82 // For loading services via the network stack.
83 class NetworkLoader : public Loader, public URLLoaderClient {
84 public:
85 explicit NetworkLoader(scoped_ptr<DynamicServiceRunner> runner,
86 NetworkService* network_service)
87 : Loader(runner.Pass()) {
88 network_service->CreateURLLoader(Get(&url_loader_));
89 url_loader_.set_client(this);
90 }
91
92 virtual void Start(const GURL& url,
93 ScopedMessagePipeHandle service_handle,
94 Context* context) OVERRIDE {
95 service_handle_ = service_handle.Pass();
96
97 URLRequestPtr request(URLRequest::New());
98 request->url = url.spec();
99 request->follow_redirects = true;
100
101 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
102 switches::kDisableCache)) {
103 request->bypass_cache = true;
49 } 104 }
50 105
51 request_ = loader_->context_->loader()->Load(url_to_load, this); 106 DataPipe data_pipe;
52 } 107 url_loader_->Start(request.Pass(), data_pipe.producer_handle.Pass());
53 108
54 virtual ~LoadContext() { 109 base::CreateTemporaryFile(&file_);
110 common::CopyToFile(data_pipe.consumer_handle.Pass(),
111 file_,
112 context->task_runners()->blocking_pool(),
113 base::Bind(&Loader::StartService,
114 base::Unretained(this),
115 file_,
116 base::Passed(&service_handle_)));
55 } 117 }
56 118
57 private: 119 private:
58 // |Loader::Delegate| method: 120 // URLLoaderClient methods:
59 virtual void DidCompleteLoad(const GURL& app_url, 121 virtual void OnReceivedRedirect(URLResponsePtr response,
60 const base::FilePath& app_path, 122 const String& new_url,
61 const std::string* mime_type) OVERRIDE { 123 const String& new_method) OVERRIDE {
62 DVLOG(2) << "Completed load of " << app_url << " (" << url_ << ") to " 124 // TODO(darin): Handle redirects properly!
63 << app_path.value(); 125 }
64 DCHECK(loader_->context_->task_runners()->ui_runner()-> 126 virtual void OnReceivedResponse(URLResponsePtr response) OVERRIDE {}
65 BelongsToCurrentThread()); 127 virtual void OnReceivedError(NetworkErrorPtr error) OVERRIDE {}
128 virtual void OnReceivedEndOfResponseBody() OVERRIDE {}
66 129
67 runner_->Start( 130 NetworkServicePtr network_service_;
68 app_path, 131 URLLoaderPtr url_loader_;
69 service_handle_.Pass(), 132 ScopedMessagePipeHandle service_handle_;
70 base::Bind(&DynamicServiceLoader::AppCompleted, 133 base::FilePath file_;
71 base::Unretained(loader_), url_)); 134 };
72 }
73 135
74 DynamicServiceLoader* const loader_; 136 } // namespace
75 const GURL url_;
76 scoped_ptr<mojo::shell::Loader::Job> request_;
77 ScopedMessagePipeHandle service_handle_;
78 scoped_ptr<DynamicServiceRunner> runner_;
79 KeepAlive keep_alive_;
80
81 DISALLOW_COPY_AND_ASSIGN(LoadContext);
82 };
83 137
84 DynamicServiceLoader::DynamicServiceLoader( 138 DynamicServiceLoader::DynamicServiceLoader(
85 Context* context, 139 Context* context,
86 scoped_ptr<DynamicServiceRunnerFactory> runner_factory) 140 scoped_ptr<DynamicServiceRunnerFactory> runner_factory)
87 : context_(context), 141 : context_(context),
88 runner_factory_(runner_factory.Pass()) { 142 runner_factory_(runner_factory.Pass()) {
89 } 143 }
90 144
91 DynamicServiceLoader::~DynamicServiceLoader() { 145 DynamicServiceLoader::~DynamicServiceLoader() {
92 DCHECK(url_to_load_context_.empty());
93 } 146 }
94 147
95 void DynamicServiceLoader::LoadService(ServiceManager* manager, 148 void DynamicServiceLoader::LoadService(ServiceManager* manager,
96 const GURL& url, 149 const GURL& url,
97 ScopedMessagePipeHandle service_handle) { 150 ScopedMessagePipeHandle service_handle) {
98 DCHECK(url_to_load_context_.find(url) == url_to_load_context_.end()); 151 scoped_ptr<DynamicServiceRunner> runner = runner_factory_->Create(context_);
99 url_to_load_context_[url] = new LoadContext( 152
100 this, url, service_handle.Pass(), runner_factory_->Create(context_)); 153 GURL resolved_url;
154 if (url.SchemeIs("mojo")) {
155 resolved_url = context_->mojo_url_resolver()->Resolve(url);
156 } else {
157 resolved_url = url;
158 }
159
160 Loader* loader;
161 if (resolved_url.SchemeIsFile()) {
162 loader = new LocalLoader(runner.Pass());
163 } else {
164 if (!network_service_.get()) {
165 context_->service_manager()->ConnectTo(GURL("mojo:mojo_network_service"),
166 &network_service_,
167 GURL());
168 }
169 loader = new NetworkLoader(runner.Pass(), network_service_.get());
170 }
171 loader->Start(resolved_url, service_handle.Pass(), context_);
101 } 172 }
102 173
103 void DynamicServiceLoader::OnServiceError(ServiceManager* manager, 174 void DynamicServiceLoader::OnServiceError(ServiceManager* manager,
104 const GURL& url) { 175 const GURL& url) {
105 } 176 // TODO(darin): What should we do about service errors? This implies that
106 177 // the app closed its handle to the service manager. Maybe we don't care?
107 void DynamicServiceLoader::AppCompleted(const GURL& url) {
108 DCHECK(context_->task_runners()->ui_runner()->BelongsToCurrentThread());
109 DVLOG(2) << "App completed (url: " << url << ")";
110
111 LoadContextMap::iterator it = url_to_load_context_.find(url);
112 DCHECK(it != url_to_load_context_.end()) << url;
113
114 LoadContext* doomed = it->second;
115 url_to_load_context_.erase(it);
116
117 delete doomed;
118 } 178 }
119 179
120 } // namespace shell 180 } // namespace shell
121 } // namespace mojo 181 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/shell/dynamic_service_loader.h ('k') | mojo/shell/in_process_dynamic_service_runner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698