diff options
author | Ben Murdoch <benm@google.com> | 2014-04-24 10:50:13 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2014-04-24 10:50:13 +0100 |
commit | 0529e5d033099cbfc42635f6f6183833b09dff6e (patch) | |
tree | badea60062e611382d8a37e3b0bfda8d69760c2b /ppapi | |
parent | 8346740f6fb555ccbb9b4148ab63402ae8f6e4ca (diff) | |
download | chromium_org-0529e5d033099cbfc42635f6f6183833b09dff6e.tar.gz |
Merge from Chromium at DEPS revision 265802
This commit was generated by merge_to_master.py.
Change-Id: I6fac2dbbce472b18ca943b6e6f247835b0bd6281
Diffstat (limited to 'ppapi')
42 files changed, 803 insertions, 561 deletions
diff --git a/ppapi/api/private/ppb_nacl_private.idl b/ppapi/api/private/ppb_nacl_private.idl index 418310dc2b..4bc02e0749 100644 --- a/ppapi/api/private/ppb_nacl_private.idl +++ b/ppapi/api/private/ppb_nacl_private.idl @@ -133,6 +133,27 @@ enum PP_NaClReadyState { PP_NACL_READY_STATE_DONE = 4 }; +struct PP_PNaClOptions { + PP_Bool translate; + PP_Bool is_debug; + int32_t opt_level; +}; + +/* ManifestService to support irt_open_resource() function. + * All functions of the service should have PP_Bool return value. It represents + * whether the service is still alive or not. Trivially Quit() should always + * return false. However, other functions also can return false. + * Once false is called, as the service has been destructed, all functions + * should never be called afterwords. + */ +interface PP_ManifestService { + /* Called when ManifestService should be destructed. */ + PP_Bool Quit([inout] mem_t user_data); + + /* Called when PPAPI initialization in the NaCl plugin is finished. */ + PP_Bool StartupInitializationComplete([inout] mem_t user_data); +}; + /* PPB_NaCl_Private */ interface PPB_NaCl_Private { /* Launches NaCl's sel_ldr process. Returns PP_EXTERNAL_PLUGIN_OK on success @@ -163,6 +184,8 @@ interface PPB_NaCl_Private { [in] PP_Bool enable_dyncode_syscalls, [in] PP_Bool enable_exception_handling, [in] PP_Bool enable_crash_throttling, + [in] PP_ManifestService manifest_service_interface, + [inout] mem_t manifest_service_user_data, [out] mem_t imc_handle, [out] PP_Var error_message, [in] PP_CompletionCallback callback); @@ -325,17 +348,9 @@ interface PPB_NaCl_Private { /* Returns the NaCl readiness status for this instance. */ PP_NaClReadyState GetNaClReadyState([in] PP_Instance instance); - /* Sets the NaCl readiness status for this instance. */ - void SetNaClReadyState([in] PP_Instance instance, - [in] PP_NaClReadyState ready_state); - /* Returns true if the plugin is an installed app. */ PP_Bool GetIsInstalled([in] PP_Instance instance); - /* Sets whether the plugin is an installed app. */ - void SetIsInstalled([in] PP_Instance instance, - [in] PP_Bool is_installed); - /* Returns the exit status of the plugin process. */ int32_t GetExitStatus([in] PP_Instance instance); @@ -346,13 +361,28 @@ interface PPB_NaCl_Private { /* Logs the message via VLOG. */ void Vlog([in] str_t message); - /* Sets the time the plugin was initialized. */ - void SetInitTime([in] PP_Instance instance); + /* Initializes internal state for a NaCl plugin. */ + void InitializePlugin([in] PP_Instance instance); /* Returns the size of the nexe. */ int64_t GetNexeSize([in] PP_Instance instance); - /* Sets the size of the nexe. */ - void SetNexeSize([in] PP_Instance instance, - [in] int64_t nexe_size); + /* Performs accounting for requesting the NaCl manifest at the given URL. */ + PP_Bool RequestNaClManifest([in] PP_Instance instance, + [in] str_t manifest_url, + [out] PP_Bool is_data_uri); + + PP_Var GetManifestBaseURL([in] PP_Instance instance); + + PP_Bool ResolvesRelativeToPluginBaseUrl([in] PP_Instance instance, + [in] str_t url); + + PP_Var ParseDataURL([in] str_t data_url); + + /* Processes the NaCl manifest once it's been retrieved. + * TODO(teravest): Move the rest of the supporting logic out of the trusted + * plugin. + */ + void ProcessNaClManifest([in] PP_Instance instance, + [in] str_t program_url); }; diff --git a/ppapi/c/private/ppb_nacl_private.h b/ppapi/c/private/ppb_nacl_private.h index 709463e159..ab85b738d7 100644 --- a/ppapi/c/private/ppb_nacl_private.h +++ b/ppapi/c/private/ppb_nacl_private.h @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* From private/ppb_nacl_private.idl modified Tue Apr 15 09:24:03 2014. */ +/* From private/ppb_nacl_private.idl modified Wed Apr 23 12:56:55 2014. */ #ifndef PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ #define PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ @@ -15,6 +15,9 @@ #include "ppapi/c/pp_stdint.h" #include "ppapi/c/pp_var.h" +#define PP_MANIFESTSERVICE_INTERFACE_1_0 "PP_ManifestService;1.0" +#define PP_MANIFESTSERVICE_INTERFACE PP_MANIFESTSERVICE_INTERFACE_1_0 + #define PPB_NACL_PRIVATE_INTERFACE_1_0 "PPB_NaCl_Private;1.0" #define PPB_NACL_PRIVATE_INTERFACE PPB_NACL_PRIVATE_INTERFACE_1_0 @@ -152,9 +155,38 @@ typedef enum { */ /** + * @addtogroup Structs + * @{ + */ +struct PP_PNaClOptions { + PP_Bool translate; + PP_Bool is_debug; + int32_t opt_level; +}; +/** + * @} + */ + +/** * @addtogroup Interfaces * @{ */ +/* ManifestService to support irt_open_resource() function. + * All functions of the service should have PP_Bool return value. It represents + * whether the service is still alive or not. Trivially Quit() should always + * return false. However, other functions also can return false. + * Once false is called, as the service has been destructed, all functions + * should never be called afterwords. + */ +struct PP_ManifestService_1_0 { + /* Called when ManifestService should be destructed. */ + PP_Bool (*Quit)(void* user_data); + /* Called when PPAPI initialization in the NaCl plugin is finished. */ + PP_Bool (*StartupInitializationComplete)(void* user_data); +}; + +typedef struct PP_ManifestService_1_0 PP_ManifestService; + /* PPB_NaCl_Private */ struct PPB_NaCl_Private_1_0 { /* Launches NaCl's sel_ldr process. Returns PP_EXTERNAL_PLUGIN_OK on success @@ -176,18 +208,21 @@ struct PPB_NaCl_Private_1_0 { * the nexe contribute to crash throttling statisics and whether nexe starts * are throttled by crash throttling. */ - void (*LaunchSelLdr)(PP_Instance instance, - const char* alleged_url, - PP_Bool uses_irt, - PP_Bool uses_ppapi, - PP_Bool uses_nonsfi_mode, - PP_Bool enable_ppapi_dev, - PP_Bool enable_dyncode_syscalls, - PP_Bool enable_exception_handling, - PP_Bool enable_crash_throttling, - void* imc_handle, - struct PP_Var* error_message, - struct PP_CompletionCallback callback); + void (*LaunchSelLdr)( + PP_Instance instance, + const char* alleged_url, + PP_Bool uses_irt, + PP_Bool uses_ppapi, + PP_Bool uses_nonsfi_mode, + PP_Bool enable_ppapi_dev, + PP_Bool enable_dyncode_syscalls, + PP_Bool enable_exception_handling, + PP_Bool enable_crash_throttling, + const struct PP_ManifestService_1_0* manifest_service_interface, + void* manifest_service_user_data, + void* imc_handle, + struct PP_Var* error_message, + struct PP_CompletionCallback callback); /* This function starts the IPC proxy so the nexe can communicate with the * browser. */ @@ -318,25 +353,31 @@ struct PPB_NaCl_Private_1_0 { void (*LogToConsole)(PP_Instance instance, const char* message); /* Returns the NaCl readiness status for this instance. */ PP_NaClReadyState (*GetNaClReadyState)(PP_Instance instance); - /* Sets the NaCl readiness status for this instance. */ - void (*SetNaClReadyState)(PP_Instance instance, - PP_NaClReadyState ready_state); /* Returns true if the plugin is an installed app. */ PP_Bool (*GetIsInstalled)(PP_Instance instance); - /* Sets whether the plugin is an installed app. */ - void (*SetIsInstalled)(PP_Instance instance, PP_Bool is_installed); /* Returns the exit status of the plugin process. */ int32_t (*GetExitStatus)(PP_Instance instance); /* Sets the exit status of the plugin process. */ void (*SetExitStatus)(PP_Instance instance, int32_t exit_status); /* Logs the message via VLOG. */ void (*Vlog)(const char* message); - /* Sets the time the plugin was initialized. */ - void (*SetInitTime)(PP_Instance instance); + /* Initializes internal state for a NaCl plugin. */ + void (*InitializePlugin)(PP_Instance instance); /* Returns the size of the nexe. */ int64_t (*GetNexeSize)(PP_Instance instance); - /* Sets the size of the nexe. */ - void (*SetNexeSize)(PP_Instance instance, int64_t nexe_size); + /* Performs accounting for requesting the NaCl manifest at the given URL. */ + PP_Bool (*RequestNaClManifest)(PP_Instance instance, + const char* manifest_url, + PP_Bool* is_data_uri); + struct PP_Var (*GetManifestBaseURL)(PP_Instance instance); + PP_Bool (*ResolvesRelativeToPluginBaseUrl)(PP_Instance instance, + const char* url); + struct PP_Var (*ParseDataURL)(const char* data_url); + /* Processes the NaCl manifest once it's been retrieved. + * TODO(teravest): Move the rest of the supporting logic out of the trusted + * plugin. + */ + void (*ProcessNaClManifest)(PP_Instance instance, const char* program_url); }; typedef struct PPB_NaCl_Private_1_0 PPB_NaCl_Private; diff --git a/ppapi/cpp/private/find_private.cc b/ppapi/cpp/private/find_private.cc index 440bc7444c..2765ae02eb 100644 --- a/ppapi/cpp/private/find_private.cc +++ b/ppapi/cpp/private/find_private.cc @@ -86,12 +86,12 @@ void Find_Private::SelectedFindResultChanged(int32_t index) { void Find_Private::SetTickmarks(const std::vector<pp::Rect>& tickmarks) { if (has_interface<PPB_Find_Private>()) { - if (tickmarks.empty()) - return; std::vector<PP_Rect> tickmarks_converted(tickmarks.begin(), tickmarks.end()); + PP_Rect* array = + tickmarks_converted.empty() ? NULL : &tickmarks_converted[0]; get_interface<PPB_Find_Private>()->SetTickmarks( - associated_instance_.pp_instance(), &tickmarks_converted[0], + associated_instance_.pp_instance(), array, static_cast<uint32_t>(tickmarks.size())); } } diff --git a/ppapi/nacl_irt/irt_start.cc b/ppapi/nacl_irt/irt_start.cc index a286737882..a7c12e6c31 100644 --- a/ppapi/nacl_irt/irt_start.cc +++ b/ppapi/nacl_irt/irt_start.cc @@ -17,7 +17,9 @@ void nacl_irt_start(uint32_t* info) { // In SFI mode, the FDs of IPC channels are NACL_CHROME_DESC_BASE and its // successor, which is set in nacl_listener.cc. ppapi::SetIPCFileDescriptors( - NACL_CHROME_DESC_BASE, NACL_CHROME_DESC_BASE + 1); + NACL_CHROME_DESC_BASE, + NACL_CHROME_DESC_BASE + 1, + -1); // Currently manifest service is disabled on NaCl in SFI mode. ppapi::StartUpPlugin(); nacl_irt_enter_user_code(info, chrome_irt_query); diff --git a/ppapi/nacl_irt/manifest_service.cc b/ppapi/nacl_irt/manifest_service.cc new file mode 100644 index 0000000000..ed7c4ebf96 --- /dev/null +++ b/ppapi/nacl_irt/manifest_service.cc @@ -0,0 +1,34 @@ +// Copyright 2014 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. + +#include "ppapi/nacl_irt/manifest_service.h" + +#include "base/message_loop/message_loop_proxy.h" +#include "ipc/ipc_channel_handle.h" +#include "ipc/ipc_channel_proxy.h" +#include "ipc/ipc_sync_message_filter.h" +#include "ppapi/proxy/ppapi_messages.h" + +namespace ppapi { + +ManifestService::ManifestService( + const IPC::ChannelHandle& handle, + scoped_refptr<base::MessageLoopProxy> io_message_loop, + base::WaitableEvent* shutdown_event) { + filter_ = new IPC::SyncMessageFilter(shutdown_event); + channel_.reset(new IPC::ChannelProxy(handle, + IPC::Channel::MODE_SERVER, + NULL, // Listener + io_message_loop)); + channel_->AddFilter(filter_.get()); +} + +ManifestService::~ManifestService() { +} + +void ManifestService::StartupInitializationComplete() { + filter_->Send(new PpapiHostMsg_StartupInitializationComplete); +} + +} // namespace ppapi diff --git a/ppapi/nacl_irt/manifest_service.h b/ppapi/nacl_irt/manifest_service.h new file mode 100644 index 0000000000..ec5e38c979 --- /dev/null +++ b/ppapi/nacl_irt/manifest_service.h @@ -0,0 +1,43 @@ +// Copyright 2014 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. + +#ifndef PPAPI_NACL_IRT_MANIFEST_SERVICE_H_ +#define PPAPI_NACL_IRT_MANIFEST_SERVICE_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" + +namespace base { +class MessageLoopProxy; +class WaitableEvent; +} // namespace base + +namespace IPC { +struct ChannelHandle; +class ChannelProxy; +class SyncMessageFilter; +} // namespace IPC + +namespace ppapi { + +class ManifestService { + public: + ManifestService(const IPC::ChannelHandle& handle, + scoped_refptr<base::MessageLoopProxy> io_message_loop, + base::WaitableEvent* shutdown_event); + ~ManifestService(); + + void StartupInitializationComplete(); + + private: + scoped_ptr<IPC::ChannelProxy> channel_; + scoped_refptr<IPC::SyncMessageFilter> filter_; + + DISALLOW_COPY_AND_ASSIGN(ManifestService); +}; + +} // namespace ppapi + +#endif // PPAPI_NACL_IRT_MANIFEST_SERVICE_H_ diff --git a/ppapi/nacl_irt/plugin_main.cc b/ppapi/nacl_irt/plugin_main.cc index eeeb50b737..668f67a3b0 100644 --- a/ppapi/nacl_irt/plugin_main.cc +++ b/ppapi/nacl_irt/plugin_main.cc @@ -24,15 +24,9 @@ void PpapiPluginRegisterThreadCreator( const struct PP_ThreadFunctions* thread_functions) { -#if defined(__native_client__) - // TODO(hidehiko): The thread creation for the PPB_Audio is not yet - // implemented on non-SFI mode. Support this. Now, this function invocation - // is just ignored. - // Initialize all classes that need to create threads that call back into // user code. ppapi::PPB_Audio_Shared::SetThreadFunctions(thread_functions); -#endif } int PpapiPluginMain() { diff --git a/ppapi/nacl_irt/plugin_startup.cc b/ppapi/nacl_irt/plugin_startup.cc index a3b5bc207e..2061fc831e 100644 --- a/ppapi/nacl_irt/plugin_startup.cc +++ b/ppapi/nacl_irt/plugin_startup.cc @@ -2,28 +2,59 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ppapi/nacl_irt/plugin_startup.h" + +#include "base/bind.h" +#include "base/file_descriptor_posix.h" #include "base/logging.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" -#include "ppapi/nacl_irt/plugin_startup.h" +#include "ipc/ipc_channel_handle.h" +#include "ppapi/nacl_irt/manifest_service.h" +#include "ppapi/shared_impl/ppb_audio_shared.h" namespace ppapi { namespace { int g_nacl_browser_ipc_fd = -1; int g_nacl_renderer_ipc_fd = -1; +int g_manifest_service_fd = -1; base::WaitableEvent* g_shutdown_event = NULL; base::Thread* g_io_thread = NULL; +ManifestService* g_manifest_service = NULL; + +// Creates the manifest service on IO thread so that its Listener's thread and +// IO thread are shared. Upon completion of the manifest service creation, +// event is signaled. +void StartUpManifestServiceOnIOThread(base::WaitableEvent* event) { + // The start up must be called only once. + DCHECK(!g_manifest_service); + // manifest_service_fd must be set. + DCHECK_NE(g_manifest_service_fd, -1); + // IOThread and shutdown event must be initialized in advance. + DCHECK(g_io_thread); + DCHECK(g_shutdown_event); + + g_manifest_service = new ManifestService( + IPC::ChannelHandle( + "NaCl IPC", base::FileDescriptor(g_manifest_service_fd, false)), + g_io_thread->message_loop_proxy(), + g_shutdown_event); + event->Signal(); +} } // namespace -void SetIPCFileDescriptors(int browser_ipc_fd, int renderer_ipc_fd) { +void SetIPCFileDescriptors( + int browser_ipc_fd, int renderer_ipc_fd, int manifest_service_fd) { // The initialization must be only once. DCHECK_EQ(g_nacl_browser_ipc_fd, -1); DCHECK_EQ(g_nacl_renderer_ipc_fd, -1); + DCHECK_EQ(g_manifest_service_fd, -1); g_nacl_browser_ipc_fd = browser_ipc_fd; g_nacl_renderer_ipc_fd = renderer_ipc_fd; + g_manifest_service_fd = manifest_service_fd; } void StartUpPlugin() { @@ -35,6 +66,22 @@ void StartUpPlugin() { g_io_thread = new base::Thread("Chrome_NaClIOThread"); g_io_thread->StartWithOptions( base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); + + if (g_manifest_service_fd != -1) { + // Manifest service must be created on IOThread so that the main message + // handling will be done on the thread, which has a message loop + // even before irt_ppapi_start invocation. + // TODO(hidehiko,dmichael): This works, but is probably not well designed + // usage. Once a better approach is made, replace this by that way. + // (crbug.com/364241). + base::WaitableEvent event(true, false); + g_io_thread->message_loop_proxy()->PostTask( + FROM_HERE, + base::Bind(StartUpManifestServiceOnIOThread, &event)); + event.Wait(); + } + + PPB_Audio_Shared::SetNaClMode(); } int GetBrowserIPCFileDescriptor() { @@ -61,4 +108,8 @@ base::Thread* GetIOThread() { return g_io_thread; } +ManifestService* GetManifestService() { + return g_manifest_service; +} + } // namespace ppapi diff --git a/ppapi/nacl_irt/plugin_startup.h b/ppapi/nacl_irt/plugin_startup.h index 73c34957a4..ea14836e60 100644 --- a/ppapi/nacl_irt/plugin_startup.h +++ b/ppapi/nacl_irt/plugin_startup.h @@ -14,11 +14,13 @@ class WaitableEvent; namespace ppapi { +class ManifestService; + // Sets the IPC channels for the browser and the renderer by the given FD // numbers. This will be used for non-SFI mode. Must be called before // PpapiPluginMain is called. PPAPI_PROXY_EXPORT void SetIPCFileDescriptors( - int browser_ipc_fd, int renderer_ipc_fd); + int browser_ipc_fd, int renderer_ipc_fd, int manifest_service_fd); // Runs start up procedure for the plugin. // Specifically, start background IO thread for IPC, and prepare @@ -38,6 +40,12 @@ base::WaitableEvent* GetShutdownEvent(); // Returns the IOThread for the plugin. Must be called after StartUpPlugin(). base::Thread* GetIOThread(); +// Returns the ManifestService interface. To use this, manifest_service_fd +// needs to be set via SetIPCFileDescriptors. Must be called after +// StartUpPlugin(). +// If not available, returns NULL. +ManifestService* GetManifestService(); + } // namespace ppapi #endif // PPAPI_NACL_IRT_PLUGIN_STARTUP_H_ diff --git a/ppapi/nacl_irt/ppapi_dispatcher.cc b/ppapi/nacl_irt/ppapi_dispatcher.cc index c0aa400037..9ca76b28b8 100644 --- a/ppapi/nacl_irt/ppapi_dispatcher.cc +++ b/ppapi/nacl_irt/ppapi_dispatcher.cc @@ -23,6 +23,8 @@ #include "ipc/ipc_message.h" #include "ppapi/c/ppp.h" #include "ppapi/c/ppp_instance.h" +#include "ppapi/nacl_irt/manifest_service.h" +#include "ppapi/nacl_irt/plugin_startup.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/plugin_globals.h" #include "ppapi/proxy/plugin_message_filter.h" @@ -199,6 +201,11 @@ void PpapiDispatcher::OnMsgInitializeNaClDispatcher( } // From here, the dispatcher will manage its own lifetime according to the // lifetime of the attached channel. + + // Notify the renderer process, if necessary. + ManifestService* manifest_service = GetManifestService(); + if (manifest_service) + manifest_service->StartupInitializationComplete(); } void PpapiDispatcher::OnPluginDispatcherMessageReceived( diff --git a/ppapi/native_client/src/trusted/plugin/file_downloader.cc b/ppapi/native_client/src/trusted/plugin/file_downloader.cc index 9bfe0e9736..1118e1dba3 100644 --- a/ppapi/native_client/src/trusted/plugin/file_downloader.cc +++ b/ppapi/native_client/src/trusted/plugin/file_downloader.cc @@ -23,9 +23,6 @@ namespace { -const int32_t kExtensionUrlRequestStatusOk = 200; -const int32_t kDataUriRequestStatusOk = 0; - struct NaClFileInfo NoFileInfo() { struct NaClFileInfo info; memset(&info, 0, sizeof(info)); @@ -125,12 +122,10 @@ bool FileDownloader::Open( return false; CHECK(instance_ != NULL); - open_time_ = NaClGetTimeOfDayMicroseconds(); status_code_ = -1; url_ = url; file_open_notify_callback_ = callback; mode_ = mode; - buffer_.clear(); file_info_.FreeResources(); pp::URLRequestInfo url_request(instance_); @@ -149,34 +144,10 @@ bool FileDownloader::Open( // Note that we have the only reference to the underlying objects, so // this will implicitly close any pending IO and destroy them. url_loader_ = pp::URLLoader(instance_); - pp::Var url_var = pp::Var(url); - url_scheme_ = instance_->nacl_interface()->GetUrlScheme(url_var.pp_var()); - bool grant_universal_access = false; - if (url_scheme_ == PP_SCHEME_DATA) { - // TODO(elijahtaylor) Remove this when data URIs can be read without - // universal access. - // https://bugs.webkit.org/show_bug.cgi?id=17352 - if (mode_ == DOWNLOAD_TO_BUFFER) { - grant_universal_access = true; - } else { - // Open is to invoke a callback on success or failure. Schedule - // it asynchronously to follow PPAPI's convention and avoid reentrancy. - pp::Core* core = pp::Module::Get()->core(); - core->CallOnMainThread(0, callback, PP_ERROR_NOACCESS); - PLUGIN_PRINTF(("FileDownloader::Open (pp_error=PP_ERROR_NOACCESS)\n")); - return true; - } - } url_request.SetRecordDownloadProgress(record_progress); if (url_loader_trusted_interface_ != NULL) { - if (grant_universal_access) { - // TODO(sehr,jvoung): See if we can remove this -- currently - // only used for data URIs. - url_loader_trusted_interface_->GrantUniversalAccess( - url_loader_.pp_resource()); - } if (progress_callback != NULL) { url_loader_trusted_interface_->RegisterStatusCallback( url_loader_.pp_resource(), progress_callback); @@ -211,7 +182,6 @@ void FileDownloader::OpenFast(const nacl::string& url, file_info_.FreeResources(); CHECK(instance_ != NULL); - open_time_ = NaClGetTimeOfDayMicroseconds(); status_code_ = NACL_HTTP_STATUS_OK; url_ = url; mode_ = DOWNLOAD_NONE; @@ -236,15 +206,6 @@ NaClFileInfo FileDownloader::GetFileInfo() { return info_to_return; } -int64_t FileDownloader::TimeSinceOpenMilliseconds() const { - int64_t now = NaClGetTimeOfDayMicroseconds(); - // If Open() wasn't called or we somehow return an earlier time now, just - // return the 0 rather than worse nonsense values. - if (open_time_ < 0 || now < open_time_) - return 0; - return (now - open_time_) / NACL_MICROS_PER_MILLI; -} - bool FileDownloader::InitialResponseIsValid() { // Process the response, validating the headers to confirm successful loading. url_response_ = url_loader_.GetResponseInfo(); @@ -262,30 +223,10 @@ bool FileDownloader::InitialResponseIsValid() { } full_url_ = full_url.AsString(); - // Note that URLs in the data-URI scheme produce different error - // codes than other schemes. This is because data-URI are really a - // special kind of file scheme, and therefore do not produce HTTP - // status codes. - bool status_ok = false; status_code_ = url_response_.GetStatusCode(); - switch (url_scheme_) { - case PP_SCHEME_CHROME_EXTENSION: - PLUGIN_PRINTF(("FileDownloader::InitialResponseIsValid (chrome-extension " - "response status_code=%" NACL_PRId32 ")\n", status_code_)); - status_ok = (status_code_ == kExtensionUrlRequestStatusOk); - break; - case PP_SCHEME_DATA: - PLUGIN_PRINTF(("FileDownloader::InitialResponseIsValid (data URI " - "response status_code=%" NACL_PRId32 ")\n", status_code_)); - status_ok = (status_code_ == kDataUriRequestStatusOk); - break; - case PP_SCHEME_OTHER: - PLUGIN_PRINTF(("FileDownloader::InitialResponseIsValid (HTTP response " - "status_code=%" NACL_PRId32 ")\n", status_code_)); - status_ok = (status_code_ == NACL_HTTP_STATUS_OK); - break; - } - return status_ok; + PLUGIN_PRINTF(("FileDownloader::InitialResponseIsValid (" + "response status_code=%" NACL_PRId32 ")\n", status_code_)); + return status_code_ == NACL_HTTP_STATUS_OK; } void FileDownloader::URLLoadStartNotify(int32_t pp_error) { @@ -356,8 +297,7 @@ void FileDownloader::URLLoadFinishNotify(int32_t pp_error) { // Validate response again on load (though it should be the same // as it was during InitialResponseIsValid?). url_response_ = url_loader_.GetResponseInfo(); - CHECK(url_response_.GetStatusCode() == NACL_HTTP_STATUS_OK || - url_response_.GetStatusCode() == kExtensionUrlRequestStatusOk); + CHECK(url_response_.GetStatusCode() == NACL_HTTP_STATUS_OK); // Record the full url from the response. pp::Var full_url = url_response_.GetURL(); @@ -403,9 +343,7 @@ void FileDownloader::URLReadBodyNotify(int32_t pp_error) { } StreamFinishNotify(PP_OK); } else { - if (mode_ == DOWNLOAD_TO_BUFFER) { - buffer_.insert(buffer_.end(), &temp_buffer_[0], &temp_buffer_[pp_error]); - } else if (mode_ == DOWNLOAD_TO_BUFFER_AND_STREAM) { + if (mode_ == DOWNLOAD_TO_BUFFER_AND_STREAM) { PLUGIN_PRINTF(("Running data_stream_callback, temp_buffer_=%p\n", &temp_buffer_[0])); StreamCallback cb = data_stream_callback_source_->GetCallback(); diff --git a/ppapi/native_client/src/trusted/plugin/file_downloader.h b/ppapi/native_client/src/trusted/plugin/file_downloader.h index 86fa6ea4bd..fa70a700be 100644 --- a/ppapi/native_client/src/trusted/plugin/file_downloader.h +++ b/ppapi/native_client/src/trusted/plugin/file_downloader.h @@ -27,7 +27,6 @@ class Plugin; typedef enum { DOWNLOAD_TO_FILE = 0, - DOWNLOAD_TO_BUFFER, DOWNLOAD_TO_BUFFER_AND_STREAM, DOWNLOAD_NONE } DownloadMode; @@ -79,9 +78,7 @@ class FileDownloader { stream_finish_callback_(pp::BlockUntilComplete()), file_io_private_interface_(NULL), url_loader_trusted_interface_(NULL), - open_time_(-1), mode_(DOWNLOAD_NONE), - url_scheme_(PP_SCHEME_OTHER), data_stream_callback_source_(NULL) {} ~FileDownloader() {} @@ -133,9 +130,6 @@ class FileDownloader { // delegate does not have to close it. struct NaClFileInfo GetFileInfo(); - // Returns the time delta between the call to Open() and this function. - int64_t TimeSinceOpenMilliseconds() const; - // Returns the url passed to Open(). const nacl::string& url() const { return url_; } @@ -161,9 +155,6 @@ class FileDownloader { bool GetDownloadProgress(int64_t* bytes_received, int64_t* total_bytes_to_be_received) const; - // Returns the buffer used for DOWNLOAD_TO_BUFFER mode. - const std::deque<char>& buffer() const { return buffer_; } - int status_code() const { return status_code_; } nacl::string GetResponseHeaders() const; @@ -178,14 +169,12 @@ class FileDownloader { // 1) Ask the browser to start streaming |url_| as a file. // 2) Ask the browser to finish streaming if headers indicate success. // 3) Ask the browser to open the file, so we can get the file descriptor. - // For DOWNLOAD_TO_BUFFER, the process is very similar: + // For DOWNLOAD_TO_BUFFER_AND_STREAM, the process is very similar: // 1) Ask the browser to start streaming |url_| to an internal buffer. // 2) Ask the browser to finish streaming to |temp_buffer_| on success. - // 3) Wait for streaming to finish, filling |buffer_| incrementally. + // 3) Wait for streaming to finish, passing the data directly to the user. // Each step is done asynchronously using callbacks. We create callbacks // through a factory to take advantage of ref-counting. - // DOWNLOAD_STREAM is similar to DOWNLOAD_TO_BUFFER except the downloaded - // data is passed directly to the user instead of saved in a buffer. // The public Open*() functions start step 1), and the public FinishStreaming // function proceeds to step 2) and 3). bool InitialResponseIsValid(); @@ -208,13 +197,10 @@ class FileDownloader { const PPB_URLLoaderTrusted* url_loader_trusted_interface_; pp::URLLoader url_loader_; pp::CompletionCallbackFactory<FileDownloader> callback_factory_; - int64_t open_time_; int32_t status_code_; DownloadMode mode_; static const uint32_t kTempBufferSize = 16384; std::vector<char> temp_buffer_; - std::deque<char> buffer_; - PP_UrlSchemeType url_scheme_; StreamCallbackSource* data_stream_callback_source_; NaClFileInfoAutoCloser file_info_; }; diff --git a/ppapi/native_client/src/trusted/plugin/json_manifest.cc b/ppapi/native_client/src/trusted/plugin/json_manifest.cc index 4ab502345f..1fb51ea40c 100644 --- a/ppapi/native_client/src/trusted/plugin/json_manifest.cc +++ b/ppapi/native_client/src/trusted/plugin/json_manifest.cc @@ -15,10 +15,10 @@ #include "native_client/src/include/nacl_string.h" #include "native_client/src/include/portability.h" #include "native_client/src/shared/platform/nacl_check.h" +#include "ppapi/c/private/ppb_nacl_private.h" #include "ppapi/cpp/dev/url_util_dev.h" #include "ppapi/cpp/var.h" #include "ppapi/native_client/src/trusted/plugin/plugin_error.h" -#include "ppapi/native_client/src/trusted/plugin/pnacl_options.h" #include "ppapi/native_client/src/trusted/plugin/utility.h" #include "third_party/jsoncpp/source/include/json/reader.h" @@ -381,15 +381,20 @@ bool IsValidISADictionary(const Json::Value& dictionary, return true; } -void GrabUrlAndPnaclOptions(const Json::Value& url_spec, +void GrabUrlAndPNaClOptions(const Json::Value& url_spec, nacl::string* url, - PnaclOptions* pnacl_options) { + PP_PNaClOptions* pnacl_options) { *url = url_spec[kUrlKey].asString(); - pnacl_options->set_translate(true); + pnacl_options->translate = PP_TRUE; if (url_spec.isMember(kOptLevelKey)) { int32_t opt_raw = url_spec[kOptLevelKey].asInt(); - // set_opt_level will normalize the values. - pnacl_options->set_opt_level(opt_raw); + int32_t opt_level; + // Currently only allow 0 or 2, since that is what we test. + if (opt_raw <= 0) + opt_level = 0; + else + opt_level = 2; + pnacl_options->opt_level = opt_level; } } @@ -503,7 +508,7 @@ bool JsonManifest::MatchesSchema(ErrorInfo* error_info) { bool JsonManifest::GetURLFromISADictionary(const Json::Value& dictionary, const nacl::string& parent_key, nacl::string* url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, bool* uses_nonsfi_mode, ErrorInfo* error_info) const { DCHECK(url != NULL && pnacl_options != NULL && error_info != NULL); @@ -546,14 +551,14 @@ bool JsonManifest::GetURLFromISADictionary(const Json::Value& dictionary, // If found, mark that it is a debug URL. Otherwise, fall back to // checking for pnacl-translate URLs, etc. and don't mark it as a debug URL. if (pnacl_debug_ && isa_spec.isMember(kPnaclDebugKey)) { - GrabUrlAndPnaclOptions(isa_spec[kPnaclDebugKey], url, pnacl_options); - pnacl_options->set_debug(true); + GrabUrlAndPNaClOptions(isa_spec[kPnaclDebugKey], url, pnacl_options); + pnacl_options->is_debug = PP_TRUE; } else if (isa_spec.isMember(kPnaclTranslateKey)) { - GrabUrlAndPnaclOptions(isa_spec[kPnaclTranslateKey], url, pnacl_options); + GrabUrlAndPNaClOptions(isa_spec[kPnaclTranslateKey], url, pnacl_options); } else { // NaCl *url = isa_spec[kUrlKey].asString(); - pnacl_options->set_translate(false); + pnacl_options->translate = PP_FALSE; } return true; @@ -562,7 +567,7 @@ bool JsonManifest::GetURLFromISADictionary(const Json::Value& dictionary, bool JsonManifest::GetKeyUrl(const Json::Value& dictionary, const nacl::string& key, nacl::string* full_url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, ErrorInfo* error_info) const { DCHECK(full_url != NULL && pnacl_options != NULL && error_info != NULL); if (!dictionary.isMember(key)) { @@ -581,7 +586,7 @@ bool JsonManifest::GetKeyUrl(const Json::Value& dictionary, } bool JsonManifest::GetProgramURL(nacl::string* full_url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, bool* uses_nonsfi_mode, ErrorInfo* error_info) const { if (full_url == NULL || pnacl_options == NULL || error_info == NULL) @@ -620,7 +625,7 @@ bool JsonManifest::GetFileKeys(std::set<nacl::string>* keys) const { bool JsonManifest::ResolveKey(const nacl::string& key, nacl::string* full_url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, ErrorInfo* error_info) const { NaClLog(3, "JsonManifest::ResolveKey(%s)\n", key.c_str()); // key must be one of kProgramKey or kFileKey '/' file-section-key diff --git a/ppapi/native_client/src/trusted/plugin/json_manifest.h b/ppapi/native_client/src/trusted/plugin/json_manifest.h index e71abebaa6..1f4180ce35 100644 --- a/ppapi/native_client/src/trusted/plugin/json_manifest.h +++ b/ppapi/native_client/src/trusted/plugin/json_manifest.h @@ -18,6 +18,8 @@ #include "ppapi/native_client/src/trusted/plugin/manifest.h" #include "third_party/jsoncpp/source/include/json/value.h" +struct PP_PNaClOptions; + namespace pp { class URLUtil_Dev; } // namespace pp @@ -25,7 +27,6 @@ class URLUtil_Dev; namespace plugin { class ErrorInfo; -class PnaclOptions; class JsonManifest : public Manifest { public: @@ -49,7 +50,7 @@ class JsonManifest : public Manifest { // Gets the full program URL for the current sandbox ISA from the // manifest file. virtual bool GetProgramURL(nacl::string* full_url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, bool* uses_nonsfi_mode, ErrorInfo* error_info) const; @@ -65,7 +66,7 @@ class JsonManifest : public Manifest { // If there was an error, details are reported via error_info. virtual bool ResolveKey(const nacl::string& key, nacl::string* full_url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, ErrorInfo* error_info) const; private: @@ -84,13 +85,13 @@ class JsonManifest : public Manifest { bool GetKeyUrl(const Json::Value& dictionary, const nacl::string& key, nacl::string* full_url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, ErrorInfo* error_info) const; bool GetURLFromISADictionary(const Json::Value& dictionary, const nacl::string& parent_key, nacl::string* url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, bool* uses_nonsfi_mode, ErrorInfo* error_info) const; diff --git a/ppapi/native_client/src/trusted/plugin/manifest.h b/ppapi/native_client/src/trusted/plugin/manifest.h index c430e1f346..aa1ad3bce6 100644 --- a/ppapi/native_client/src/trusted/plugin/manifest.h +++ b/ppapi/native_client/src/trusted/plugin/manifest.h @@ -17,6 +17,8 @@ #include "native_client/src/include/nacl_string.h" #include "third_party/jsoncpp/source/include/json/value.h" +struct PP_PNaClOptions; + namespace pp { class URLUtil_Dev; } // namespace pp @@ -24,7 +26,6 @@ class URLUtil_Dev; namespace plugin { class ErrorInfo; -class PnaclOptions; class Manifest { public: @@ -42,7 +43,7 @@ class Manifest { // manifest file. Fills in |pnacl_options| if the program requires // PNaCl translation. virtual bool GetProgramURL(nacl::string* full_url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, bool* uses_nonsfi_mode, ErrorInfo* error_info) const = 0; @@ -60,7 +61,7 @@ class Manifest { // If there was an error, details are reported via error_info. virtual bool ResolveKey(const nacl::string& key, nacl::string* full_url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, ErrorInfo* error_info) const = 0; protected: diff --git a/ppapi/native_client/src/trusted/plugin/nacl_entry_points.h b/ppapi/native_client/src/trusted/plugin/nacl_entry_points.h index 2f02d6b298..4d4c92328a 100644 --- a/ppapi/native_client/src/trusted/plugin/nacl_entry_points.h +++ b/ppapi/native_client/src/trusted/plugin/nacl_entry_points.h @@ -16,6 +16,7 @@ #include "ppapi/c/pp_completion_callback.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/private/ppb_instance_private.h" +#include "ppapi/c/private/ppb_nacl_private.h" typedef PP_ExternalPluginResult (*LaunchNaClProcessFunc)( PP_Instance instance, @@ -27,6 +28,8 @@ typedef PP_ExternalPluginResult (*LaunchNaClProcessFunc)( PP_Bool enable_dyncode_syscalls, PP_Bool enable_exception_handling, PP_Bool enable_crash_throttling, + const PP_ManifestService* manifest_service_interface, + void* manifest_service_user_data, NaClHandle* result_socket, struct PP_Var* error_message, PP_CompletionCallback callback); diff --git a/ppapi/native_client/src/trusted/plugin/plugin.cc b/ppapi/native_client/src/trusted/plugin/plugin.cc index 270d71d844..c4b1aafbc1 100644 --- a/ppapi/native_client/src/trusted/plugin/plugin.cc +++ b/ppapi/native_client/src/trusted/plugin/plugin.cc @@ -268,7 +268,10 @@ void Plugin::LoadNaClModule(nacl::DescWrapper* wrapper, // associated listener threads do not go unjoined because if they // outlive the Plugin object, they will not be memory safe. ShutDownSubprocesses(); - SelLdrStartParams params(manifest_base_url(), + pp::Var manifest_base_url = + pp::Var(pp::PASS_REF, nacl_interface_->GetManifestBaseURL(pp_instance())); + std::string manifest_base_url_str = manifest_base_url.AsString(); + SelLdrStartParams params(manifest_base_url_str, true /* uses_irt */, true /* uses_ppapi */, uses_nonsfi_mode, @@ -431,7 +434,7 @@ Plugin* Plugin::New(PP_Instance pp_instance) { // failure. Note that module loading functions will log their own errors. bool Plugin::Init(uint32_t argc, const char* argn[], const char* argv[]) { PLUGIN_PRINTF(("Plugin::Init (argc=%" NACL_PRIu32 ")\n", argc)); - nacl_interface_->SetInitTime(pp_instance()); + nacl_interface_->InitializePlugin(pp_instance()); url_util_ = pp::URLUtil_Dev::Get(); if (url_util_ == NULL) @@ -461,16 +464,6 @@ bool Plugin::Init(uint32_t argc, const char* argn[], const char* argv[]) { } else { manifest_url = LookupArgument(kSrcManifestAttribute); } - // Use the document URL as the base for resolving relative URLs to find the - // manifest. This takes into account the setting of <base> tags that - // precede the embed/object. - CHECK(url_util_ != NULL); - pp::Var base_var = url_util_->GetDocumentURL(this); - if (!base_var.is_string()) { - PLUGIN_PRINTF(("Plugin::Init (unable to find document url)\n")); - return false; - } - set_plugin_base_url(base_var.AsString()); if (manifest_url.empty()) { // TODO(sehr,polina): this should be a hard error when scripting // the src property is no longer allowed. @@ -484,7 +477,7 @@ bool Plugin::Init(uint32_t argc, const char* argn[], const char* argv[]) { // Issue a GET for the manifest_url. The manifest file will be parsed to // determine the nexe URL. // Sets src property to full manifest URL. - RequestNaClManifest(manifest_url.c_str()); + RequestNaClManifest(manifest_url); } } @@ -499,6 +492,8 @@ Plugin::Plugin(PP_Instance pp_instance) wrapper_factory_(NULL), enable_dev_interfaces_(false), time_of_last_progress_event_(0), + manifest_open_time_(-1), + nexe_open_time_(-1), nacl_interface_(NULL), uma_interface_(this) { PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%" @@ -592,6 +587,13 @@ void Plugin::NexeFileDidOpen(int32_t pp_error) { nexe_bytes_read = stat_buf.st_size; } + int64_t now = NaClGetTimeOfDayMicroseconds(); + int64_t download_time; + if (now < nexe_open_time_) + download_time = 0; + else + download_time = now - nexe_open_time_; + nacl_interface_->NexeFileDidOpen( pp_instance(), pp_error, @@ -599,7 +601,7 @@ void Plugin::NexeFileDidOpen(int32_t pp_error) { nexe_downloader_.status_code(), nexe_bytes_read, nexe_downloader_.url().c_str(), - nexe_downloader_.TimeSinceOpenMilliseconds()); + download_time / 1000); if (nexe_bytes_read == -1) return; @@ -683,47 +685,17 @@ void Plugin::BitcodeDidTranslateContinuation(int32_t pp_error) { } } -void Plugin::NaClManifestBufferReady(int32_t pp_error) { - PLUGIN_PRINTF(("Plugin::NaClManifestBufferReady (pp_error=%" - NACL_PRId32 ")\n", pp_error)); - ErrorInfo error_info; - if (pp_error != PP_OK) { - if (pp_error == PP_ERROR_ABORTED) { - ReportLoadAbort(); - } else { - error_info.SetReport(PP_NACL_ERROR_MANIFEST_LOAD_URL, - "could not load manifest url."); - ReportLoadError(error_info); - } - return; - } - - const std::deque<char>& buffer = nexe_downloader_.buffer(); - size_t buffer_size = buffer.size(); - if (buffer_size > kNaClManifestMaxFileBytes) { - error_info.SetReport(PP_NACL_ERROR_MANIFEST_TOO_LARGE, - "manifest file too large."); - ReportLoadError(error_info); - return; - } - nacl::scoped_array<char> json_buffer(new char[buffer_size + 1]); - if (json_buffer == NULL) { - error_info.SetReport(PP_NACL_ERROR_MANIFEST_MEMORY_ALLOC, - "could not allocate manifest memory."); - ReportLoadError(error_info); - return; - } - std::copy(buffer.begin(), buffer.begin() + buffer_size, &json_buffer[0]); - json_buffer[buffer_size] = '\0'; - - ProcessNaClManifest(json_buffer.get()); -} - void Plugin::NaClManifestFileDidOpen(int32_t pp_error) { PLUGIN_PRINTF(("Plugin::NaClManifestFileDidOpen (pp_error=%" NACL_PRId32 ")\n", pp_error)); + int64_t now = NaClGetTimeOfDayMicroseconds(); + int64_t download_time; + if (now < manifest_open_time_) + download_time = 0; + else + download_time = now - manifest_open_time_; HistogramTimeSmall("NaCl.Perf.StartupTime.ManifestDownload", - nexe_downloader_.TimeSinceOpenMilliseconds()); + download_time / 1000); HistogramHTTPStatusCode( nacl_interface_->GetIsInstalled(pp_instance()) ? "NaCl.HttpStatusCodeClass.Manifest.InstalledApp" : @@ -796,22 +768,15 @@ void Plugin::ProcessNaClManifest(const nacl::string& manifest_json) { } nacl::string program_url; - PnaclOptions pnacl_options; + PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, 2}; bool uses_nonsfi_mode; if (manifest_->GetProgramURL( &program_url, &pnacl_options, &uses_nonsfi_mode, &error_info)) { - pp::Var program_url_var(program_url); - nacl_interface_->SetIsInstalled( - pp_instance(), - PP_FromBool( - nacl_interface_->GetUrlScheme(program_url_var.pp_var()) == - PP_SCHEME_CHROME_EXTENSION)); + // TODO(teravest): Make ProcessNaClManifest take responsibility for more of + // this function. + nacl_interface_->ProcessNaClManifest(pp_instance(), program_url.c_str()); uses_nonsfi_mode_ = uses_nonsfi_mode; - nacl_interface_->SetNaClReadyState(pp_instance(), - PP_NACL_READY_STATE_LOADING); - // Inform JavaScript that we found a nexe URL to load. - EnqueueProgressEvent(PP_NACL_EVENT_PROGRESS); - if (pnacl_options.translate()) { + if (pnacl_options.translate) { pp::CompletionCallback translate_callback = callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate); // Will always call the callback on success or failure. @@ -822,6 +787,7 @@ void Plugin::ProcessNaClManifest(const nacl::string& manifest_json) { translate_callback)); return; } else { + nexe_open_time_ = NaClGetTimeOfDayMicroseconds(); // Try the fast path first. This will only block if the file is installed. if (OpenURLFast(program_url, &nexe_downloader_)) { NexeFileDidOpen(PP_OK); @@ -845,48 +811,34 @@ void Plugin::ProcessNaClManifest(const nacl::string& manifest_json) { void Plugin::RequestNaClManifest(const nacl::string& url) { PLUGIN_PRINTF(("Plugin::RequestNaClManifest (url='%s')\n", url.c_str())); - PLUGIN_PRINTF(("Plugin::RequestNaClManifest (plugin base url='%s')\n", - plugin_base_url().c_str())); - // The full URL of the manifest file is relative to the base url. - CHECK(url_util_ != NULL); - pp::Var nmf_resolved_url = - url_util_->ResolveRelativeToURL(plugin_base_url(), pp::Var(url)); - if (!nmf_resolved_url.is_string()) { - ErrorInfo error_info; - error_info.SetReport( - PP_NACL_ERROR_MANIFEST_RESOLVE_URL, - nacl::string("could not resolve URL \"") + url.c_str() + - "\" relative to \"" + plugin_base_url().c_str() + "\"."); - ReportLoadError(error_info); + PP_Bool is_data_uri; + ErrorInfo error_info; + if (!nacl_interface_->RequestNaClManifest(pp_instance(), url.c_str(), + &is_data_uri)) return; - } - PLUGIN_PRINTF(("Plugin::RequestNaClManifest (resolved url='%s')\n", - nmf_resolved_url.AsString().c_str())); - nacl_interface_->SetIsInstalled( - pp_instance(), - PP_FromBool( - nacl_interface_->GetUrlScheme(nmf_resolved_url.pp_var()) == - PP_SCHEME_CHROME_EXTENSION)); - set_manifest_base_url(nmf_resolved_url.AsString()); - // Inform JavaScript that a load is starting. - nacl_interface_->SetNaClReadyState(pp_instance(), PP_NACL_READY_STATE_OPENED); - EnqueueProgressEvent(PP_NACL_EVENT_LOADSTART); - bool is_data_uri = - (nacl_interface_->GetUrlScheme(nmf_resolved_url.pp_var()) == - PP_SCHEME_DATA); - HistogramEnumerateManifestIsDataURI(static_cast<int>(is_data_uri)); + pp::Var nmf_resolved_url = + pp::Var(pp::PASS_REF, nacl_interface_->GetManifestBaseURL(pp_instance())); if (is_data_uri) { - pp::CompletionCallback open_callback = - callback_factory_.NewCallback(&Plugin::NaClManifestBufferReady); - // Will always call the callback on success or failure. - CHECK(nexe_downloader_.Open(nmf_resolved_url.AsString(), - DOWNLOAD_TO_BUFFER, - open_callback, - false, - NULL)); + std::string string_nmf_resolved_url = nmf_resolved_url.AsString(); + pp::Var nmf_data = pp::Var( + pp::PASS_REF, + nacl_interface_->ParseDataURL(string_nmf_resolved_url.c_str())); + if (!nmf_data.is_string()) { + error_info.SetReport(PP_NACL_ERROR_MANIFEST_LOAD_URL, + "could not load manifest url."); + ReportLoadError(error_info); + } else if (nmf_data.AsString().size() > kNaClManifestMaxFileBytes) { + error_info.SetReport(PP_NACL_ERROR_MANIFEST_TOO_LARGE, + "manifest file too large."); + ReportLoadError(error_info); + } else { + // TODO(teravest): Does this have to be async for any reason? + ProcessNaClManifest(nmf_data.AsString()); + } } else { pp::CompletionCallback open_callback = callback_factory_.NewCallback(&Plugin::NaClManifestFileDidOpen); + manifest_open_time_ = NaClGetTimeOfDayMicroseconds(); // Will always call the callback on success or failure. CHECK(nexe_downloader_.Open(nmf_resolved_url.AsString(), DOWNLOAD_TO_FILE, @@ -908,12 +860,15 @@ bool Plugin::SetManifestObject(const nacl::string& manifest_json, bool is_pnacl = (mime_type() == kPnaclMIMEType); bool nonsfi_mode_enabled = PP_ToBool(nacl_interface_->IsNonSFIModeEnabled()); + pp::Var manifest_base_url = + pp::Var(pp::PASS_REF, nacl_interface_->GetManifestBaseURL(pp_instance())); + std::string manifest_base_url_str = manifest_base_url.AsString(); bool pnacl_debug = GetNaClInterface()->NaClDebugEnabledForURL( - manifest_base_url().c_str()); + manifest_base_url_str.c_str()); const char* sandbox_isa = nacl_interface_->GetSandboxArch(); nacl::scoped_ptr<JsonManifest> json_manifest( new JsonManifest(url_util_, - manifest_base_url(), + manifest_base_url_str, (is_pnacl ? kPortableArch : sandbox_isa), nonsfi_mode_enabled, pnacl_debug)); @@ -973,17 +928,11 @@ bool Plugin::StreamAsFile(const nacl::string& url, FileDownloader* downloader = new FileDownloader(); downloader->Initialize(this); url_downloaders_.insert(downloader); + // Untrusted loads are always relative to the page's origin. - CHECK(url_util_ != NULL); - pp::Var resolved_url = - url_util_->ResolveRelativeToURL(pp::Var(plugin_base_url()), url); - if (!resolved_url.is_string()) { - PLUGIN_PRINTF(("Plugin::StreamAsFile: " - "could not resolve url \"%s\" relative to plugin \"%s\".", - url.c_str(), - plugin_base_url().c_str())); + if (!GetNaClInterface()->ResolvesRelativeToPluginBaseUrl(pp_instance(), + url.c_str())) return false; - } // Try the fast path first. This will only block if the file is installed. if (OpenURLFast(url, downloader)) { @@ -1081,14 +1030,6 @@ void Plugin::ReportSelLdrLoadStatus(int status) { HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status)); } -void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type) { - EnqueueProgressEvent(event_type, - NACL_NO_URL, - Plugin::LENGTH_IS_NOT_COMPUTABLE, - Plugin::kUnknownBytes, - Plugin::kUnknownBytes); -} - void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type, const nacl::string& url, LengthComputable length_computable, diff --git a/ppapi/native_client/src/trusted/plugin/plugin.gypi b/ppapi/native_client/src/trusted/plugin/plugin.gypi index f8c8b8a57e..d9de561d39 100644 --- a/ppapi/native_client/src/trusted/plugin/plugin.gypi +++ b/ppapi/native_client/src/trusted/plugin/plugin.gypi @@ -13,7 +13,6 @@ 'nacl_subprocess.cc', 'plugin.cc', 'pnacl_coordinator.cc', - 'pnacl_options.cc', 'pnacl_resources.cc', 'pnacl_translate_thread.cc', 'sel_ldr_launcher_chrome.cc', diff --git a/ppapi/native_client/src/trusted/plugin/plugin.h b/ppapi/native_client/src/trusted/plugin/plugin.h index f7864218cb..a1e12c3537 100644 --- a/ppapi/native_client/src/trusted/plugin/plugin.h +++ b/ppapi/native_client/src/trusted/plugin/plugin.h @@ -134,7 +134,6 @@ class Plugin : public pp::Instance { // event (loadstart, progress, error, abort, load, loadend). Events are // enqueued on the JavaScript event loop, which then calls back through // DispatchProgressEvent. - void EnqueueProgressEvent(PP_NaClEventType event_type); void EnqueueProgressEvent(PP_NaClEventType event_type, const nacl::string& url, LengthComputable length_computable, @@ -144,18 +143,6 @@ class Plugin : public pp::Instance { // Report the error code that sel_ldr produces when starting a nexe. void ReportSelLdrLoadStatus(int status); - // URL resolution support. - // plugin_base_url is the URL used for resolving relative URLs used in - // src="...". - nacl::string plugin_base_url() const { return plugin_base_url_; } - void set_plugin_base_url(const nacl::string& url) { plugin_base_url_ = url; } - // manifest_base_url is the URL used for resolving relative URLs mentioned - // in manifest files. If the manifest is a data URI, this is an empty string. - nacl::string manifest_base_url() const { return manifest_base_url_; } - void set_manifest_base_url(const nacl::string& url) { - manifest_base_url_ = url; - } - nacl::DescWrapperFactory* wrapper_factory() const { return wrapper_factory_; } // Requests a NaCl manifest download from a |url| relative to the page origin. @@ -297,9 +284,6 @@ class Plugin : public pp::Instance { // chosen for the sandbox ISA, any current service runtime is shut down, the // .nexe is loaded and run. - // Callback used when getting the manifest file as a buffer (e.g., data URIs) - void NaClManifestBufferReady(int32_t pp_error); - // Callback used when getting the manifest file as a local file descriptor. void NaClManifestFileDidOpen(int32_t pp_error); @@ -413,6 +397,10 @@ class Plugin : public pp::Instance { int64_t time_of_last_progress_event_; int exit_status_; + // Open times are in microseconds. + int64_t manifest_open_time_; + int64_t nexe_open_time_; + const PPB_NaCl_Private* nacl_interface_; pp::UMAPrivate uma_interface_; }; diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc index 74e84eb14c..7c04043418 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc @@ -42,7 +42,7 @@ class PnaclManifest : public Manifest { virtual ~PnaclManifest() { } virtual bool GetProgramURL(nacl::string* full_url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, bool* uses_nonsfi_mode, ErrorInfo* error_info) const { // Does not contain program urls. @@ -65,10 +65,10 @@ class PnaclManifest : public Manifest { virtual bool ResolveKey(const nacl::string& key, nacl::string* full_url, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, ErrorInfo* error_info) const { // All of the component files are native (do not require pnacl translate). - pnacl_options->set_translate(false); + pnacl_options->translate = PP_FALSE; // We can only resolve keys in the files/ namespace. const nacl::string kFilesPrefix = "files/"; size_t files_prefix_pos = key.find(kFilesPrefix); @@ -181,7 +181,7 @@ CallbackSource<FileStreamData>::~CallbackSource() {} PnaclCoordinator* PnaclCoordinator::BitcodeToNative( Plugin* plugin, const nacl::string& pexe_url, - const PnaclOptions& pnacl_options, + const PP_PNaClOptions& pnacl_options, const pp::CompletionCallback& translate_notify_callback) { PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (plugin=%p, pexe=%s)\n", static_cast<void*>(plugin), pexe_url.c_str())); @@ -207,7 +207,7 @@ PnaclCoordinator* PnaclCoordinator::BitcodeToNative( PnaclCoordinator::PnaclCoordinator( Plugin* plugin, const nacl::string& pexe_url, - const PnaclOptions& pnacl_options, + const PP_PNaClOptions& pnacl_options, const pp::CompletionCallback& translate_notify_callback) : translate_finish_error_(PP_OK), plugin_(plugin), @@ -325,7 +325,7 @@ void PnaclCoordinator::TranslateFinished(int32_t pp_error) { } // If there are no errors, report stats from this thread (the main thread). - HistogramOptLevel(plugin_->uma_interface(), pnacl_options_.opt_level()); + HistogramOptLevel(plugin_->uma_interface(), pnacl_options_.opt_level); HistogramKBPerSec(plugin_->uma_interface(), "NaCl.Perf.PNaClLoadTime.CompileKBPerSec", pexe_size_ / 1024.0, @@ -483,7 +483,7 @@ void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) { // TODO(dschuff): Get this value from the pnacl json file after it // rolls in from NaCl. 1, - pnacl_options_.opt_level(), + pnacl_options_.opt_level, headers.c_str(), "", // No extra compile flags yet. &is_cache_hit_, diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h index 20b3d85ff0..99d6e7052b 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h @@ -21,9 +21,9 @@ #include "ppapi/native_client/src/trusted/plugin/file_downloader.h" #include "ppapi/native_client/src/trusted/plugin/nacl_subprocess.h" #include "ppapi/native_client/src/trusted/plugin/plugin_error.h" -#include "ppapi/native_client/src/trusted/plugin/pnacl_options.h" #include "ppapi/native_client/src/trusted/plugin/pnacl_resources.h" +struct PP_PNaClOptions; namespace plugin { @@ -86,7 +86,7 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { static PnaclCoordinator* BitcodeToNative( Plugin* plugin, const nacl::string& pexe_url, - const PnaclOptions& pnacl_options, + const PP_PNaClOptions& pnacl_options, const pp::CompletionCallback& translate_notify_callback); // Call this to take ownership of the FD of the translated nexe after @@ -144,7 +144,7 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { // Therefore the constructor is private. PnaclCoordinator(Plugin* plugin, const nacl::string& pexe_url, - const PnaclOptions& pnacl_options, + const PP_PNaClOptions& pnacl_options, const pp::CompletionCallback& translate_notify_callback); // Invoke to issue a GET request for bitcode. @@ -211,7 +211,7 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { // The URL for the pexe file. nacl::string pexe_url_; // Options for translation. - PnaclOptions pnacl_options_; + PP_PNaClOptions pnacl_options_; // Object file, produced by the translator and consumed by the linker. std::vector<TempFile*> obj_files_; diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_options.cc b/ppapi/native_client/src/trusted/plugin/pnacl_options.cc deleted file mode 100644 index 46d7c24730..0000000000 --- a/ppapi/native_client/src/trusted/plugin/pnacl_options.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2013 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. - -#include "ppapi/native_client/src/trusted/plugin/pnacl_options.h" - -#include <iterator> -#include <vector> - -#include "native_client/src/include/nacl_string.h" - -namespace plugin { - -PnaclOptions::PnaclOptions() - : translate_(false), - is_debug_(false), - opt_level_(2) { -} - -PnaclOptions::~PnaclOptions() { -} - -void PnaclOptions::set_opt_level(int32_t l) { - if (l <= 0) { - opt_level_ = 0; - return; - } - // Currently only allow 0 or 2, since that is what we test. - opt_level_ = 2; -} - -std::vector<char> PnaclOptions::GetOptCommandline() const { - std::vector<char> result; - nacl::string str; - - nacl::stringstream ss; - ss << "-O" << opt_level_; - str = ss.str(); - std::copy(str.begin(), str.end(), std::back_inserter(result)); - result.push_back('\x00'); - // Debug info is only available in LLVM format pexes, - // not in PNaCl format pexes. - if (is_debug_) { - str = "-bitcode-format=llvm"; - std::copy(str.begin(), str.end(), std::back_inserter(result)); - result.push_back('\x00'); - } - - return result; -} - -} // namespace plugin diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_options.h b/ppapi/native_client/src/trusted/plugin/pnacl_options.h deleted file mode 100644 index 2d30c3b327..0000000000 --- a/ppapi/native_client/src/trusted/plugin/pnacl_options.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2013 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. - -#ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_OPTIONS_H_ -#define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_OPTIONS_H_ - -#include <vector> - -#include "native_client/src/include/nacl_string.h" -#include "native_client/src/include/portability.h" - -namespace plugin { - -// Options for PNaCl translation. -class PnaclOptions { - - public: - PnaclOptions(); - ~PnaclOptions(); - - // Return a character array of \x00 delimited commandline options. - std::vector<char> GetOptCommandline() const; - - bool translate() const { return translate_; } - void set_translate(bool t) { translate_ = t; } - - bool is_debug() const { return is_debug_; } - void set_debug(bool t) { is_debug_ = t; } - - int32_t opt_level() const { return opt_level_; } - void set_opt_level(int32_t l); - - private: - // NOTE: There are users of this class that use the copy constructor. - // Currently the default copy constructor is good enough, but - // double-check that it is the case when more fields are added. - bool translate_; - bool is_debug_; - int32_t opt_level_; -}; - -} // namespace plugin; -#endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_OPTIONS_H_ diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc index 7cb98b8398..10f01bb31e 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc +++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc @@ -15,6 +15,25 @@ #include "ppapi/native_client/src/trusted/plugin/utility.h" namespace plugin { +namespace { + +nacl::string GetOptCommandLine(int32_t opt_level, bool is_debug) { + nacl::string str; + nacl::stringstream ss; + ss << "-O" << opt_level; + str = ss.str(); + str += '\x00'; + + // Debug info is only available in LLVM format pexes, + // not in PNaCl format pexes. + if (is_debug) { + str += "-bitcode-format=llvm"; + str += '\x00'; + } + return str; +} + +} // namespace PnaclTranslateThread::PnaclTranslateThread() : llc_subprocess_active_(false), ld_subprocess_active_(false), @@ -40,7 +59,7 @@ void PnaclTranslateThread::RunTranslate( nacl::DescWrapper* invalid_desc_wrapper, ErrorInfo* error_info, PnaclResources* resources, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, PnaclCoordinator* coordinator, Plugin* plugin) { PLUGIN_PRINTF(("PnaclStreamingTranslateThread::RunTranslate)\n")); @@ -187,7 +206,8 @@ void PnaclTranslateThread::DoTranslate() { nacl::string split_arg = ss.str(); std::copy(split_arg.begin(), split_arg.end(), std::back_inserter(split_args)); split_args.push_back('\x00'); - std::vector<char> options = pnacl_options_->GetOptCommandline(); + nacl::string options = GetOptCommandLine(pnacl_options_->opt_level, + pnacl_options_->is_debug); std::copy(options.begin(), options.end(), std::back_inserter(split_args)); init_success = llc_subprocess_->InvokeSrpcMethod( "StreamInitWithSplit", diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h index 4de0963383..db1dbf03a9 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h +++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h @@ -19,6 +19,8 @@ #include "ppapi/native_client/src/trusted/plugin/plugin_error.h" #include "ppapi/native_client/src/trusted/plugin/service_runtime.h" +struct PP_PNaClOptions; + namespace nacl { class DescWrapper; } @@ -30,7 +32,6 @@ class Manifest; class NaClSubprocess; class Plugin; class PnaclCoordinator; -class PnaclOptions; class PnaclResources; class TempFile; @@ -48,7 +49,7 @@ class PnaclTranslateThread { nacl::DescWrapper* invalid_desc_wrapper, ErrorInfo* error_info, PnaclResources* resources, - PnaclOptions* pnacl_options, + PP_PNaClOptions* pnacl_options, PnaclCoordinator* coordinator, Plugin* plugin); @@ -119,7 +120,7 @@ class PnaclTranslateThread { nacl::DescWrapper* invalid_desc_wrapper_; ErrorInfo* coordinator_error_info_; PnaclResources* resources_; - PnaclOptions* pnacl_options_; + PP_PNaClOptions* pnacl_options_; PnaclCoordinator* coordinator_; Plugin* plugin_; private: diff --git a/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.cc b/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.cc index ce7b566b86..bd8ee9eb51 100644 --- a/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.cc +++ b/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.cc @@ -17,17 +17,20 @@ bool SelLdrLauncherChrome::Start(const char* url) { return false; } -void SelLdrLauncherChrome::Start(PP_Instance instance, - const char* url, - bool uses_irt, - bool uses_ppapi, - bool uses_nonsfi_mode, - bool enable_ppapi_dev, - bool enable_dyncode_syscalls, - bool enable_exception_handling, - bool enable_crash_throttling, - PP_Var* error_message, - pp::CompletionCallback callback) { +void SelLdrLauncherChrome::Start( + PP_Instance instance, + const char* url, + bool uses_irt, + bool uses_ppapi, + bool uses_nonsfi_mode, + bool enable_ppapi_dev, + bool enable_dyncode_syscalls, + bool enable_exception_handling, + bool enable_crash_throttling, + const PP_ManifestService* manifest_service_interface, + void* manifest_service_user_data, + PP_Var* error_message, + pp::CompletionCallback callback) { if (!launch_nacl_process) { pp::Module::Get()->core()->CallOnMainThread(0, callback, PP_ERROR_FAILED); return; @@ -41,6 +44,8 @@ void SelLdrLauncherChrome::Start(PP_Instance instance, PP_FromBool(enable_dyncode_syscalls), PP_FromBool(enable_exception_handling), PP_FromBool(enable_crash_throttling), + manifest_service_interface, + manifest_service_user_data, &channel_, error_message, callback.pp_completion_callback()); diff --git a/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h b/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h index f512535c6f..50e884836c 100644 --- a/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h +++ b/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h @@ -8,6 +8,7 @@ #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_var.h" +#include "ppapi/c/private/ppb_nacl_private.h" #include "ppapi/cpp/completion_callback.h" namespace plugin { @@ -24,6 +25,8 @@ class SelLdrLauncherChrome : public nacl::SelLdrLauncherBase { bool enable_dyncode_syscalls, bool enable_exception_handling, bool enable_crash_throttling, + const PP_ManifestService* manifest_service_interface, + void* manifest_service_user_data, PP_Var* error_message, pp::CompletionCallback callback); }; diff --git a/ppapi/native_client/src/trusted/plugin/service_runtime.cc b/ppapi/native_client/src/trusted/plugin/service_runtime.cc index 2a3048e701..e9eba18348 100644 --- a/ppapi/native_client/src/trusted/plugin/service_runtime.cc +++ b/ppapi/native_client/src/trusted/plugin/service_runtime.cc @@ -50,12 +50,12 @@ #include "ppapi/native_client/src/trusted/plugin/manifest.h" #include "ppapi/native_client/src/trusted/plugin/plugin.h" #include "ppapi/native_client/src/trusted/plugin/plugin_error.h" -#include "ppapi/native_client/src/trusted/plugin/pnacl_options.h" #include "ppapi/native_client/src/trusted/plugin/pnacl_resources.h" #include "ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h" #include "ppapi/native_client/src/trusted/plugin/srpc_client.h" #include "ppapi/native_client/src/trusted/weak_ref/call_on_main_thread.h" +namespace plugin { namespace { // For doing crude quota enforcement on writes to temp files. @@ -64,9 +64,58 @@ namespace { // should be plenty for static data const int64_t kMaxTempQuota = 0x8000000; -} // namespace +class ManifestService { + public: + ManifestService(nacl::WeakRefAnchor* anchor, + PluginReverseInterface* plugin_reverse) + : anchor_(anchor), + plugin_reverse_(plugin_reverse) { + } -namespace plugin { + ~ManifestService() { + anchor_->Unref(); + } + + bool Quit() { + delete this; + return false; + } + + bool StartupInitializationComplete() { + // Release this instance if the ServiceRuntime is already destructed. + if (anchor_->is_abandoned()) { + delete this; + return false; + } + + plugin_reverse_->StartupInitializationComplete(); + return true; + } + + static PP_Bool QuitTrampoline(void* user_data) { + return PP_FromBool(static_cast<ManifestService*>(user_data)->Quit()); + } + + static PP_Bool StartupInitializationCompleteTrampoline(void* user_data) { + return PP_FromBool(static_cast<ManifestService*>(user_data)-> + StartupInitializationComplete()); + } + + private: + // Weak reference to check if plugin_reverse is legally accessible or not. + nacl::WeakRefAnchor* anchor_; + PluginReverseInterface* plugin_reverse_; + + DISALLOW_COPY_AND_ASSIGN(ManifestService); +}; + +// Vtable to pass functions to LaunchSelLdr. +const PP_ManifestService kManifestServiceVTable = { + &ManifestService::QuitTrampoline, + &ManifestService::StartupInitializationCompleteTrampoline, +}; + +} // namespace PluginReverseInterface::PluginReverseInterface( nacl::WeakRefAnchor* anchor, @@ -216,7 +265,7 @@ void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation( NaClLog(4, "Entered OpenManifestEntry_MainThreadContinuation\n"); std::string mapped_url; - PnaclOptions pnacl_options; + PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, 2}; ErrorInfo error_info; if (!manifest_->ResolveKey(p->url, &mapped_url, &pnacl_options, &error_info)) { @@ -236,9 +285,9 @@ void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation( NaClLog(4, "OpenManifestEntry_MainThreadContinuation: " "ResolveKey: %s -> %s (pnacl_translate(%d))\n", - p->url.c_str(), mapped_url.c_str(), pnacl_options.translate()); + p->url.c_str(), mapped_url.c_str(), pnacl_options.translate); - if (pnacl_options.translate()) { + if (pnacl_options.translate) { // Requires PNaCl translation, but that's not supported. NaClLog(4, "OpenManifestEntry_MainThreadContinuation: " @@ -469,14 +518,7 @@ bool ServiceRuntime::LoadModule(nacl::DescWrapper* nacl_desc, bool ServiceRuntime::InitReverseService(ErrorInfo* error_info) { if (uses_nonsfi_mode_) { - // In non-SFI mode, open_resource() is not yet supported, so we do not - // need the reverse service. So, skip the initialization (with calling - // the completion callback). - // Note that there is on going work to replace SRPC by Chrome IPC (not only - // for non-SFI mode, but also for SFI mode) (crbug.com/333950), - // and non-SFI mode will use Chrome IPC for open_resource() after the - // refactoring is done. - rev_interface_->StartupInitializationComplete(); + // In non-SFI mode, no reverse service is set up. Just returns success. return true; } @@ -572,6 +614,8 @@ void ServiceRuntime::StartSelLdr(const SelLdrStartParams& params, callback_factory_.NewCallback(&ServiceRuntime::StartSelLdrContinuation, callback); + ManifestService* manifest_service = + new ManifestService(anchor_->Ref(), rev_interface_); tmp_subprocess->Start(plugin_->pp_instance(), params.url.c_str(), params.uses_irt, @@ -581,6 +625,8 @@ void ServiceRuntime::StartSelLdr(const SelLdrStartParams& params, params.enable_dyncode_syscalls, params.enable_exception_handling, params.enable_crash_throttling, + &kManifestServiceVTable, + manifest_service, &start_sel_ldr_error_message_, internal_callback); subprocess_.reset(tmp_subprocess.release()); diff --git a/ppapi/native_client/src/untrusted/irt_stub/thread_creator.h b/ppapi/native_client/src/untrusted/irt_stub/thread_creator.h index ac4258f996..7adbabe780 100644 --- a/ppapi/native_client/src/untrusted/irt_stub/thread_creator.h +++ b/ppapi/native_client/src/untrusted/irt_stub/thread_creator.h @@ -10,6 +10,14 @@ #include "native_client/src/untrusted/irt/irt.h" #include "ppapi/nacl_irt/public/irt_ppapi.h" +#ifdef __cplusplus +extern "C" { +#endif + void __nacl_register_thread_creator(const struct nacl_irt_ppapihook *hooks); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c index 162e00528d..b085cfbbeb 100644 --- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c +++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c @@ -3085,11 +3085,13 @@ static int32_t Pnacl_M33_PPB_IsolatedFileSystem_Private_Open(PP_Instance instanc /* End wrapper methods for PPB_IsolatedFileSystem_Private_0_2 */ +/* Not generating wrapper methods for PP_ManifestService_1_0 */ + /* Begin wrapper methods for PPB_NaCl_Private_1_0 */ -static void Pnacl_M25_PPB_NaCl_Private_LaunchSelLdr(PP_Instance instance, const char* alleged_url, PP_Bool uses_irt, PP_Bool uses_ppapi, PP_Bool uses_nonsfi_mode, PP_Bool enable_ppapi_dev, PP_Bool enable_dyncode_syscalls, PP_Bool enable_exception_handling, PP_Bool enable_crash_throttling, void* imc_handle, struct PP_Var* error_message, struct PP_CompletionCallback* callback) { +static void Pnacl_M25_PPB_NaCl_Private_LaunchSelLdr(PP_Instance instance, const char* alleged_url, PP_Bool uses_irt, PP_Bool uses_ppapi, PP_Bool uses_nonsfi_mode, PP_Bool enable_ppapi_dev, PP_Bool enable_dyncode_syscalls, PP_Bool enable_exception_handling, PP_Bool enable_crash_throttling, const struct PP_ManifestService_1_0* manifest_service_interface, void* manifest_service_user_data, void* imc_handle, struct PP_Var* error_message, struct PP_CompletionCallback* callback) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; - iface->LaunchSelLdr(instance, alleged_url, uses_irt, uses_ppapi, uses_nonsfi_mode, enable_ppapi_dev, enable_dyncode_syscalls, enable_exception_handling, enable_crash_throttling, imc_handle, error_message, *callback); + iface->LaunchSelLdr(instance, alleged_url, uses_irt, uses_ppapi, uses_nonsfi_mode, enable_ppapi_dev, enable_dyncode_syscalls, enable_exception_handling, enable_crash_throttling, manifest_service_interface, manifest_service_user_data, imc_handle, error_message, *callback); } static PP_Bool Pnacl_M25_PPB_NaCl_Private_StartPpapiProxy(PP_Instance instance) { @@ -3212,21 +3214,11 @@ static PP_NaClReadyState Pnacl_M25_PPB_NaCl_Private_GetNaClReadyState(PP_Instanc return iface->GetNaClReadyState(instance); } -static void Pnacl_M25_PPB_NaCl_Private_SetNaClReadyState(PP_Instance instance, PP_NaClReadyState ready_state) { - const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; - iface->SetNaClReadyState(instance, ready_state); -} - static PP_Bool Pnacl_M25_PPB_NaCl_Private_GetIsInstalled(PP_Instance instance) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; return iface->GetIsInstalled(instance); } -static void Pnacl_M25_PPB_NaCl_Private_SetIsInstalled(PP_Instance instance, PP_Bool is_installed) { - const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; - iface->SetIsInstalled(instance, is_installed); -} - static int32_t Pnacl_M25_PPB_NaCl_Private_GetExitStatus(PP_Instance instance) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; return iface->GetExitStatus(instance); @@ -3242,9 +3234,9 @@ static void Pnacl_M25_PPB_NaCl_Private_Vlog(const char* message) { iface->Vlog(message); } -static void Pnacl_M25_PPB_NaCl_Private_SetInitTime(PP_Instance instance) { +static void Pnacl_M25_PPB_NaCl_Private_InitializePlugin(PP_Instance instance) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; - iface->SetInitTime(instance); + iface->InitializePlugin(instance); } static int64_t Pnacl_M25_PPB_NaCl_Private_GetNexeSize(PP_Instance instance) { @@ -3252,9 +3244,29 @@ static int64_t Pnacl_M25_PPB_NaCl_Private_GetNexeSize(PP_Instance instance) { return iface->GetNexeSize(instance); } -static void Pnacl_M25_PPB_NaCl_Private_SetNexeSize(PP_Instance instance, int64_t nexe_size) { +static PP_Bool Pnacl_M25_PPB_NaCl_Private_RequestNaClManifest(PP_Instance instance, const char* manifest_url, PP_Bool* is_data_uri) { + const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; + return iface->RequestNaClManifest(instance, manifest_url, is_data_uri); +} + +static void Pnacl_M25_PPB_NaCl_Private_GetManifestBaseURL(struct PP_Var* _struct_result, PP_Instance instance) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; - iface->SetNexeSize(instance, nexe_size); + *_struct_result = iface->GetManifestBaseURL(instance); +} + +static PP_Bool Pnacl_M25_PPB_NaCl_Private_ResolvesRelativeToPluginBaseUrl(PP_Instance instance, const char* url) { + const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; + return iface->ResolvesRelativeToPluginBaseUrl(instance, url); +} + +static void Pnacl_M25_PPB_NaCl_Private_ParseDataURL(struct PP_Var* _struct_result, const char* data_url) { + const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; + *_struct_result = iface->ParseDataURL(data_url); +} + +static void Pnacl_M25_PPB_NaCl_Private_ProcessNaClManifest(PP_Instance instance, const char* program_url) { + const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; + iface->ProcessNaClManifest(instance, program_url); } /* End wrapper methods for PPB_NaCl_Private_1_0 */ @@ -5130,8 +5142,10 @@ static const struct PPB_IsolatedFileSystem_Private_0_2 Pnacl_Wrappers_PPB_Isolat .Open = (int32_t (*)(PP_Instance instance, PP_IsolatedFileSystemType_Private type, PP_Resource* file_system, struct PP_CompletionCallback callback))&Pnacl_M33_PPB_IsolatedFileSystem_Private_Open }; +/* Not generating wrapper interface for PP_ManifestService_1_0 */ + static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = { - .LaunchSelLdr = (void (*)(PP_Instance instance, const char* alleged_url, PP_Bool uses_irt, PP_Bool uses_ppapi, PP_Bool uses_nonsfi_mode, PP_Bool enable_ppapi_dev, PP_Bool enable_dyncode_syscalls, PP_Bool enable_exception_handling, PP_Bool enable_crash_throttling, void* imc_handle, struct PP_Var* error_message, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_LaunchSelLdr, + .LaunchSelLdr = (void (*)(PP_Instance instance, const char* alleged_url, PP_Bool uses_irt, PP_Bool uses_ppapi, PP_Bool uses_nonsfi_mode, PP_Bool enable_ppapi_dev, PP_Bool enable_dyncode_syscalls, PP_Bool enable_exception_handling, PP_Bool enable_crash_throttling, const struct PP_ManifestService_1_0* manifest_service_interface, void* manifest_service_user_data, void* imc_handle, struct PP_Var* error_message, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_LaunchSelLdr, .StartPpapiProxy = (PP_Bool (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_StartPpapiProxy, .UrandomFD = (int32_t (*)(void))&Pnacl_M25_PPB_NaCl_Private_UrandomFD, .Are3DInterfacesDisabled = (PP_Bool (*)(void))&Pnacl_M25_PPB_NaCl_Private_Are3DInterfacesDisabled, @@ -5156,15 +5170,17 @@ static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = { .GetUrlScheme = (PP_UrlSchemeType (*)(struct PP_Var url))&Pnacl_M25_PPB_NaCl_Private_GetUrlScheme, .LogToConsole = (void (*)(PP_Instance instance, const char* message))&Pnacl_M25_PPB_NaCl_Private_LogToConsole, .GetNaClReadyState = (PP_NaClReadyState (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetNaClReadyState, - .SetNaClReadyState = (void (*)(PP_Instance instance, PP_NaClReadyState ready_state))&Pnacl_M25_PPB_NaCl_Private_SetNaClReadyState, .GetIsInstalled = (PP_Bool (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetIsInstalled, - .SetIsInstalled = (void (*)(PP_Instance instance, PP_Bool is_installed))&Pnacl_M25_PPB_NaCl_Private_SetIsInstalled, .GetExitStatus = (int32_t (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetExitStatus, .SetExitStatus = (void (*)(PP_Instance instance, int32_t exit_status))&Pnacl_M25_PPB_NaCl_Private_SetExitStatus, .Vlog = (void (*)(const char* message))&Pnacl_M25_PPB_NaCl_Private_Vlog, - .SetInitTime = (void (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_SetInitTime, + .InitializePlugin = (void (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_InitializePlugin, .GetNexeSize = (int64_t (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetNexeSize, - .SetNexeSize = (void (*)(PP_Instance instance, int64_t nexe_size))&Pnacl_M25_PPB_NaCl_Private_SetNexeSize + .RequestNaClManifest = (PP_Bool (*)(PP_Instance instance, const char* manifest_url, PP_Bool* is_data_uri))&Pnacl_M25_PPB_NaCl_Private_RequestNaClManifest, + .GetManifestBaseURL = (struct PP_Var (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetManifestBaseURL, + .ResolvesRelativeToPluginBaseUrl = (PP_Bool (*)(PP_Instance instance, const char* url))&Pnacl_M25_PPB_NaCl_Private_ResolvesRelativeToPluginBaseUrl, + .ParseDataURL = (struct PP_Var (*)(const char* data_url))&Pnacl_M25_PPB_NaCl_Private_ParseDataURL, + .ProcessNaClManifest = (void (*)(PP_Instance instance, const char* program_url))&Pnacl_M25_PPB_NaCl_Private_ProcessNaClManifest }; static const struct PPB_NetAddress_Private_0_1 Pnacl_Wrappers_PPB_NetAddress_Private_0_1 = { diff --git a/ppapi/native_client/tests/nacl_browser/fault_injection/fault_pm_nameservice_test.cc b/ppapi/native_client/tests/nacl_browser/fault_injection/fault_pm_nameservice_test.cc index 61ed0f36e5..72ae9286ee 100644 --- a/ppapi/native_client/tests/nacl_browser/fault_injection/fault_pm_nameservice_test.cc +++ b/ppapi/native_client/tests/nacl_browser/fault_injection/fault_pm_nameservice_test.cc @@ -74,31 +74,6 @@ void dump_output(nacl::StringBuffer *sb, int d, size_t nbytes) { sb->Printf("\n"); } -void EnumerateNames(NaClSrpcChannel *nschan, nacl::StringBuffer *sb) { - char buffer[1024]; - uint32_t nbytes = sizeof buffer; - - if (NACL_SRPC_RESULT_OK != NaClSrpcInvokeBySignature(nschan, - NACL_NAME_SERVICE_LIST, - &nbytes, buffer)) { - sb->Printf("NaClSrpcInvokeBySignature failed\n"); - return; - } - sb->Printf("nbytes = %u\n", (size_t) nbytes); - if (nbytes == sizeof buffer) { - sb->Printf("Insufficent space for namespace enumeration\n"); - return; - } - - size_t name_len; - for (char *p = buffer; - static_cast<size_t>(p - buffer) < nbytes; - p += name_len) { - name_len = strlen(p) + 1; - sb->Printf("%s\n", p); - } -} - void Initialize(const pp::Var& message_data, nacl::StringBuffer* sb) { if (g_ns_channel_initialized) { return; @@ -119,14 +94,6 @@ void Initialize(const pp::Var& message_data, nacl::StringBuffer* sb) { } // -// Return name service output -// -void NameServiceDump(const pp::Var& message_data, nacl::StringBuffer* sb) { - Initialize(message_data, sb); - EnumerateNames(&g_ns_channel, sb); -} - -// // Dump RNG output into a string. // void RngDump(const pp::Var& message_data, nacl::StringBuffer* sb) { @@ -203,7 +170,6 @@ class MyInstance : public pp::Instance { void MyInstance::HandleMessage(const pp::Var& message_data) { static struct PostMessageHandlerDesc kMsgHandlers[] = { { "init", Initialize }, - { "nameservice", NameServiceDump }, { "rng", RngDump }, { "manifest_test", ManifestTest }, { reinterpret_cast<char const *>(NULL), diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index 11eb697655..f8605db61b 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -247,6 +247,8 @@ 'nacl_irt/irt_ppapi.cc', 'nacl_irt/irt_ppapi.h', 'nacl_irt/irt_start.cc', + 'nacl_irt/manifest_service.cc', + 'nacl_irt/manifest_service.h', 'nacl_irt/plugin_main.cc', 'nacl_irt/plugin_main.h', 'nacl_irt/plugin_startup.cc', diff --git a/ppapi/proxy/file_system_resource_unittest.cc b/ppapi/proxy/file_system_resource_unittest.cc index f93695439c..9b5d981242 100644 --- a/ppapi/proxy/file_system_resource_unittest.cc +++ b/ppapi/proxy/file_system_resource_unittest.cc @@ -74,7 +74,15 @@ class MockRequestQuotaCallback { class FileSystemResourceTest : public PluginProxyTest { public: - FileSystemResourceTest() {} + const PPB_FileSystem_1_0* file_system_iface; + const PPB_FileRef_1_1* file_ref_iface; + const PPB_FileIO_1_1* file_io_iface; + + FileSystemResourceTest() + : file_system_iface(thunk::GetPPB_FileSystem_1_0_Thunk()), + file_ref_iface(thunk::GetPPB_FileRef_1_1_Thunk()), + file_io_iface(thunk::GetPPB_FileIO_1_1_Thunk()) { + } void SendReply(const ResourceMessageCallParams& params, int32_t result, @@ -93,7 +101,7 @@ class FileSystemResourceTest : public PluginProxyTest { // Opens the given file system. void OpenFileSystem(PP_Resource file_system) { MockCompletionCallback cb; - int32_t result = thunk::GetPPB_FileSystem_1_0_Thunk()->Open( + int32_t result = file_system_iface->Open( file_system, kExpectedFileSystemSize, PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb)); @@ -119,7 +127,7 @@ class FileSystemResourceTest : public PluginProxyTest { PP_Resource file_ref, PP_Resource file_system) { MockCompletionCallback cb; - int32_t result = thunk::GetPPB_FileIO_1_1_Thunk()->Open( + int32_t result = file_io_iface->Open( file_io, file_ref, PP_FILEOPENFLAG_WRITE, @@ -149,14 +157,14 @@ class FileSystemResourceTest : public PluginProxyTest { // Test that Open fails if either host returns failure. The other tests exercise // the case where both hosts return PP_OK. TEST_F(FileSystemResourceTest, OpenFailure) { - const PPB_FileSystem_1_0* fs_iface = thunk::GetPPB_FileSystem_1_0_Thunk(); // Fail if the first reply doesn't return PP_OK. { LockingResourceReleaser file_system( - fs_iface->Create(pp_instance(), PP_FILESYSTEMTYPE_LOCALTEMPORARY)); + file_system_iface->Create(pp_instance(), + PP_FILESYSTEMTYPE_LOCALTEMPORARY)); MockCompletionCallback cb; - int32_t result = thunk::GetPPB_FileSystem_1_0_Thunk()->Open( + int32_t result = file_system_iface->Open( file_system.get(), kExpectedFileSystemSize, PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb)); @@ -176,10 +184,11 @@ TEST_F(FileSystemResourceTest, OpenFailure) { // Fail if the second reply doesn't return PP_OK. { LockingResourceReleaser file_system( - fs_iface->Create(pp_instance(), PP_FILESYSTEMTYPE_LOCALTEMPORARY)); + file_system_iface->Create(pp_instance(), + PP_FILESYSTEMTYPE_LOCALTEMPORARY)); MockCompletionCallback cb; - int32_t result = thunk::GetPPB_FileSystem_1_0_Thunk()->Open( + int32_t result = file_system_iface->Open( file_system.get(), kExpectedFileSystemSize, PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb)); @@ -199,24 +208,21 @@ TEST_F(FileSystemResourceTest, OpenFailure) { } TEST_F(FileSystemResourceTest, RequestQuota) { - const PPB_FileSystem_1_0* fs_iface = thunk::GetPPB_FileSystem_1_0_Thunk(); - const PPB_FileRef_1_1* fref_iface = thunk::GetPPB_FileRef_1_1_Thunk(); - const PPB_FileIO_1_1* fio_iface = thunk::GetPPB_FileIO_1_1_Thunk(); - LockingResourceReleaser file_system( - fs_iface->Create(pp_instance(), PP_FILESYSTEMTYPE_LOCALTEMPORARY)); + file_system_iface->Create(pp_instance(), + PP_FILESYSTEMTYPE_LOCALTEMPORARY)); OpenFileSystem(file_system.get()); // Create and open two files in the file system. FileIOResource calls // FileSystemResource::OpenQuotaFile on success. LockingResourceReleaser file_ref1( - fref_iface->Create(file_system.get(), "/file1")); - LockingResourceReleaser file_io1(fio_iface->Create(pp_instance())); + file_ref_iface->Create(file_system.get(), "/file1")); + LockingResourceReleaser file_io1(file_io_iface->Create(pp_instance())); OpenFile(file_io1.get(), file_ref1.get(), file_system.get()); LockingResourceReleaser file_ref2( - fref_iface->Create(file_system.get(), "/file2")); - LockingResourceReleaser file_io2(fio_iface->Create(pp_instance())); + file_ref_iface->Create(file_system.get(), "/file2")); + LockingResourceReleaser file_io2(file_io_iface->Create(pp_instance())); OpenFile(file_io2.get(), file_ref2.get(), file_system.get()); EnterResource<PPB_FileSystem_API> enter(file_system.get(), true); diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.cc b/ppapi/proxy/ppapi_command_buffer_proxy.cc index 1e4820d5ec..d747019158 100644 --- a/ppapi/proxy/ppapi_command_buffer_proxy.cc +++ b/ppapi/proxy/ppapi_command_buffer_proxy.cc @@ -132,6 +132,7 @@ scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::CreateTransferBuffer( // Map the shared memory on demand. if (!shared_memory->memory()) { if (!shared_memory->Map(handle.size())) { + *id = -1; return NULL; } } diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index e54dae72ef..e099b36709 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -753,6 +753,9 @@ IPC_MESSAGE_CONTROL0(PpapiHostMsg_Keepalive) IPC_MESSAGE_CONTROL1(PpapiHostMsg_ChannelCreated, IPC::ChannelHandle /* handle */) +// Notify the renderer that the PPAPI channel gets ready in the plugin. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_StartupInitializationComplete); + // Logs the given message to the console of all instances. IPC_MESSAGE_CONTROL4(PpapiHostMsg_LogWithSource, PP_Instance /* instance */, diff --git a/ppapi/proxy/ppb_audio_proxy.cc b/ppapi/proxy/ppb_audio_proxy.cc index 58f5abc0d4..d84c3cb699 100644 --- a/ppapi/proxy/ppb_audio_proxy.cc +++ b/ppapi/proxy/ppb_audio_proxy.cc @@ -95,6 +95,8 @@ PP_Resource Audio::GetCurrentConfig() { PP_Bool Audio::StartPlayback() { if (playing()) return PP_TRUE; + if (!PPB_Audio_Shared::IsThreadFunctionReady()) + return PP_FALSE; SetStartPlaybackState(); PluginDispatcher::GetForResource(this)->Send( new PpapiHostMsg_PPBAudio_StartOrStop( diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc index be0cc34751..85f1f16210 100644 --- a/ppapi/proxy/ppb_instance_proxy.cc +++ b/ppapi/proxy/ppb_instance_proxy.cc @@ -959,12 +959,11 @@ void PPB_Instance_Proxy::OnHostMsgSetTickmarks( const std::vector<PP_Rect>& tickmarks) { if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) return; - if (tickmarks.empty()) - return; + const PP_Rect* array = tickmarks.empty() ? NULL : &tickmarks[0]; EnterInstanceNoLock enter(instance); if (enter.succeeded()) { enter.functions()->SetTickmarks(instance, - &tickmarks[0], + array, static_cast<uint32_t>(tickmarks.size())); } } diff --git a/ppapi/shared_impl/ppb_audio_shared.cc b/ppapi/shared_impl/ppb_audio_shared.cc index ced1146697..741a86f99b 100644 --- a/ppapi/shared_impl/ppb_audio_shared.cc +++ b/ppapi/shared_impl/ppb_audio_shared.cc @@ -5,18 +5,18 @@ #include "ppapi/shared_impl/ppb_audio_shared.h" #include "base/logging.h" +#include "ppapi/nacl_irt/public/irt_ppapi.h" #include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/ppb_audio_config_shared.h" #include "ppapi/shared_impl/proxy_lock.h" namespace ppapi { -#if defined(OS_NACL) namespace { +bool g_nacl_mode = false; // Because this is static, the function pointers will be NULL initially. -PP_ThreadFunctions thread_functions; +PP_ThreadFunctions g_thread_functions; } -#endif // defined(OS_NACL) AudioCallbackCombined::AudioCallbackCombined() : callback_1_0_(NULL), callback_(NULL) {} @@ -50,10 +50,7 @@ void AudioCallbackCombined::Run(void* sample_buffer, PPB_Audio_Shared::PPB_Audio_Shared() : playing_(false), shared_memory_size_(0), -#if defined(OS_NACL) - thread_id_(0), - thread_active_(false), -#endif + nacl_thread_active_(false), user_data_(NULL), client_buffer_size_bytes_(0), bytes_per_second_(0), @@ -75,11 +72,8 @@ void PPB_Audio_Shared::SetCallback(const AudioCallbackCombined& callback, void PPB_Audio_Shared::SetStartPlaybackState() { DCHECK(!playing_); -#if !defined(OS_NACL) DCHECK(!audio_thread_.get()); -#else - DCHECK(!thread_active_); -#endif + DCHECK(!nacl_thread_active_); // If the socket doesn't exist, that means that the plugin has started before // the browser has had a chance to create all the shared memory info and // notify us. This is a common case. In this case, we just set the playing_ @@ -138,54 +132,68 @@ void PPB_Audio_Shared::StartThread() { // start up quickly enough. memset(shared_memory_->memory(), 0, shared_memory_size_); memset(client_buffer_.get(), 0, client_buffer_size_bytes_); -#if !defined(OS_NACL) - DCHECK(!audio_thread_.get()); - audio_thread_.reset( - new base::DelegateSimpleThread(this, "plugin_audio_thread")); - audio_thread_->Start(); -#else - // Use NaCl's special API for IRT code that creates threads that call back - // into user code. - if (NULL == thread_functions.thread_create || - NULL == thread_functions.thread_join) - return; - int result = thread_functions.thread_create(&thread_id_, CallRun, this); - DCHECK_EQ(result, 0); - thread_active_ = true; -#endif + if (g_nacl_mode) { + // Use NaCl's special API for IRT code that creates threads that call back + // into user code. + if (!IsThreadFunctionReady()) + return; + + DCHECK(!nacl_thread_active_); + int result = + g_thread_functions.thread_create(&nacl_thread_id_, CallRun, this); + DCHECK_EQ(0, result); + nacl_thread_active_ = true; + } else { + DCHECK(!audio_thread_.get()); + audio_thread_.reset( + new base::DelegateSimpleThread(this, "plugin_audio_thread")); + audio_thread_->Start(); + } } void PPB_Audio_Shared::StopThread() { -#if !defined(OS_NACL) - if (audio_thread_.get()) { - // In general, the audio thread should not do Pepper calls, but it might - // anyway (for example, our Audio test does CallOnMainThread). If it did - // a pepper call which acquires the lock (most of them do), and we try to - // shut down the thread and Join it while holding the lock, we would - // deadlock. So we give up the lock here so that the thread at least _can_ - // make Pepper calls without causing deadlock. - CallWhileUnlocked(base::Bind(&base::DelegateSimpleThread::Join, - base::Unretained(audio_thread_.get()))); - audio_thread_.reset(); - } -#else - if (thread_active_) { - // See comment above about why we unlock here. - int result = CallWhileUnlocked(thread_functions.thread_join, thread_id_); - DCHECK_EQ(0, result); - thread_active_ = false; + // In general, the audio thread should not do Pepper calls, but it might + // anyway (for example, our Audio test does CallOnMainThread). If it did a + // pepper call which acquires the lock (most of them do), and we try to shut + // down the thread and Join it while holding the lock, we would deadlock. So + // we give up the lock here so that the thread at least _can_ make Pepper + // calls without causing deadlock. + if (g_nacl_mode) { + if (nacl_thread_active_) { + int result = + CallWhileUnlocked(g_thread_functions.thread_join, nacl_thread_id_); + DCHECK_EQ(0, result); + nacl_thread_active_ = false; + } + } else { + if (audio_thread_.get()) { + CallWhileUnlocked(base::Bind(&base::DelegateSimpleThread::Join, + base::Unretained(audio_thread_.get()))); + audio_thread_.reset(); + } } -#endif } -#if defined(OS_NACL) +// static +bool PPB_Audio_Shared::IsThreadFunctionReady() { + if (!g_nacl_mode) + return true; + + return (g_thread_functions.thread_create != NULL && + g_thread_functions.thread_join != NULL); +} + +// static +void PPB_Audio_Shared::SetNaClMode() { + g_nacl_mode = true; +} + // static void PPB_Audio_Shared::SetThreadFunctions( const struct PP_ThreadFunctions* functions) { - DCHECK(thread_functions.thread_create == NULL); - DCHECK(thread_functions.thread_join == NULL); - thread_functions = *functions; + DCHECK(g_nacl_mode); + g_thread_functions = *functions; } // static @@ -193,7 +201,6 @@ void PPB_Audio_Shared::CallRun(void* self) { PPB_Audio_Shared* audio = static_cast<PPB_Audio_Shared*>(self); audio->Run(); } -#endif void PPB_Audio_Shared::Run() { int pending_data = 0; diff --git a/ppapi/shared_impl/ppb_audio_shared.h b/ppapi/shared_impl/ppb_audio_shared.h index 6ba8cac2e6..31888c8826 100644 --- a/ppapi/shared_impl/ppb_audio_shared.h +++ b/ppapi/shared_impl/ppb_audio_shared.h @@ -15,9 +15,7 @@ #include "ppapi/shared_impl/resource.h" #include "ppapi/thunk/ppb_audio_api.h" -#if defined(OS_NACL) -#include "ppapi/nacl_irt/public/irt_ppapi.h" -#endif +struct PP_ThreadFunctions; namespace ppapi { @@ -79,11 +77,20 @@ class PPAPI_SHARED_EXPORT PPB_Audio_Shared PP_AudioSampleRate sample_rate, int sample_frame_count); -#if defined(OS_NACL) + // Returns whether a thread can be created on the client context. + // In trusted plugin, this should always return true, as it uses Chrome's + // thread library. In NaCl plugin, this returns whether SetThreadFunctions + // was invoked properly. + static bool IsThreadFunctionReady(); + + // Configures this class to run in a NaCl plugin. + // If called, SetThreadFunctions() must be called before calling + // SetStartPlaybackState() on any instance of this class. + static void SetNaClMode(); + // NaCl has a special API for IRT code to create threads that can call back // into user code. static void SetThreadFunctions(const struct PP_ThreadFunctions* functions); -#endif private: // Starts execution of the audio thread. @@ -110,15 +117,12 @@ class PPAPI_SHARED_EXPORT PPB_Audio_Shared // The size of the sample buffer in bytes. size_t shared_memory_size_; -#if !defined(OS_NACL) // When the callback is set, this thread is spawned for calling it. scoped_ptr<base::DelegateSimpleThread> audio_thread_; -#else - uintptr_t thread_id_; - bool thread_active_; + uintptr_t nacl_thread_id_; + bool nacl_thread_active_; static void CallRun(void* self); -#endif // Callback to call when audio is ready to accept new samples. AudioCallbackCombined callback_; diff --git a/ppapi/tests/DEPS b/ppapi/tests/DEPS index 4f757144fc..06b64ab19b 100644 --- a/ppapi/tests/DEPS +++ b/ppapi/tests/DEPS @@ -12,6 +12,11 @@ include_rules = [ "+ppapi/lib", "+ppapi/tests", "+ppapi/utility", + + # Test to confirm whether PPB_Audio_Shared works properly in NaCl needs to + # call nacl_irt_ppapihook internally to emulate some erroneous situation. + "+native_client/src/untrusted/irt/irt.h", + "+ppapi/native_client/src/untrusted/irt_stub/thread_creator.h", ] # checkdeps.py shouldn't check include paths for files in clang, which aren't # part of the chrome build. diff --git a/ppapi/tests/test_audio.cc b/ppapi/tests/test_audio.cc index 4fea6e8646..1c1c9b594a 100644 --- a/ppapi/tests/test_audio.cc +++ b/ppapi/tests/test_audio.cc @@ -12,10 +12,87 @@ #include "ppapi/tests/testing_instance.h" #include "ppapi/tests/test_utils.h" +#if defined(__native_client__) +#include "native_client/src/untrusted/irt/irt.h" +#include "ppapi/native_client/src/untrusted/irt_stub/thread_creator.h" +#endif + #define ARRAYSIZE_UNSAFE(a) \ ((sizeof(a) / sizeof(*(a))) / \ static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) +#if defined(__native_client__) +namespace { + +void GetNaClIrtPpapiHook(struct nacl_irt_ppapihook* hooks) { + nacl_interface_query(NACL_IRT_PPAPIHOOK_v0_1, hooks, sizeof(*hooks)); +} + +struct PP_ThreadFunctions g_thread_funcs = {}; + +void ThreadFunctionsGetter(const struct PP_ThreadFunctions* thread_funcs) { + g_thread_funcs = *thread_funcs; +} + +// In order to check if the thread_create is called, CountingThreadCreate() +// increments this variable. Callers can check if the function is actually +// called by looking at this value. +int g_num_thread_create_called = 0; +int g_num_thread_join_called = 0; + +int CountingThreadCreate(uintptr_t* tid, + void (*func)(void* thread_argument), + void* thread_argument) { + ++g_num_thread_create_called; + return g_thread_funcs.thread_create(tid, func, thread_argument); +} + +int CountingThreadJoin(uintptr_t tid) { + ++g_num_thread_join_called; + return g_thread_funcs.thread_join(tid); +} + +// Sets NULL for PP_ThreadFunctions to emulate the situation that +// ppapi_register_thread_creator() is not yet called. +void SetNullThreadFunctions() { + nacl_irt_ppapihook hooks; + GetNaClIrtPpapiHook(&hooks); + PP_ThreadFunctions thread_functions = {}; + hooks.ppapi_register_thread_creator(&thread_functions); +} + +void InjectCountingThreadFunctions() { + // First of all, we extract the system default thread functions. + // Internally, __nacl_register_thread_creator calls + // hooks.ppapi_register_thread_creator with default PP_ThreadFunctions + // instance. ThreadFunctionGetter stores it to g_thread_funcs. + nacl_irt_ppapihook hooks = { NULL, ThreadFunctionsGetter }; + __nacl_register_thread_creator(&hooks); + + // Here g_thread_funcs stores the thread functions. + // Inject the CountingThreadCreate. + PP_ThreadFunctions thread_functions = { + CountingThreadCreate, + CountingThreadJoin, + }; + GetNaClIrtPpapiHook(&hooks); + hooks.ppapi_register_thread_creator(&thread_functions); +} + +// Resets the PP_ThreadFunctions on exit from the scope. +class ScopedThreadFunctionsResetter { + public: + ScopedThreadFunctionsResetter() {} + ~ScopedThreadFunctionsResetter() { + nacl_irt_ppapihook hooks; + GetNaClIrtPpapiHook(&hooks); + __nacl_register_thread_creator(&hooks); + } +}; + +} // namespace +#endif // __native_client__ + REGISTER_TEST_CASE(Audio); TestAudio::TestAudio(TestingInstance* instance) @@ -53,6 +130,11 @@ void TestAudio::RunTests(const std::string& filter) { RUN_TEST(AudioCallback2, filter); RUN_TEST(AudioCallback3, filter); RUN_TEST(AudioCallback4, filter); + +#if defined(__native_client__) + RUN_TEST(AudioThreadCreatorIsRequired, filter); + RUN_TEST(AudioThreadCreatorIsCalled, filter); +#endif } // Test creating audio resources for all guaranteed sample rates and various @@ -319,6 +401,91 @@ std::string TestAudio::TestAudioCallback4() { PASS(); } +#if defined(__native_client__) +// Tests the behavior of the thread_create functions. +// For PPB_Audio_Shared to work properly, the user code must call +// ppapi_register_thread_creator(). This test checks the error handling for the +// case when user code doesn't call ppapi_register_thread_creator(). +std::string TestAudio::TestAudioThreadCreatorIsRequired() { + // We'll inject some thread functions in this test case. + // Reset them at the end of this case. + ScopedThreadFunctionsResetter thread_resetter; + + // Set the thread functions to NULLs to emulate the situation where + // ppapi_register_thread_creator() is not called by user code. + SetNullThreadFunctions(); + + PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024); + ASSERT_TRUE(ac); + audio_callback_method_ = NULL; + PP_Resource audio = audio_interface_->Create( + instance_->pp_instance(), ac, AudioCallbackTrampoline, this); + core_interface_->ReleaseResource(ac); + ac = 0; + + // StartPlayback() fails, because no thread creating function + // is available. + ASSERT_FALSE(audio_interface_->StartPlayback(audio)); + + // If any more audio callbacks are generated, + // we should crash (which is good). + audio_callback_method_ = NULL; + + core_interface_->ReleaseResource(audio); + + PASS(); +} + +// Tests whether the thread functions passed from the user code are actually +// called. +std::string TestAudio::TestAudioThreadCreatorIsCalled() { + // We'll inject some thread functions in this test case. + // Reset them at the end of this case. + ScopedThreadFunctionsResetter thread_resetter; + + // Inject the thread counting function. In the injected function, + // when called, g_num_thread_create_called is incremented. + g_num_thread_create_called = 0; + g_num_thread_join_called = 0; + InjectCountingThreadFunctions(); + + PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024); + ASSERT_TRUE(ac); + audio_callback_method_ = NULL; + PP_Resource audio = audio_interface_->Create( + instance_->pp_instance(), ac, AudioCallbackTrampoline, this); + core_interface_->ReleaseResource(ac); + ac = 0; + + audio_callback_event_.Reset(); + test_done_ = false; + + audio_callback_method_ = &TestAudio::AudioCallbackTest; + ASSERT_TRUE(audio_interface_->StartPlayback(audio)); + + // Wait for the audio callback to be called. + audio_callback_event_.Wait(); + // Here, the injected thread_create is called, but thread_join is not yet. + ASSERT_EQ(1, g_num_thread_create_called); + ASSERT_EQ(0, g_num_thread_join_called); + + ASSERT_TRUE(audio_interface_->StopPlayback(audio)); + + test_done_ = true; + + // Here, the injected thread_join is called. + ASSERT_EQ(1, g_num_thread_join_called); + + // If any more audio callbacks are generated, + // we should crash (which is good). + audio_callback_method_ = NULL; + + core_interface_->ReleaseResource(audio); + + PASS(); +} +#endif + // TODO(raymes): Test that actually playback happens correctly, etc. static void Crash() { diff --git a/ppapi/tests/test_audio.h b/ppapi/tests/test_audio.h index 56e6254e18..63e06f48e2 100644 --- a/ppapi/tests/test_audio.h +++ b/ppapi/tests/test_audio.h @@ -30,6 +30,11 @@ class TestAudio : public TestCase { std::string TestAudioCallback3(); std::string TestAudioCallback4(); +#if defined(__native_client__) + std::string TestAudioThreadCreatorIsRequired(); + std::string TestAudioThreadCreatorIsCalled(); +#endif + // Calls |audio_callback_method_| (where |user_data| is "this"). static void AudioCallbackTrampoline(void* sample_buffer, uint32_t buffer_size_in_bytes, |