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

Side by Side Diff: services/nacl/content_handler_main.cc

Issue 1303343007: Created a blocking copy to temporary file function. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Added new BlockingCopy function to SFI content handler Created 5 years, 3 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "base/files/file_path.h"
6 #include "base/files/file_util.h" 5 #include "base/files/file_util.h"
7 #include "base/message_loop/message_loop.h" 6 #include "base/message_loop/message_loop.h"
8 #include "build/build_config.h" 7 #include "build/build_config.h"
9 #include "mojo/application/application_runner_chromium.h" 8 #include "mojo/application/application_runner_chromium.h"
10 #include "mojo/application/content_handler_factory.h" 9 #include "mojo/application/content_handler_factory.h"
11 #include "mojo/data_pipe_utils/data_pipe_utils.h" 10 #include "mojo/data_pipe_utils/data_pipe_utils.h"
12 #include "mojo/message_pump/message_pump_mojo.h" 11 #include "mojo/message_pump/message_pump_mojo.h"
13 #include "mojo/public/c/system/main.h" 12 #include "mojo/public/c/system/main.h"
14 #include "mojo/public/cpp/application/application_connection.h" 13 #include "mojo/public/cpp/application/application_connection.h"
15 #include "mojo/public/cpp/application/application_delegate.h" 14 #include "mojo/public/cpp/application/application_delegate.h"
16 #include "mojo/public/cpp/application/application_impl.h" 15 #include "mojo/public/cpp/application/application_impl.h"
17 #include "mojo/services/network/public/interfaces/network_service.mojom.h" 16 #include "mojo/services/network/public/interfaces/network_service.mojom.h"
18 #include "mojo/services/network/public/interfaces/url_loader.mojom.h" 17 #include "mojo/services/network/public/interfaces/url_loader.mojom.h"
19 #include "nacl_bindings/monacl_sel_main.h" 18 #include "nacl_bindings/monacl_sel_main.h"
20 #include "native_client/src/public/nacl_desc.h" 19 #include "native_client/src/public/nacl_desc.h"
21 #include "url/gurl.h" 20 #include "url/gurl.h"
22 21
23 namespace nacl { 22 namespace nacl {
24 namespace content_handler { 23 namespace content_handler {
25 24
26 namespace { 25 namespace {
27 bool URLResponseToTempFile(mojo::URLResponsePtr& response, 26 FILE* TempFileForURL(mojo::URLLoaderPtr& url_loader,
28 base::FilePath* file_path) { 27 const GURL& url) {
Mark Seaborn 2015/09/02 18:46:45 Nit: Fix indentation. Fits on previous line? You
Sean Klein 2015/09/02 21:49:11 Done.
29 if (!base::CreateTemporaryFile(file_path)) {
30 return false;
31 }
32
33 if (!mojo::common::BlockingCopyToFile(response->body.Pass(), *file_path)) {
34 base::DeleteFile(*file_path, false);
35 return false;
36 }
37
38 // TODO(ncbray): can we ensure temp file deletion even if we crash?
39 return true;
40 }
41
42 bool TempFileForURL(mojo::URLLoaderPtr& url_loader,
43 const GURL& url,
44 base::FilePath* path) {
45 mojo::URLRequestPtr request(mojo::URLRequest::New()); 28 mojo::URLRequestPtr request(mojo::URLRequest::New());
46 request->url = url.spec(); 29 request->url = url.spec();
47 request->method = "GET"; 30 request->method = "GET";
48 request->auto_follow_redirects = true; 31 request->auto_follow_redirects = true;
49 32
50 // Handle the callback synchonously. 33 // Handle the callback synchonously.
51 mojo::URLResponsePtr response; 34 mojo::URLResponsePtr response;
52 url_loader->Start(request.Pass(), [&response](mojo::URLResponsePtr r) { 35 url_loader->Start(request.Pass(), [&response](mojo::URLResponsePtr r) {
53 response = r.Pass(); 36 response = r.Pass();
54 }); 37 });
55 url_loader.WaitForIncomingResponse(); 38 url_loader.WaitForIncomingResponse();
56 if (response.is_null()) { 39 if (response.is_null()) {
57 LOG(FATAL) << "something went horribly wrong (missed a callback?)"; 40 LOG(FATAL) << "something went horribly wrong (missed a callback?)";
58 } 41 }
59 42
60 if (response->error) { 43 if (response->error) {
61 LOG(ERROR) << "could not load " << url.spec() << " (" 44 LOG(ERROR) << "could not load " << url.spec() << " ("
62 << response->error->code << ") " 45 << response->error->code << ") "
63 << response->error->description.get().c_str(); 46 << response->error->description.get().c_str();
64 return false; 47 return NULL;
65 } 48 }
66 49
67 return URLResponseToTempFile(response, path); 50 return mojo::common::BlockingCopyToTempFile(response->body.Pass());
68 }
69
70 NaClDesc* NaClDescFromNexePath(base::FilePath& path) {
71 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ |
72 base::File::FLAG_EXECUTE);
73 if (!file.IsValid()) {
74 LOG(FATAL) << "failed to open " << path.value();
75 }
76 // Note: potentially unsafe, assumes the file is immutable. This should be
77 // OK because we're currently only using temp files.
78 return NaClDescCreateWithFilePathMetadata(file.TakePlatformFile(),
79 path.AsUTF8Unsafe().c_str());
80 } 51 }
81 52
82 } // namespace 53 } // namespace
83 54
84 class NaClContentHandler : public mojo::ApplicationDelegate, 55 class NaClContentHandler : public mojo::ApplicationDelegate,
85 public mojo::ContentHandlerFactory::Delegate { 56 public mojo::ContentHandlerFactory::Delegate {
86 public: 57 public:
87 NaClContentHandler() : content_handler_factory_(this) {} 58 NaClContentHandler() : content_handler_factory_(this) {}
88 59
89 private: 60 private:
(...skipping 12 matching lines...) Expand all
102 GURL irt_url; 73 GURL irt_url;
103 #if defined(ARCH_CPU_X86_64) 74 #if defined(ARCH_CPU_X86_64)
104 irt_url = url_.Resolve("irt_x64/irt_mojo.nexe"); 75 irt_url = url_.Resolve("irt_x64/irt_mojo.nexe");
105 #else 76 #else
106 #error "Unknown / unsupported CPU architecture." 77 #error "Unknown / unsupported CPU architecture."
107 #endif 78 #endif
108 if (!irt_url.is_valid()) { 79 if (!irt_url.is_valid()) {
109 LOG(FATAL) << "Cannot resolve IRT URL"; 80 LOG(FATAL) << "Cannot resolve IRT URL";
110 } 81 }
111 82
112 if (!TempFileForURL(url_loader, irt_url, &irt_path_)) { 83 if ((irt_fp_ = TempFileForURL(url_loader, irt_url)) == NULL) {
Mark Seaborn 2015/09/02 18:46:45 I'd prefer using two lines for this, to avoid doin
Sean Klein 2015/09/02 21:49:11 Done.
113 LOG(FATAL) << "Could not aquire the IRT"; 84 LOG(FATAL) << "Could not acquire the IRT";
114 } 85 }
115 } 86 }
116 87
117 // Overridden from ApplicationDelegate: 88 // Overridden from ApplicationDelegate:
118 bool ConfigureIncomingConnection( 89 bool ConfigureIncomingConnection(
119 mojo::ApplicationConnection* connection) override { 90 mojo::ApplicationConnection* connection) override {
120 connection->AddService(&content_handler_factory_); 91 connection->AddService(&content_handler_factory_);
121 return true; 92 return true;
122 } 93 }
123 94
124 // Overridden from ContentHandlerFactory::ManagedDelegate: 95 // Overridden from ContentHandlerFactory::ManagedDelegate:
125 void RunApplication( 96 void RunApplication(
126 mojo::InterfaceRequest<mojo::Application> application_request, 97 mojo::InterfaceRequest<mojo::Application> application_request,
127 mojo::URLResponsePtr response) override { 98 mojo::URLResponsePtr response) override {
128 // Needed to use Mojo interfaces on this thread. 99 // Needed to use Mojo interfaces on this thread.
129 base::MessageLoop loop(mojo::common::MessagePumpMojo::Create()); 100 base::MessageLoop loop(mojo::common::MessagePumpMojo::Create());
130 101
131 // Aquire the nexe. 102 // Acquire the nexe.
132 base::FilePath nexe_path; 103 FILE* nexe_fp = mojo::common::BlockingCopyToTempFile(
133 if (!URLResponseToTempFile(response, &nexe_path)) { 104 response->body.Pass());
105 if (nexe_fp == NULL) {
134 LOG(FATAL) << "could not redirect nexe to temp file"; 106 LOG(FATAL) << "could not redirect nexe to temp file";
135 } 107 }
136 108
137 // Aquire the IRT. 109 // Acquire the IRT.
138 mojo::URLLoaderPtr url_loader = url_loader_.Pass(); 110 mojo::URLLoaderPtr url_loader = url_loader_.Pass();
139 LoadIRT(url_loader); 111 LoadIRT(url_loader);
140 112
141 // Get file handles to the IRT and nexe. 113 // Get file handles to the IRT and nexe.
142 NaClDesc* irt_desc = NaClDescFromNexePath(irt_path_); 114 int irt_fd = fileno(irt_fp_);
Mark Seaborn 2015/09/02 18:46:45 It looks like you could combine: fileno() + dup()
Sean Klein 2015/09/02 21:49:11 Done.
143 NaClDesc* nexe_desc = NaClDescFromNexePath(nexe_path); 115 if (irt_fd == -1) {
116 LOG(FATAL) << "Could not open the irt stream pointer's file descriptor";
117 }
118 int nexe_fd = fileno(nexe_fp);
119 if (nexe_fd == -1) {
120 LOG(FATAL) << "Could not open the nexe stream pointer's file descriptor";
121 }
122
123 // These file descriptors must be dup'd, since NaClDesc takes ownership
124 // of the file descriptor. The descriptor is still needed to close
125 // the file stream.
126 if ((irt_fd = dup(irt_fd)) == -1) {
127 LOG(FATAL) << "Could not dup the irt file descriptor";
128 }
129 if ((nexe_fd = dup(nexe_fd)) == -1) {
130 LOG(FATAL) << "Could not dup the nexe file descriptor";
131 }
132
133 NaClDesc* irt_desc = NaClDescCreateWithFilePathMetadata(
134 irt_fd, "");
135 NaClDesc* nexe_desc = NaClDescCreateWithFilePathMetadata(
136 nexe_fd, "");
144 137
145 // Run. 138 // Run.
146 int exit_code = mojo::LaunchNaCl( 139 int exit_code = mojo::LaunchNaCl(
147 nexe_desc, irt_desc, 0, NULL, 140 nexe_desc, irt_desc, 0, NULL,
148 application_request.PassMessagePipe().release().value()); 141 application_request.PassMessagePipe().release().value());
149 142
150 // TODO(ncbray): are the file handles actually closed at this point?
151
152 // Clean up. 143 // Clean up.
153 if (!base::DeleteFile(irt_path_, false)) { 144 if (fclose(irt_fp_)) {
Mark Seaborn 2015/09/02 18:46:45 Nit: you could do this before LaunchNaCl()
Sean Klein 2015/09/02 21:49:11 Done.
154 LOG(FATAL) << "Failed to remove irt temp file " << irt_path_.value(); 145 LOG(FATAL) << "Failed to close irt temp file";
155 } 146 }
156 if (!base::DeleteFile(nexe_path, false)) { 147 if (fclose(nexe_fp)) {
157 LOG(FATAL) << "Failed to remove nexe temp file " << nexe_path.value(); 148 LOG(FATAL) << "Failed to close nexe temp file";
158 } 149 }
159 150
160 // Exits the process cleanly, does not return. 151 // Exits the process cleanly, does not return.
161 mojo::NaClExit(exit_code); 152 mojo::NaClExit(exit_code);
162 NOTREACHED(); 153 NOTREACHED();
163 } 154 }
164 155
165 mojo::ContentHandlerFactory content_handler_factory_; 156 mojo::ContentHandlerFactory content_handler_factory_;
166 GURL url_; 157 GURL url_;
167 base::FilePath irt_path_; 158 FILE* irt_fp_;
168 159
169 mojo::URLLoaderPtr url_loader_; 160 mojo::URLLoaderPtr url_loader_;
170 161
171 DISALLOW_COPY_AND_ASSIGN(NaClContentHandler); 162 DISALLOW_COPY_AND_ASSIGN(NaClContentHandler);
172 }; 163 };
173 164
174 } // namespace content_handler 165 } // namespace content_handler
175 } // namespace nacl 166 } // namespace nacl
176 167
177 MojoResult MojoMain(MojoHandle application_request) { 168 MojoResult MojoMain(MojoHandle application_request) {
178 mojo::ApplicationRunnerChromium runner( 169 mojo::ApplicationRunnerChromium runner(
179 new nacl::content_handler::NaClContentHandler()); 170 new nacl::content_handler::NaClContentHandler());
180 return runner.Run(application_request); 171 return runner.Run(application_request);
181 } 172 }
OLDNEW
« mojo/data_pipe_utils/data_pipe_file_utils.cc ('K') | « mojo/data_pipe_utils/data_pipe_utils.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698