15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define NACL_LOG_MODULE_NAME "Plugin_ServiceRuntime"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/service_runtime.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/include/portability_io.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/include/portability_string.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/include/nacl_macros.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/include/nacl_scoped_ptr.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/shared/platform/nacl_check.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/shared/platform/nacl_log.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/shared/platform/nacl_sync.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/shared/platform/nacl_sync_checked.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/shared/platform/nacl_sync_raii.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "native_client/src/public/imc_types.h"
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "native_client/src/public/nacl_file_info.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/trusted/service_runtime/nacl_error_code.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/core.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/completion_callback.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/plugin.h"
37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/plugin_error.h"
38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/pnacl_resources.h"
39ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h"
40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/srpc_client.h"
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ppapi/native_client/src/trusted/plugin/utility.h"
42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/weak_ref/call_on_main_thread.h"
43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace plugin {
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)OpenManifestEntryResource::~OpenManifestEntryResource() {
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginReverseInterface::PluginReverseInterface(
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nacl::WeakRefAnchor* anchor,
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    PP_Instance pp_instance,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ServiceRuntime* service_runtime,
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    pp::CompletionCallback init_done_cb)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : anchor_(anchor),
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        pp_instance_(pp_instance),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        service_runtime_(service_runtime),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shutting_down_(false),
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        init_done_cb_(init_done_cb) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClXMutexCtor(&mu_);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClXCondVarCtor(&cv_);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginReverseInterface::~PluginReverseInterface() {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClCondVarDtor(&cv_);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClMutexDtor(&mu_);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginReverseInterface::ShutDown() {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClLog(4, "PluginReverseInterface::Shutdown: entered\n");
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nacl::MutexLocker take(&mu_);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shutting_down_ = true;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClXCondVarBroadcast(&cv_);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClLog(4, "PluginReverseInterface::Shutdown: broadcasted, exiting\n");
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PluginReverseInterface::DoPostMessage(std::string message) {
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // This feature is no longer used.
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(teravest): Remove this once this is gone from nacl::ReverseInterface.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginReverseInterface::StartupInitializationComplete() {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClLog(4, "PluginReverseInterface::StartupInitializationComplete\n");
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (init_done_cb_.pp_completion_callback().func != NULL) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NaClLog(4,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "PluginReverseInterface::StartupInitializationComplete:"
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            " invoking CB\n");
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::Module::Get()->core()->CallOnMainThread(0, init_done_cb_, PP_OK);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NaClLog(1,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "PluginReverseInterface::StartupInitializationComplete:"
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            " init_done_cb_ not valid, skipping.\n");
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(bsy): OpenManifestEntry should use the manifest to ResolveKey
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and invoke StreamAsFile with a completion callback that invokes
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GetPOSIXFileDesc.
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool PluginReverseInterface::OpenManifestEntry(std::string url_key,
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                               struct NaClFileInfo* info) {
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // This method should only ever be called from the PNaCl translator, as the
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // IRT is not available there.
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(teravest): Remove support for OpenManifestEntry here once
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // crbug.com/302078 is resolved.
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (service_runtime_->main_service_runtime()) {
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NaClLog(LOG_ERROR,
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "OpenManifestEntry should only be used by PNaCl translator.\n");
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool op_complete = false;  // NB: mu_ and cv_ also controls access to this!
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The to_open object is owned by the weak ref callback. Because this function
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // waits for the callback to finish, the to_open object will be deallocated on
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // the main thread before this function can return. The pointers it contains
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // to stack variables will not leak.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenManifestEntryResource* to_open =
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new OpenManifestEntryResource(url_key, info, &op_complete);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(to_open != NULL);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClLog(4, "PluginReverseInterface::OpenManifestEntry: %s\n",
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          url_key.c_str());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This assumes we are not on the main thread.  If false, we deadlock.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  plugin::WeakRefCallOnMainThread(
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      anchor_,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &plugin::PluginReverseInterface::OpenManifestEntry_MainThreadContinuation,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      to_open);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClLog(4,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "PluginReverseInterface::OpenManifestEntry:"
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          " waiting on main thread\n");
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nacl::MutexLocker take(&mu_);
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    while (!shutting_down_ && !op_complete)
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NaClXCondVarWait(&cv_, &mu_);
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NaClLog(4, "PluginReverseInterface::OpenManifestEntry: done!\n");
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (shutting_down_) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NaClLog(4,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "PluginReverseInterface::OpenManifestEntry:"
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              " plugin is shutting down\n");
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return false;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // info->desc has the returned descriptor if successful, else -1.
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The caller is responsible for not closing info->desc.  If it is
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // closed prematurely, then another open could re-use the OS
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptor, confusing the opened_ map.  If the caller is going to
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // want to make a NaClDesc object and transfer it etc., then the
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // caller should DUP the descriptor (but remember the original
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value) for use by the NaClDesc object, which closes when the
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // object is destroyed.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClLog(4,
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          "PluginReverseInterface::OpenManifestEntry: info->desc = %d\n",
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          info->desc);
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (info->desc == -1) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(bsy,ncbray): what else should we do with the error?  This
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is a runtime error that may simply be a programming error in
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the untrusted code, or it may be something else wrong w/ the
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // manifest.
16123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    NaClLog(4, "OpenManifestEntry: failed for key %s", url_key.c_str());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Transfer point from OpenManifestEntry() which runs on the main thread
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (Some PPAPI actions -- like StreamAsFile -- can only run on the main thread).
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OpenManifestEntry() is waiting on a condvar for this continuation to
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// complete.  We Broadcast and awaken OpenManifestEntry() whenever we are done
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// either here, or in a later MainThreadContinuation step, if there are
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multiple steps.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation(
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenManifestEntryResource* p,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t err) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(err);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CallOnMainThread continuations always called with err == PP_OK.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClLog(4, "Entered OpenManifestEntry_MainThreadContinuation\n");
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Because p is owned by the callback of this invocation, so it is necessary
181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // to create another instance.
182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  OpenManifestEntryResource* open_cont = new OpenManifestEntryResource(*p);
183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  pp::CompletionCallback stream_cc = WeakRefNewCallback(
184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      anchor_,
185effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      this,
186effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      &PluginReverseInterface::StreamAsFile_MainThreadContinuation,
187effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      open_cont);
188effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GetNaClInterface()->OpenManifestEntry(
190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      pp_instance_,
191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PP_FromBool(!service_runtime_->main_service_runtime()),
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      p->url.c_str(),
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      &open_cont->pp_file_info,
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      stream_cc.pp_completion_callback());
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // p is deleted automatically.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginReverseInterface::StreamAsFile_MainThreadContinuation(
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenManifestEntryResource* p,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result) {
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NaClLog(4, "Entered StreamAsFile_MainThreadContinuation\n");
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  {
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    nacl::MutexLocker take(&mu_);
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (result == PP_OK) {
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // We downloaded this file to temporary storage for this plugin; it's
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // reasonable to provide a file descriptor with write access.
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      p->file_info->desc = ConvertFileDescriptor(p->pp_file_info.handle, false);
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      p->file_info->file_token.lo = p->pp_file_info.token_lo;
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      p->file_info->file_token.hi = p->pp_file_info.token_hi;
210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      NaClLog(4,
211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)              "StreamAsFile_MainThreadContinuation: PP_OK, desc %d\n",
212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)              p->file_info->desc);
213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      NaClLog(
215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          4,
216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          "StreamAsFile_MainThreadContinuation: !PP_OK, setting desc -1\n");
217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      p->file_info->desc = -1;
218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    *p->op_complete_ptr = true;
220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    NaClXCondVarBroadcast(&cv_);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginReverseInterface::ReportCrash() {
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // This is now handled through Chromium IPC.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginReverseInterface::ReportExitStatus(int exit_status) {
22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // We do nothing here; reporting exit status is handled through a separate
23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // embedder interface.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64_t PluginReverseInterface::RequestQuotaForWrite(
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string file_id, int64_t offset, int64_t bytes_to_write) {
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return bytes_to_write;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceRuntime::ServiceRuntime(Plugin* plugin,
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               PP_Instance pp_instance,
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               bool main_service_runtime,
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               bool uses_nonsfi_mode,
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               pp::CompletionCallback init_done_cb)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : plugin_(plugin),
244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      pp_instance_(pp_instance),
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      main_service_runtime_(main_service_runtime),
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      uses_nonsfi_mode_(uses_nonsfi_mode),
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reverse_service_(NULL),
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      anchor_(new nacl::WeakRefAnchor()),
249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      rev_interface_(new PluginReverseInterface(anchor_, pp_instance, this,
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                init_done_cb)),
25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      start_sel_ldr_done_(false),
252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      start_nexe_done_(false),
253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      nexe_started_ok_(false),
254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      bootstrap_channel_(NACL_INVALID_HANDLE) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClSrpcChannelInitialize(&command_channel_);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClXMutexCtor(&mu_);
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NaClXCondVarCtor(&cond_);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ServiceRuntime::SetupCommandChannel() {
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NaClLog(4, "ServiceRuntime::SetupCommand (this=%p, subprocess=%p)\n",
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          static_cast<void*>(this),
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          static_cast<void*>(subprocess_.get()));
264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Set up the bootstrap channel in our subprocess so that we can establish
265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // SRPC.
266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  subprocess_->set_channel(bootstrap_channel_);
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (uses_nonsfi_mode_) {
269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // In non-SFI mode, no SRPC is used. Just skips and returns success.
270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return true;
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!subprocess_->SetupCommand(&command_channel_)) {
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ErrorInfo error_info;
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    error_info.SetReport(PP_NACL_ERROR_SEL_LDR_COMMUNICATION_CMD_CHANNEL,
276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         "ServiceRuntime: command channel creation failed");
277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReportLoadError(error_info);
278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ServiceRuntime::InitReverseService() {
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (uses_nonsfi_mode_) {
2850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // In non-SFI mode, no reverse service is set up. Just returns success.
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return true;
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Hook up the reverse service channel.  We are the IMC client, but
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // provide SRPC service.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClDesc* out_conn_cap;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClSrpcResultCodes rpc_result =
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NaClSrpcInvokeBySignature(&command_channel_,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                "reverse_setup::h",
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                &out_conn_cap);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NACL_SRPC_RESULT_OK != rpc_result) {
298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorInfo error_info;
299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_info.SetReport(PP_NACL_ERROR_SEL_LDR_COMMUNICATION_REV_SETUP,
300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         "ServiceRuntime: reverse setup rpc failed");
301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReportLoadError(error_info);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  Get connection capability to service runtime where the IMC
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  server/SRPC client is waiting for a rendezvous.
306bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  NaClLog(4, "ServiceRuntime: got 0x%" NACL_PRIxPTR "\n",
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          (uintptr_t) out_conn_cap);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nacl::DescWrapper* conn_cap = plugin_->wrapper_factory()->MakeGenericCleanup(
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out_conn_cap);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (conn_cap == NULL) {
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorInfo error_info;
312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_info.SetReport(PP_NACL_ERROR_SEL_LDR_COMMUNICATION_WRAPPER,
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         "ServiceRuntime: wrapper allocation failure");
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReportLoadError(error_info);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out_conn_cap = NULL;  // ownership passed
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NaClLog(4, "ServiceRuntime::InitReverseService: starting reverse service\n");
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reverse_service_ = new nacl::ReverseService(conn_cap, rev_interface_->Ref());
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!reverse_service_->Start()) {
321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorInfo error_info;
322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_info.SetReport(PP_NACL_ERROR_SEL_LDR_COMMUNICATION_REV_SERVICE,
323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         "ServiceRuntime: starting reverse services failed");
324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReportLoadError(error_info);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ServiceRuntime::StartModule() {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // start the module.  otherwise we cannot connect for multimedia
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // subsystem since that is handled by user-level code (not secure!)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in libsrpc.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int load_status = -1;
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (uses_nonsfi_mode_) {
336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // In non-SFI mode, we don't need to call start_module SRPC to launch
337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // the plugin.
338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    load_status = LOAD_OK;
339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NaClSrpcResultCodes rpc_result =
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        NaClSrpcInvokeBySignature(&command_channel_,
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  "start_module::i",
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  &load_status);
344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (NACL_SRPC_RESULT_OK != rpc_result) {
346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ErrorInfo error_info;
347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      error_info.SetReport(PP_NACL_ERROR_SEL_LDR_START_MODULE,
348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           "ServiceRuntime: could not start nacl module");
349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ReportLoadError(error_info);
350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return false;
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NaClLog(4, "ServiceRuntime::StartModule (load_status=%d)\n", load_status);
35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (main_service_runtime_) {
35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (load_status < 0 || load_status > NACL_ERROR_CODE_MAX)
35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      load_status = LOAD_STATUS_UNKNOWN;
358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetNaClInterface()->ReportSelLdrStatus(pp_instance_,
35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                           load_status,
36046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                           NACL_ERROR_CODE_MAX);
36146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (LOAD_OK != load_status) {
364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorInfo error_info;
365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_info.SetReport(
366116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        PP_NACL_ERROR_SEL_LDR_START_STATUS,
367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        NaClErrorString(static_cast<NaClErrorCode>(load_status)));
368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReportLoadError(error_info);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ServiceRuntime::StartSelLdr(const SelLdrStartParams& params,
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 pp::CompletionCallback callback) {
3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NaClLog(4, "ServiceRuntime::Start\n");
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nacl::scoped_ptr<SelLdrLauncherChrome>
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tmp_subprocess(new SelLdrLauncherChrome());
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == tmp_subprocess.get()) {
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NaClLog(LOG_ERROR, "ServiceRuntime::Start (subprocess create failed)\n");
382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ErrorInfo error_info;
383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error_info.SetReport(
384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        PP_NACL_ERROR_SEL_LDR_CREATE_LAUNCHER,
385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        "ServiceRuntime: failed to create sel_ldr launcher");
386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReportLoadError(error_info);
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp::Module::Get()->core()->CallOnMainThread(0, callback, PP_ERROR_FAILED);
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
39146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool enable_dev_interfaces =
392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GetNaClInterface()->DevInterfacesEnabled(pp_instance_);
393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GetNaClInterface()->LaunchSelLdr(
395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      pp_instance_,
396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PP_FromBool(main_service_runtime_),
397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      params.url.c_str(),
398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      &params.file_info,
399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PP_FromBool(params.uses_irt),
400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PP_FromBool(params.uses_ppapi),
401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PP_FromBool(uses_nonsfi_mode_),
402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PP_FromBool(enable_dev_interfaces),
403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PP_FromBool(params.enable_dyncode_syscalls),
404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PP_FromBool(params.enable_exception_handling),
405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PP_FromBool(params.enable_crash_throttling),
406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      &bootstrap_channel_,
407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      callback.pp_completion_callback());
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subprocess_.reset(tmp_subprocess.release());
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
411a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool ServiceRuntime::WaitForSelLdrStart() {
412a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Time to wait on condvar (for browser to create a new sel_ldr process on
413a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // our behalf). Use 6 seconds to be *fairly* conservative.
414a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  //
415a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // On surfaway, the CallOnMainThread above may never get scheduled
416a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // to unblock this condvar, or the IPC reply from the browser to renderer
417a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // might get canceled/dropped. However, it is currently important to
418a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // avoid waiting indefinitely because ~PnaclCoordinator will attempt to
419a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // join() the PnaclTranslateThread, and the PnaclTranslateThread is waiting
420a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // for the signal before exiting.
421a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  static int64_t const kWaitTimeMicrosecs = 6 * NACL_MICROS_PER_UNIT;
422a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int64_t left_to_wait = kWaitTimeMicrosecs;
423a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int64_t deadline = NaClGetTimeOfDayMicroseconds() + left_to_wait;
4247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  nacl::MutexLocker take(&mu_);
425a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  while(!start_sel_ldr_done_ && left_to_wait > 0) {
426a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    struct nacl_abi_timespec left_timespec;
427a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    left_timespec.tv_sec = left_to_wait / NACL_MICROS_PER_UNIT;
428a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    left_timespec.tv_nsec =
429a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        (left_to_wait % NACL_MICROS_PER_UNIT) * NACL_NANOS_PER_MICRO;
430a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    NaClXCondVarTimedWaitRelative(&cond_, &mu_, &left_timespec);
431a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    int64_t now = NaClGetTimeOfDayMicroseconds();
432a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    left_to_wait = deadline - now;
4337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
434a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return start_sel_ldr_done_;
4357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
4367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ServiceRuntime::SignalStartSelLdrDone() {
4387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  nacl::MutexLocker take(&mu_);
4397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  start_sel_ldr_done_ = true;
4407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NaClXCondVarSignal(&cond_);
4417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
4427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
443116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool ServiceRuntime::WaitForNexeStart() {
44446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  nacl::MutexLocker take(&mu_);
445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  while (!start_nexe_done_)
44646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    NaClXCondVarWait(&cond_, &mu_);
447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return nexe_started_ok_;
44846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
44946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
450116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ServiceRuntime::SignalNexeStarted(bool ok) {
45146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  nacl::MutexLocker take(&mu_);
452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  start_nexe_done_ = true;
453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  nexe_started_ok_ = ok;
45446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  NaClXCondVarSignal(&cond_);
45546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
45646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ServiceRuntime::StartNexe() {
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool ok = StartNexeInternal();
459116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (ok) {
4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NaClLog(4, "ServiceRuntime::StartNexe (success)\n");
461116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReapLogs();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // This only matters if a background thread is waiting, but we signal in all
465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // cases to simplify the code.
466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SignalNexeStarted(ok);
467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool ServiceRuntime::StartNexeInternal() {
4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!SetupCommandChannel())
471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!InitReverseService())
473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return StartModule();
475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
477116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ServiceRuntime::ReapLogs() {
4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(teravest): We should allow the NaCl process to crash itself when a
4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // module fails to start, and remove the call to RemoteLog() here. The
4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // reverse channel is no longer needed for crash reporting.
4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  //
4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The reasoning behind the current code behavior follows:
4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // On a load failure the NaCl process does not crash itself to
484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // avoid a race where the no-more-senders error on the reverse
485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // channel service thread might cause the crash-detection logic to
486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // kick in before the start_module RPC reply has been received. So
4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // we induce a NaCl process crash here.
488116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  RemoteLog(LOG_FATAL, "reap logs\n");
4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(teravest): Release subprocess_ here since it's no longer needed. It
4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // was previously kept around to collect crash log output from the bootstrap
4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // channel.
493116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
494116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
495116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ServiceRuntime::ReportLoadError(const ErrorInfo& error_info) {
496116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (main_service_runtime_) {
497116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    plugin_->ReportLoadError(error_info);
498116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SrpcClient* ServiceRuntime::SetupAppChannel() {
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NaClLog(4, "ServiceRuntime::SetupAppChannel (subprocess_=%p)\n",
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          reinterpret_cast<void*>(subprocess_.get()));
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nacl::DescWrapper* connect_desc = subprocess_->socket_addr()->Connect();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == connect_desc) {
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NaClLog(LOG_ERROR, "ServiceRuntime::SetupAppChannel (connect failed)\n");
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NaClLog(4, "ServiceRuntime::SetupAppChannel (conect_desc=%p)\n",
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            static_cast<void*>(connect_desc));
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SrpcClient* srpc_client = SrpcClient::New(connect_desc);
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NaClLog(4, "ServiceRuntime::SetupAppChannel (srpc_client=%p)\n",
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            static_cast<void*>(srpc_client));
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete connect_desc;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return srpc_client;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ServiceRuntime::RemoteLog(int severity, const std::string& msg) {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClSrpcResultCodes rpc_result =
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NaClSrpcInvokeBySignature(&command_channel_,
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                "log:is:",
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                severity,
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                strdup(msg.c_str()));
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (NACL_SRPC_RESULT_OK == rpc_result);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceRuntime::Shutdown() {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rev_interface_->ShutDown();
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  anchor_->Abandon();
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Abandon callbacks, tell service threads to quit if they were
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // blocked waiting for main thread operations to finish.  Note that
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // some callbacks must still await their completion event, e.g.,
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CallOnMainThread must still wait for the time out, or I/O events
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // must finish, so resources associated with pending events cannot
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be deallocated.
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that this does waitpid() to get rid of any zombie subprocess.
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subprocess_.reset(NULL);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClSrpcDtor(&command_channel_);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // subprocess_ has been shut down, but threads waiting on messages
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the service runtime may not have noticed yet.  The low-level
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NaClSimpleRevService code takes care to refcount the data objects
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that it needs, and reverse_service_ is also refcounted.  We wait
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for the service threads to get their EOF indications.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reverse_service_ != NULL) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reverse_service_->WaitForServiceThreadsToExit();
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reverse_service_->Unref();
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reverse_service_ = NULL;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceRuntime::~ServiceRuntime() {
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NaClLog(4, "ServiceRuntime::~ServiceRuntime (this=%p)\n",
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          static_cast<void*>(this));
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do this just in case Shutdown() was not called.
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subprocess_.reset(NULL);
560cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (reverse_service_ != NULL)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reverse_service_->Unref();
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rev_interface_->Unref();
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  anchor_->Unref();
5667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NaClCondVarDtor(&cond_);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClMutexDtor(&mu_);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace plugin
571