Chromium Code Reviews| OLD | NEW |
|---|---|
| 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_application_loader.h" | 5 #include "mojo/shell/dynamic_application_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/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| 11 #include "base/format_macros.h" | |
| 12 #include "base/logging.h" | |
| 11 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/memory/weak_ptr.h" | 14 #include "base/memory/weak_ptr.h" |
| 13 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 14 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "base/strings/stringprintf.h" | |
| 15 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 16 #include "mojo/common/common_type_converters.h" | 19 #include "mojo/common/common_type_converters.h" |
| 17 #include "mojo/common/data_pipe_utils.h" | 20 #include "mojo/common/data_pipe_utils.h" |
| 21 #include "mojo/public/cpp/system/data_pipe.h" | |
| 18 #include "mojo/services/public/interfaces/network/url_loader.mojom.h" | 22 #include "mojo/services/public/interfaces/network/url_loader.mojom.h" |
| 19 #include "mojo/shell/context.h" | 23 #include "mojo/shell/context.h" |
| 20 #include "mojo/shell/data_pipe_peek.h" | 24 #include "mojo/shell/data_pipe_peek.h" |
| 21 #include "mojo/shell/filename_util.h" | 25 #include "mojo/shell/filename_util.h" |
| 22 #include "mojo/shell/switches.h" | 26 #include "mojo/shell/switches.h" |
| 23 #include "url/url_util.h" | 27 #include "url/url_util.h" |
| 24 | 28 |
| 25 namespace mojo { | 29 namespace mojo { |
| 26 namespace shell { | 30 namespace shell { |
| 27 | 31 |
| 28 // Encapsulates loading and running one individual application. | 32 namespace { |
| 29 // | 33 |
| 30 // Loaders are owned by DynamicApplicationLoader. DynamicApplicationLoader must | 34 static const char kMojoMagic[] = "#!mojo:"; |
| 31 // ensure that all the parameters passed to Loader subclasses stay valid through | 35 static const size_t kMaxShebangLength = 2048; |
| 32 // Loader's lifetime. | 36 |
| 33 // | 37 void IgnoreResult(bool result) { |
| 34 // Async operations are done with WeakPtr to protect against | 38 } |
| 35 // DynamicApplicationLoader going away (and taking all the Loaders with it) | 39 |
| 36 // while the async operation is outstanding. | 40 // A request to load a given URL. |
| 37 class DynamicApplicationLoader::Loader { | 41 class LoaderRequest { |
| 38 public: | 42 public: |
| 39 Loader(Context* context, | 43 virtual ~LoaderRequest() {} |
| 40 DynamicServiceRunnerFactory* runner_factory, | |
| 41 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | |
| 42 const LoaderCompleteCallback& loader_complete_callback) | |
| 43 : load_callbacks_(load_callbacks), | |
| 44 loader_complete_callback_(loader_complete_callback), | |
| 45 context_(context), | |
| 46 runner_factory_(runner_factory), | |
| 47 weak_ptr_factory_(this) {} | |
| 48 | 44 |
| 49 virtual ~Loader() {} | 45 virtual URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, |
| 46 uint32_t skip) = 0; | |
| 47 | |
| 48 virtual void AsPath( | |
| 49 base::TaskRunner* task_runner, | |
| 50 base::Callback<void(const base::FilePath&, bool)> callback) = 0; | |
| 51 | |
| 52 bool PeekContentHandler(std::string* mojo_shebang, | |
|
Aaron Boodman
2014/11/07 08:56:27
I would prefer this function in loader, and make L
| |
| 53 GURL* mojo_content_handler_url) { | |
| 54 std::string shebang; | |
| 55 if (HasMojoMagic() && PeekFirstLine(&shebang)) { | |
| 56 GURL url(shebang.substr(2, std::string::npos)); | |
| 57 if (url.is_valid()) { | |
| 58 *mojo_shebang = shebang; | |
| 59 *mojo_content_handler_url = url; | |
| 60 return true; | |
| 61 } | |
| 62 } | |
| 63 return false; | |
| 64 } | |
| 65 | |
| 66 virtual std::string MimeType() = 0; | |
| 50 | 67 |
| 51 protected: | 68 protected: |
| 52 void RunLibrary(const base::FilePath& path, bool path_exists) { | 69 virtual bool HasMojoMagic() = 0; |
| 53 ScopedMessagePipeHandle shell_handle = | 70 virtual bool PeekFirstLine(std::string* line) = 0; |
| 54 load_callbacks_->RegisterApplication(); | 71 }; |
| 55 if (!shell_handle.is_valid()) { | 72 |
| 56 LoaderComplete(); | 73 // A request to load a remote URL. |
| 74 class NetworkLoaderRequest : public LoaderRequest { | |
| 75 public: | |
| 76 NetworkLoaderRequest(const GURL& url, | |
| 77 NetworkService* network_service, | |
| 78 const base::Callback<void(bool)>& completion_callback) | |
| 79 : completion_callback_(completion_callback), weak_ptr_factory_(this) { | |
| 80 Load(url, network_service); | |
| 81 } | |
| 82 | |
| 83 ~NetworkLoaderRequest() override { | |
| 84 if (!path_.empty()) | |
| 85 base::DeleteFile(path_, false); | |
| 86 } | |
| 87 | |
| 88 URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, | |
| 89 uint32_t skip) override { | |
| 90 if (skip != 0) { | |
| 91 MojoResult result = ReadDataRaw( | |
| 92 response_->body.get(), nullptr, &skip, | |
| 93 MOJO_READ_DATA_FLAG_ALL_OR_NONE | MOJO_READ_DATA_FLAG_DISCARD); | |
| 94 DCHECK_EQ(result, MOJO_RESULT_OK); | |
| 95 } | |
| 96 return response_.Pass(); | |
| 97 } | |
| 98 | |
| 99 void AsPath( | |
| 100 base::TaskRunner* task_runner, | |
| 101 base::Callback<void(const base::FilePath&, bool)> callback) override { | |
| 102 if (!path_.empty() || !response_) { | |
| 103 base::MessageLoop::current()->PostTask( | |
| 104 FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); | |
| 57 return; | 105 return; |
| 58 } | 106 } |
| 107 base::CreateTemporaryFile(&path_); | |
| 108 common::CopyToFile(response_->body.Pass(), path_, task_runner, | |
| 109 base::Bind(callback, path_)); | |
| 110 } | |
| 59 | 111 |
| 60 if (!path_exists) { | 112 std::string MimeType() override { |
| 61 LOG(ERROR) << "Library not started because library path '" << path.value() | 113 DCHECK(response_); |
| 62 << "' does not exist."; | 114 return response_->mime_type; |
| 63 LoaderComplete(); | 115 } |
| 116 | |
| 117 private: | |
| 118 // TODO(hansmuller): Revisit this when a real peek operation is available. | |
| 119 static const MojoDeadline kPeekTimeout = MOJO_DEADLINE_INDEFINITE; | |
| 120 | |
| 121 bool HasMojoMagic() override { | |
| 122 std::string magic; | |
| 123 return BlockingPeekNBytes(response_->body.get(), &magic, strlen(kMojoMagic), | |
| 124 kPeekTimeout) && | |
| 125 magic == kMojoMagic; | |
| 126 } | |
| 127 | |
| 128 bool PeekFirstLine(std::string* line) override { | |
| 129 return BlockingPeekLine(response_->body.get(), line, kMaxShebangLength, | |
| 130 kPeekTimeout); | |
| 131 } | |
| 132 | |
| 133 void Load(const GURL& url, NetworkService* network_service) { | |
| 134 URLRequestPtr request(URLRequest::New()); | |
| 135 request->url = String::From(url); | |
| 136 request->auto_follow_redirects = true; | |
| 137 | |
| 138 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 139 switches::kDisableCache)) { | |
| 140 request->bypass_cache = true; | |
| 141 } | |
| 142 | |
| 143 network_service->CreateURLLoader(GetProxy(&url_loader_)); | |
| 144 url_loader_->Start(request.Pass(), | |
| 145 base::Bind(&NetworkLoaderRequest::OnLoadComplete, | |
| 146 weak_ptr_factory_.GetWeakPtr())); | |
| 147 } | |
| 148 | |
| 149 void OnLoadComplete(URLResponsePtr response) { | |
| 150 if (response->error) { | |
| 151 LOG(ERROR) << "Error (" << response->error->code << ": " | |
| 152 << response->error->description << ") while fetching " | |
| 153 << response->url; | |
| 154 completion_callback_.Run(false); | |
| 64 return; | 155 return; |
| 65 } | 156 } |
| 66 | 157 response_ = response.Pass(); |
| 67 runner_ = runner_factory_->Create(context_); | 158 completion_callback_.Run(true); |
| 68 runner_->Start( | |
| 69 path, | |
| 70 shell_handle.Pass(), | |
| 71 base::Bind(&Loader::LoaderComplete, weak_ptr_factory_.GetWeakPtr())); | |
| 72 } | 159 } |
| 73 | 160 |
| 74 void LoaderComplete() { loader_complete_callback_.Run(this); } | 161 base::Callback<void(bool)> completion_callback_; |
| 162 URLLoaderPtr url_loader_; | |
| 163 URLResponsePtr response_; | |
| 164 base::FilePath path_; | |
| 165 base::WeakPtrFactory<NetworkLoaderRequest> weak_ptr_factory_; | |
| 75 | 166 |
| 76 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks_; | 167 DISALLOW_COPY_AND_ASSIGN(NetworkLoaderRequest); |
| 77 LoaderCompleteCallback loader_complete_callback_; | 168 }; |
| 78 Context* context_; | 169 |
| 170 // A request to load a file URL. | |
| 171 class LocalLoaderRequest : public LoaderRequest { | |
| 172 public: | |
| 173 LocalLoaderRequest(const GURL& url, | |
| 174 const base::Callback<void(bool)>& completion_callback) | |
| 175 : url_(url), path_(UrlToFile(url)) { | |
| 176 base::MessageLoop::current()->PostTask( | |
| 177 FROM_HERE, base::Bind(completion_callback, true)); | |
| 178 } | |
| 179 | |
| 180 URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, | |
| 181 uint32_t skip) override { | |
| 182 URLResponsePtr response(URLResponse::New()); | |
| 183 response->url = String::From(url_); | |
| 184 DataPipe data_pipe; | |
| 185 response->body = data_pipe.consumer_handle.Pass(); | |
| 186 int64 file_size; | |
| 187 if (base::GetFileSize(path_, &file_size)) { | |
| 188 response->headers = Array<String>(1); | |
| 189 response->headers[0] = | |
| 190 base::StringPrintf("Content-Length: %" PRId64, file_size); | |
| 191 } | |
| 192 common::CopyFromFile(path_, data_pipe.producer_handle.Pass(), skip, | |
| 193 task_runner, base::Bind(&IgnoreResult)); | |
| 194 return response.Pass(); | |
| 195 } | |
| 196 | |
| 197 void AsPath( | |
| 198 base::TaskRunner* task_runner, | |
| 199 base::Callback<void(const base::FilePath&, bool)> callback) override { | |
| 200 base::MessageLoop::current()->PostTask( | |
| 201 FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); | |
| 202 } | |
| 203 | |
| 204 std::string MimeType() override { return ""; } | |
| 79 | 205 |
| 80 private: | 206 private: |
| 81 DynamicServiceRunnerFactory* runner_factory_; | 207 static base::FilePath UrlToFile(const GURL& url) { |
| 82 scoped_ptr<DynamicServiceRunner> runner_; | |
| 83 base::WeakPtrFactory<Loader> weak_ptr_factory_; | |
| 84 }; | |
| 85 | |
| 86 // A loader for local files. | |
| 87 class DynamicApplicationLoader::LocalLoader : public Loader { | |
| 88 public: | |
| 89 LocalLoader(const GURL& url, | |
| 90 Context* context, | |
| 91 DynamicServiceRunnerFactory* runner_factory, | |
| 92 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | |
| 93 const LoaderCompleteCallback& loader_complete_callback) | |
| 94 : Loader(context, | |
| 95 runner_factory, | |
| 96 load_callbacks, | |
| 97 loader_complete_callback), | |
| 98 weak_ptr_factory_(this) { | |
| 99 DCHECK(url.SchemeIsFile()); | 208 DCHECK(url.SchemeIsFile()); |
| 100 url::RawCanonOutputW<1024> output; | 209 url::RawCanonOutputW<1024> output; |
| 101 url::DecodeURLEscapeSequences( | 210 url::DecodeURLEscapeSequences( |
| 102 url.path().data(), static_cast<int>(url.path().length()), &output); | 211 url.path().data(), static_cast<int>(url.path().length()), &output); |
| 103 base::string16 decoded_path = | 212 base::string16 decoded_path = |
| 104 base::string16(output.data(), output.length()); | 213 base::string16(output.data(), output.length()); |
| 105 #if defined(OS_WIN) | 214 #if defined(OS_WIN) |
| 106 base::TrimString(decoded_path, L"/", &decoded_path); | 215 base::TrimString(decoded_path, L"/", &decoded_path); |
| 107 base::FilePath path(decoded_path); | 216 base::FilePath path(decoded_path); |
| 108 #else | 217 #else |
| 109 base::FilePath path(base::UTF16ToUTF8(decoded_path)); | 218 base::FilePath path(base::UTF16ToUTF8(decoded_path)); |
| 110 #endif | 219 #endif |
| 111 | 220 return path; |
| 112 // Async for consistency with network case. | |
| 113 base::MessageLoop::current()->PostTask( | |
| 114 FROM_HERE, | |
| 115 base::Bind(&LocalLoader::RunLibrary, | |
| 116 weak_ptr_factory_.GetWeakPtr(), | |
| 117 path, | |
| 118 base::PathExists(path))); | |
| 119 } | 221 } |
| 120 | 222 |
| 121 ~LocalLoader() override {} | 223 bool HasMojoMagic() override { |
| 224 std::string magic; | |
| 225 ReadFileToString(path_, &magic, strlen(kMojoMagic)); | |
| 226 return magic == kMojoMagic; | |
| 227 } | |
| 228 | |
| 229 bool PeekFirstLine(std::string* line) override { | |
| 230 std::string start_of_file; | |
| 231 ReadFileToString(path_, &start_of_file, kMaxShebangLength); | |
| 232 size_t return_position = start_of_file.find('\n'); | |
| 233 if (return_position == std::string::npos) | |
| 234 return false; | |
| 235 *line = start_of_file.substr(0, return_position + 1); | |
| 236 return true; | |
| 237 } | |
| 238 | |
| 239 GURL url_; | |
| 240 base::FilePath path_; | |
| 241 | |
| 242 DISALLOW_COPY_AND_ASSIGN(LocalLoaderRequest); | |
| 243 }; | |
| 244 | |
| 245 } // namespace | |
| 246 | |
| 247 // Encapsulates loading and running one individual application. | |
| 248 // | |
| 249 // Loaders are owned by DynamicApplicationLoader. DynamicApplicationLoader must | |
| 250 // ensure that all the parameters passed to Loader subclasses stay valid through | |
| 251 // Loader's lifetime. | |
| 252 // | |
| 253 // Async operations are done with WeakPtr to protect against | |
| 254 // DynamicApplicationLoader going away (and taking all the Loaders with it) | |
| 255 // while the async operation is outstanding. | |
| 256 class DynamicApplicationLoader::Loader { | |
| 257 public: | |
| 258 Loader(const GURL& url, | |
| 259 MimeTypeToURLMap* mime_type_to_url, | |
| 260 Context* context, | |
| 261 DynamicServiceRunnerFactory* runner_factory, | |
| 262 NetworkServicePtr* network_service, | |
| 263 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | |
| 264 const LoaderCompleteCallback& loader_complete_callback) | |
| 265 : load_callbacks_(load_callbacks), | |
| 266 loader_complete_callback_(loader_complete_callback), | |
| 267 context_(context), | |
| 268 mime_type_to_url_(mime_type_to_url), | |
| 269 runner_factory_(runner_factory), | |
| 270 network_service_(network_service), | |
| 271 weak_ptr_factory_(this) { | |
| 272 Load(url, network_service); | |
| 273 } | |
| 274 | |
| 275 virtual ~Loader() {} | |
| 122 | 276 |
| 123 private: | 277 private: |
| 124 base::WeakPtrFactory<LocalLoader> weak_ptr_factory_; | 278 void RunLibrary(const base::FilePath& path, bool path_exists) { |
| 125 }; | 279 ScopedMessagePipeHandle shell_handle = |
| 126 | 280 load_callbacks_->RegisterApplication(); |
| 127 // A loader for network files. | 281 if (!shell_handle.is_valid()) { |
| 128 class DynamicApplicationLoader::NetworkLoader : public Loader { | |
| 129 public: | |
| 130 NetworkLoader(const GURL& url, | |
| 131 MimeTypeToURLMap* mime_type_to_url, | |
| 132 Context* context, | |
| 133 DynamicServiceRunnerFactory* runner_factory, | |
| 134 NetworkService* network_service, | |
| 135 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | |
| 136 const LoaderCompleteCallback& loader_complete_callback) | |
| 137 : Loader(context, | |
| 138 runner_factory, | |
| 139 load_callbacks, | |
| 140 loader_complete_callback), | |
| 141 mime_type_to_url_(mime_type_to_url), | |
| 142 weak_ptr_factory_(this) { | |
| 143 URLRequestPtr request(URLRequest::New()); | |
| 144 request->url = String::From(url); | |
| 145 request->auto_follow_redirects = true; | |
| 146 | |
| 147 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 148 switches::kDisableCache)) { | |
| 149 request->bypass_cache = true; | |
| 150 } | |
| 151 | |
| 152 network_service->CreateURLLoader(GetProxy(&url_loader_)); | |
| 153 url_loader_->Start(request.Pass(), | |
| 154 base::Bind(&NetworkLoader::OnLoadComplete, | |
| 155 weak_ptr_factory_.GetWeakPtr())); | |
| 156 } | |
| 157 | |
| 158 ~NetworkLoader() override { | |
| 159 if (!file_.empty()) | |
| 160 base::DeleteFile(file_, false); | |
| 161 } | |
| 162 | |
| 163 private: | |
| 164 bool PeekContentHandler(DataPipeConsumerHandle source, | |
| 165 std::string* mojo_shebang, | |
| 166 GURL* mojo_content_handler_url) | |
| 167 { | |
| 168 const char* kMojoMagic = "#!mojo:"; | |
| 169 // TODO(hansmuller): Revisit this when a real peek operation is available. | |
| 170 const MojoDeadline kPeekTimeout = MOJO_DEADLINE_INDEFINITE; | |
| 171 const size_t kMaxShebangLength = 2048; | |
| 172 | |
| 173 std::string magic; | |
| 174 std::string shebang; | |
| 175 if (BlockingPeekNBytes(source, &magic, strlen(kMojoMagic), kPeekTimeout) && | |
| 176 magic == kMojoMagic && | |
| 177 BlockingPeekLine(source, &shebang, kMaxShebangLength, kPeekTimeout)) { | |
| 178 GURL url(shebang.substr(2, std::string::npos)); | |
| 179 if (url.is_valid()) { | |
| 180 *mojo_shebang = shebang; | |
| 181 *mojo_content_handler_url = url; | |
| 182 return true; | |
| 183 } | |
| 184 } | |
| 185 return false; | |
| 186 } | |
| 187 | |
| 188 void OnLoadComplete(URLResponsePtr response) { | |
| 189 if (response->error) { | |
| 190 LOG(ERROR) << "Error (" << response->error->code << ": " | |
| 191 << response->error->description << ") while fetching " | |
| 192 << response->url; | |
| 193 LoaderComplete(); | 282 LoaderComplete(); |
| 194 return; | 283 return; |
| 195 } | 284 } |
| 285 | |
| 286 if (!path_exists) { | |
| 287 LOG(ERROR) << "Library not started because library path '" << path.value() | |
| 288 << "' does not exist."; | |
| 289 LoaderComplete(); | |
| 290 return; | |
| 291 } | |
| 292 | |
| 293 runner_ = runner_factory_->Create(context_); | |
| 294 runner_->Start( | |
| 295 path, shell_handle.Pass(), | |
| 296 base::Bind(&Loader::LoaderComplete, weak_ptr_factory_.GetWeakPtr())); | |
| 297 } | |
| 298 | |
| 299 void LoaderComplete() { loader_complete_callback_.Run(this); } | |
| 300 | |
| 301 void OnResponse(bool success) { | |
| 302 if (!success) { | |
| 303 LoaderComplete(); | |
| 304 return; | |
| 305 } | |
| 196 | 306 |
| 197 // If the response begins with a #!mojo:<content-handler-url>, use it. | 307 // If the response begins with a #!mojo:<content-handler-url>, use it. |
| 198 { | 308 { |
| 199 GURL url; | 309 GURL url; |
| 200 std::string shebang; | 310 std::string shebang; |
| 201 if (PeekContentHandler(response->body.get(), &shebang, &url)) { | 311 if (request_->PeekContentHandler(&shebang, &url)) { |
| 202 uint32_t num_skip_bytes = shebang.size(); | 312 load_callbacks_->LoadWithContentHandler( |
| 203 if (ReadDataRaw(response->body.get(), | 313 url, |
| 204 nullptr, | 314 request_->AsURLResponse(context_->task_runners()->blocking_pool(), |
| 205 &num_skip_bytes, | 315 shebang.size())); |
| 206 MOJO_READ_DATA_FLAG_ALL_OR_NONE | | 316 return; |
| 207 MOJO_READ_DATA_FLAG_DISCARD) == | |
| 208 MOJO_RESULT_OK) { | |
| 209 load_callbacks_->LoadWithContentHandler(url, response.Pass()); | |
| 210 return; | |
| 211 } | |
| 212 } | 317 } |
| 213 } | 318 } |
| 214 | 319 |
| 215 MimeTypeToURLMap::iterator iter = | 320 MimeTypeToURLMap::iterator iter = |
| 216 mime_type_to_url_->find(response->mime_type); | 321 mime_type_to_url_->find(request_->MimeType()); |
| 217 if (iter != mime_type_to_url_->end()) { | 322 if (iter != mime_type_to_url_->end()) { |
| 218 load_callbacks_->LoadWithContentHandler(iter->second, response.Pass()); | 323 load_callbacks_->LoadWithContentHandler( |
| 324 iter->second, request_->AsURLResponse( | |
| 325 context_->task_runners()->blocking_pool(), 0)); | |
| 219 return; | 326 return; |
| 220 } | 327 } |
| 221 | 328 |
| 222 // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo | 329 // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo |
| 223 // application. That could either mean looking for the platform-specific dll | 330 // application. That could either mean looking for the platform-specific dll |
| 224 // header, or looking for some specific mojo signature prepended to the | 331 // header, or looking for some specific mojo signature prepended to the |
| 225 // library. | 332 // library. |
| 226 | 333 |
| 227 base::CreateTemporaryFile(&file_); | 334 request_->AsPath( |
| 228 common::CopyToFile( | |
| 229 response->body.Pass(), | |
| 230 file_, | |
| 231 context_->task_runners()->blocking_pool(), | 335 context_->task_runners()->blocking_pool(), |
| 232 base::Bind( | 336 base::Bind(&Loader::RunLibrary, weak_ptr_factory_.GetWeakPtr())); |
| 233 &NetworkLoader::RunLibrary, weak_ptr_factory_.GetWeakPtr(), file_)); | |
| 234 } | 337 } |
| 235 | 338 |
| 339 void Load(const GURL& url, NetworkServicePtr* network_service) { | |
|
Aaron Boodman
2014/11/07 08:56:27
second param never used.
| |
| 340 GURL resolved_url; | |
| 341 if (url.SchemeIs("mojo")) { | |
| 342 resolved_url = context_->mojo_url_resolver()->Resolve(url); | |
| 343 } else { | |
| 344 resolved_url = url; | |
| 345 } | |
| 346 | |
| 347 if (resolved_url.SchemeIsFile()) { | |
| 348 request_.reset(new LocalLoaderRequest( | |
| 349 resolved_url, | |
| 350 base::Bind(&DynamicApplicationLoader::Loader::OnResponse, | |
| 351 weak_ptr_factory_.GetWeakPtr()))); | |
| 352 return; | |
| 353 } | |
| 354 | |
| 355 if (!network_service_->get()) { | |
|
Aaron Boodman
2014/11/07 08:56:27
Put this back in DAL::Load() so that we share one
| |
| 356 context_->application_manager()->ConnectToService( | |
| 357 GURL("mojo:network_service"), network_service_); | |
|
Aaron Boodman
2014/11/07 08:56:27
network_service_ is a pointer, so I guess this pip
qsr
2014/11/07 09:33:22
I mixed 2 things here, sorry. network_service_ sho
| |
| 358 } | |
| 359 | |
| 360 request_.reset(new NetworkLoaderRequest( | |
| 361 resolved_url, network_service_->get(), | |
| 362 base::Bind(&DynamicApplicationLoader::Loader::OnResponse, | |
| 363 weak_ptr_factory_.GetWeakPtr()))); | |
| 364 } | |
| 365 | |
| 366 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks_; | |
| 367 LoaderCompleteCallback loader_complete_callback_; | |
| 368 Context* context_; | |
| 236 MimeTypeToURLMap* mime_type_to_url_; | 369 MimeTypeToURLMap* mime_type_to_url_; |
| 237 URLLoaderPtr url_loader_; | 370 DynamicServiceRunnerFactory* runner_factory_; |
| 238 base::FilePath file_; | 371 NetworkServicePtr* network_service_; |
| 239 base::WeakPtrFactory<NetworkLoader> weak_ptr_factory_; | 372 scoped_ptr<DynamicServiceRunner> runner_; |
| 373 scoped_ptr<LoaderRequest> request_; | |
| 374 base::WeakPtrFactory<Loader> weak_ptr_factory_; | |
| 240 }; | 375 }; |
| 376 | |
| 241 DynamicApplicationLoader::DynamicApplicationLoader( | 377 DynamicApplicationLoader::DynamicApplicationLoader( |
| 242 Context* context, | 378 Context* context, |
| 243 scoped_ptr<DynamicServiceRunnerFactory> runner_factory) | 379 scoped_ptr<DynamicServiceRunnerFactory> runner_factory) |
| 244 : context_(context), | 380 : context_(context), |
| 245 runner_factory_(runner_factory.Pass()), | 381 runner_factory_(runner_factory.Pass()), |
| 246 | 382 |
| 247 // Unretained() is correct here because DynamicApplicationLoader owns the | 383 // Unretained() is correct here because DynamicApplicationLoader owns the |
| 248 // loaders that we pass this callback to. | 384 // loaders that we pass this callback to. |
| 249 loader_complete_callback_( | 385 loader_complete_callback_( |
| 250 base::Bind(&DynamicApplicationLoader::LoaderComplete, | 386 base::Bind(&DynamicApplicationLoader::LoaderComplete, |
| 251 base::Unretained(this))) { | 387 base::Unretained(this))) { |
| 252 } | 388 } |
| 253 | 389 |
| 254 DynamicApplicationLoader::~DynamicApplicationLoader() { | 390 DynamicApplicationLoader::~DynamicApplicationLoader() { |
| 255 } | 391 } |
| 256 | 392 |
| 257 void DynamicApplicationLoader::RegisterContentHandler( | 393 void DynamicApplicationLoader::RegisterContentHandler( |
| 258 const std::string& mime_type, | 394 const std::string& mime_type, |
| 259 const GURL& content_handler_url) { | 395 const GURL& content_handler_url) { |
| 260 mime_type_to_url_[mime_type] = content_handler_url; | 396 mime_type_to_url_[mime_type] = content_handler_url; |
| 261 } | 397 } |
| 262 | 398 |
| 263 void DynamicApplicationLoader::Load( | 399 void DynamicApplicationLoader::Load( |
| 264 ApplicationManager* manager, | 400 ApplicationManager* manager, |
| 265 const GURL& url, | 401 const GURL& url, |
| 266 scoped_refptr<LoadCallbacks> load_callbacks) { | 402 scoped_refptr<LoadCallbacks> load_callbacks) { |
| 267 GURL resolved_url; | 403 loaders_.push_back(new Loader(url, &mime_type_to_url_, context_, |
| 268 if (url.SchemeIs("mojo")) { | 404 runner_factory_.get(), &network_service_, |
|
Aaron Boodman
2014/11/07 08:56:27
this is always null.
| |
| 269 resolved_url = context_->mojo_url_resolver()->Resolve(url); | 405 load_callbacks, loader_complete_callback_)); |
| 270 } else { | |
| 271 resolved_url = url; | |
| 272 } | |
| 273 | |
| 274 if (resolved_url.SchemeIsFile()) { | |
| 275 loaders_.push_back(new LocalLoader(resolved_url, | |
| 276 context_, | |
| 277 runner_factory_.get(), | |
| 278 load_callbacks, | |
| 279 loader_complete_callback_)); | |
| 280 return; | |
| 281 } | |
| 282 | |
| 283 if (!network_service_) { | |
| 284 context_->application_manager()->ConnectToService( | |
| 285 GURL("mojo:network_service"), &network_service_); | |
| 286 } | |
| 287 | |
| 288 loaders_.push_back(new NetworkLoader(resolved_url, | |
| 289 &mime_type_to_url_, | |
| 290 context_, | |
| 291 runner_factory_.get(), | |
| 292 network_service_.get(), | |
| 293 load_callbacks, | |
| 294 loader_complete_callback_)); | |
| 295 } | 406 } |
| 296 | 407 |
| 297 void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager, | 408 void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager, |
| 298 const GURL& url) { | 409 const GURL& url) { |
| 299 // TODO(darin): What should we do about service errors? This implies that | 410 // TODO(darin): What should we do about service errors? This implies that |
| 300 // the app closed its handle to the service manager. Maybe we don't care? | 411 // the app closed its handle to the service manager. Maybe we don't care? |
| 301 } | 412 } |
| 302 | 413 |
| 303 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { | 414 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { |
| 304 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); | 415 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); |
| 305 } | 416 } |
| 306 | 417 |
| 307 } // namespace shell | 418 } // namespace shell |
| 308 } // namespace mojo | 419 } // namespace mojo |
| OLD | NEW |