OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #define NACL_LOG_MODULE_NAME "Plugin_ServiceRuntime" | 7 #define NACL_LOG_MODULE_NAME "Plugin_ServiceRuntime" |
8 | 8 |
9 #include "ppapi/native_client/src/trusted/plugin/service_runtime.h" | 9 #include "ppapi/native_client/src/trusted/plugin/service_runtime.h" |
10 | 10 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 | 57 |
58 namespace plugin { | 58 namespace plugin { |
59 namespace { | 59 namespace { |
60 | 60 |
61 // For doing crude quota enforcement on writes to temp files. | 61 // For doing crude quota enforcement on writes to temp files. |
62 // We do not allow a temp file bigger than 128 MB for now. | 62 // We do not allow a temp file bigger than 128 MB for now. |
63 // There is currently a limit of 32M for nexe text size, so 128M | 63 // There is currently a limit of 32M for nexe text size, so 128M |
64 // should be plenty for static data | 64 // should be plenty for static data |
65 const int64_t kMaxTempQuota = 0x8000000; | 65 const int64_t kMaxTempQuota = 0x8000000; |
66 | 66 |
| 67 class OpenManifestEntryAsyncCallback { |
| 68 public: |
| 69 OpenManifestEntryAsyncCallback(PP_FileHandle* file_handle, |
| 70 const pp::CompletionCallback& callback) |
| 71 : file_handle_(file_handle), |
| 72 callback_(callback) { |
| 73 } |
| 74 |
| 75 ~OpenManifestEntryAsyncCallback() { |
| 76 if (callback_.pp_completion_callback().func) |
| 77 callback_.RunAndClear(PP_ERROR_ABORTED); |
| 78 } |
| 79 |
| 80 void Run(int32_t pp_error) { |
| 81 *file_handle_ = (pp_error == PP_OK) ? info_.desc : -1; |
| 82 callback_.RunAndClear(pp_error); |
| 83 delete this; |
| 84 } |
| 85 |
| 86 NaClFileInfo* mutable_info() { return &info_; } |
| 87 pp::CompletionCallback pp_completion_callback() { |
| 88 return pp::CompletionCallback(&RunTrampoline, this); |
| 89 } |
| 90 |
| 91 private: |
| 92 static void RunTrampoline(void* user_data, int32_t pp_error) { |
| 93 static_cast<OpenManifestEntryAsyncCallback*>(user_data)->Run(pp_error); |
| 94 } |
| 95 |
| 96 PP_FileHandle* file_handle_; |
| 97 NaClFileInfo info_; |
| 98 pp::CompletionCallback callback_; |
| 99 DISALLOW_COPY_AND_ASSIGN(OpenManifestEntryAsyncCallback); |
| 100 }; |
| 101 |
67 class ManifestService { | 102 class ManifestService { |
68 public: | 103 public: |
69 ManifestService(nacl::WeakRefAnchor* anchor, | 104 ManifestService(nacl::WeakRefAnchor* anchor, |
70 PluginReverseInterface* plugin_reverse) | 105 PluginReverseInterface* plugin_reverse) |
71 : anchor_(anchor), | 106 : anchor_(anchor), |
72 plugin_reverse_(plugin_reverse) { | 107 plugin_reverse_(plugin_reverse) { |
73 } | 108 } |
74 | 109 |
75 ~ManifestService() { | 110 ~ManifestService() { |
76 anchor_->Unref(); | 111 anchor_->Unref(); |
77 } | 112 } |
78 | 113 |
79 bool Quit() { | 114 bool Quit() { |
80 delete this; | 115 delete this; |
81 return false; | 116 return false; |
82 } | 117 } |
83 | 118 |
84 bool StartupInitializationComplete() { | 119 bool StartupInitializationComplete() { |
85 // Release this instance if the ServiceRuntime is already destructed. | 120 // Release this instance if the ServiceRuntime is already destructed. |
86 if (anchor_->is_abandoned()) { | 121 if (anchor_->is_abandoned()) { |
87 delete this; | 122 delete this; |
88 return false; | 123 return false; |
89 } | 124 } |
90 | 125 |
91 plugin_reverse_->StartupInitializationComplete(); | 126 plugin_reverse_->StartupInitializationComplete(); |
92 return true; | 127 return true; |
93 } | 128 } |
94 | 129 |
| 130 bool OpenResource(const char* entry_key, PP_FileHandle* file, |
| 131 const pp::CompletionCallback& callback) { |
| 132 // Release this instance if the ServiceRuntime is already destructed. |
| 133 if (anchor_->is_abandoned()) { |
| 134 delete this; |
| 135 return false; |
| 136 } |
| 137 |
| 138 OpenManifestEntryAsyncCallback* open_manifest_callback = |
| 139 new OpenManifestEntryAsyncCallback(file, callback); |
| 140 plugin_reverse_->OpenManifestEntryAsync( |
| 141 entry_key, |
| 142 open_manifest_callback->mutable_info(), |
| 143 open_manifest_callback->pp_completion_callback()); |
| 144 return true; |
| 145 } |
| 146 |
95 static PP_Bool QuitTrampoline(void* user_data) { | 147 static PP_Bool QuitTrampoline(void* user_data) { |
96 return PP_FromBool(static_cast<ManifestService*>(user_data)->Quit()); | 148 return PP_FromBool(static_cast<ManifestService*>(user_data)->Quit()); |
97 } | 149 } |
98 | 150 |
99 static PP_Bool StartupInitializationCompleteTrampoline(void* user_data) { | 151 static PP_Bool StartupInitializationCompleteTrampoline(void* user_data) { |
100 return PP_FromBool(static_cast<ManifestService*>(user_data)-> | 152 return PP_FromBool(static_cast<ManifestService*>(user_data)-> |
101 StartupInitializationComplete()); | 153 StartupInitializationComplete()); |
102 } | 154 } |
103 | 155 |
| 156 static PP_Bool OpenResourceTrampoline( |
| 157 void* user_data, const char* entry_key, PP_FileHandle* file, |
| 158 struct PP_CompletionCallback callback) { |
| 159 return PP_FromBool( |
| 160 static_cast<ManifestService*>(user_data)->OpenResource( |
| 161 entry_key, file, |
| 162 pp::CompletionCallback(callback.func, callback.user_data))); |
| 163 } |
| 164 |
104 private: | 165 private: |
105 // Weak reference to check if plugin_reverse is legally accessible or not. | 166 // Weak reference to check if plugin_reverse is legally accessible or not. |
106 nacl::WeakRefAnchor* anchor_; | 167 nacl::WeakRefAnchor* anchor_; |
107 PluginReverseInterface* plugin_reverse_; | 168 PluginReverseInterface* plugin_reverse_; |
108 | 169 |
109 DISALLOW_COPY_AND_ASSIGN(ManifestService); | 170 DISALLOW_COPY_AND_ASSIGN(ManifestService); |
110 }; | 171 }; |
111 | 172 |
112 // Vtable to pass functions to LaunchSelLdr. | 173 // Vtable to pass functions to LaunchSelLdr. |
113 const PP_ManifestService kManifestServiceVTable = { | 174 const PPB_ManifestService kManifestServiceVTable = { |
114 &ManifestService::QuitTrampoline, | 175 &ManifestService::QuitTrampoline, |
115 &ManifestService::StartupInitializationCompleteTrampoline, | 176 &ManifestService::StartupInitializationCompleteTrampoline, |
| 177 &ManifestService::OpenResourceTrampoline, |
116 }; | 178 }; |
117 | 179 |
118 } // namespace | 180 } // namespace |
119 | 181 |
120 PluginReverseInterface::PluginReverseInterface( | 182 PluginReverseInterface::PluginReverseInterface( |
121 nacl::WeakRefAnchor* anchor, | 183 nacl::WeakRefAnchor* anchor, |
122 Plugin* plugin, | 184 Plugin* plugin, |
123 const Manifest* manifest, | 185 const Manifest* manifest, |
124 ServiceRuntime* service_runtime, | 186 ServiceRuntime* service_runtime, |
125 pp::CompletionCallback init_done_cb, | 187 pp::CompletionCallback init_done_cb, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 // and invoke StreamAsFile with a completion callback that invokes | 255 // and invoke StreamAsFile with a completion callback that invokes |
194 // GetPOSIXFileDesc. | 256 // GetPOSIXFileDesc. |
195 bool PluginReverseInterface::OpenManifestEntry(nacl::string url_key, | 257 bool PluginReverseInterface::OpenManifestEntry(nacl::string url_key, |
196 struct NaClFileInfo* info) { | 258 struct NaClFileInfo* info) { |
197 bool op_complete = false; // NB: mu_ and cv_ also controls access to this! | 259 bool op_complete = false; // NB: mu_ and cv_ also controls access to this! |
198 // The to_open object is owned by the weak ref callback. Because this function | 260 // The to_open object is owned by the weak ref callback. Because this function |
199 // waits for the callback to finish, the to_open object will be deallocated on | 261 // waits for the callback to finish, the to_open object will be deallocated on |
200 // the main thread before this function can return. The pointers it contains | 262 // the main thread before this function can return. The pointers it contains |
201 // to stack variables will not leak. | 263 // to stack variables will not leak. |
202 OpenManifestEntryResource* to_open = | 264 OpenManifestEntryResource* to_open = |
203 new OpenManifestEntryResource(url_key, info, &op_complete); | 265 new OpenManifestEntryResource(url_key, info, &op_complete, |
| 266 pp::CompletionCallback()); |
204 CHECK(to_open != NULL); | 267 CHECK(to_open != NULL); |
205 NaClLog(4, "PluginReverseInterface::OpenManifestEntry: %s\n", | 268 NaClLog(4, "PluginReverseInterface::OpenManifestEntry: %s\n", |
206 url_key.c_str()); | 269 url_key.c_str()); |
207 // This assumes we are not on the main thread. If false, we deadlock. | 270 // This assumes we are not on the main thread. If false, we deadlock. |
208 plugin::WeakRefCallOnMainThread( | 271 plugin::WeakRefCallOnMainThread( |
209 anchor_, | 272 anchor_, |
210 0, | 273 0, |
211 this, | 274 this, |
212 &plugin::PluginReverseInterface::OpenManifestEntry_MainThreadContinuation, | 275 &plugin::PluginReverseInterface::OpenManifestEntry_MainThreadContinuation, |
213 to_open); | 276 to_open); |
(...skipping 29 matching lines...) Expand all Loading... |
243 if (info->desc == -1) { | 306 if (info->desc == -1) { |
244 // TODO(bsy,ncbray): what else should we do with the error? This | 307 // TODO(bsy,ncbray): what else should we do with the error? This |
245 // is a runtime error that may simply be a programming error in | 308 // is a runtime error that may simply be a programming error in |
246 // the untrusted code, or it may be something else wrong w/ the | 309 // the untrusted code, or it may be something else wrong w/ the |
247 // manifest. | 310 // manifest. |
248 NaClLog(4, "OpenManifestEntry: failed for key %s", url_key.c_str()); | 311 NaClLog(4, "OpenManifestEntry: failed for key %s", url_key.c_str()); |
249 } | 312 } |
250 return true; | 313 return true; |
251 } | 314 } |
252 | 315 |
| 316 void PluginReverseInterface::OpenManifestEntryAsync( |
| 317 const nacl::string& entry_key, |
| 318 struct NaClFileInfo* info, |
| 319 const pp::CompletionCallback& callback) { |
| 320 bool op_complete = false; |
| 321 OpenManifestEntryResource to_open( |
| 322 entry_key, info, &op_complete, callback); |
| 323 OpenManifestEntry_MainThreadContinuation(&to_open, PP_OK); |
| 324 } |
| 325 |
253 // Transfer point from OpenManifestEntry() which runs on the main thread | 326 // Transfer point from OpenManifestEntry() which runs on the main thread |
254 // (Some PPAPI actions -- like StreamAsFile -- can only run on the main thread). | 327 // (Some PPAPI actions -- like StreamAsFile -- can only run on the main thread). |
255 // OpenManifestEntry() is waiting on a condvar for this continuation to | 328 // OpenManifestEntry() is waiting on a condvar for this continuation to |
256 // complete. We Broadcast and awaken OpenManifestEntry() whenever we are done | 329 // complete. We Broadcast and awaken OpenManifestEntry() whenever we are done |
257 // either here, or in a later MainThreadContinuation step, if there are | 330 // either here, or in a later MainThreadContinuation step, if there are |
258 // multiple steps. | 331 // multiple steps. |
259 void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation( | 332 void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation( |
260 OpenManifestEntryResource* p, | 333 OpenManifestEntryResource* p, |
261 int32_t err) { | 334 int32_t err) { |
262 UNREFERENCED_PARAMETER(err); | 335 UNREFERENCED_PARAMETER(err); |
263 // CallOnMainThread continuations always called with err == PP_OK. | 336 // CallOnMainThread continuations always called with err == PP_OK. |
264 | 337 |
265 NaClLog(4, "Entered OpenManifestEntry_MainThreadContinuation\n"); | 338 NaClLog(4, "Entered OpenManifestEntry_MainThreadContinuation\n"); |
266 | 339 |
267 std::string mapped_url; | 340 std::string mapped_url; |
268 PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, 2}; | 341 PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, 2}; |
269 ErrorInfo error_info; | 342 ErrorInfo error_info; |
270 if (!manifest_->ResolveKey(p->url, &mapped_url, | 343 if (!manifest_->ResolveKey(p->url, &mapped_url, |
271 &pnacl_options, &error_info)) { | 344 &pnacl_options, &error_info)) { |
272 NaClLog(4, "OpenManifestEntry_MainThreadContinuation: ResolveKey failed\n"); | 345 NaClLog(4, "OpenManifestEntry_MainThreadContinuation: ResolveKey failed\n"); |
273 NaClLog(4, | 346 NaClLog(4, |
274 "Error code %d, string %s\n", | 347 "Error code %d, string %s\n", |
275 error_info.error_code(), | 348 error_info.error_code(), |
276 error_info.message().c_str()); | 349 error_info.message().c_str()); |
277 // Failed, and error_info has the details on what happened. Wake | 350 // Failed, and error_info has the details on what happened. Wake |
278 // up requesting thread -- we are done. | 351 // up requesting thread -- we are done. |
279 nacl::MutexLocker take(&mu_); | 352 { |
280 *p->op_complete_ptr = true; // done... | 353 nacl::MutexLocker take(&mu_); |
281 p->file_info->desc = -1; // but failed. | 354 *p->op_complete_ptr = true; // done... |
282 NaClXCondVarBroadcast(&cv_); | 355 p->file_info->desc = -1; // but failed. |
| 356 NaClXCondVarBroadcast(&cv_); |
| 357 } |
| 358 if (p->callback.pp_completion_callback().func) |
| 359 p->callback.RunAndClear(PP_OK); |
283 return; | 360 return; |
284 } | 361 } |
285 NaClLog(4, | 362 NaClLog(4, |
286 "OpenManifestEntry_MainThreadContinuation: " | 363 "OpenManifestEntry_MainThreadContinuation: " |
287 "ResolveKey: %s -> %s (pnacl_translate(%d))\n", | 364 "ResolveKey: %s -> %s (pnacl_translate(%d))\n", |
288 p->url.c_str(), mapped_url.c_str(), pnacl_options.translate); | 365 p->url.c_str(), mapped_url.c_str(), pnacl_options.translate); |
289 | 366 |
290 if (pnacl_options.translate) { | 367 if (pnacl_options.translate) { |
291 // Requires PNaCl translation, but that's not supported. | 368 // Requires PNaCl translation, but that's not supported. |
292 NaClLog(4, | 369 NaClLog(4, |
293 "OpenManifestEntry_MainThreadContinuation: " | 370 "OpenManifestEntry_MainThreadContinuation: " |
294 "Requires PNaCl translation -- not supported\n"); | 371 "Requires PNaCl translation -- not supported\n"); |
295 nacl::MutexLocker take(&mu_); | 372 { |
296 *p->op_complete_ptr = true; // done... | 373 nacl::MutexLocker take(&mu_); |
297 p->file_info->desc = -1; // but failed. | 374 *p->op_complete_ptr = true; // done... |
298 NaClXCondVarBroadcast(&cv_); | 375 p->file_info->desc = -1; // but failed. |
| 376 NaClXCondVarBroadcast(&cv_); |
| 377 } |
| 378 if (p->callback.pp_completion_callback().func) |
| 379 p->callback.RunAndClear(PP_OK); |
299 return; | 380 return; |
300 } | 381 } |
301 | 382 |
302 if (PnaclUrls::IsPnaclComponent(mapped_url)) { | 383 if (PnaclUrls::IsPnaclComponent(mapped_url)) { |
303 // Special PNaCl support files, that are installed on the | 384 // Special PNaCl support files, that are installed on the |
304 // user machine. | 385 // user machine. |
305 int32_t fd = PnaclResources::GetPnaclFD( | 386 int32_t fd = PnaclResources::GetPnaclFD( |
306 plugin_, | 387 plugin_, |
307 PnaclUrls::PnaclComponentURLToFilename(mapped_url).c_str()); | 388 PnaclUrls::PnaclComponentURLToFilename(mapped_url).c_str()); |
308 if (fd < 0) { | 389 if (fd < 0) { |
309 // We checked earlier if the pnacl component wasn't installed | 390 // We checked earlier if the pnacl component wasn't installed |
310 // yet, so this shouldn't happen. At this point, we can't do much | 391 // yet, so this shouldn't happen. At this point, we can't do much |
311 // anymore, so just continue with an invalid fd. | 392 // anymore, so just continue with an invalid fd. |
312 NaClLog(4, | 393 NaClLog(4, |
313 "OpenManifestEntry_MainThreadContinuation: " | 394 "OpenManifestEntry_MainThreadContinuation: " |
314 "GetReadonlyPnaclFd failed\n"); | 395 "GetReadonlyPnaclFd failed\n"); |
315 } | 396 } |
316 nacl::MutexLocker take(&mu_); | 397 { |
317 *p->op_complete_ptr = true; // done! | 398 nacl::MutexLocker take(&mu_); |
318 // TODO(ncbray): enable the fast loading and validation paths for this | 399 *p->op_complete_ptr = true; // done! |
319 // type of file. | 400 // TODO(ncbray): enable the fast loading and validation paths for this |
320 p->file_info->desc = fd; | 401 // type of file. |
321 NaClXCondVarBroadcast(&cv_); | 402 p->file_info->desc = fd; |
| 403 NaClXCondVarBroadcast(&cv_); |
| 404 } |
322 NaClLog(4, | 405 NaClLog(4, |
323 "OpenManifestEntry_MainThreadContinuation: GetPnaclFd okay\n"); | 406 "OpenManifestEntry_MainThreadContinuation: GetPnaclFd okay\n"); |
| 407 if (p->callback.pp_completion_callback().func) |
| 408 p->callback.RunAndClear(PP_OK); |
324 return; | 409 return; |
325 } | 410 } |
326 | 411 |
327 // Hereafter, normal files. | 412 // Hereafter, normal files. |
328 | 413 |
329 // Because p is owned by the callback of this invocation, so it is necessary | 414 // Because p is owned by the callback of this invocation, so it is necessary |
330 // to create another instance. | 415 // to create another instance. |
331 OpenManifestEntryResource* open_cont = new OpenManifestEntryResource(*p); | 416 OpenManifestEntryResource* open_cont = new OpenManifestEntryResource(*p); |
332 open_cont->url = mapped_url; | 417 open_cont->url = mapped_url; |
| 418 // Callback is now delegated from p to open_cont. So, here we manually clear |
| 419 // complete callback. |
| 420 p->callback = pp::CompletionCallback(); |
333 pp::CompletionCallback stream_cc = WeakRefNewCallback( | 421 pp::CompletionCallback stream_cc = WeakRefNewCallback( |
334 anchor_, | 422 anchor_, |
335 this, | 423 this, |
336 &PluginReverseInterface::StreamAsFile_MainThreadContinuation, | 424 &PluginReverseInterface::StreamAsFile_MainThreadContinuation, |
337 open_cont); | 425 open_cont); |
338 | 426 |
339 if (!plugin_->StreamAsFile(mapped_url, stream_cc)) { | 427 if (!plugin_->StreamAsFile(mapped_url, stream_cc)) { |
340 NaClLog(4, | 428 NaClLog(4, |
341 "OpenManifestEntry_MainThreadContinuation: " | 429 "OpenManifestEntry_MainThreadContinuation: " |
342 "StreamAsFile failed\n"); | 430 "StreamAsFile failed\n"); |
343 // Here, StreamAsFile is failed and stream_cc is not called. | 431 // Here, StreamAsFile is failed and stream_cc is not called. |
344 // However, open_cont will be released only by the invocation. | 432 // However, open_cont will be released only by the invocation. |
345 // So, we manually call it here with error. | 433 // So, we manually call it here with error. |
346 stream_cc.Run(PP_ERROR_FAILED); | 434 stream_cc.Run(PP_ERROR_FAILED); |
347 return; | 435 return; |
348 } | 436 } |
349 | 437 |
350 NaClLog(4, "OpenManifestEntry_MainThreadContinuation: StreamAsFile okay\n"); | 438 NaClLog(4, "OpenManifestEntry_MainThreadContinuation: StreamAsFile okay\n"); |
351 // p is deleted automatically | 439 // p is deleted automatically |
352 } | 440 } |
353 | 441 |
354 void PluginReverseInterface::StreamAsFile_MainThreadContinuation( | 442 void PluginReverseInterface::StreamAsFile_MainThreadContinuation( |
355 OpenManifestEntryResource* p, | 443 OpenManifestEntryResource* p, |
356 int32_t result) { | 444 int32_t result) { |
357 NaClLog(4, | 445 NaClLog(4, |
358 "Entered StreamAsFile_MainThreadContinuation\n"); | 446 "Entered StreamAsFile_MainThreadContinuation\n"); |
359 | 447 |
360 nacl::MutexLocker take(&mu_); | 448 { |
361 if (result == PP_OK) { | 449 nacl::MutexLocker take(&mu_); |
362 NaClLog(4, "StreamAsFile_MainThreadContinuation: GetFileInfo(%s)\n", | 450 if (result == PP_OK) { |
363 p->url.c_str()); | 451 NaClLog(4, "StreamAsFile_MainThreadContinuation: GetFileInfo(%s)\n", |
364 *p->file_info = plugin_->GetFileInfo(p->url); | 452 p->url.c_str()); |
| 453 *p->file_info = plugin_->GetFileInfo(p->url); |
365 | 454 |
366 NaClLog(4, | 455 NaClLog(4, |
367 "StreamAsFile_MainThreadContinuation: PP_OK, desc %d\n", | 456 "StreamAsFile_MainThreadContinuation: PP_OK, desc %d\n", |
368 p->file_info->desc); | 457 p->file_info->desc); |
369 } else { | 458 } else { |
370 NaClLog(4, | 459 NaClLog( |
371 "StreamAsFile_MainThreadContinuation: !PP_OK, setting desc -1\n"); | 460 4, |
372 p->file_info->desc = -1; | 461 "StreamAsFile_MainThreadContinuation: !PP_OK, setting desc -1\n"); |
| 462 p->file_info->desc = -1; |
| 463 } |
| 464 *p->op_complete_ptr = true; |
| 465 NaClXCondVarBroadcast(&cv_); |
373 } | 466 } |
374 *p->op_complete_ptr = true; | 467 if (p->callback.pp_completion_callback().func) |
375 NaClXCondVarBroadcast(&cv_); | 468 p->callback.RunAndClear(PP_OK); |
376 } | 469 } |
377 | 470 |
378 bool PluginReverseInterface::CloseManifestEntry(int32_t desc) { | 471 bool PluginReverseInterface::CloseManifestEntry(int32_t desc) { |
379 bool op_complete = false; | 472 bool op_complete = false; |
380 bool op_result; | 473 bool op_result; |
381 CloseManifestEntryResource* to_close = | 474 CloseManifestEntryResource* to_close = |
382 new CloseManifestEntryResource(desc, &op_complete, &op_result); | 475 new CloseManifestEntryResource(desc, &op_complete, &op_result); |
383 | 476 |
384 plugin::WeakRefCallOnMainThread( | 477 plugin::WeakRefCallOnMainThread( |
385 anchor_, | 478 anchor_, |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 | 894 |
802 nacl::string ServiceRuntime::GetCrashLogOutput() { | 895 nacl::string ServiceRuntime::GetCrashLogOutput() { |
803 if (NULL != subprocess_.get()) { | 896 if (NULL != subprocess_.get()) { |
804 return subprocess_->GetCrashLogOutput(); | 897 return subprocess_->GetCrashLogOutput(); |
805 } else { | 898 } else { |
806 return std::string(); | 899 return std::string(); |
807 } | 900 } |
808 } | 901 } |
809 | 902 |
810 } // namespace plugin | 903 } // namespace plugin |
OLD | NEW |