blob: b06a706ae8898758df19b96ede9d25c29c9c5dc9 [file] [log] [blame]
/* -*- c++ -*- */
/*
* Copyright (c) 2012 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// A class containing information regarding a socket connection to a
// service runtime instance.
#ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
#define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
#include <set>
#include "native_client/src/include/nacl_macros.h"
#include "native_client/src/include/nacl_scoped_ptr.h"
#include "native_client/src/include/nacl_string.h"
#include "native_client/src/shared/platform/nacl_sync.h"
#include "native_client/src/shared/srpc/nacl_srpc.h"
#include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
#include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
#include "native_client/src/trusted/reverse_service/reverse_service.h"
#include "native_client/src/trusted/weak_ref/weak_ref.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/native_client/src/trusted/plugin/utility.h"
struct NaClFileInfo;
namespace nacl {
class DescWrapper;
} // namespace
namespace pp {
class FileIO;
} // namespace
namespace plugin {
class ErrorInfo;
class Manifest;
class Plugin;
class PnaclCoordinator;
class SrpcClient;
class ServiceRuntime;
// Struct of params used by StartSelLdr. Use a struct so that callback
// creation templates aren't overwhelmed with too many parameters.
struct SelLdrStartParams {
SelLdrStartParams(const nacl::string& url,
ErrorInfo* error_info,
bool uses_irt,
bool uses_ppapi,
bool enable_dev_interfaces,
bool enable_dyncode_syscalls,
bool enable_exception_handling,
bool enable_crash_throttling)
: url(url),
error_info(error_info),
uses_irt(uses_irt),
uses_ppapi(uses_ppapi),
enable_dev_interfaces(enable_dev_interfaces),
enable_dyncode_syscalls(enable_dyncode_syscalls),
enable_exception_handling(enable_exception_handling),
enable_crash_throttling(enable_crash_throttling) {
}
nacl::string url;
ErrorInfo* error_info;
bool uses_irt;
bool uses_ppapi;
bool enable_dev_interfaces;
bool enable_dyncode_syscalls;
bool enable_exception_handling;
bool enable_crash_throttling;
};
// Callback resources are essentially our continuation state.
struct LogToJavaScriptConsoleResource {
public:
explicit LogToJavaScriptConsoleResource(std::string msg)
: message(msg) {}
std::string message;
};
struct PostMessageResource {
public:
explicit PostMessageResource(std::string msg)
: message(msg) {}
std::string message;
};
struct OpenManifestEntryResource {
public:
OpenManifestEntryResource(const std::string& target_url,
struct NaClFileInfo* finfo,
ErrorInfo* infop,
bool* op_complete)
: url(target_url),
file_info(finfo),
error_info(infop),
op_complete_ptr(op_complete) {}
std::string url;
struct NaClFileInfo* file_info;
ErrorInfo* error_info;
bool* op_complete_ptr;
};
struct CloseManifestEntryResource {
public:
CloseManifestEntryResource(int32_t desc_to_close,
bool* op_complete,
bool* op_result)
: desc(desc_to_close),
op_complete_ptr(op_complete),
op_result_ptr(op_result) {}
int32_t desc;
bool* op_complete_ptr;
bool* op_result_ptr;
};
struct QuotaRequest {
public:
QuotaRequest(PP_Resource pp_resource,
int64_t start_offset,
int64_t quota_bytes_requested,
int64_t* quota_bytes_granted,
bool* op_complete)
: resource(pp_resource),
offset(start_offset),
bytes_requested(quota_bytes_requested),
bytes_granted(quota_bytes_granted),
op_complete_ptr(op_complete) { }
PP_Resource resource;
int64_t offset;
int64_t bytes_requested;
int64_t* bytes_granted;
bool* op_complete_ptr;
};
// Do not invoke from the main thread, since the main methods will
// invoke CallOnMainThread and then wait on a condvar for the task to
// complete: if invoked from the main thread, the main method not
// returning (and thus unblocking the main thread) means that the
// main-thread continuation methods will never get called, and thus
// we'd get a deadlock.
class PluginReverseInterface: public nacl::ReverseInterface {
public:
PluginReverseInterface(nacl::WeakRefAnchor* anchor,
Plugin* plugin,
const Manifest* manifest,
ServiceRuntime* service_runtime,
pp::CompletionCallback init_done_cb,
pp::CompletionCallback crash_cb);
virtual ~PluginReverseInterface();
void ShutDown();
virtual void Log(nacl::string message);
virtual void DoPostMessage(nacl::string message);
virtual void StartupInitializationComplete();
virtual bool EnumerateManifestKeys(std::set<nacl::string>* out_keys);
virtual bool OpenManifestEntry(nacl::string url_key,
struct NaClFileInfo *info);
virtual bool CloseManifestEntry(int32_t desc);
virtual void ReportCrash();
virtual void ReportExitStatus(int exit_status);
virtual int64_t RequestQuotaForWrite(nacl::string file_id,
int64_t offset,
int64_t bytes_to_write);
void AddQuotaManagedFile(const nacl::string& file_id,
const pp::FileIO& file_io);
void AddTempQuotaManagedFile(const nacl::string& file_id);
protected:
virtual void Log_MainThreadContinuation(LogToJavaScriptConsoleResource* p,
int32_t err);
virtual void PostMessage_MainThreadContinuation(PostMessageResource* p,
int32_t err);
virtual void OpenManifestEntry_MainThreadContinuation(
OpenManifestEntryResource* p,
int32_t err);
virtual void StreamAsFile_MainThreadContinuation(
OpenManifestEntryResource* p,
int32_t result);
virtual void BitcodeTranslate_MainThreadContinuation(
OpenManifestEntryResource* p,
int32_t result);
virtual void CloseManifestEntry_MainThreadContinuation(
CloseManifestEntryResource* cls,
int32_t err);
private:
nacl::WeakRefAnchor* anchor_; // holds a ref
Plugin* plugin_; // value may be copied, but should be used only in
// main thread in WeakRef-protected callbacks.
const Manifest* manifest_;
ServiceRuntime* service_runtime_;
NaClMutex mu_;
NaClCondVar cv_;
std::set<int64_t> quota_files_;
bool shutting_down_;
nacl::scoped_ptr<PnaclCoordinator> pnacl_coordinator_;
pp::CompletionCallback init_done_cb_;
pp::CompletionCallback crash_cb_;
};
// ServiceRuntime abstracts a NativeClient sel_ldr instance.
class ServiceRuntime {
public:
// TODO(sehr): This class should also implement factory methods, using the
// Start method below.
ServiceRuntime(Plugin* plugin,
const Manifest* manifest,
bool should_report_uma,
pp::CompletionCallback init_done_cb,
pp::CompletionCallback crash_cb);
// The destructor terminates the sel_ldr process.
~ServiceRuntime();
// Spawn the sel_ldr instance. On success, returns true.
// On failure, returns false and |error_string| is set to something
// describing the error.
bool StartSelLdr(const SelLdrStartParams& params);
// If starting sel_ldr from a background thread, wait for sel_ldr to
// actually start.
void WaitForSelLdrStart();
// Signal to waiting threads that StartSelLdr is complete.
// Done externally, in case external users want to write to shared
// memory that is yet to be fenced.
void SignalStartSelLdrDone();
// Establish an SrpcClient to the sel_ldr instance and load the nexe.
// The nexe to be started is passed through |nacl_file_desc|.
// On success, returns true. On failure, returns false and |error_string|
// is set to something describing the error.
bool LoadNexeAndStart(nacl::DescWrapper* nacl_file_desc,
ErrorInfo* error_info,
const pp::CompletionCallback& crash_cb);
// Starts the application channel to the nexe.
SrpcClient* SetupAppChannel();
bool Log(int severity, const nacl::string& msg);
Plugin* plugin() const { return plugin_; }
void Shutdown();
// exit_status is -1 when invalid; when we set it, we will ensure
// that it is non-negative (the portion of the exit status from the
// nexe that is transferred is the low 8 bits of the argument to the
// exit syscall).
int exit_status(); // const, but grabs mutex etc.
void set_exit_status(int exit_status);
nacl::string GetCrashLogOutput();
// To establish quota callbacks the pnacl coordinator needs to communicate
// with the reverse interface.
PluginReverseInterface* rev_interface() const { return rev_interface_; }
private:
NACL_DISALLOW_COPY_AND_ASSIGN(ServiceRuntime);
bool InitCommunication(nacl::DescWrapper* shm, ErrorInfo* error_info);
NaClSrpcChannel command_channel_;
Plugin* plugin_;
bool should_report_uma_;
nacl::ReverseService* reverse_service_;
nacl::scoped_ptr<nacl::SelLdrLauncherBase> subprocess_;
nacl::WeakRefAnchor* anchor_;
PluginReverseInterface* rev_interface_;
// Mutex to protect exit_status_.
// Also, in conjunction with cond_ it is used to signal when
// StartSelLdr is complete with either success or error.
NaClMutex mu_;
NaClCondVar cond_;
int exit_status_;
bool start_sel_ldr_done_;
};
} // namespace plugin
#endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_