| Index: src/trusted/plugin/plugin.cc
|
| diff --git a/src/trusted/plugin/plugin.cc b/src/trusted/plugin/plugin.cc
|
| deleted file mode 100644
|
| index 6a3d5c86a8cba21eadf5f330ee8f58ee55a08f70..0000000000000000000000000000000000000000
|
| --- a/src/trusted/plugin/plugin.cc
|
| +++ /dev/null
|
| @@ -1,1869 +0,0 @@
|
| -/*
|
| - * Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - */
|
| -
|
| -#ifdef _MSC_VER
|
| -// Do not warn about use of std::copy with raw pointers.
|
| -#pragma warning(disable : 4996)
|
| -#endif
|
| -
|
| -#include "native_client/src/trusted/plugin/plugin.h"
|
| -
|
| -#include <assert.h>
|
| -#include <fcntl.h>
|
| -#include <stdarg.h>
|
| -#include <stdio.h>
|
| -#include <stdlib.h>
|
| -#include <string.h>
|
| -
|
| -#include <sys/types.h>
|
| -#include <sys/stat.h>
|
| -
|
| -#include <algorithm>
|
| -#include <deque>
|
| -#include <string>
|
| -#include <vector>
|
| -
|
| -#include "native_client/src/include/nacl_base.h"
|
| -#include "native_client/src/include/nacl_macros.h"
|
| -#include "native_client/src/include/nacl_scoped_ptr.h"
|
| -#include "native_client/src/include/nacl_string.h"
|
| -#include "native_client/src/include/portability.h"
|
| -#include "native_client/src/include/portability_io.h"
|
| -#include "native_client/src/include/portability_string.h"
|
| -#include "native_client/src/shared/platform/nacl_check.h"
|
| -#include "native_client/src/shared/platform/nacl_time.h"
|
| -#include "native_client/src/shared/ppapi_proxy/browser_ppp.h"
|
| -#include "native_client/src/trusted/desc/nacl_desc_base.h"
|
| -#include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
|
| -#include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
|
| -#include "native_client/src/trusted/handle_pass/browser_handle.h"
|
| -#include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
|
| -#include "native_client/src/trusted/plugin/browser_interface.h"
|
| -#include "native_client/src/trusted/plugin/desc_based_handle.h"
|
| -#include "native_client/src/trusted/plugin/manifest.h"
|
| -#include "native_client/src/trusted/plugin/nacl_subprocess.h"
|
| -#include "native_client/src/trusted/plugin/nexe_arch.h"
|
| -#include "native_client/src/trusted/plugin/plugin_error.h"
|
| -#include "native_client/src/trusted/plugin/scriptable_handle.h"
|
| -#include "native_client/src/trusted/plugin/service_runtime.h"
|
| -#include "native_client/src/trusted/plugin/string_encoding.h"
|
| -#include "native_client/src/trusted/plugin/utility.h"
|
| -#include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
|
| -#include "native_client/src/trusted/service_runtime/nacl_error_code.h"
|
| -
|
| -#include "ppapi/c/dev/ppp_find_dev.h"
|
| -#include "ppapi/c/dev/ppp_printing_dev.h"
|
| -#include "ppapi/c/dev/ppp_scrollbar_dev.h"
|
| -#include "ppapi/c/dev/ppp_selection_dev.h"
|
| -#include "ppapi/c/dev/ppp_widget_dev.h"
|
| -#include "ppapi/c/dev/ppp_zoom_dev.h"
|
| -#include "ppapi/c/pp_errors.h"
|
| -#include "ppapi/c/ppp_input_event.h"
|
| -#include "ppapi/c/ppp_instance.h"
|
| -#include "ppapi/c/private/ppb_uma_private.h"
|
| -#include "ppapi/cpp/dev/find_dev.h"
|
| -#include "ppapi/cpp/dev/printing_dev.h"
|
| -#include "ppapi/cpp/dev/scrollbar_dev.h"
|
| -#include "ppapi/cpp/dev/selection_dev.h"
|
| -#include "ppapi/cpp/dev/url_util_dev.h"
|
| -#include "ppapi/cpp/dev/widget_client_dev.h"
|
| -#include "ppapi/cpp/dev/zoom_dev.h"
|
| -#include "ppapi/cpp/image_data.h"
|
| -#include "ppapi/cpp/input_event.h"
|
| -#include "ppapi/cpp/module.h"
|
| -#include "ppapi/cpp/rect.h"
|
| -
|
| -using ppapi_proxy::BrowserPpp;
|
| -
|
| -namespace plugin {
|
| -
|
| -namespace {
|
| -
|
| -bool GetReadyStateProperty(void* obj, SrpcParams* params) {
|
| - Plugin* plugin = static_cast<Plugin*>(obj);
|
| - params->outs()[0]->u.ival = plugin->nacl_ready_state();
|
| - return true;
|
| -}
|
| -
|
| -const char* const kTypeAttribute = "type";
|
| -// The "src" attribute of the <embed> tag. The value is expected to be either
|
| -// a URL or URI pointing to the manifest file (which is expected to contain
|
| -// JSON matching ISAs with .nexe URLs).
|
| -const char* const kSrcManifestAttribute = "src";
|
| -// The "nacl" attribute of the <embed> tag. We use the value of this attribute
|
| -// to find the manifest file when NaCl is registered as a plug-in for another
|
| -// MIME type because the "src" attribute is used to supply us with the resource
|
| -// of that MIME type that we're supposed to display.
|
| -const char* const kNaClManifestAttribute = "nacl";
|
| -// This is a pretty arbitrary limit on the byte size of the NaCl manfest file.
|
| -// Note that the resulting string object has to have at least one byte extra
|
| -// for the null termination character.
|
| -const size_t kNaClManifestMaxFileBytes = 1024 * 1024;
|
| -
|
| -// URL schemes that we treat in special ways.
|
| -const char* const kChromeExtensionUriScheme = "chrome-extension";
|
| -const char* const kDataUriScheme = "data";
|
| -
|
| -// The key used to find the dictionary nexe URLs in the manifest file.
|
| -const char* const kNexesKey = "nexes";
|
| -
|
| -bool GetLastError(void* obj, SrpcParams* params) {
|
| - NaClSrpcArg** outs = params->outs();
|
| - PLUGIN_PRINTF(("GetLastError (obj=%p)\n", obj));
|
| -
|
| - Plugin* plugin = static_cast<Plugin*>(obj);
|
| - outs[0]->arrays.str = strdup(plugin->last_error_string().c_str());
|
| - return true;
|
| -}
|
| -
|
| -// Up to 20 seconds
|
| -const int64_t kTimeSmallMin = 1; // in ms
|
| -const int64_t kTimeSmallMax = 20000; // in ms
|
| -const uint32_t kTimeSmallBuckets = 100;
|
| -
|
| -// Up to 3 minutes, 20 seconds
|
| -const int64_t kTimeMediumMin = 10; // in ms
|
| -const int64_t kTimeMediumMax = 200000; // in ms
|
| -const uint32_t kTimeMediumBuckets = 100;
|
| -
|
| -// Up to 33 minutes.
|
| -const int64_t kTimeLargeMin = 100; // in ms
|
| -const int64_t kTimeLargeMax = 2000000; // in ms
|
| -const uint32_t kTimeLargeBuckets = 100;
|
| -
|
| -const int64_t kSizeKBMin = 1;
|
| -const int64_t kSizeKBMax = 512*1024; // very large .nexe
|
| -const uint32_t kSizeKBBuckets = 100;
|
| -
|
| -const PPB_UMA_Private* GetUMAInterface() {
|
| - pp::Module *module = pp::Module::Get();
|
| - CHECK(module);
|
| - return static_cast<const PPB_UMA_Private*>(
|
| - module->GetBrowserInterface(PPB_UMA_PRIVATE_INTERFACE));
|
| -}
|
| -
|
| -void HistogramTimeSmall(const std::string& name, int64_t ms) {
|
| - if (ms < 0) return;
|
| -
|
| - const PPB_UMA_Private* ptr = GetUMAInterface();
|
| - if (ptr == NULL) return;
|
| -
|
| - ptr->HistogramCustomTimes(pp::Var(name).pp_var(),
|
| - ms,
|
| - kTimeSmallMin, kTimeSmallMax,
|
| - kTimeSmallBuckets);
|
| -}
|
| -
|
| -void HistogramTimeMedium(const std::string& name, int64_t ms) {
|
| - if (ms < 0) return;
|
| -
|
| - const PPB_UMA_Private* ptr = GetUMAInterface();
|
| - if (ptr == NULL) return;
|
| -
|
| - ptr->HistogramCustomTimes(pp::Var(name).pp_var(),
|
| - ms,
|
| - kTimeMediumMin, kTimeMediumMax,
|
| - kTimeMediumBuckets);
|
| -}
|
| -
|
| -void HistogramTimeLarge(const std::string& name, int64_t ms) {
|
| - if (ms < 0) return;
|
| -
|
| - const PPB_UMA_Private* ptr = GetUMAInterface();
|
| - if (ptr == NULL) return;
|
| -
|
| - ptr->HistogramCustomTimes(pp::Var(name).pp_var(),
|
| - ms,
|
| - kTimeLargeMin, kTimeLargeMax,
|
| - kTimeLargeBuckets);
|
| -}
|
| -
|
| -void HistogramSizeKB(const std::string& name, int32_t sample) {
|
| - if (sample < 0) return;
|
| -
|
| - const PPB_UMA_Private* ptr = GetUMAInterface();
|
| - if (ptr == NULL) return;
|
| -
|
| - ptr->HistogramCustomCounts(pp::Var(name).pp_var(),
|
| - sample,
|
| - kSizeKBMin, kSizeKBMax,
|
| - kSizeKBBuckets);
|
| -}
|
| -
|
| -void HistogramEnumerate(const std::string& name, int sample, int maximum,
|
| - int out_of_range_replacement) {
|
| - if (sample < 0 || sample >= maximum) {
|
| - if (out_of_range_replacement < 0)
|
| - // No replacement for bad input, abort.
|
| - return;
|
| - else
|
| - // Use a specific value to signal a bad input.
|
| - sample = out_of_range_replacement;
|
| - }
|
| - const PPB_UMA_Private* ptr = GetUMAInterface();
|
| - if (ptr == NULL) return;
|
| - ptr->HistogramEnumeration(pp::Var(name).pp_var(), sample, maximum);
|
| -}
|
| -
|
| -void HistogramEnumerateOsArch(const std::string& sandbox_isa) {
|
| - enum NaClOSArch {
|
| - kNaClLinux32 = 0,
|
| - kNaClLinux64,
|
| - kNaClLinuxArm,
|
| - kNaClMac32,
|
| - kNaClMac64,
|
| - kNaClMacArm,
|
| - kNaClWin32,
|
| - kNaClWin64,
|
| - kNaClWinArm,
|
| - kNaClOSArchMax
|
| - };
|
| -
|
| - NaClOSArch os_arch = kNaClOSArchMax;
|
| -#if NACL_LINUX
|
| - os_arch = kNaClLinux32;
|
| -#elif NACL_OSX
|
| - os_arch = kNaClMac32;
|
| -#elif NACL_WINDOWS
|
| - os_arch = kNaClWin32;
|
| -#endif
|
| -
|
| - if (sandbox_isa == "x86-64")
|
| - os_arch = static_cast<NaClOSArch>(os_arch + 1);
|
| - if (sandbox_isa == "arm")
|
| - os_arch = static_cast<NaClOSArch>(os_arch + 2);
|
| -
|
| - HistogramEnumerate("NaCl.Client.OSArch", os_arch, kNaClOSArchMax, -1);
|
| -}
|
| -
|
| -void HistogramEnumerateLoadStatus(PluginErrorCode error_code) {
|
| - HistogramEnumerate("NaCl.LoadStatus.Plugin", error_code, ERROR_MAX,
|
| - ERROR_UNKNOWN);
|
| -}
|
| -
|
| -void HistogramEnumerateSelLdrLoadStatus(NaClErrorCode error_code) {
|
| - HistogramEnumerate("NaCl.LoadStatus.SelLdr", error_code, NACL_ERROR_CODE_MAX,
|
| - LOAD_STATUS_UNKNOWN);
|
| -}
|
| -
|
| -void HistogramEnumerateManifestIsDataURI(bool is_data_uri) {
|
| - HistogramEnumerate("NaCl.Manifest.IsDataURI", is_data_uri, 2, -1);
|
| -}
|
| -
|
| -// Derive a class from pp::Find_Dev to forward PPP_Find_Dev calls to
|
| -// the plugin.
|
| -class FindAdapter : public pp::Find_Dev {
|
| - public:
|
| - explicit FindAdapter(Plugin* plugin)
|
| - : pp::Find_Dev(plugin),
|
| - plugin_(plugin) {
|
| - BrowserPpp* proxy = plugin_->ppapi_proxy();
|
| - CHECK(proxy != NULL);
|
| - ppp_find_ = static_cast<const PPP_Find_Dev*>(
|
| - proxy->GetPluginInterface(PPP_FIND_DEV_INTERFACE));
|
| - }
|
| -
|
| - bool StartFind(const std::string& text, bool case_sensitive) {
|
| - if (ppp_find_ != NULL) {
|
| - PP_Bool pp_success =
|
| - ppp_find_->StartFind(plugin_->pp_instance(),
|
| - text.c_str(),
|
| - PP_FromBool(case_sensitive));
|
| - return pp_success == PP_TRUE;
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - void SelectFindResult(bool forward) {
|
| - if (ppp_find_ != NULL) {
|
| - ppp_find_->SelectFindResult(plugin_->pp_instance(),
|
| - PP_FromBool(forward));
|
| - }
|
| - }
|
| -
|
| - void StopFind() {
|
| - if (ppp_find_ != NULL)
|
| - ppp_find_->StopFind(plugin_->pp_instance());
|
| - }
|
| -
|
| - private:
|
| - Plugin* plugin_;
|
| - const PPP_Find_Dev* ppp_find_;
|
| -
|
| - NACL_DISALLOW_COPY_AND_ASSIGN(FindAdapter);
|
| -};
|
| -
|
| -
|
| -// Derive a class from pp::Printing_Dev to forward PPP_Printing_Dev calls to
|
| -// the plugin.
|
| -class PrintingAdapter : public pp::Printing_Dev {
|
| - public:
|
| - explicit PrintingAdapter(Plugin* plugin)
|
| - : pp::Printing_Dev(plugin),
|
| - plugin_(plugin) {
|
| - BrowserPpp* proxy = plugin_->ppapi_proxy();
|
| - CHECK(proxy != NULL);
|
| - ppp_printing_ = static_cast<const PPP_Printing_Dev*>(
|
| - proxy->GetPluginInterface(PPP_PRINTING_DEV_INTERFACE));
|
| - }
|
| -
|
| - PP_PrintOutputFormat_Dev*
|
| - QuerySupportedPrintOutputFormats(uint32_t* format_count) {
|
| - if (ppp_printing_ != NULL) {
|
| - return ppp_printing_->QuerySupportedFormats(plugin_->pp_instance(),
|
| - format_count);
|
| - }
|
| - *format_count = 0;
|
| - return NULL;
|
| - }
|
| -
|
| - int32_t PrintBegin(const PP_PrintSettings_Dev& print_settings) {
|
| - if (ppp_printing_ != NULL) {
|
| - return ppp_printing_->Begin(plugin_->pp_instance(), &print_settings);
|
| - }
|
| - return 0;
|
| - }
|
| -
|
| - pp::Resource PrintPages(const PP_PrintPageNumberRange_Dev* page_ranges,
|
| - uint32_t page_range_count) {
|
| - if (ppp_printing_ != NULL) {
|
| - PP_Resource image_data = ppp_printing_->PrintPages(plugin_->pp_instance(),
|
| - page_ranges,
|
| - page_range_count);
|
| - return pp::ImageData(pp::ImageData::PassRef(), image_data);
|
| - }
|
| - return pp::Resource();
|
| - }
|
| -
|
| - void PrintEnd() {
|
| - if (ppp_printing_ != NULL)
|
| - ppp_printing_->End(plugin_->pp_instance());
|
| - }
|
| -
|
| - private:
|
| - Plugin* plugin_;
|
| - const PPP_Printing_Dev* ppp_printing_;
|
| -
|
| - NACL_DISALLOW_COPY_AND_ASSIGN(PrintingAdapter);
|
| -};
|
| -
|
| -
|
| -// Derive a class from pp::Selection_Dev to forward PPP_Selection_Dev calls to
|
| -// the plugin.
|
| -class SelectionAdapter : public pp::Selection_Dev {
|
| - public:
|
| - explicit SelectionAdapter(Plugin* plugin)
|
| - : pp::Selection_Dev(plugin),
|
| - plugin_(plugin) {
|
| - BrowserPpp* proxy = plugin_->ppapi_proxy();
|
| - CHECK(proxy != NULL);
|
| - ppp_selection_ = static_cast<const PPP_Selection_Dev*>(
|
| - proxy->GetPluginInterface(PPP_SELECTION_DEV_INTERFACE));
|
| - }
|
| -
|
| - pp::Var GetSelectedText(bool html) {
|
| - if (ppp_selection_ != NULL) {
|
| - PP_Var var = ppp_selection_->GetSelectedText(plugin_->pp_instance(),
|
| - PP_FromBool(html));
|
| - return pp::Var(pp::Var::PassRef(), var);
|
| - }
|
| - return pp::Var();
|
| - }
|
| -
|
| - private:
|
| - Plugin* plugin_;
|
| - const PPP_Selection_Dev* ppp_selection_;
|
| -
|
| - NACL_DISALLOW_COPY_AND_ASSIGN(SelectionAdapter);
|
| -};
|
| -
|
| -
|
| -// Derive a class from pp::WidgetClient_Dev to forward PPP_Widget_Dev
|
| -// and PPP_Scrollbar_Dev calls to the plugin.
|
| -class WidgetClientAdapter : public pp::WidgetClient_Dev {
|
| - public:
|
| - explicit WidgetClientAdapter(Plugin* plugin)
|
| - : pp::WidgetClient_Dev(plugin),
|
| - plugin_(plugin) {
|
| - BrowserPpp* proxy = plugin_->ppapi_proxy();
|
| - CHECK(proxy != NULL);
|
| - ppp_widget_ = static_cast<const PPP_Widget_Dev*>(
|
| - proxy->GetPluginInterface(PPP_WIDGET_DEV_INTERFACE));
|
| - ppp_scrollbar_ = static_cast<const PPP_Scrollbar_Dev*>(
|
| - proxy->GetPluginInterface(PPP_SCROLLBAR_DEV_INTERFACE));
|
| - }
|
| -
|
| - void InvalidateWidget(pp::Widget_Dev widget, const pp::Rect& dirty_rect) {
|
| - if (ppp_widget_ != NULL) {
|
| - ppp_widget_->Invalidate(plugin_->pp_instance(),
|
| - widget.pp_resource(),
|
| - &dirty_rect.pp_rect());
|
| - }
|
| - }
|
| -
|
| - void ScrollbarValueChanged(pp::Scrollbar_Dev scrollbar, uint32_t value) {
|
| - if (ppp_scrollbar_ != NULL) {
|
| - ppp_scrollbar_->ValueChanged(plugin_->pp_instance(),
|
| - scrollbar.pp_resource(),
|
| - value);
|
| - }
|
| - }
|
| -
|
| - void ScrollbarOverlayChanged(pp::Scrollbar_Dev scrollbar, bool overlay) {
|
| - if (ppp_scrollbar_ != NULL) {
|
| - ppp_scrollbar_->OverlayChanged(plugin_->pp_instance(),
|
| - scrollbar.pp_resource(),
|
| - PP_FromBool(overlay));
|
| - }
|
| - }
|
| -
|
| - private:
|
| - Plugin* plugin_;
|
| - const PPP_Widget_Dev* ppp_widget_;
|
| - const PPP_Scrollbar_Dev* ppp_scrollbar_;
|
| -
|
| - NACL_DISALLOW_COPY_AND_ASSIGN(WidgetClientAdapter);
|
| -};
|
| -
|
| -
|
| -// Derive a class from pp::Zoom_Dev to forward PPP_Zoom_Dev calls to
|
| -// the plugin.
|
| -class ZoomAdapter : public pp::Zoom_Dev {
|
| - public:
|
| - explicit ZoomAdapter(Plugin* plugin)
|
| - : pp::Zoom_Dev(plugin),
|
| - plugin_(plugin) {
|
| - BrowserPpp* proxy = plugin_->ppapi_proxy();
|
| - CHECK(proxy != NULL);
|
| - ppp_zoom_ = static_cast<const PPP_Zoom_Dev*>(
|
| - proxy->GetPluginInterface(PPP_ZOOM_DEV_INTERFACE));
|
| - }
|
| -
|
| - void Zoom(double factor, bool text_only) {
|
| - if (ppp_zoom_ != NULL) {
|
| - ppp_zoom_->Zoom(plugin_->pp_instance(),
|
| - factor,
|
| - PP_FromBool(text_only));
|
| - }
|
| - }
|
| -
|
| - private:
|
| - Plugin* plugin_;
|
| - const PPP_Zoom_Dev* ppp_zoom_;
|
| -
|
| - NACL_DISALLOW_COPY_AND_ASSIGN(ZoomAdapter);
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -bool Plugin::ExperimentalJavaScriptApisAreEnabled() {
|
| - return getenv("NACL_ENABLE_EXPERIMENTAL_JAVASCRIPT_APIS") != NULL;
|
| -}
|
| -
|
| -static int const kAbiHeaderBuffer = 256; // must be at least EI_ABIVERSION + 1
|
| -
|
| -void Plugin::LoadMethods() {
|
| - PLUGIN_PRINTF(("Plugin::LoadMethods ()\n"));
|
| - // Properties implemented by Plugin.
|
| - AddPropertyGet(GetReadyStateProperty, "readyState", "i");
|
| -}
|
| -
|
| -bool Plugin::HasMethod(uintptr_t method_id, CallType call_type) {
|
| - PLUGIN_PRINTF(("Plugin::HasMethod (method_id=%x) = ",
|
| - static_cast<int>(method_id)));
|
| - if (GetMethodInfo(method_id, call_type)) {
|
| - PLUGIN_PRINTF(("true\n"));
|
| - return true;
|
| - }
|
| - if (!ExperimentalJavaScriptApisAreEnabled()) {
|
| - PLUGIN_PRINTF(("false\n"));
|
| - return false;
|
| - }
|
| - if (call_type != METHOD_CALL) {
|
| - // SRPC nexes can only export methods.
|
| - PLUGIN_PRINTF(("false\n"));
|
| - return false;
|
| - }
|
| - bool has_method = main_subprocess_.HasMethod(method_id);
|
| - PLUGIN_PRINTF(("%s\n", (has_method ? "true" : "false")));
|
| - return has_method;
|
| -}
|
| -
|
| -bool Plugin::InitParams(uintptr_t method_id,
|
| - CallType call_type,
|
| - SrpcParams* params) {
|
| - MethodInfo* method_info = GetMethodInfo(method_id, call_type);
|
| - PLUGIN_PRINTF(("Plugin::InitParams (id=%"NACL_PRIxPTR", method_info=%p)\n",
|
| - method_id, method_info));
|
| - if (NULL != method_info) {
|
| - return params->Init(method_info->ins(), method_info->outs());
|
| - }
|
| - if (!ExperimentalJavaScriptApisAreEnabled()) {
|
| - return false;
|
| - }
|
| - if (call_type != METHOD_CALL) {
|
| - // SRPC nexes can only export methods.
|
| - return false;
|
| - }
|
| - return main_subprocess_.InitParams(method_id, params);
|
| -}
|
| -
|
| -bool Plugin::Invoke(uintptr_t method_id,
|
| - CallType call_type,
|
| - SrpcParams* params) {
|
| - MethodInfo* method_info = GetMethodInfo(method_id, call_type);
|
| -
|
| - if (NULL != method_info && NULL != method_info->function_ptr()) {
|
| - return method_info->function_ptr()(static_cast<void*>(this), params);
|
| - }
|
| - if (!ExperimentalJavaScriptApisAreEnabled()) {
|
| - return false;
|
| - }
|
| - if (call_type != METHOD_CALL) {
|
| - // SRPC nexes can only export methods.
|
| - return false;
|
| - }
|
| - return main_subprocess_.Invoke(method_id, params);
|
| -}
|
| -
|
| -bool Plugin::Init(BrowserInterface* browser_interface,
|
| - int argc,
|
| - char* argn[],
|
| - char* argv[]) {
|
| - PLUGIN_PRINTF(("Plugin::Init (instance=%p)\n", static_cast<void*>(this)));
|
| -
|
| - browser_interface_ = browser_interface;
|
| - // Remember the embed/object argn/argv pairs.
|
| - argn_ = new(std::nothrow) char*[argc];
|
| - argv_ = new(std::nothrow) char*[argc];
|
| - argc_ = 0;
|
| - for (int i = 0; i < argc; ++i) {
|
| - if (NULL != argn_ && NULL != argv_) {
|
| - argn_[argc_] = strdup(argn[i]);
|
| - argv_[argc_] = strdup(argv[i]);
|
| - if (NULL == argn_[argc_] || NULL == argv_[argc_]) {
|
| - // Give up on passing arguments.
|
| - free(argn_[argc_]);
|
| - free(argv_[argc_]);
|
| - continue;
|
| - }
|
| - ++argc_;
|
| - }
|
| - }
|
| - // TODO(sehr): this leaks strings if there is a subsequent failure.
|
| -
|
| - // Set up the factory used to produce DescWrappers.
|
| - wrapper_factory_ = new nacl::DescWrapperFactory();
|
| - if (NULL == wrapper_factory_) {
|
| - return false;
|
| - }
|
| - PLUGIN_PRINTF(("Plugin::Init (wrapper_factory=%p)\n",
|
| - static_cast<void*>(wrapper_factory_)));
|
| -
|
| - // Set up the scriptable methods for the plugin.
|
| - LoadMethods();
|
| -
|
| - PLUGIN_PRINTF(("Plugin::Init (return 1)\n"));
|
| - // Return success.
|
| - return true;
|
| -}
|
| -
|
| -void Plugin::ShutDownSubprocesses() {
|
| - PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (this=%p)\n",
|
| - static_cast<void*>(this)));
|
| - PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (%s)\n",
|
| - main_subprocess_.detailed_description().c_str()));
|
| -
|
| - // Shutdown service runtime. This must be done before all other calls so
|
| - // they don't block forever when waiting for the upcall thread to exit.
|
| - main_subprocess_.Shutdown();
|
| - for (size_t i = 0; i < nacl_subprocesses_.size(); ++i) {
|
| - PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (%s)\n",
|
| - nacl_subprocesses_[i]->detailed_description().c_str()));
|
| - delete nacl_subprocesses_[i];
|
| - }
|
| - nacl_subprocesses_.clear();
|
| -
|
| - PLUGIN_PRINTF(("Plugin::ShutDownSubprocess (this=%p, return)\n",
|
| - static_cast<void*>(this)));
|
| -}
|
| -
|
| -bool Plugin::LoadNaClModuleCommon(nacl::DescWrapper* wrapper,
|
| - NaClSubprocess* subprocess,
|
| - ErrorInfo* error_info,
|
| - pp::CompletionCallback init_done_cb) {
|
| - ServiceRuntime* new_service_runtime = new(std::nothrow) ServiceRuntime(
|
| - this,
|
| - init_done_cb);
|
| - subprocess->set_service_runtime(new_service_runtime);
|
| - PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon (service_runtime=%p)\n",
|
| - static_cast<void*>(new_service_runtime)));
|
| - if (NULL == new_service_runtime) {
|
| - error_info->SetReport(ERROR_SEL_LDR_INIT,
|
| - "sel_ldr init failure " + subprocess->description());
|
| - return false;
|
| - }
|
| -
|
| - bool service_runtime_started =
|
| - new_service_runtime->Start(wrapper, error_info);
|
| - PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon (service_runtime_started=%d)\n",
|
| - service_runtime_started));
|
| - if (!service_runtime_started) {
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool Plugin::StartSrpcServicesCommon(NaClSubprocess* subprocess,
|
| - ErrorInfo* error_info) {
|
| - if (!subprocess->StartSrpcServices()) {
|
| - error_info->SetReport(ERROR_SRPC_CONNECTION_FAIL,
|
| - "SRPC connection failure for " +
|
| - subprocess->description());
|
| - return false;
|
| - }
|
| - PLUGIN_PRINTF(("Plugin::StartSrpcServicesCommon (established srpc_client "
|
| - "%p)\n",
|
| - static_cast<void*>(subprocess->srpc_client())));
|
| - return true;
|
| -}
|
| -
|
| -bool Plugin::StartSrpcServices(NaClSubprocess* subprocess,
|
| - ErrorInfo* error_info) {
|
| - if (!StartSrpcServicesCommon(subprocess, error_info)) {
|
| - return false;
|
| - }
|
| - // TODO(jvoung): This next bit is likely not needed...
|
| - // If StartSrpcServices is only in the JS API that is just for SRPC nexes
|
| - // (namely __startSrpcServices), then attempts to start the JS proxy
|
| - // will fail anyway?
|
| - // If that is the case, by removing the following line,
|
| - // the StartSrpcServices == StartSrpcServicesCommon.
|
| - // We still need this function though, to launch helper SRPC nexes within
|
| - // the plugin.
|
| - return StartJSObjectProxy(subprocess, error_info);
|
| -}
|
| -
|
| -bool Plugin::StartJSObjectProxy(NaClSubprocess* subprocess,
|
| - ErrorInfo* error_info) {
|
| - if (!subprocess->StartJSObjectProxy(this, error_info)) {
|
| - // TODO(sehr,polina): rename the function and env var
|
| - // to ExperimentalJavaScriptApisAreEnabled.
|
| - if (error_info->error_code() == ERROR_START_PROXY_CHECK_PPP &&
|
| - ExperimentalJavaScriptApisAreEnabled()) {
|
| - // It is not an error for the proxy to fail to find PPP methods if
|
| - // experimental APIs are enabled. This means we have an SRPC nexe.
|
| - error_info->Reset();
|
| - } else {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool Plugin::LoadNaClModule(nacl::DescWrapper* wrapper,
|
| - ErrorInfo* error_info,
|
| - pp::CompletionCallback init_done_cb) {
|
| - // Before forking a new sel_ldr process, ensure that we do not leak
|
| - // the ServiceRuntime object for an existing subprocess, and that any
|
| - // associated listener threads do not go unjoined because if they
|
| - // outlive the Plugin object, they will not be memory safe.
|
| - ShutDownSubprocesses();
|
| - if (!(LoadNaClModuleCommon(wrapper, &main_subprocess_, error_info,
|
| - init_done_cb))) {
|
| - return false;
|
| - }
|
| - PLUGIN_PRINTF(("Plugin::LoadNaClModule (%s)\n",
|
| - main_subprocess_.detailed_description().c_str()));
|
| - return true;
|
| -}
|
| -
|
| -bool Plugin::LoadNaClModuleContinuationIntern(ErrorInfo* error_info) {
|
| - if (!(StartSrpcServicesCommon(&main_subprocess_, error_info)
|
| - && StartJSObjectProxy(&main_subprocess_, error_info))) {
|
| - return false;
|
| - }
|
| - PLUGIN_PRINTF(("Plugin::LoadNaClModule (%s)\n",
|
| - main_subprocess_.detailed_description().c_str()));
|
| - return true;
|
| -}
|
| -
|
| -NaClSubprocessId Plugin::LoadHelperNaClModule(nacl::DescWrapper* wrapper,
|
| - ErrorInfo* error_info) {
|
| - NaClSubprocessId next_id = next_nacl_subprocess_id();
|
| - nacl::scoped_ptr<NaClSubprocess> nacl_subprocess(
|
| - new(std::nothrow) NaClSubprocess(next_id, NULL, NULL));
|
| - if (NULL == nacl_subprocess.get()) {
|
| - error_info->SetReport(ERROR_SEL_LDR_INIT,
|
| - "unable to allocate helper subprocess.");
|
| - return kInvalidNaClSubprocessId;
|
| - }
|
| -
|
| - if (!(LoadNaClModuleCommon(wrapper, nacl_subprocess.get(), error_info,
|
| - pp::BlockUntilComplete())
|
| - // We need not wait for the init_done callback. We can block
|
| - // here in StartSrpcServicesCommon, since helper NaCl modules
|
| - // are spawned from a private thread.
|
| - //
|
| - // NB: More refactoring might be needed, however, if helper
|
| - // NaCl modules have their own manifest. Currently the
|
| - // manifest is a per-plugin-instance object, not a per
|
| - // NaClSubprocess object.
|
| - && StartSrpcServicesCommon(nacl_subprocess.get(), error_info))) {
|
| - return kInvalidNaClSubprocessId;
|
| - }
|
| -
|
| - PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule (%s)\n",
|
| - nacl_subprocess.get()->detailed_description().c_str()));
|
| -
|
| - nacl_subprocesses_.push_back(nacl_subprocess.release());
|
| - return next_id;
|
| -}
|
| -
|
| -char* Plugin::LookupArgument(const char* key) {
|
| - char** keys = argn();
|
| - for (int ii = 0, len = argc(); ii < len; ++ii) {
|
| - if (!strcmp(keys[ii], key)) {
|
| - return argv()[ii];
|
| - }
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -void Plugin::AddPropertyGet(RpcFunction function_ptr,
|
| - const char* name,
|
| - const char* outs) {
|
| - uintptr_t method_id = browser_interface()->StringToIdentifier(name);
|
| - PLUGIN_PRINTF(("Plugin::AddPropertyGet (name='%s', id=%"
|
| - NACL_PRIxPTR")\n", name, method_id));
|
| - MethodInfo* new_method = new MethodInfo(function_ptr, name, "", outs);
|
| - property_get_methods_.AddMethod(method_id, new_method);
|
| -}
|
| -
|
| -MethodInfo* Plugin::GetMethodInfo(uintptr_t method_id, CallType call_type) {
|
| - MethodInfo* method_info = NULL;
|
| - switch (call_type) {
|
| - case PROPERTY_GET:
|
| - method_info = property_get_methods_.GetMethod(method_id);
|
| - break;
|
| - case PROPERTY_SET:
|
| - case METHOD_CALL:
|
| - break;
|
| - }
|
| - PLUGIN_PRINTF(("Plugin::GetMethodInfo (id=%"NACL_PRIxPTR", "
|
| - "return %p)\n", method_id, static_cast<void*>(method_info)));
|
| - return method_info;
|
| -}
|
| -
|
| -class ProgressEvent {
|
| - public:
|
| - ProgressEvent(const char* event_type,
|
| - Plugin::LengthComputable length_computable,
|
| - uint64_t loaded_bytes,
|
| - uint64_t total_bytes) :
|
| - event_type_(event_type),
|
| - length_computable_(length_computable),
|
| - loaded_bytes_(loaded_bytes),
|
| - total_bytes_(total_bytes) { }
|
| - const char* event_type() const { return event_type_; }
|
| - Plugin::LengthComputable length_computable() const {
|
| - return length_computable_;
|
| - }
|
| - uint64_t loaded_bytes() const { return loaded_bytes_; }
|
| - uint64_t total_bytes() const { return total_bytes_; }
|
| -
|
| - private:
|
| - // event_type_ is always passed from a string literal, so ownership is
|
| - // not taken. Hence it does not need to be deleted when ProgressEvent is
|
| - // destroyed.
|
| - const char* event_type_;
|
| - Plugin::LengthComputable length_computable_;
|
| - uint64_t loaded_bytes_;
|
| - uint64_t total_bytes_;
|
| -};
|
| -
|
| -const char* const Plugin::kNaClMIMEType = "application/x-nacl";
|
| -
|
| -bool Plugin::IsForeignMIMEType() const {
|
| - return
|
| - !mime_type().empty() &&
|
| - mime_type() != kNaClMIMEType;
|
| -}
|
| -
|
| -
|
| -Plugin* Plugin::New(PP_Instance pp_instance) {
|
| - PLUGIN_PRINTF(("Plugin::New (pp_instance=%"NACL_PRId32")\n", pp_instance));
|
| -#if NACL_WINDOWS && !defined(NACL_STANDALONE)
|
| - if (!NaClHandlePassBrowserCtor()) {
|
| - return NULL;
|
| - }
|
| -#endif
|
| - Plugin* plugin = new(std::nothrow) Plugin(pp_instance);
|
| - PLUGIN_PRINTF(("Plugin::New (plugin=%p)\n", static_cast<void*>(plugin)));
|
| - if (plugin == NULL) {
|
| - return NULL;
|
| - }
|
| - return plugin;
|
| -}
|
| -
|
| -
|
| -// All failures of this function will show up as "Missing Plugin-in", so
|
| -// there is no need to log to JS console that there was an initialization
|
| -// 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));
|
| - HistogramEnumerateOsArch(GetSandboxISA());
|
| - init_time_ = NaClGetTimeOfDayMicroseconds();
|
| -
|
| - BrowserInterface* browser_interface = new(std::nothrow) BrowserInterface;
|
| - if (browser_interface == NULL) {
|
| - return false;
|
| - }
|
| - ScriptableHandle* handle = ScriptableHandle::NewPlugin(this);
|
| - if (handle == NULL) {
|
| - return false;
|
| - }
|
| - set_scriptable_handle(handle);
|
| - PLUGIN_PRINTF(("Plugin::Init (scriptable_handle=%p)\n",
|
| - static_cast<void*>(scriptable_handle())));
|
| - url_util_ = pp::URLUtil_Dev::Get();
|
| - if (url_util_ == NULL) {
|
| - return false;
|
| - }
|
| - PLUGIN_PRINTF(("Plugin::Init (url_util_=%p)\n",
|
| - static_cast<const void*>(url_util_)));
|
| -
|
| - bool status = Plugin::Init(
|
| - browser_interface,
|
| - static_cast<int>(argc),
|
| - // TODO(polina): Can we change the args on our end to be const to
|
| - // avoid these ugly casts?
|
| - const_cast<char**>(argn),
|
| - const_cast<char**>(argv));
|
| - if (status) {
|
| - const char* type_attr = LookupArgument(kTypeAttribute);
|
| - if (type_attr != NULL) {
|
| - mime_type_ = nacl::string(type_attr);
|
| - std::transform(mime_type_.begin(), mime_type_.end(), mime_type_.begin(),
|
| - tolower);
|
| - }
|
| -
|
| - const char* manifest_url = LookupArgument(kSrcManifestAttribute);
|
| - // If the MIME type is foreign, then 'src' will be the URL for the content
|
| - // and 'nacl' will be the URL for the manifest.
|
| - if (IsForeignMIMEType()) {
|
| - manifest_url = LookupArgument(kNaClManifestAttribute);
|
| - enable_dev_interface_ = RequiresDevInterface(manifest_url);
|
| - }
|
| - // 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 == NULL) {
|
| - // TODO(sehr,polina): this should be a hard error when scripting
|
| - // the src property is no longer allowed.
|
| - PLUGIN_PRINTF(("Plugin::Init:"
|
| - " WARNING: no 'src' property, so no manifest loaded.\n"));
|
| - if (NULL != LookupArgument(kNaClManifestAttribute)) {
|
| - PLUGIN_PRINTF(("Plugin::Init:"
|
| - " WARNING: 'nacl' property is incorrect. Use 'src'.\n"));
|
| - }
|
| - } else {
|
| - // 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);
|
| - }
|
| - }
|
| -
|
| - // Export a property to allow us to get the last error description.
|
| - AddPropertyGet(GetLastError, "lastError", "s");
|
| -
|
| - PLUGIN_PRINTF(("Plugin::Init (status=%d)\n", status));
|
| - return status;
|
| -}
|
| -
|
| -
|
| -Plugin::Plugin(PP_Instance pp_instance)
|
| - : pp::InstancePrivate(pp_instance),
|
| - browser_interface_(NULL),
|
| - scriptable_handle_(NULL),
|
| - argc_(-1),
|
| - argn_(NULL),
|
| - argv_(NULL),
|
| - main_subprocess_(kMainSubprocessId, NULL, NULL),
|
| - nacl_ready_state_(UNSENT),
|
| - wrapper_factory_(NULL),
|
| - last_error_string_(""),
|
| - ppapi_proxy_(NULL),
|
| - enable_dev_interface_(false),
|
| - replayDidChangeView(false),
|
| - replayHandleDocumentLoad(false),
|
| - init_time_(0),
|
| - ready_time_(0),
|
| - nexe_size_(0) {
|
| - PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%"
|
| - NACL_PRId32")\n", static_cast<void*>(this), pp_instance));
|
| - NaClSrpcModuleInit();
|
| - nexe_downloader_.Initialize(this);
|
| - pnacl_.Initialize(this);
|
| - callback_factory_.Initialize(this);
|
| -}
|
| -
|
| -
|
| -Plugin::~Plugin() {
|
| - int64_t shutdown_start = NaClGetTimeOfDayMicroseconds();
|
| -
|
| - PLUGIN_PRINTF(("Plugin::~Plugin (this=%p, scriptable_handle=%p)\n",
|
| - static_cast<void*>(this),
|
| - static_cast<void*>(scriptable_handle())));
|
| -
|
| - // If the proxy has been shutdown before now, it's likely the plugin suffered
|
| - // an error while loading.
|
| - if (ppapi_proxy_ != NULL) {
|
| - HistogramTimeLarge(
|
| - "NaCl.ModuleUptime.Normal",
|
| - (shutdown_start - ready_time_) / NACL_MICROS_PER_MILLI);
|
| - }
|
| -
|
| -#if NACL_WINDOWS && !defined(NACL_STANDALONE)
|
| - NaClHandlePassBrowserDtor();
|
| -#endif
|
| -
|
| - url_downloaders_.erase(url_downloaders_.begin(), url_downloaders_.end());
|
| -
|
| - ShutdownProxy();
|
| - ScriptableHandle* scriptable_handle_ = scriptable_handle();
|
| - ScriptableHandle::Unref(&scriptable_handle_);
|
| - NaClSrpcModuleFini();
|
| -
|
| - // TODO(sehr,polina): We should not need to call ShutDownSubprocesses() here.
|
| - ShutDownSubprocesses();
|
| -
|
| - delete wrapper_factory_;
|
| - delete browser_interface_;
|
| - delete[] argv_;
|
| - delete[] argn_;
|
| -
|
| - HistogramTimeSmall(
|
| - "NaCl.Perf.ShutdownTime.Total",
|
| - (NaClGetTimeOfDayMicroseconds() - shutdown_start)
|
| - / NACL_MICROS_PER_MILLI);
|
| -
|
| - PLUGIN_PRINTF(("Plugin::~Plugin (this=%p, return)\n",
|
| - static_cast<void*>(this)));
|
| -}
|
| -
|
| -
|
| -void Plugin::DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
|
| - PLUGIN_PRINTF(("Plugin::DidChangeView (this=%p)\n",
|
| - static_cast<void*>(this)));
|
| -
|
| - if (!BrowserPpp::is_valid(ppapi_proxy_)) {
|
| - // Store this event and replay it when the proxy becomes available.
|
| - replayDidChangeView = true;
|
| - replayDidChangeViewPosition = position;
|
| - replayDidChangeViewClip = clip;
|
| - return;
|
| - } else {
|
| - ppapi_proxy_->ppp_instance_interface()->DidChangeView(
|
| - pp_instance(), &(position.pp_rect()), &(clip.pp_rect()));
|
| - }
|
| -}
|
| -
|
| -
|
| -void Plugin::DidChangeFocus(bool has_focus) {
|
| - PLUGIN_PRINTF(("Plugin::DidChangeFocus (this=%p)\n",
|
| - static_cast<void*>(this)));
|
| - if (!BrowserPpp::is_valid(ppapi_proxy_)) {
|
| - return;
|
| - } else {
|
| - ppapi_proxy_->ppp_instance_interface()->DidChangeFocus(
|
| - pp_instance(), PP_FromBool(has_focus));
|
| - }
|
| -}
|
| -
|
| -
|
| -bool Plugin::HandleInputEvent(const pp::InputEvent& event) {
|
| - PLUGIN_PRINTF(("Plugin::HandleInputEvent (this=%p)\n",
|
| - static_cast<void*>(this)));
|
| - if (!BrowserPpp::is_valid(ppapi_proxy_) ||
|
| - ppapi_proxy_->ppp_input_event_interface() == NULL) {
|
| - return false; // event is not handled here.
|
| - } else {
|
| - bool handled = PP_ToBool(
|
| - ppapi_proxy_->ppp_input_event_interface()->HandleInputEvent(
|
| - pp_instance(), event.pp_resource()));
|
| - PLUGIN_PRINTF(("Plugin::HandleInputEvent (handled=%d)\n", handled));
|
| - return handled;
|
| - }
|
| -}
|
| -
|
| -
|
| -bool Plugin::HandleDocumentLoad(const pp::URLLoader& url_loader) {
|
| - PLUGIN_PRINTF(("Plugin::HandleDocumentLoad (this=%p)\n",
|
| - static_cast<void*>(this)));
|
| - if (!BrowserPpp::is_valid(ppapi_proxy_)) {
|
| - // Store this event and replay it when the proxy becomes available.
|
| - replayHandleDocumentLoad = true;
|
| - replayHandleDocumentLoadURLLoader = url_loader;
|
| - // Return true so that the browser keeps servicing this loader so we can
|
| - // perform requests on it later.
|
| - return true;
|
| - } else {
|
| - return PP_ToBool(
|
| - ppapi_proxy_->ppp_instance_interface()->HandleDocumentLoad(
|
| - pp_instance(), url_loader.pp_resource()));
|
| - }
|
| -}
|
| -
|
| -
|
| -void Plugin::HandleMessage(const pp::Var& message) {
|
| - PLUGIN_PRINTF(("Plugin::HandleMessage (this=%p)\n",
|
| - static_cast<void*>(this)));
|
| - if (BrowserPpp::is_valid(ppapi_proxy_) &&
|
| - ppapi_proxy_->ppp_messaging_interface() != NULL) {
|
| - ppapi_proxy_->ppp_messaging_interface()->HandleMessage(
|
| - pp_instance(), message.pp_var());
|
| - }
|
| -}
|
| -
|
| -
|
| -pp::Var Plugin::GetInstanceObject() {
|
| - PLUGIN_PRINTF(("Plugin::GetInstanceObject (this=%p)\n",
|
| - static_cast<void*>(this)));
|
| - // The browser will unref when it discards the var for this object.
|
| - ScriptableHandle* handle =
|
| - static_cast<ScriptableHandle*>(scriptable_handle()->AddRef());
|
| - pp::Var* handle_var = handle->var();
|
| - PLUGIN_PRINTF(("Plugin::GetInstanceObject (handle=%p, handle_var=%p)\n",
|
| - static_cast<void*>(handle), static_cast<void*>(handle_var)));
|
| - return *handle_var; // make a copy
|
| -}
|
| -
|
| -void Plugin::HistogramStartupTimeSmall(const std::string& name, float dt) {
|
| - if (nexe_size_ > 0) {
|
| - float size_in_MB = static_cast<float>(nexe_size_) / (1024.f * 1024.f);
|
| - HistogramTimeSmall(name, static_cast<int64_t>(dt));
|
| - HistogramTimeSmall(name + "PerMB", static_cast<int64_t>(dt / size_in_MB));
|
| - }
|
| -}
|
| -
|
| -void Plugin::HistogramStartupTimeMedium(const std::string& name, float dt) {
|
| - if (nexe_size_ > 0) {
|
| - float size_in_MB = static_cast<float>(nexe_size_) / (1024.f * 1024.f);
|
| - HistogramTimeMedium(name, static_cast<int64_t>(dt));
|
| - HistogramTimeMedium(name + "PerMB", static_cast<int64_t>(dt / size_in_MB));
|
| - }
|
| -}
|
| -
|
| -void Plugin::NexeFileDidOpen(int32_t pp_error) {
|
| - PLUGIN_PRINTF(("Plugin::NexeFileDidOpen (pp_error=%"NACL_PRId32")\n",
|
| - pp_error));
|
| - int32_t file_desc = nexe_downloader_.GetPOSIXFileDescriptor();
|
| - PLUGIN_PRINTF(("Plugin::NexeFileDidOpen (file_desc=%"NACL_PRId32")\n",
|
| - file_desc));
|
| - ErrorInfo error_info;
|
| - if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) {
|
| - if (pp_error == PP_ERROR_ABORTED) {
|
| - ReportLoadAbort();
|
| - } else {
|
| - error_info.SetReport(ERROR_NEXE_LOAD_URL, "could not load nexe url.");
|
| - ReportLoadError(error_info);
|
| - }
|
| - return;
|
| - }
|
| - int32_t file_desc_ok_to_close = DUP(file_desc);
|
| - if (file_desc_ok_to_close == NACL_NO_FILE_DESC) {
|
| - error_info.SetReport(ERROR_NEXE_FH_DUP,
|
| - "could not duplicate loaded file handle.");
|
| - ReportLoadError(error_info);
|
| - return;
|
| - }
|
| - struct stat stat_buf;
|
| - if (0 != fstat(file_desc_ok_to_close, &stat_buf)) {
|
| - CLOSE(file_desc_ok_to_close);
|
| - error_info.SetReport(ERROR_NEXE_STAT, "could not stat nexe file.");
|
| - ReportLoadError(error_info);
|
| - return;
|
| - }
|
| - size_t nexe_bytes_read = static_cast<size_t>(stat_buf.st_size);
|
| -
|
| - nexe_size_ = nexe_bytes_read;
|
| - HistogramSizeKB("NaCl.Perf.Size.Nexe",
|
| - static_cast<int32_t>(nexe_size_ / 1024));
|
| - HistogramStartupTimeMedium(
|
| - "NaCl.Perf.StartupTime.NexeDownload",
|
| - static_cast<float>(nexe_downloader_.TimeSinceOpenMilliseconds()));
|
| -
|
| - // Inform JavaScript that we successfully downloaded the nacl module.
|
| - EnqueueProgressEvent("progress",
|
| - LENGTH_IS_COMPUTABLE,
|
| - nexe_bytes_read,
|
| - nexe_bytes_read);
|
| -
|
| - load_start_ = NaClGetTimeOfDayMicroseconds();
|
| - nacl::scoped_ptr<nacl::DescWrapper>
|
| - wrapper(wrapper_factory()->MakeFileDesc(file_desc_ok_to_close, O_RDONLY));
|
| - NaClLog(4, "NexeFileDidOpen: invoking LoadNaClModule\n");
|
| - bool was_successful = LoadNaClModule(
|
| - wrapper.get(), &error_info,
|
| - callback_factory_.NewCallback(&Plugin::NexeFileDidOpenContinuation));
|
| -
|
| - if (!was_successful) {
|
| - ReportLoadError(error_info);
|
| - }
|
| -}
|
| -
|
| -void Plugin::NexeFileDidOpenContinuation(int32_t pp_error) {
|
| - ErrorInfo error_info;
|
| - bool was_successful;
|
| -
|
| - UNREFERENCED_PARAMETER(pp_error);
|
| - NaClLog(4, "Entered NexeFileDidOpenContinuation\n");
|
| - NaClLog(4, "NexeFileDidOpenContinuation: invoking"
|
| - " LoadNaClModuleContinuationIntern\n");
|
| - was_successful = LoadNaClModuleContinuationIntern(&error_info);
|
| - if (was_successful) {
|
| - NaClLog(4, "NexeFileDidOpenContinuation: success;"
|
| - " setting histograms\n");
|
| - ready_time_ = NaClGetTimeOfDayMicroseconds();
|
| - HistogramStartupTimeSmall(
|
| - "NaCl.Perf.StartupTime.LoadModule",
|
| - static_cast<float>(ready_time_ - load_start_) / NACL_MICROS_PER_MILLI);
|
| - HistogramStartupTimeMedium(
|
| - "NaCl.Perf.StartupTime.Total",
|
| - static_cast<float>(ready_time_ - init_time_) / NACL_MICROS_PER_MILLI);
|
| -
|
| - ReportLoadSuccess(LENGTH_IS_COMPUTABLE, nexe_size_, nexe_size_);
|
| - } else {
|
| - NaClLog(4, "NexeFileDidOpenContinuation: failed.");
|
| - ReportLoadError(error_info);
|
| - }
|
| - NaClLog(4, "Leaving NexeFileDidOpenContinuation\n");
|
| -}
|
| -
|
| -void Plugin::BitcodeDidTranslate(int32_t pp_error) {
|
| - PLUGIN_PRINTF(("Plugin::BitcodeDidTranslate (pp_error=%"NACL_PRId32")\n",
|
| - pp_error));
|
| - if (pp_error != PP_OK) {
|
| - // Error should have been reported by pnacl. Just return.
|
| - PLUGIN_PRINTF(("Plugin::BitcodeDidTranslate error in Pnacl\n"));
|
| - return;
|
| - }
|
| - // Inform JavaScript that we successfully translated the bitcode to a nexe.
|
| - EnqueueProgressEvent("progress",
|
| - LENGTH_IS_NOT_COMPUTABLE,
|
| - kUnknownBytes,
|
| - kUnknownBytes);
|
| - nacl::scoped_ptr<nacl::DescWrapper>
|
| - wrapper(pnacl_.ReleaseTranslatedFD());
|
| - ErrorInfo error_info;
|
| - bool was_successful = LoadNaClModule(
|
| - wrapper.get(), &error_info,
|
| - callback_factory_.NewCallback(&Plugin::BitcodeDidTranslateContinuation));
|
| -
|
| - if (!was_successful) {
|
| - ReportLoadError(error_info);
|
| - }
|
| -}
|
| -
|
| -void Plugin::BitcodeDidTranslateContinuation(int32_t pp_error) {
|
| - ErrorInfo error_info;
|
| - bool was_successful = LoadNaClModuleContinuationIntern(&error_info);
|
| -
|
| - NaClLog(4, "Entered BitcodeDidTranslateContinuation\n");
|
| - UNREFERENCED_PARAMETER(pp_error);
|
| - if (was_successful) {
|
| - ReportLoadSuccess(LENGTH_IS_NOT_COMPUTABLE,
|
| - kUnknownBytes,
|
| - kUnknownBytes);
|
| - } else {
|
| - ReportLoadError(error_info);
|
| - }
|
| -}
|
| -
|
| -// Check manifest_url and return whether or not to enable PPAPI Dev interfaces.
|
| -// Returning true here will enable the PPAPI Dev interfaces regardless of
|
| -// the environment variable NACL_ENABLE_PPAPI_DEV.
|
| -bool Plugin::RequiresDevInterface(const nacl::string& manifest_url) {
|
| - const char* extensions[] = {
|
| - "chrome-extension://acadkphlmlegjaadjagenfimbpphcgnh/", // PDF
|
| - };
|
| - for (size_t i = 0; i < sizeof(extensions) / sizeof(const char*); ++i) {
|
| - if (manifest_url.find(extensions[i]) == 0) {
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool Plugin::StartProxiedExecution(NaClSrpcChannel* srpc_channel,
|
| - ErrorInfo* error_info) {
|
| - PLUGIN_PRINTF(("Plugin::StartProxiedExecution (srpc_channel=%p)\n",
|
| - static_cast<void*>(srpc_channel)));
|
| -
|
| - // Log the amound of time that has passed between the trusted plugin being
|
| - // initialized and the untrusted plugin being initialized. This is (roughly)
|
| - // the cost of using NaCl, in terms of startup time.
|
| - HistogramStartupTimeMedium(
|
| - "NaCl.Perf.StartupTime.NaClOverhead",
|
| - static_cast<float>(NaClGetTimeOfDayMicroseconds() - init_time_)
|
| - / NACL_MICROS_PER_MILLI);
|
| -
|
| - // Check that the .nexe exports the PPAPI intialization method.
|
| - NaClSrpcService* client_service = srpc_channel->client;
|
| - if (NaClSrpcServiceMethodIndex(client_service,
|
| - "PPP_InitializeModule:iihs:ii") ==
|
| - kNaClSrpcInvalidMethodIndex) {
|
| - error_info->SetReport(
|
| - ERROR_START_PROXY_CHECK_PPP,
|
| - "could not find PPP_InitializeModule() - toolchain version mismatch?");
|
| - PLUGIN_PRINTF(("Plugin::StartProxiedExecution (%s)\n",
|
| - error_info->message().c_str()));
|
| - return false;
|
| - }
|
| - nacl::scoped_ptr<BrowserPpp> ppapi_proxy(
|
| - new(std::nothrow) BrowserPpp(srpc_channel, this));
|
| - PLUGIN_PRINTF(("Plugin::StartProxiedExecution (ppapi_proxy=%p)\n",
|
| - static_cast<void*>(ppapi_proxy.get())));
|
| - if (ppapi_proxy.get() == NULL) {
|
| - error_info->SetReport(ERROR_START_PROXY_ALLOC,
|
| - "could not allocate proxy memory.");
|
| - return false;
|
| - }
|
| - pp::Module* module = pp::Module::Get();
|
| - PLUGIN_PRINTF(("Plugin::StartProxiedExecution (module=%p)\n",
|
| - static_cast<void*>(module)));
|
| - CHECK(module != NULL); // We could not have gotten past init stage otherwise.
|
| - int32_t pp_error =
|
| - ppapi_proxy->InitializeModule(module->pp_module(),
|
| - module->get_browser_interface());
|
| - PLUGIN_PRINTF(("Plugin::StartProxiedExecution (pp_error=%"
|
| - NACL_PRId32")\n", pp_error));
|
| - if (pp_error != PP_OK) {
|
| - error_info->SetReport(ERROR_START_PROXY_MODULE,
|
| - "could not initialize module.");
|
| - return false;
|
| - }
|
| - const PPP_Instance* instance_interface =
|
| - ppapi_proxy->ppp_instance_interface();
|
| - PLUGIN_PRINTF(("Plugin::StartProxiedExecution (ppp_instance=%p)\n",
|
| - static_cast<const void*>(instance_interface)));
|
| - CHECK(instance_interface != NULL); // Verified on module initialization.
|
| - PP_Bool did_create = instance_interface->DidCreate(
|
| - pp_instance(),
|
| - argc(),
|
| - const_cast<const char**>(argn()),
|
| - const_cast<const char**>(argv()));
|
| - PLUGIN_PRINTF(("Plugin::StartProxiedExecution (did_create=%d)\n",
|
| - did_create));
|
| - if (did_create == PP_FALSE) {
|
| - error_info->SetReport(ERROR_START_PROXY_INSTANCE,
|
| - "could not create instance.");
|
| - return false;
|
| - }
|
| -
|
| - ppapi_proxy_ = ppapi_proxy.release();
|
| -
|
| - // Create PPP* interface adapters to forward calls to .nexe.
|
| - find_adapter_.reset(new(std::nothrow) FindAdapter(this));
|
| - printing_adapter_.reset(new(std::nothrow) PrintingAdapter(this));
|
| - selection_adapter_.reset(new(std::nothrow) SelectionAdapter(this));
|
| - widget_client_adapter_.reset(new(std::nothrow) WidgetClientAdapter(this));
|
| - zoom_adapter_.reset(new(std::nothrow) ZoomAdapter(this));
|
| -
|
| - // Replay missed events.
|
| - if (replayDidChangeView) {
|
| - replayDidChangeView = false;
|
| - DidChangeView(replayDidChangeViewPosition, replayDidChangeViewClip);
|
| - }
|
| - if (replayHandleDocumentLoad) {
|
| - replayHandleDocumentLoad = false;
|
| - HandleDocumentLoad(replayHandleDocumentLoadURLLoader);
|
| - // Release our reference on this loader.
|
| - replayHandleDocumentLoadURLLoader = pp::URLLoader();
|
| - }
|
| - bool is_valid_proxy = BrowserPpp::is_valid(ppapi_proxy_);
|
| - PLUGIN_PRINTF(("Plugin::StartProxiedExecution (is_valid_proxy=%d)\n",
|
| - is_valid_proxy));
|
| - if (!is_valid_proxy) {
|
| - error_info->SetReport(ERROR_START_PROXY_CRASH,
|
| - "instance crashed after creation.");
|
| - }
|
| - return is_valid_proxy;
|
| -}
|
| -
|
| -void Plugin::ReportDeadNexe() {
|
| - PLUGIN_PRINTF(("Plugin::ReportDeadNexe\n"));
|
| -
|
| - if (nacl_ready_state() == DONE) { // After loadEnd.
|
| - int64_t crash_time = NaClGetTimeOfDayMicroseconds();
|
| - // Crashes will be more likely near startup, so use a medium histogram
|
| - // instead of a large one.
|
| - HistogramTimeMedium(
|
| - "NaCl.ModuleUptime.Crash",
|
| - (crash_time - ready_time_) / NACL_MICROS_PER_MILLI);
|
| -
|
| - EnqueueProgressEvent("crash",
|
| - LENGTH_IS_NOT_COMPUTABLE,
|
| - kUnknownBytes,
|
| - kUnknownBytes);
|
| - CHECK(ppapi_proxy_ != NULL && !ppapi_proxy_->is_valid());
|
| - ShutdownProxy();
|
| - }
|
| - // else LoadNaClModule and NexeFileDidOpen will provide error handling.
|
| - // NOTE: not all crashes during load will make it here.
|
| - // Those in BrowserPpp::InitializeModule and creation of PPP interfaces
|
| - // will just get reported back as PP_ERROR_FAILED.
|
| -}
|
| -
|
| -void Plugin::ShutdownProxy() {
|
| - PLUGIN_PRINTF(("Plugin::ShutdownProxy (ppapi_proxy=%p)\n",
|
| - static_cast<void*>(ppapi_proxy_)));
|
| - // We do not call remote PPP_Instance::DidDestroy because the untrusted
|
| - // side can no longer take full advantage of mostly asynchronous Pepper
|
| - // per-Instance interfaces at this point.
|
| - if (BrowserPpp::is_valid(ppapi_proxy_))
|
| - ppapi_proxy_->ShutdownModule();
|
| - delete ppapi_proxy_;
|
| - ppapi_proxy_ = NULL;
|
| -}
|
| -
|
| -void Plugin::NaClManifestBufferReady(int32_t pp_error) {
|
| - PLUGIN_PRINTF(("Plugin::NaClManifestBufferReady (pp_error=%"
|
| - NACL_PRId32")\n", pp_error));
|
| - ErrorInfo error_info;
|
| - set_manifest_url(nexe_downloader_.url());
|
| - if (pp_error != PP_OK) {
|
| - if (pp_error == PP_ERROR_ABORTED) {
|
| - ReportLoadAbort();
|
| - } else {
|
| - error_info.SetReport(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(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(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));
|
| - HistogramTimeSmall("NaCl.Perf.StartupTime.ManifestDownload",
|
| - nexe_downloader_.TimeSinceOpenMilliseconds());
|
| - ErrorInfo error_info;
|
| - // The manifest file was successfully opened. Set the src property on the
|
| - // plugin now, so that the full url is available to error handlers.
|
| - set_manifest_url(nexe_downloader_.url());
|
| - int32_t file_desc = nexe_downloader_.GetPOSIXFileDescriptor();
|
| - PLUGIN_PRINTF(("Plugin::NaClManifestFileDidOpen (file_desc=%"
|
| - NACL_PRId32")\n", file_desc));
|
| - if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) {
|
| - if (pp_error == PP_ERROR_ABORTED) {
|
| - ReportLoadAbort();
|
| - } else {
|
| - error_info.SetReport(ERROR_MANIFEST_LOAD_URL,
|
| - "could not load manifest url.");
|
| - ReportLoadError(error_info);
|
| - }
|
| - return;
|
| - }
|
| - // Duplicate the file descriptor in order to create a FILE stream with it
|
| - // that can later be closed without closing the original descriptor. The
|
| - // browser will take care of the original descriptor.
|
| - int dup_file_desc = DUP(file_desc);
|
| - struct stat stat_buf;
|
| - if (0 != fstat(dup_file_desc, &stat_buf)) {
|
| - CLOSE(dup_file_desc);
|
| - error_info.SetReport(ERROR_MANIFEST_STAT,
|
| - "could not stat manifest file.");
|
| - ReportLoadError(error_info);
|
| - return;
|
| - }
|
| - size_t bytes_to_read = static_cast<size_t>(stat_buf.st_size);
|
| - if (bytes_to_read > kNaClManifestMaxFileBytes) {
|
| - CLOSE(dup_file_desc);
|
| - error_info.SetReport(ERROR_MANIFEST_TOO_LARGE,
|
| - "manifest file too large.");
|
| - ReportLoadError(error_info);
|
| - return;
|
| - }
|
| - FILE* json_file = fdopen(dup_file_desc, "rb");
|
| - PLUGIN_PRINTF(("Plugin::NaClManifestFileDidOpen "
|
| - "(dup_file_desc=%"NACL_PRId32", json_file=%p)\n",
|
| - dup_file_desc, static_cast<void*>(json_file)));
|
| - if (json_file == NULL) {
|
| - CLOSE(dup_file_desc);
|
| - error_info.SetReport(ERROR_MANIFEST_OPEN,
|
| - "could not open manifest file.");
|
| - ReportLoadError(error_info);
|
| - return;
|
| - }
|
| - nacl::scoped_array<char> json_buffer(new char[bytes_to_read + 1]);
|
| - if (json_buffer == NULL) {
|
| - fclose(json_file);
|
| - error_info.SetReport(ERROR_MANIFEST_MEMORY_ALLOC,
|
| - "could not allocate manifest memory.");
|
| - ReportLoadError(error_info);
|
| - return;
|
| - }
|
| - // json_buffer could hold a large enough buffer that the system might need
|
| - // multiple reads to fill it, so iterate through reads.
|
| - size_t total_bytes_read = 0;
|
| - while (0 < bytes_to_read) {
|
| - size_t bytes_this_read = fread(&json_buffer[total_bytes_read],
|
| - sizeof(char),
|
| - bytes_to_read,
|
| - json_file);
|
| - if (bytes_this_read < bytes_to_read &&
|
| - (feof(json_file) || ferror(json_file))) {
|
| - PLUGIN_PRINTF(("Plugin::NaClManifestFileDidOpen failed: "
|
| - "total_bytes_read=%"NACL_PRIuS" "
|
| - "bytes_to_read=%"NACL_PRIuS"\n",
|
| - total_bytes_read, bytes_to_read));
|
| - fclose(json_file);
|
| - error_info.SetReport(ERROR_MANIFEST_READ,
|
| - "could not read manifest file.");
|
| - ReportLoadError(error_info);
|
| - return;
|
| - }
|
| - total_bytes_read += bytes_this_read;
|
| - bytes_to_read -= bytes_this_read;
|
| - }
|
| - // Once the bytes are read, the FILE is no longer needed, so close it. This
|
| - // allows for early returns without leaking the |json_file| FILE object.
|
| - fclose(json_file);
|
| - // No need to close |file_desc|, that is handled by |nexe_downloader_|.
|
| - json_buffer[total_bytes_read] = '\0'; // Force null termination.
|
| -
|
| - ProcessNaClManifest(json_buffer.get());
|
| -}
|
| -
|
| -void Plugin::ProcessNaClManifest(const nacl::string& manifest_json) {
|
| - HistogramSizeKB("NaCl.Perf.Size.Manifest",
|
| - static_cast<int32_t>(manifest_json.length() / 1024));
|
| - nacl::string program_url;
|
| - bool is_portable;
|
| - ErrorInfo error_info;
|
| - if (!SetManifestObject(manifest_json, &error_info)) {
|
| - ReportLoadError(error_info);
|
| - return;
|
| - }
|
| -
|
| - if (SelectProgramURLFromManifest(&program_url, &error_info, &is_portable)) {
|
| - set_nacl_ready_state(LOADING);
|
| - // Inform JavaScript that we found a nexe URL to load.
|
| - EnqueueProgressEvent("progress",
|
| - LENGTH_IS_NOT_COMPUTABLE,
|
| - kUnknownBytes,
|
| - kUnknownBytes);
|
| - if (is_portable) {
|
| - // TODO(jvoung): Do we want to check an ENV var if pnacl is enabled first?
|
| - nacl::string llc_url;
|
| - nacl::string ld_url;
|
| - if (SelectLLCURLFromManifest(&llc_url, &error_info) &&
|
| - SelectLDURLFromManifest(&ld_url, &error_info)) {
|
| - pp::CompletionCallback translate_callback =
|
| - callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate);
|
| - // Will always call the callback on success or failure.
|
| - pnacl_.BitcodeToNative(program_url,
|
| - llc_url,
|
| - ld_url,
|
| - translate_callback);
|
| - return;
|
| - }
|
| - } else {
|
| - pp::CompletionCallback open_callback =
|
| - callback_factory_.NewRequiredCallback(&Plugin::NexeFileDidOpen);
|
| - // Will always call the callback on success or failure.
|
| - CHECK(
|
| - nexe_downloader_.Open(program_url, DOWNLOAD_TO_FILE, open_callback));
|
| - return;
|
| - }
|
| - }
|
| - // Failed to select the program and/or the translator.
|
| - ReportLoadError(error_info);
|
| -}
|
| -
|
| -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(
|
| - ERROR_MANIFEST_RESOLVE_URL,
|
| - nacl::string("could not resolve URL \"") + url.c_str() +
|
| - "\" relative to \"" + plugin_base_url().c_str() + "\".");
|
| - ReportLoadError(error_info);
|
| - return;
|
| - }
|
| - PLUGIN_PRINTF(("Plugin::RequestNaClManifest (resolved url='%s')\n",
|
| - nmf_resolved_url.AsString().c_str()));
|
| - set_manifest_base_url(nmf_resolved_url.AsString());
|
| - set_manifest_url(url);
|
| - // Inform JavaScript that a load is starting.
|
| - set_nacl_ready_state(OPENED);
|
| - EnqueueProgressEvent("loadstart",
|
| - LENGTH_IS_NOT_COMPUTABLE,
|
| - kUnknownBytes,
|
| - kUnknownBytes);
|
| - bool is_data_uri = GetUrlScheme(nmf_resolved_url.AsString()) == SCHEME_DATA;
|
| - HistogramEnumerateManifestIsDataURI(static_cast<int>(is_data_uri));
|
| - if (is_data_uri) {
|
| - pp::CompletionCallback open_callback =
|
| - callback_factory_.NewRequiredCallback(&Plugin::NaClManifestBufferReady);
|
| - // Will always call the callback on success or failure.
|
| - CHECK(nexe_downloader_.Open(nmf_resolved_url.AsString(),
|
| - DOWNLOAD_TO_BUFFER,
|
| - open_callback));
|
| - } else {
|
| - pp::CompletionCallback open_callback =
|
| - callback_factory_.NewRequiredCallback(&Plugin::NaClManifestFileDidOpen);
|
| - // Will always call the callback on success or failure.
|
| - CHECK(nexe_downloader_.Open(nmf_resolved_url.AsString(),
|
| - DOWNLOAD_TO_FILE,
|
| - open_callback));
|
| - }
|
| -}
|
| -
|
| -
|
| -bool Plugin::SetManifestObject(const nacl::string& manifest_json,
|
| - ErrorInfo* error_info) {
|
| - PLUGIN_PRINTF(("Plugin::SetManifestObject(): manifest_json='%s'.\n",
|
| - manifest_json.c_str()));
|
| - if (error_info == NULL)
|
| - return false;
|
| - manifest_.reset(
|
| - new Manifest(url_util_, manifest_base_url(), GetSandboxISA()));
|
| - if (!manifest_->Init(manifest_json, error_info)) {
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool Plugin::SelectProgramURLFromManifest(nacl::string* result,
|
| - ErrorInfo* error_info,
|
| - bool* is_portable) {
|
| - const nacl::string sandbox_isa(GetSandboxISA());
|
| - PLUGIN_PRINTF(("Plugin::SelectProgramURLFromManifest(): sandbox='%s'.\n",
|
| - sandbox_isa.c_str()));
|
| - if (result == NULL || error_info == NULL || manifest_ == NULL)
|
| - return false;
|
| - return manifest_->GetProgramURL(result, error_info, is_portable);
|
| -}
|
| -
|
| -// TODO(jvoung): get rid of these when we have a better hosting solution
|
| -// for PNaCl's nexes.
|
| -bool Plugin::SelectLLCURLFromManifest(nacl::string* result,
|
| - ErrorInfo* error_info) {
|
| - PLUGIN_PRINTF(("Plugin::SelectLLCURLFromManifest()\n"));
|
| - if (result == NULL || error_info == NULL || manifest_ == NULL)
|
| - return false;
|
| - return manifest_->GetLLCURL(result, error_info);
|
| -}
|
| -
|
| -bool Plugin::SelectLDURLFromManifest(nacl::string* result,
|
| - ErrorInfo* error_info) {
|
| - PLUGIN_PRINTF(("Plugin::SelectLDURLFromManifest()\n"));
|
| - if (result == NULL || error_info == NULL || manifest_ == NULL)
|
| - return false;
|
| - return manifest_->GetLDURL(result, error_info);
|
| -}
|
| -// end TODO(jvoung)
|
| -
|
| -
|
| -void Plugin::UrlDidOpenForStreamAsFile(int32_t pp_error,
|
| - FileDownloader*& url_downloader,
|
| - PP_CompletionCallback callback) {
|
| - PLUGIN_PRINTF(("Plugin::UrlDidOpen (pp_error=%"NACL_PRId32
|
| - ", url_downloader=%p)\n", pp_error,
|
| - static_cast<void*>(url_downloader)));
|
| - url_downloaders_.erase(url_downloader);
|
| - nacl::scoped_ptr<FileDownloader> scoped_url_downloader(url_downloader);
|
| - int32_t file_desc = scoped_url_downloader->GetPOSIXFileDescriptor();
|
| -
|
| - if (pp_error != PP_OK) {
|
| - PP_RunCompletionCallback(&callback, pp_error);
|
| - } else if (file_desc > NACL_NO_FILE_DESC) {
|
| - url_fd_map_[url_downloader->url_to_open()] = file_desc;
|
| - PP_RunCompletionCallback(&callback, PP_OK);
|
| - } else {
|
| - PP_RunCompletionCallback(&callback, PP_ERROR_FAILED);
|
| - }
|
| -}
|
| -
|
| -int32_t Plugin::GetPOSIXFileDesc(const nacl::string& url) {
|
| - PLUGIN_PRINTF(("Plugin::GetFileDesc (url=%s)\n", url.c_str()));
|
| - int32_t file_desc_ok_to_close = NACL_NO_FILE_DESC;
|
| - std::map<nacl::string, int32_t>::iterator it = url_fd_map_.find(url);
|
| - if (it != url_fd_map_.end())
|
| - file_desc_ok_to_close = DUP(it->second);
|
| - return file_desc_ok_to_close;
|
| -}
|
| -
|
| -
|
| -bool Plugin::StreamAsFile(const nacl::string& url,
|
| - PP_CompletionCallback callback) {
|
| - PLUGIN_PRINTF(("Plugin::StreamAsFile (url='%s')\n", url.c_str()));
|
| - FileDownloader* downloader = new FileDownloader();
|
| - downloader->Initialize(this);
|
| - url_downloaders_.insert(downloader);
|
| - pp::CompletionCallback open_callback =
|
| - callback_factory_.NewRequiredCallback(
|
| - &Plugin::UrlDidOpenForStreamAsFile, downloader, callback);
|
| - // 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()));
|
| - return false;
|
| - }
|
| - // If true, will always call the callback on success or failure.
|
| - return downloader->Open(url, DOWNLOAD_TO_FILE, open_callback);
|
| -}
|
| -
|
| -#ifndef HACK_FOR_MACOS_HANG_REMOVED
|
| -// The following is needed to avoid a plugin startup hang in the
|
| -// MacOS "chrome_browser_tests under gyp" stage.
|
| -// TODO(sehr,mseaborn): remove this hack.
|
| -void (plugin::Plugin::*pmem)(int32_t,
|
| - plugin::FileDownloader*&,
|
| - pp::VarPrivate&);
|
| -void Plugin::XYZZY(const nacl::string& url,
|
| - pp::VarPrivate js_callback) {
|
| - UNREFERENCED_PARAMETER(url);
|
| - UNREFERENCED_PARAMETER(js_callback);
|
| - pp::CompletionCallback open_callback =
|
| - callback_factory_.NewRequiredCallback(pmem,
|
| - reinterpret_cast<plugin::FileDownloader*>(NULL),
|
| - js_callback);
|
| -}
|
| -#endif // HACK_FOR_MACOS_HANG_REMOVED
|
| -
|
| -
|
| -void Plugin::ReportLoadSuccess(LengthComputable length_computable,
|
| - uint64_t loaded_bytes,
|
| - uint64_t total_bytes) {
|
| - // Set the readyState attribute to indicate loaded.
|
| - set_nacl_ready_state(DONE);
|
| - // Inform JavaScript that loading was successful and is complete.
|
| - EnqueueProgressEvent("load", length_computable, loaded_bytes, total_bytes);
|
| - EnqueueProgressEvent("loadend", length_computable, loaded_bytes, total_bytes);
|
| -
|
| - // UMA
|
| - HistogramEnumerateLoadStatus(ERROR_LOAD_SUCCESS);
|
| -}
|
| -
|
| -
|
| -// TODO(ncbray): report UMA stats
|
| -void Plugin::ReportLoadError(const ErrorInfo& error_info) {
|
| - PLUGIN_PRINTF(("Plugin::ReportLoadError (error='%s')\n",
|
| - error_info.message().c_str()));
|
| - // Set the readyState attribute to indicate we need to start over.
|
| - set_nacl_ready_state(DONE);
|
| - // Report an error in lastError and on the JavaScript console.
|
| - nacl::string message = nacl::string("NaCl module load failed: ") +
|
| - error_info.message();
|
| - set_last_error_string(message);
|
| - browser_interface()->AddToConsole(this, message);
|
| - ShutdownProxy();
|
| - // Inform JavaScript that loading encountered an error and is complete.
|
| - EnqueueProgressEvent("error",
|
| - LENGTH_IS_NOT_COMPUTABLE,
|
| - kUnknownBytes,
|
| - kUnknownBytes);
|
| - EnqueueProgressEvent("loadend",
|
| - LENGTH_IS_NOT_COMPUTABLE,
|
| - kUnknownBytes,
|
| - kUnknownBytes);
|
| -
|
| - // UMA
|
| - HistogramEnumerateLoadStatus(error_info.error_code());
|
| -}
|
| -
|
| -
|
| -void Plugin::ReportLoadAbort() {
|
| - PLUGIN_PRINTF(("Plugin::ReportLoadAbort\n"));
|
| - // Set the readyState attribute to indicate we need to start over.
|
| - set_nacl_ready_state(DONE);
|
| - // Report an error in lastError and on the JavaScript console.
|
| - nacl::string error_string("NaCl module load failed: user aborted");
|
| - set_last_error_string(error_string);
|
| - browser_interface()->AddToConsole(this, error_string);
|
| - ShutdownProxy();
|
| - // Inform JavaScript that loading was aborted and is complete.
|
| - EnqueueProgressEvent("abort",
|
| - LENGTH_IS_NOT_COMPUTABLE,
|
| - kUnknownBytes,
|
| - kUnknownBytes);
|
| - EnqueueProgressEvent("loadend",
|
| - LENGTH_IS_NOT_COMPUTABLE,
|
| - kUnknownBytes,
|
| - kUnknownBytes);
|
| -
|
| - // UMA
|
| - HistogramEnumerateLoadStatus(ERROR_LOAD_ABORTED);
|
| -}
|
| -
|
| -
|
| -void Plugin::EnqueueProgressEvent(const char* event_type,
|
| - LengthComputable length_computable,
|
| - uint64_t loaded_bytes,
|
| - uint64_t total_bytes) {
|
| - PLUGIN_PRINTF(("Plugin::EnqueueProgressEvent ("
|
| - "event_type='%s', length_computable=%d, "
|
| - "loaded=%"NACL_PRIu64", total=%"NACL_PRIu64")\n",
|
| - event_type,
|
| - static_cast<int>(length_computable),
|
| - loaded_bytes,
|
| - total_bytes));
|
| -
|
| - progress_events_.push(new ProgressEvent(event_type,
|
| - length_computable,
|
| - loaded_bytes,
|
| - total_bytes));
|
| - // Note that using callback_factory_ in this way is not thread safe.
|
| - // If/when EnqueueProgressEvent is callable from another thread, this
|
| - // will need to change.
|
| - pp::CompletionCallback callback =
|
| - callback_factory_.NewCallback(&Plugin::DispatchProgressEvent);
|
| - pp::Core* core = pp::Module::Get()->core();
|
| - core->CallOnMainThread(0, callback, 0);
|
| -}
|
| -
|
| -void Plugin::ReportSelLdrLoadStatus(int status) {
|
| - HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status));
|
| -}
|
| -
|
| -void Plugin::DispatchProgressEvent(int32_t result) {
|
| - PLUGIN_PRINTF(("Plugin::DispatchProgressEvent (result=%"
|
| - NACL_PRId32")\n", result));
|
| - if (result < 0) {
|
| - return;
|
| - }
|
| - if (progress_events_.empty()) {
|
| - PLUGIN_PRINTF(("Plugin::DispatchProgressEvent: no pending events\n"));
|
| - return;
|
| - }
|
| - nacl::scoped_ptr<ProgressEvent> event(progress_events_.front());
|
| - progress_events_.pop();
|
| - PLUGIN_PRINTF(("Plugin::DispatchProgressEvent ("
|
| - "event_type='%s', length_computable=%d, "
|
| - "loaded=%"NACL_PRIu64", total=%"NACL_PRIu64")\n",
|
| - event->event_type(),
|
| - static_cast<int>(event->length_computable()),
|
| - event->loaded_bytes(),
|
| - event->total_bytes()));
|
| -
|
| - static const char* kEventClosureJS =
|
| - "(function(target, type, lengthComputable, loadedBytes, totalBytes) {"
|
| - " var progress_event = document.createEvent('ProgressEvent');"
|
| - " progress_event.initProgressEvent(type, false, true,"
|
| - " lengthComputable,"
|
| - " loadedBytes,"
|
| - " totalBytes);"
|
| - " target.dispatchEvent(progress_event);"
|
| - "})";
|
| -
|
| - // Create a function object by evaluating the JavaScript text.
|
| - // TODO(sehr, polina): We should probably cache the created function object to
|
| - // avoid JavaScript reparsing.
|
| - pp::VarPrivate exception;
|
| - pp::VarPrivate function_object = ExecuteScript(kEventClosureJS, &exception);
|
| - if (!exception.is_undefined() || !function_object.is_object()) {
|
| - PLUGIN_PRINTF(("Plugin::DispatchProgressEvent:"
|
| - " Function object creation failed.\n"));
|
| - return;
|
| - }
|
| - // Get the target of the event to be dispatched.
|
| - pp::Var owner_element_object = GetOwnerElementObject();
|
| - if (!owner_element_object.is_object()) {
|
| - PLUGIN_PRINTF(("Plugin::DispatchProgressEvent:"
|
| - " Couldn't get owner element object.\n"));
|
| - NACL_NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - pp::Var argv[5];
|
| - static const uint32_t argc = NACL_ARRAY_SIZE(argv);
|
| - argv[0] = owner_element_object;
|
| - argv[1] = pp::Var(event->event_type());
|
| - argv[2] = pp::Var(event->length_computable() == LENGTH_IS_COMPUTABLE);
|
| - argv[3] = pp::Var(static_cast<double>(event->loaded_bytes()));
|
| - argv[4] = pp::Var(static_cast<double>(event->total_bytes()));
|
| -
|
| - // Dispatch the event.
|
| - const pp::Var default_method;
|
| - function_object.Call(default_method, argc, argv, &exception);
|
| - if (!exception.is_undefined()) {
|
| - PLUGIN_PRINTF(("Plugin::DispatchProgressEvent:"
|
| - " event dispatch failed.\n"));
|
| - }
|
| -}
|
| -
|
| -UrlSchemeType Plugin::GetUrlScheme(const std::string& url) {
|
| - CHECK(url_util_ != NULL);
|
| - PP_URLComponents_Dev comps;
|
| - pp::Var canonicalized =
|
| - url_util_->Canonicalize(pp::Var(url), &comps);
|
| -
|
| - if (canonicalized.is_null() ||
|
| - (comps.scheme.begin == 0 && comps.scheme.len == -1)) {
|
| - // |url| was an invalid URL or has no scheme.
|
| - return SCHEME_OTHER;
|
| - }
|
| -
|
| - CHECK(comps.scheme.begin <
|
| - static_cast<int>(canonicalized.AsString().size()));
|
| - CHECK(comps.scheme.begin + comps.scheme.len <
|
| - static_cast<int>(canonicalized.AsString().size()));
|
| -
|
| - std::string scheme = canonicalized.AsString().substr(comps.scheme.begin,
|
| - comps.scheme.len);
|
| - if (scheme == kChromeExtensionUriScheme)
|
| - return SCHEME_CHROME_EXTENSION;
|
| - if (scheme == kDataUriScheme)
|
| - return SCHEME_DATA;
|
| - return SCHEME_OTHER;
|
| -}
|
| -
|
| -} // namespace plugin
|
|
|