Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / mojo / shell / dynamic_application_loader.cc
blob718ece4263714b9f81fd388f3b683eb554efaf84
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_application_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/switches.h"
18 #include "net/base/filename_util.h"
20 namespace mojo {
21 namespace shell {
23 DynamicApplicationLoader::DynamicApplicationLoader(
24 Context* context,
25 scoped_ptr<DynamicServiceRunnerFactory> runner_factory)
26 : context_(context),
27 runner_factory_(runner_factory.Pass()),
28 weak_ptr_factory_(this) {
31 DynamicApplicationLoader::~DynamicApplicationLoader() {
34 void DynamicApplicationLoader::RegisterContentHandler(
35 const std::string& mime_type,
36 const GURL& content_handler_url) {
37 mime_type_to_url_[mime_type] = content_handler_url;
40 void DynamicApplicationLoader::Load(ApplicationManager* manager,
41 const GURL& url,
42 scoped_refptr<LoadCallbacks> callbacks) {
43 GURL resolved_url;
44 if (url.SchemeIs("mojo")) {
45 resolved_url = context_->mojo_url_resolver()->Resolve(url);
46 } else {
47 resolved_url = url;
50 if (resolved_url.SchemeIsFile())
51 LoadLocalService(resolved_url, callbacks);
52 else
53 LoadNetworkService(resolved_url, callbacks);
56 void DynamicApplicationLoader::LoadLocalService(
57 const GURL& resolved_url,
58 scoped_refptr<LoadCallbacks> callbacks) {
59 base::FilePath path;
60 net::FileURLToFilePath(resolved_url, &path);
61 const bool kDeleteFileAfter = false;
63 // Async for consistency with network case.
64 base::MessageLoop::current()->PostTask(
65 FROM_HERE,
66 base::Bind(&DynamicApplicationLoader::RunLibrary,
67 weak_ptr_factory_.GetWeakPtr(),
68 path,
69 callbacks,
70 kDeleteFileAfter,
71 base::PathExists(path)));
74 void DynamicApplicationLoader::LoadNetworkService(
75 const GURL& resolved_url,
76 scoped_refptr<LoadCallbacks> callbacks) {
77 if (!network_service_) {
78 context_->application_manager()->ConnectToService(
79 GURL("mojo:mojo_network_service"), &network_service_);
81 if (!url_loader_)
82 network_service_->CreateURLLoader(Get(&url_loader_));
84 URLRequestPtr request(URLRequest::New());
85 request->url = String::From(resolved_url);
86 request->auto_follow_redirects = true;
88 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
89 switches::kDisableCache)) {
90 request->bypass_cache = true;
93 url_loader_->Start(
94 request.Pass(),
95 base::Bind(&DynamicApplicationLoader::OnLoadNetworkServiceComplete,
96 weak_ptr_factory_.GetWeakPtr(),
97 callbacks));
100 void DynamicApplicationLoader::OnLoadNetworkServiceComplete(
101 scoped_refptr<LoadCallbacks> callbacks,
102 URLResponsePtr response) {
103 if (response->error) {
104 LOG(ERROR) << "Error (" << response->error->code << ": "
105 << response->error->description << ") while fetching "
106 << response->url;
109 MimeTypeToURLMap::iterator iter = mime_type_to_url_.find(response->mime_type);
110 if (iter != mime_type_to_url_.end()) {
111 callbacks->LoadWithContentHandler(iter->second, response.Pass());
112 return;
115 base::FilePath file;
116 base::CreateTemporaryFile(&file);
118 const bool kDeleteFileAfter = true;
119 common::CopyToFile(response->body.Pass(),
120 file,
121 context_->task_runners()->blocking_pool(),
122 base::Bind(&DynamicApplicationLoader::RunLibrary,
123 weak_ptr_factory_.GetWeakPtr(),
124 file,
125 callbacks,
126 kDeleteFileAfter));
129 void DynamicApplicationLoader::RunLibrary(
130 const base::FilePath& path,
131 scoped_refptr<LoadCallbacks> callbacks,
132 bool delete_file_after,
133 bool path_exists) {
135 ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
136 if (!shell_handle.is_valid())
137 return;
139 if (!path_exists) {
140 DVLOG(1) << "Library not started because library path '"
141 << path.value() << "' does not exist.";
142 return;
145 scoped_ptr<DynamicServiceRunner> runner =
146 runner_factory_->Create(context_).Pass();
147 runner->Start(path,
148 shell_handle.Pass(),
149 base::Bind(&DynamicApplicationLoader::OnRunLibraryComplete,
150 weak_ptr_factory_.GetWeakPtr(),
151 base::Unretained(runner.get()),
152 delete_file_after ? path : base::FilePath()));
153 runners_.push_back(runner.release());
156 void DynamicApplicationLoader::OnRunLibraryComplete(
157 DynamicServiceRunner* runner,
158 const base::FilePath& temp_file) {
159 for (ScopedVector<DynamicServiceRunner>::iterator it = runners_.begin();
160 it != runners_.end(); ++it) {
161 if (*it == runner) {
162 runners_.erase(it);
163 if (!temp_file.empty())
164 base::DeleteFile(temp_file, false);
165 return;
170 void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager,
171 const GURL& url) {
172 // TODO(darin): What should we do about service errors? This implies that
173 // the app closed its handle to the service manager. Maybe we don't care?
176 } // namespace shell
177 } // namespace mojo