diff options
author | teravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-23 16:58:15 +0000 |
---|---|---|
committer | teravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-23 16:58:15 +0000 |
commit | b7a490e0be828962ef7d89c30dd551afb34ea221 (patch) | |
tree | a3aad4324bc736d148c599a70647db4980fd38b4 | |
parent | ed6fb9859804cde4602cb57dc12652bea23da651 (diff) | |
download | chromium_src-b7a490e0be828962ef7d89c30dd551afb34ea221.zip chromium_src-b7a490e0be828962ef7d89c30dd551afb34ea221.tar.gz chromium_src-b7a490e0be828962ef7d89c30dd551afb34ea221.tar.bz2 |
Pepper: Delete FileDownloader in trusted plugin.
This simplifies PnaclCoordinator considerably and reduces the total
amount of code in the trusted plugin.
BUG=239656
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=284684
R=dmichael@chromium.org
Review URL: https://codereview.chromium.org/393693004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284961 0039d316-1c4b-4281-b951-d872f2087c98
17 files changed, 438 insertions, 649 deletions
diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc index aa66f08..9ada43d 100644 --- a/components/nacl/renderer/ppb_nacl_private_impl.cc +++ b/components/nacl/renderer/ppb_nacl_private_impl.cc @@ -17,6 +17,8 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/rand_util.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "components/nacl/common/nacl_host_messages.h" #include "components/nacl/common/nacl_messages.h" #include "components/nacl/common/nacl_nonsfi_util.h" @@ -52,6 +54,7 @@ #include "ppapi/shared_impl/var_tracker.h" #include "ppapi/thunk/enter.h" #include "third_party/WebKit/public/platform/WebURLLoader.h" +#include "third_party/WebKit/public/platform/WebURLResponse.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebElement.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" @@ -587,80 +590,40 @@ PP_Bool PPIsNonSFIModeEnabled() { return PP_FromBool(IsNonSFIModeEnabled()); } -void GetNexeFdContinuation(scoped_refptr<ppapi::TrackedCallback> callback, - PP_Bool* out_is_hit, - PP_FileHandle* out_handle, - int32_t pp_error, - bool is_hit, - PP_FileHandle handle) { - if (pp_error == PP_OK) { - *out_is_hit = PP_FromBool(is_hit); - *out_handle = handle; - } - callback->PostRun(pp_error); -} - -int32_t GetNexeFd(PP_Instance instance, - const char* pexe_url, - uint32_t abi_version, - uint32_t opt_level, - const char* http_headers_param, - const char* extra_flags, - PP_Bool* is_hit, - PP_FileHandle* handle, - struct PP_CompletionCallback callback) { - ppapi::thunk::EnterInstance enter(instance, callback); - if (enter.failed()) - return enter.retval(); - if (!pexe_url || !is_hit || !handle) - return enter.SetResult(PP_ERROR_BADARGUMENT); - if (!InitializePnaclResourceHost()) - return enter.SetResult(PP_ERROR_FAILED); - - std::string http_headers(http_headers_param); - net::HttpUtil::HeadersIterator iter( - http_headers.begin(), http_headers.end(), "\r\n"); - - std::string last_modified; - std::string etag; - bool has_no_store_header = false; - while (iter.GetNext()) { - if (StringToLowerASCII(iter.name()) == "last-modified") - last_modified = iter.values(); - if (StringToLowerASCII(iter.name()) == "etag") - etag = iter.values(); - if (StringToLowerASCII(iter.name()) == "cache-control") { - net::HttpUtil::ValuesIterator values_iter( - iter.values_begin(), iter.values_end(), ','); - while (values_iter.GetNext()) { - if (StringToLowerASCII(values_iter.value()) == "no-store") - has_no_store_header = true; - } - } +void GetNexeFd(PP_Instance instance, + const std::string& pexe_url, + uint32_t opt_level, + const base::Time& last_modified_time, + const std::string& etag, + bool has_no_store_header, + base::Callback<void(int32_t, bool, PP_FileHandle)> callback) { + if (!InitializePnaclResourceHost()) { + ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( + FROM_HERE, + base::Bind(callback, + static_cast<int32_t>(PP_ERROR_FAILED), + false, + PP_kInvalidFileHandle)); + return; } - base::Time last_modified_time; - // If FromString fails, it doesn't touch last_modified_time and we just send - // the default-constructed null value. - base::Time::FromString(last_modified.c_str(), &last_modified_time); - PnaclCacheInfo cache_info; cache_info.pexe_url = GURL(pexe_url); - cache_info.abi_version = abi_version; + // TODO(dschuff): Get this value from the pnacl json file after it + // rolls in from NaCl. + cache_info.abi_version = 1; cache_info.opt_level = opt_level; cache_info.last_modified = last_modified_time; cache_info.etag = etag; cache_info.has_no_store_header = has_no_store_header; cache_info.sandbox_isa = GetSandboxArch(); - cache_info.extra_flags = std::string(extra_flags); + cache_info.extra_flags = GetCpuFeatures(); g_pnacl_resource_host.Get()->RequestNexeFd( GetRoutingID(instance), instance, cache_info, - base::Bind(&GetNexeFdContinuation, enter.callback(), is_hit, handle)); - - return enter.SetResult(PP_OK_COMPLETIONPENDING); + callback); } void ReportTranslationFinished(PP_Instance instance, @@ -1563,6 +1526,160 @@ void SetPNaClStartTime(PP_Instance instance) { load_manager->set_pnacl_start_time(base::Time::Now()); } +class PexeDownloader : public blink::WebURLLoaderClient { + public: + PexeDownloader(PP_Instance instance, + scoped_ptr<blink::WebURLLoader> url_loader, + const std::string& pexe_url, + int32_t pexe_opt_level, + const PPP_PexeStreamHandler* stream_handler, + void* stream_handler_user_data) + : instance_(instance), + url_loader_(url_loader.Pass()), + pexe_url_(pexe_url), + pexe_opt_level_(pexe_opt_level), + stream_handler_(stream_handler), + stream_handler_user_data_(stream_handler_user_data), + success_(false), + expected_content_length_(-1), + weak_factory_(this) { } + + void Load(const blink::WebURLRequest& request) { + url_loader_->loadAsynchronously(request, this); + } + + private: + virtual void didReceiveResponse(blink::WebURLLoader* loader, + const blink::WebURLResponse& response) { + success_ = (response.httpStatusCode() == 200); + if (!success_) + return; + + expected_content_length_ = response.expectedContentLength(); + + // Defer loading after receiving headers. This is because we may already + // have a cached translated nexe, so check for that now. + url_loader_->setDefersLoading(true); + + std::string etag = response.httpHeaderField("etag").utf8(); + std::string last_modified = + response.httpHeaderField("last-modified").utf8(); + base::Time last_modified_time; + base::Time::FromString(last_modified.c_str(), &last_modified_time); + + bool has_no_store_header = false; + std::string cache_control = + response.httpHeaderField("cache-control").utf8(); + + std::vector<std::string> values; + base::SplitString(cache_control, ',', &values); + for (std::vector<std::string>::const_iterator it = values.begin(); + it != values.end(); + ++it) { + if (StringToLowerASCII(*it) == "no-store") + has_no_store_header = true; + } + + GetNexeFd(instance_, + pexe_url_, + pexe_opt_level_, + last_modified_time, + etag, + has_no_store_header, + base::Bind(&PexeDownloader::didGetNexeFd, + weak_factory_.GetWeakPtr())); + } + + virtual void didGetNexeFd(int32_t pp_error, + bool cache_hit, + PP_FileHandle file_handle) { + if (cache_hit) { + stream_handler_->DidCacheHit(stream_handler_user_data_, file_handle); + + // We delete the PexeDownloader at this point since we successfully got a + // cached, translated nexe. + delete this; + return; + } + stream_handler_->DidCacheMiss(stream_handler_user_data_, + expected_content_length_); + + // No translated nexe was found in the cache, so we should download the + // file to start streaming it. + url_loader_->setDefersLoading(false); + } + + virtual void didReceiveData(blink::WebURLLoader* loader, + const char* data, + int data_length, + int encoded_data_length) { + // Stream the data we received to the stream callback. + stream_handler_->DidStreamData(stream_handler_user_data_, + data, + data_length); + } + + virtual void didFinishLoading(blink::WebURLLoader* loader, + double finish_time, + int64_t total_encoded_data_length) { + int32_t result = success_ ? PP_OK : PP_ERROR_FAILED; + stream_handler_->DidFinishStream(stream_handler_user_data_, result); + delete this; + } + + virtual void didFail(blink::WebURLLoader* loader, + const blink::WebURLError& error) { + success_ = false; + } + + PP_Instance instance_; + scoped_ptr<blink::WebURLLoader> url_loader_; + std::string pexe_url_; + int32_t pexe_opt_level_; + const PPP_PexeStreamHandler* stream_handler_; + void* stream_handler_user_data_; + bool success_; + int64_t expected_content_length_; + base::WeakPtrFactory<PexeDownloader> weak_factory_; +}; + +void StreamPexe(PP_Instance instance, + const char* pexe_url, + int32_t opt_level, + const PPP_PexeStreamHandler* handler, + void* handler_user_data) { + content::PepperPluginInstance* plugin_instance = + content::PepperPluginInstance::Get(instance); + if (!plugin_instance) { + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(handler->DidFinishStream, + handler_user_data, + static_cast<int32_t>(PP_ERROR_FAILED))); + return; + } + + GURL gurl(pexe_url); + const blink::WebDocument& document = + plugin_instance->GetContainer()->element().document(); + scoped_ptr<blink::WebURLLoader> url_loader( + CreateWebURLLoader(document, gurl)); + PexeDownloader* downloader = new PexeDownloader(instance, + url_loader.Pass(), + pexe_url, + opt_level, + handler, + handler_user_data); + + blink::WebURLRequest url_request = CreateWebURLRequest(document, gurl); + // Mark the request as requesting a PNaCl bitcode file, + // so that component updater can detect this user action. + url_request.addHTTPHeaderField( + blink::WebString::fromUTF8("Accept"), + blink::WebString::fromUTF8("application/x-pnacl, */*")); + downloader->Load(url_request); +} + const PPB_NaCl_Private nacl_interface = { &LaunchSelLdr, &StartPpapiProxy, @@ -1573,7 +1690,6 @@ const PPB_NaCl_Private nacl_interface = { &CreateTemporaryFile, &GetNumberOfProcessors, &PPIsNonSFIModeEnabled, - &GetNexeFd, &ReportTranslationFinished, &DispatchEvent, &ReportLoadSuccess, @@ -1603,7 +1719,8 @@ const PPB_NaCl_Private nacl_interface = { &ReportSelLdrStatus, &LogTranslateTime, &OpenManifestEntry, - &SetPNaClStartTime + &SetPNaClStartTime, + &StreamPexe }; } // namespace diff --git a/ppapi/api/private/ppb_nacl_private.idl b/ppapi/api/private/ppb_nacl_private.idl index 1992aed..d847cc7 100644 --- a/ppapi/api/private/ppb_nacl_private.idl +++ b/ppapi/api/private/ppb_nacl_private.idl @@ -237,28 +237,6 @@ interface PPB_NaCl_Private { /* Return whether the non-SFI mode is enabled. */ PP_Bool IsNonSFIModeEnabled(); - /* Create a temporary file, which will be deleted by the time the - * last handle is closed (or earlier on POSIX systems), to use for - * the nexe with the cache information given by |pexe_url|, - * |abi_version|, |opt_level|, and |headers|. If the nexe is already present - * in the cache, |is_hit| is set to PP_TRUE and the contents of the nexe will - * be copied into the temporary file. Otherwise |is_hit| is set to PP_FALSE - * and the temporary file will be writeable. Currently the implementation is - * a stub, which always sets is_hit to false and calls the implementation of - * CreateTemporaryFile. In a subsequent CL it will call into the browser - * which will remember the association between the cache key and the fd, and - * copy the nexe into the cache after the translation finishes. - */ - int32_t GetNexeFd([in] PP_Instance instance, - [in] str_t pexe_url, - [in] uint32_t abi_version, - [in] uint32_t opt_level, - [in] str_t headers, - [in] str_t extra_flags, - [out] PP_Bool is_hit, - [out] PP_FileHandle nexe_handle, - [in] PP_CompletionCallback callback); - /* Report to the browser that translation of the pexe for |instance| * has finished, or aborted with an error. If |success| is true, the * browser may then store the translation in the cache. The renderer @@ -419,4 +397,18 @@ interface PPB_NaCl_Private { * time. */ void SetPNaClStartTime([in] PP_Instance instance); + + /* Downloads and streams a pexe file for PNaCl translation. + * Fetches the content at |pexe_url| for the given instance and opt_level. + * If a translated cached nexe is already available, |cache_hit_handle| + * is set and |cache_hit_callback| is called. + * Otherwise, |stream_callback| is called repeatedly with blocks of data + * as they are received. |stream_finished_callback| is called after all + * data has been received and dispatched to |stream_callback|. + */ + void StreamPexe([in] PP_Instance instance, + [in] str_t pexe_url, + [in] int32_t opt_level, + [in] PPP_PexeStreamHandler stream_handler, + [inout] mem_t stream_handler_user_data); }; diff --git a/ppapi/api/private/ppp_pexe_stream_handler.idl b/ppapi/api/private/ppp_pexe_stream_handler.idl new file mode 100644 index 0000000..c2c8bf1 --- /dev/null +++ b/ppapi/api/private/ppp_pexe_stream_handler.idl @@ -0,0 +1,45 @@ +/* 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. + */ + +/* This file contains NaCl private interfaces. This interface is not versioned + * and is for internal Chrome use. It may change without notice. */ + +#inline c +#include "ppapi/c/private/pp_file_handle.h" +#endinl + +label Chrome { + M25 = 1.0 +}; + +interface PPP_PexeStreamHandler { + /** + * Invoked as a result of a cache hit for a translated pexe. + */ + void DidCacheHit([inout] mem_t user_data, + [in] PP_FileHandle nexe_file_handle); + + /** + * Invoked as a result of a cache miss for a translated pexe. + * Provides the expected length of the pexe, as read from HTTP headers. + */ + void DidCacheMiss([inout] mem_t user_data, + [in] int64_t expected_total_length); + + /** + * Invoked when a block of data has been downloaded. + * Only invoked after DidCacheMiss(). + */ + void DidStreamData([inout] mem_t user_data, + [in] mem_t data, + [in] int32_t length); + + /** + * Invoked when the stream has finished downloading, regardless of whether it + * succeeded. Not invoked if DidCacheHit() was called. + */ + void DidFinishStream([inout] mem_t user_data, + [in] int32_t pp_error); +}; diff --git a/ppapi/c/private/ppb_nacl_private.h b/ppapi/c/private/ppb_nacl_private.h index 29ef59c..940979f 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 Wed Jul 9 11:09:04 2014. */ +/* From private/ppb_nacl_private.idl modified Thu Jul 10 10:34:30 2014. */ #ifndef PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ #define PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ @@ -14,6 +14,7 @@ #include "ppapi/c/pp_macros.h" #include "ppapi/c/pp_stdint.h" #include "ppapi/c/pp_var.h" +#include "ppapi/c/private/ppp_pexe_stream_handler.h" #define PPB_NACL_PRIVATE_INTERFACE_1_0 "PPB_NaCl_Private;1.0" #define PPB_NACL_PRIVATE_INTERFACE PPB_NACL_PRIVATE_INTERFACE_1_0 @@ -270,27 +271,6 @@ struct PPB_NaCl_Private_1_0 { int32_t (*GetNumberOfProcessors)(void); /* Return whether the non-SFI mode is enabled. */ PP_Bool (*IsNonSFIModeEnabled)(void); - /* Create a temporary file, which will be deleted by the time the - * last handle is closed (or earlier on POSIX systems), to use for - * the nexe with the cache information given by |pexe_url|, - * |abi_version|, |opt_level|, and |headers|. If the nexe is already present - * in the cache, |is_hit| is set to PP_TRUE and the contents of the nexe will - * be copied into the temporary file. Otherwise |is_hit| is set to PP_FALSE - * and the temporary file will be writeable. Currently the implementation is - * a stub, which always sets is_hit to false and calls the implementation of - * CreateTemporaryFile. In a subsequent CL it will call into the browser - * which will remember the association between the cache key and the fd, and - * copy the nexe into the cache after the translation finishes. - */ - int32_t (*GetNexeFd)(PP_Instance instance, - const char* pexe_url, - uint32_t abi_version, - uint32_t opt_level, - const char* headers, - const char* extra_flags, - PP_Bool* is_hit, - PP_FileHandle* nexe_handle, - struct PP_CompletionCallback callback); /* Report to the browser that translation of the pexe for |instance| * has finished, or aborted with an error. If |success| is true, the * browser may then store the translation in the cache. The renderer @@ -416,6 +396,19 @@ struct PPB_NaCl_Private_1_0 { * time. */ void (*SetPNaClStartTime)(PP_Instance instance); + /* Downloads and streams a pexe file for PNaCl translation. + * Fetches the content at |pexe_url| for the given instance and opt_level. + * If a translated cached nexe is already available, |cache_hit_handle| + * is set and |cache_hit_callback| is called. + * Otherwise, |stream_callback| is called repeatedly with blocks of data + * as they are received. |stream_finished_callback| is called after all + * data has been received and dispatched to |stream_callback|. + */ + void (*StreamPexe)(PP_Instance instance, + const char* pexe_url, + int32_t opt_level, + const struct PPP_PexeStreamHandler_1_0* stream_handler, + void* stream_handler_user_data); }; typedef struct PPB_NaCl_Private_1_0 PPB_NaCl_Private; diff --git a/ppapi/c/private/ppp_pexe_stream_handler.h b/ppapi/c/private/ppp_pexe_stream_handler.h new file mode 100644 index 0000000..abb2cb0 --- /dev/null +++ b/ppapi/c/private/ppp_pexe_stream_handler.h @@ -0,0 +1,59 @@ +/* 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. + */ + +/* From private/ppp_pexe_stream_handler.idl, + * modified Thu Jul 10 11:05:31 2014. + */ + +#ifndef PPAPI_C_PRIVATE_PPP_PEXE_STREAM_HANDLER_H_ +#define PPAPI_C_PRIVATE_PPP_PEXE_STREAM_HANDLER_H_ + +#include "ppapi/c/pp_macros.h" +#include "ppapi/c/pp_stdint.h" + +#define PPP_PEXESTREAMHANDLER_INTERFACE_1_0 "PPP_PexeStreamHandler;1.0" +#define PPP_PEXESTREAMHANDLER_INTERFACE PPP_PEXESTREAMHANDLER_INTERFACE_1_0 + +/** + * @file + * This file contains NaCl private interfaces. This interface is not versioned + * and is for internal Chrome use. It may change without notice. */ + + +#include "ppapi/c/private/pp_file_handle.h" + +/** + * @addtogroup Interfaces + * @{ + */ +struct PPP_PexeStreamHandler_1_0 { + /** + * Invoked as a result of a cache hit for a translated pexe. + */ + void (*DidCacheHit)(void* user_data, PP_FileHandle nexe_file_handle); + /** + * Invoked as a result of a cache miss for a translated pexe. + * Provides the expected length of the pexe, as read from HTTP headers. + */ + void (*DidCacheMiss)(void* user_data, int64_t expected_total_length); + /** + * Invoked when a block of data has been downloaded. + * Only invoked after DidCacheMiss(). + */ + void (*DidStreamData)(void* user_data, const void* data, int32_t length); + /** + * Invoked when the stream has finished downloading, regardless of whether it + * succeeded. Not invoked if DidCacheHit() was called. + */ + void (*DidFinishStream)(void* user_data, int32_t pp_error); +}; + +typedef struct PPP_PexeStreamHandler_1_0 PPP_PexeStreamHandler; +/** + * @} + */ + +#endif /* PPAPI_C_PRIVATE_PPP_PEXE_STREAM_HANDLER_H_ */ + diff --git a/ppapi/native_client/src/trusted/plugin/callback_source.h b/ppapi/native_client/src/trusted/plugin/callback_source.h deleted file mode 100644 index 928a577..0000000 --- a/ppapi/native_client/src/trusted/plugin/callback_source.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_CALLBACK_SOURCE_H -#define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_CALLBACK_SOURCE_H - -#include "ppapi/cpp/completion_callback.h" - -namespace plugin { - -// Classes that implement this interface can be used with FileDownloader's -// DOWNLOAD_STREAM mode. For each chunk of the file as it downloads, -// The FileDownloader will get a callback of type -// pp::CompletionCallbackWithOutput<std::vector<char>*> using the -// GetCallback function, and call it immediately, passing a pointer to a -// vector with the data as the output field. The class is templatized just -// in case there are any other use cases in the future. -// This class really only exists as a way to get callbacks -// bound to an object (i.e. we don't need the asynchronous behavior of PPAPI) -// All we really need is tr1::function or base::bind or some such, but we don't -// have those in the plugin. - -template<class T> -class CallbackSource { - public: - virtual ~CallbackSource(); - // Returns a callback from callback_factory's NewCallbackWithOutput, - // bound to the implementing object. - virtual pp::CompletionCallbackWithOutput<T> GetCallback() = 0; -}; -} -#endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_CALLBACK_SOURCE_H diff --git a/ppapi/native_client/src/trusted/plugin/file_downloader.cc b/ppapi/native_client/src/trusted/plugin/file_downloader.cc deleted file mode 100644 index ccddfe8..0000000 --- a/ppapi/native_client/src/trusted/plugin/file_downloader.cc +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ppapi/native_client/src/trusted/plugin/file_downloader.h" - -#include <stdio.h> -#include <string.h> -#include <string> - -#include "native_client/src/include/portability_io.h" -#include "native_client/src/shared/platform/nacl_check.h" -#include "native_client/src/shared/platform/nacl_time.h" -#include "ppapi/c/pp_errors.h" -#include "ppapi/cpp/url_request_info.h" -#include "ppapi/cpp/url_response_info.h" -#include "ppapi/native_client/src/trusted/plugin/callback_source.h" -#include "ppapi/native_client/src/trusted/plugin/plugin.h" -#include "ppapi/native_client/src/trusted/plugin/utility.h" - -namespace plugin { - -FileDownloader::FileDownloader(Plugin* instance) - : instance_(instance), - file_open_notify_callback_(pp::BlockUntilComplete()), - stream_finish_callback_(pp::BlockUntilComplete()), - mode_(DOWNLOAD_NONE), - data_stream_callback_source_(NULL) { - callback_factory_.Initialize(this); - temp_buffer_.resize(kTempBufferSize); -} - -bool FileDownloader::OpenStream( - const nacl::string& url, - const pp::CompletionCallback& callback, - StreamCallbackSource* stream_callback_source) { - data_stream_callback_source_ = stream_callback_source; - PLUGIN_PRINTF(("FileDownloader::Open (url=%s)\n", url.c_str())); - if (callback.pp_completion_callback().func == NULL || instance_ == NULL) - return false; - - status_code_ = -1; - file_open_notify_callback_ = callback; - mode_ = DOWNLOAD_TO_BUFFER_AND_STREAM; - pp::URLRequestInfo url_request(instance_); - - // Allow CORS. - // Note that "SetAllowCrossOriginRequests" (currently) has the side effect of - // preventing credentials from being sent on same-origin requests. We - // therefore avoid setting this flag unless we know for sure it is a - // cross-origin request, resulting in behavior similar to XMLHttpRequest. - if (!instance_->DocumentCanRequest(url)) - url_request.SetAllowCrossOriginRequests(true); - - if (!extra_request_headers_.empty()) - url_request.SetHeaders(extra_request_headers_); - - // Reset the url loader and file reader. - // 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_); - url_request.SetRecordDownloadProgress(true); - - // Prepare the url request. - url_request.SetURL(url); - - // Request asynchronous download of the url providing an on-load callback. - // As long as this step is guaranteed to be asynchronous, we can call - // synchronously all other internal callbacks that eventually result in the - // invocation of the user callback. The user code will not be reentered. - pp::CompletionCallback onload_callback = - callback_factory_.NewCallback(&FileDownloader::URLLoadStartNotify); - int32_t pp_error = url_loader_.Open(url_request, onload_callback); - PLUGIN_PRINTF(("FileDownloader::Open (pp_error=%" NACL_PRId32 ")\n", - pp_error)); - CHECK(pp_error == PP_OK_COMPLETIONPENDING); - return true; -} - -bool FileDownloader::InitialResponseIsValid() { - // Process the response, validating the headers to confirm successful loading. - url_response_ = url_loader_.GetResponseInfo(); - if (url_response_.is_null()) { - PLUGIN_PRINTF(( - "FileDownloader::InitialResponseIsValid (url_response_=NULL)\n")); - return false; - } - - pp::Var full_url = url_response_.GetURL(); - if (!full_url.is_string()) { - PLUGIN_PRINTF(( - "FileDownloader::InitialResponseIsValid (url is not a string)\n")); - return false; - } - full_url_ = full_url.AsString(); - - status_code_ = url_response_.GetStatusCode(); - 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) { - PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (pp_error=%" - NACL_PRId32")\n", pp_error)); - if (pp_error != PP_OK) { - file_open_notify_callback_.RunAndClear(pp_error); - return; - } - - if (!InitialResponseIsValid()) { - file_open_notify_callback_.RunAndClear(PP_ERROR_FAILED); - return; - } - - file_open_notify_callback_.RunAndClear(PP_OK); -} - -void FileDownloader::BeginStreaming( - const pp::CompletionCallback& callback) { - stream_finish_callback_ = callback; - - // Finish streaming the body providing an optional callback. - pp::CompletionCallback onread_callback = - callback_factory_.NewOptionalCallback( - &FileDownloader::URLReadBodyNotify); - int32_t temp_size = static_cast<int32_t>(temp_buffer_.size()); - int32_t pp_error = url_loader_.ReadResponseBody(&temp_buffer_[0], - temp_size, - onread_callback); - if (pp_error != PP_OK_COMPLETIONPENDING) - onread_callback.RunAndClear(pp_error); -} - -void FileDownloader::URLReadBodyNotify(int32_t pp_error) { - PLUGIN_PRINTF(("FileDownloader::URLReadBodyNotify (pp_error=%" - NACL_PRId32")\n", pp_error)); - if (pp_error < PP_OK) { - stream_finish_callback_.RunAndClear(pp_error); - } else if (pp_error == PP_OK) { - data_stream_callback_source_->GetCallback().RunAndClear(PP_OK); - stream_finish_callback_.RunAndClear(PP_OK); - } else { - PLUGIN_PRINTF(("Running data_stream_callback, temp_buffer_=%p\n", - &temp_buffer_[0])); - StreamCallback cb = data_stream_callback_source_->GetCallback(); - *(cb.output()) = &temp_buffer_; - cb.RunAndClear(pp_error); - - pp::CompletionCallback onread_callback = - callback_factory_.NewOptionalCallback( - &FileDownloader::URLReadBodyNotify); - int32_t temp_size = static_cast<int32_t>(temp_buffer_.size()); - pp_error = url_loader_.ReadResponseBody(&temp_buffer_[0], - temp_size, - onread_callback); - if (pp_error != PP_OK_COMPLETIONPENDING) - onread_callback.RunAndClear(pp_error); - } -} - -bool FileDownloader::GetDownloadProgress( - int64_t* bytes_received, - int64_t* total_bytes_to_be_received) const { - return url_loader_.GetDownloadProgress(bytes_received, - total_bytes_to_be_received); -} - -nacl::string FileDownloader::GetResponseHeaders() const { - pp::Var headers = url_response_.GetHeaders(); - if (!headers.is_string()) { - PLUGIN_PRINTF(( - "FileDownloader::GetResponseHeaders (headers are not a string)\n")); - return nacl::string(); - } - return headers.AsString(); -} - -} // namespace plugin diff --git a/ppapi/native_client/src/trusted/plugin/file_downloader.h b/ppapi/native_client/src/trusted/plugin/file_downloader.h deleted file mode 100644 index 4a1a71a..0000000 --- a/ppapi/native_client/src/trusted/plugin/file_downloader.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_FILE_DOWNLOADER_H_ -#define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_FILE_DOWNLOADER_H_ - -#include <deque> - -#include "native_client/src/include/nacl_macros.h" -#include "native_client/src/include/nacl_string.h" -#include "native_client/src/public/nacl_file_info.h" -#include "ppapi/c/private/ppb_nacl_private.h" -#include "ppapi/cpp/file_io.h" -#include "ppapi/cpp/instance.h" -#include "ppapi/cpp/url_loader.h" -#include "ppapi/cpp/url_response_info.h" -#include "ppapi/native_client/src/trusted/plugin/callback_source.h" -#include "ppapi/utility/completion_callback_factory.h" - -namespace plugin { - -class Plugin; - -typedef enum { - DOWNLOAD_TO_BUFFER_AND_STREAM = 0, - DOWNLOAD_NONE -} DownloadMode; - -typedef std::vector<char>* FileStreamData; -typedef CallbackSource<FileStreamData> StreamCallbackSource; -typedef pp::CompletionCallbackWithOutput<FileStreamData> StreamCallback; - -// A class that wraps PPAPI URLLoader and FileIO functionality for downloading -// the url into a file and providing an open file descriptor. -class FileDownloader { - public: - explicit FileDownloader(Plugin* instance); - ~FileDownloader() {} - - // Issues a GET on |url| to start downloading the response into a file, - // and finish streaming it. |callback| will be run after streaming is - // done or if an error prevents streaming from completing. - // Returns true when callback is scheduled to be called on success or failure. - // Returns false if callback is NULL, or if the PPB_FileIO_Trusted interface - // is not available. - // If |record_progress| is true, then download progress will be recorded, - // and can be polled through GetDownloadProgress(). - // If |progress_callback| is not NULL and |record_progress| is true, - // then the callback will be invoked for every progress update received - // by the loader. - - // Similar to Open(), but used for streaming the |url| data directly to the - // caller without writing to a temporary file. The callbacks provided by - // |stream_callback_source| are expected to copy the data before returning. - // |callback| is called once the response headers are received, - // and streaming must be completed separately via BeginStreaming(). - bool OpenStream(const nacl::string& url, - const pp::CompletionCallback& callback, - StreamCallbackSource* stream_callback_source); - - // Finish streaming the response body for a URL request started by either - // OpenStream(). Runs the given |callback| when streaming is done. - void BeginStreaming(const pp::CompletionCallback& callback); - - // Once the GET request has finished, and the contents of the file - // represented by |url_| are available, |full_url_| is the full URL including - // the scheme, host and full path. - // Returns an empty string before the GET request has finished. - const nacl::string& full_url() const { return full_url_; } - - // GetDownloadProgress() returns the current download progress, which is - // meaningful after Open() has been called. Progress only refers to the - // response body and does not include the headers. - // - // This data is only available if the |record_progress| true in the - // Open() call. If progress is being recorded, then |bytes_received| - // will be set to the number of bytes received thus far, - // and |total_bytes_to_be_received| will be set to the total number - // of bytes to be received. The total bytes to be received may be unknown, - // in which case |total_bytes_to_be_received| will be set to -1. - bool GetDownloadProgress(int64_t* bytes_received, - int64_t* total_bytes_to_be_received) const; - - int status_code() const { return status_code_; } - nacl::string GetResponseHeaders() const; - - void set_request_headers(const nacl::string& extra_request_headers) { - extra_request_headers_ = extra_request_headers; - } - - private: - NACL_DISALLOW_COPY_AND_ASSIGN(FileDownloader); - - // 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, 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. - // The public Open*() functions start step 1), and the public BeginStreaming - // function proceeds to step 2) and 3). - bool InitialResponseIsValid(); - void URLLoadStartNotify(int32_t pp_error); - void URLReadBodyNotify(int32_t pp_error); - - Plugin* instance_; - nacl::string full_url_; - - nacl::string extra_request_headers_; - pp::URLResponseInfo url_response_; - pp::CompletionCallback file_open_notify_callback_; - pp::CompletionCallback stream_finish_callback_; - pp::URLLoader url_loader_; - pp::CompletionCallbackFactory<FileDownloader> callback_factory_; - int32_t status_code_; - DownloadMode mode_; - static const uint32_t kTempBufferSize = 16384; - std::vector<char> temp_buffer_; - StreamCallbackSource* data_stream_callback_source_; -}; - -} // namespace plugin - -#endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_FILE_DOWNLOADER_H_ diff --git a/ppapi/native_client/src/trusted/plugin/plugin.gypi b/ppapi/native_client/src/trusted/plugin/plugin.gypi index 38bcd5c..a29fac1 100644 --- a/ppapi/native_client/src/trusted/plugin/plugin.gypi +++ b/ppapi/native_client/src/trusted/plugin/plugin.gypi @@ -6,7 +6,6 @@ 'variables': { 'chromium_code': 1, # Use higher warning level. 'common_sources': [ - 'file_downloader.cc', 'module_ppapi.cc', 'nacl_subprocess.cc', 'plugin.cc', diff --git a/ppapi/native_client/src/trusted/plugin/plugin.h b/ppapi/native_client/src/trusted/plugin/plugin.h index 29409c4..721018c 100644 --- a/ppapi/native_client/src/trusted/plugin/plugin.h +++ b/ppapi/native_client/src/trusted/plugin/plugin.h @@ -28,12 +28,13 @@ #include "ppapi/cpp/var.h" #include "ppapi/cpp/view.h" -#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/pnacl_coordinator.h" #include "ppapi/native_client/src/trusted/plugin/service_runtime.h" #include "ppapi/native_client/src/trusted/plugin/utility.h" +#include "ppapi/utility/completion_callback_factory.h" + namespace nacl { class DescWrapper; class DescWrapperFactory; diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc index 3669159..7b425a0c 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc @@ -63,12 +63,34 @@ nacl::string GetArchitectureAttributes(Plugin* plugin) { return attrs_var.AsString(); } -} // namespace +void DidCacheHit(void* user_data, PP_FileHandle nexe_file_handle) { + PnaclCoordinator* coordinator = static_cast<PnaclCoordinator*>(user_data); + coordinator->BitcodeStreamCacheHit(nexe_file_handle); +} -// Out-of-line destructor to keep it from getting put in every .o where -// callback_source.h is included -template<> -CallbackSource<FileStreamData>::~CallbackSource() {} +void DidCacheMiss(void* user_data, int64_t expected_pexe_size) { + PnaclCoordinator* coordinator = static_cast<PnaclCoordinator*>(user_data); + coordinator->BitcodeStreamCacheMiss(expected_pexe_size); +} + +void DidStreamData(void* user_data, const void* stream_data, int32_t length) { + PnaclCoordinator* coordinator = static_cast<PnaclCoordinator*>(user_data); + coordinator->BitcodeStreamGotData(stream_data, length); +} + +void DidFinishStream(void* user_data, int32_t pp_error) { + PnaclCoordinator* coordinator = static_cast<PnaclCoordinator*>(user_data); + coordinator->BitcodeStreamDidFinish(pp_error); +} + +PPP_PexeStreamHandler kPexeStreamHandler = { + &DidCacheHit, + &DidCacheMiss, + &DidStreamData, + &DidFinishStream +}; + +} // namespace PnaclCoordinator* PnaclCoordinator::BitcodeToNative( Plugin* plugin, @@ -107,7 +129,6 @@ PnaclCoordinator::PnaclCoordinator( pnacl_options_(pnacl_options), architecture_attributes_(GetArchitectureAttributes(plugin)), split_module_count_(1), - is_cache_hit_(PP_FALSE), error_already_reported_(false), pexe_size_(0), pexe_bytes_compiled_(0), @@ -265,44 +286,6 @@ void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { } void PnaclCoordinator::OpenBitcodeStream() { - // Now open the pexe stream. - streaming_downloader_.reset(new FileDownloader(plugin_)); - // Mark the request as requesting a PNaCl bitcode file, - // so that component updater can detect this user action. - streaming_downloader_->set_request_headers( - "Accept: application/x-pnacl, */*"); - - // Even though we haven't started downloading, create the translation - // thread object immediately. This ensures that any pieces of the file - // that get downloaded before the compilation thread is accepting - // SRPCs won't get dropped. - translate_thread_.reset(new PnaclTranslateThread()); - if (translate_thread_ == NULL) { - ReportNonPpapiError( - PP_NACL_ERROR_PNACL_THREAD_CREATE, - "PnaclCoordinator: could not allocate translation thread."); - return; - } - - pp::CompletionCallback cb = - callback_factory_.NewCallback(&PnaclCoordinator::BitcodeStreamDidOpen); - if (!streaming_downloader_->OpenStream(pexe_url_, cb, this)) { - ReportNonPpapiError( - PP_NACL_ERROR_PNACL_PEXE_FETCH_OTHER, - nacl::string("PnaclCoordinator: failed to open stream ") + pexe_url_); - return; - } -} - -void PnaclCoordinator::BitcodeStreamDidOpen(int32_t pp_error) { - if (pp_error != PP_OK) { - BitcodeStreamDidFinish(pp_error); - // We have not spun up the translation process yet, so we need to call - // TranslateFinished here. - TranslateFinished(pp_error); - return; - } - // The component updater's resource throttles + OnDemand update/install // should block the URL request until the compiler is present. Now we // can load the resources (e.g. llc and ld nexes). @@ -326,87 +309,74 @@ void PnaclCoordinator::BitcodeStreamDidOpen(int32_t pp_error) { return; } - // Okay, now that we've started the HTTP request for the pexe - // and we've ensured that the PNaCl compiler + metadata is installed, - // get the cache key from the response headers and from the - // compiler's version metadata. - nacl::string headers = streaming_downloader_->GetResponseHeaders(); - - temp_nexe_file_.reset(new TempFile(plugin_)); - pp::CompletionCallback cb = - callback_factory_.NewCallback(&PnaclCoordinator::NexeFdDidOpen); - int32_t nexe_fd_err = - plugin_->nacl_interface()->GetNexeFd( - plugin_->pp_instance(), - streaming_downloader_->full_url().c_str(), - // TODO(dschuff): Get this value from the pnacl json file after it - // rolls in from NaCl. - 1, - pnacl_options_.opt_level, - headers.c_str(), - architecture_attributes_.c_str(), // Extra compile flags. - &is_cache_hit_, - temp_nexe_file_->internal_handle(), - cb.pp_completion_callback()); - if (nexe_fd_err < PP_OK_COMPLETIONPENDING) { - ReportPpapiError(PP_NACL_ERROR_PNACL_CREATE_TEMP, nexe_fd_err, - nacl::string("Call to GetNexeFd failed")); - } -} - -void PnaclCoordinator::NexeFdDidOpen(int32_t pp_error) { - PLUGIN_PRINTF(("PnaclCoordinator::NexeFdDidOpen (pp_error=%" - NACL_PRId32 ", hit=%d)\n", pp_error, - is_cache_hit_ == PP_TRUE)); - if (pp_error < PP_OK) { - ReportPpapiError(PP_NACL_ERROR_PNACL_CREATE_TEMP, pp_error, - nacl::string("GetNexeFd failed")); + // Even though we haven't started downloading, create the translation + // thread object immediately. This ensures that any pieces of the file + // that get downloaded before the compilation thread is accepting + // SRPCs won't get dropped. + translate_thread_.reset(new PnaclTranslateThread()); + if (translate_thread_ == NULL) { + ReportNonPpapiError( + PP_NACL_ERROR_PNACL_THREAD_CREATE, + "PnaclCoordinator: could not allocate translation thread."); return; } - if (*temp_nexe_file_->internal_handle() == PP_kInvalidFileHandle) { + GetNaClInterface()->StreamPexe(plugin_->pp_instance(), + pexe_url_.c_str(), + pnacl_options_.opt_level, + &kPexeStreamHandler, + this); +} + +void PnaclCoordinator::BitcodeStreamCacheHit(PP_FileHandle handle) { + HistogramEnumerateTranslationCache(plugin_->uma_interface(), true); + if (handle == PP_kInvalidFileHandle) { ReportNonPpapiError( PP_NACL_ERROR_PNACL_CREATE_TEMP, nacl::string( "PnaclCoordinator: Got bad temp file handle from GetNexeFd")); + BitcodeStreamDidFinish(PP_ERROR_FAILED); return; } - HistogramEnumerateTranslationCache(plugin_->uma_interface(), is_cache_hit_); + temp_nexe_file_.reset(new TempFile(plugin_, handle)); + // Open it for reading as the cached nexe file. + NexeReadDidOpen(temp_nexe_file_->Open(false)); +} - if (is_cache_hit_ == PP_TRUE) { - // Cache hit -- no need to stream the rest of the file. - streaming_downloader_.reset(NULL); - // Open it for reading as the cached nexe file. - NexeReadDidOpen(temp_nexe_file_->Open(false)); - } else { - // Open an object file first so the translator can start writing to it - // during streaming translation. - for (int i = 0; i < split_module_count_; i++) { - nacl::scoped_ptr<TempFile> temp_file(new TempFile(plugin_)); - int32_t pp_error = temp_file->Open(true); - if (pp_error != PP_OK) { - ReportPpapiError(PP_NACL_ERROR_PNACL_CREATE_TEMP, - pp_error, - "Failed to open scratch object file."); - return; - } else { - obj_files_.push_back(temp_file.release()); - } +void PnaclCoordinator::BitcodeStreamCacheMiss(int64_t expected_pexe_size) { + HistogramEnumerateTranslationCache(plugin_->uma_interface(), false); + expected_pexe_size_ = expected_pexe_size; + + for (int i = 0; i < split_module_count_; i++) { + PP_FileHandle obj_handle = + plugin_->nacl_interface()->CreateTemporaryFile(plugin_->pp_instance()); + nacl::scoped_ptr<TempFile> temp_file(new TempFile(plugin_, obj_handle)); + int32_t pp_error = temp_file->Open(true); + if (pp_error != PP_OK) { + ReportPpapiError(PP_NACL_ERROR_PNACL_CREATE_TEMP, + pp_error, + "Failed to open scratch object file."); + return; + } else { + obj_files_.push_back(temp_file.release()); } - invalid_desc_wrapper_.reset(plugin_->wrapper_factory()->MakeInvalid()); - - // Meanwhile, a miss means we know we need to stream the bitcode, so stream - // the rest of it now. (Calling BeginStreaming means that the downloader - // will begin handing data to the coordinator, which is safe any time after - // the translate_thread_ object has been initialized). - pp::CompletionCallback finish_cb = callback_factory_.NewCallback( - &PnaclCoordinator::BitcodeStreamDidFinish); - streaming_downloader_->BeginStreaming(finish_cb); - - // Open the nexe file for connecting ld and sel_ldr. - // Start translation when done with this last step of setup! - RunTranslate(temp_nexe_file_->Open(true)); } + invalid_desc_wrapper_.reset(plugin_->wrapper_factory()->MakeInvalid()); + + PP_FileHandle nexe_handle = + plugin_->nacl_interface()->CreateTemporaryFile(plugin_->pp_instance()); + temp_nexe_file_.reset(new TempFile(plugin_, nexe_handle)); + // Open the nexe file for connecting ld and sel_ldr. + // Start translation when done with this last step of setup! + RunTranslate(temp_nexe_file_->Open(true)); +} + +void PnaclCoordinator::BitcodeStreamGotData(const void* data, int32_t length) { + DCHECK(translate_thread_.get()); + + translate_thread_->PutBytes(data, length); + if (data && length > 0) + pexe_size_ += length; } void PnaclCoordinator::BitcodeStreamDidFinish(int32_t pp_error) { @@ -429,47 +399,24 @@ void PnaclCoordinator::BitcodeStreamDidFinish(int32_t pp_error) { ss << "PnaclCoordinator: pexe load failed (pp_error=" << pp_error << ")."; error_info_.SetReport(PP_NACL_ERROR_PNACL_PEXE_FETCH_OTHER, ss.str()); } - translate_thread_->AbortSubprocesses(); + + if (translate_thread_->started()) + translate_thread_->AbortSubprocesses(); + else + TranslateFinished(pp_error); } else { // Compare download completion pct (100% now), to compile completion pct. HistogramRatio(plugin_->uma_interface(), "NaCl.Perf.PNaClLoadTime.PctCompiledWhenFullyDownloaded", pexe_bytes_compiled_, pexe_size_); - } -} - -void PnaclCoordinator::BitcodeStreamGotData(int32_t pp_error, - FileStreamData data) { - PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamGotData (pp_error=%" - NACL_PRId32 ", data=%p)\n", pp_error, data ? &(*data)[0] : 0)); - DCHECK(translate_thread_.get()); - - // When we have received data, pp_error is set to the number of bytes - // received. - if (pp_error > 0) { - CHECK(data); - translate_thread_->PutBytes(data, pp_error); - pexe_size_ += pp_error; - } else { translate_thread_->EndStream(); } } -StreamCallback PnaclCoordinator::GetCallback() { - return callback_factory_.NewCallbackWithOutput( - &PnaclCoordinator::BitcodeStreamGotData); -} - void PnaclCoordinator::BitcodeGotCompiled(int32_t pp_error, int64_t bytes_compiled) { DCHECK(pp_error == PP_OK); pexe_bytes_compiled_ += bytes_compiled; - // If we don't know the expected total yet, ask. - if (expected_pexe_size_ == -1) { - int64_t amount_downloaded; // dummy variable. - streaming_downloader_->GetDownloadProgress(&amount_downloaded, - &expected_pexe_size_); - } // Hold off reporting the last few bytes of progress, since we don't know // when they are actually completely compiled. "bytes_compiled" only means // that bytes were sent to the compiler. diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h index 44a1d54..ac1a330 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h @@ -17,12 +17,12 @@ #include "ppapi/cpp/completion_callback.h" -#include "ppapi/native_client/src/trusted/plugin/callback_source.h" -#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_resources.h" +#include "ppapi/utility/completion_callback_factory.h" + struct PP_PNaClOptions; namespace plugin { @@ -51,7 +51,7 @@ class TempFile; // Translation proceeds in two steps: // (1) llc translates the bitcode in pexe_url_ to an object in obj_file_. // (2) ld links the object code in obj_file_ and produces a nexe in nexe_file_. -class PnaclCoordinator: public CallbackSource<FileStreamData> { +class PnaclCoordinator { public: // Maximum number of object files passable to the translator. Cannot be // changed without changing the RPC signatures. @@ -69,12 +69,6 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { // BitcodeToNative has completed (and the finish_callback called). PP_FileHandle TakeTranslatedFileHandle(); - // Implement FileDownloader's template of the CallbackSource interface. - // This method returns a callback which will be called by the FileDownloader - // to stream the bitcode data as it arrives. The callback - // (BitcodeStreamGotData) passes it to llc over SRPC. - StreamCallback GetCallback(); - // Return a callback that should be notified when |bytes_compiled| bytes // have been compiled. pp::CompletionCallback GetCompileProgressCallback(int64_t bytes_compiled); @@ -92,6 +86,16 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { expected_pexe_size_) < kProgressEventSlopPct; } + + void BitcodeStreamCacheHit(PP_FileHandle handle); + void BitcodeStreamCacheMiss(int64_t expected_pexe_size); + + // Invoked when a pexe data chunk arrives (when using streaming translation) + void BitcodeStreamGotData(const void* data, int32_t length); + + // Invoked when the pexe download finishes (using streaming translation) + void BitcodeStreamDidFinish(int32_t pp_error); + private: NACL_DISALLOW_COPY_AND_ASSIGN(PnaclCoordinator); @@ -104,19 +108,9 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { // Invoke to issue a GET request for bitcode. void OpenBitcodeStream(); - // Invoked when we've started an URL fetch for the pexe to check for - // caching metadata. - void BitcodeStreamDidOpen(int32_t pp_error); - // Invoked when we've gotten a temp FD for the nexe, either with the nexe - // data, or a writeable fd to save to. - void NexeFdDidOpen(int32_t pp_error); - // Invoked when a pexe data chunk arrives (when using streaming translation) - void BitcodeStreamGotData(int32_t pp_error, FileStreamData data); // Invoked when a pexe data chunk is compiled. void BitcodeGotCompiled(int32_t pp_error, int64_t bytes_compiled); - // Invoked when the pexe download finishes (using streaming translation) - void BitcodeStreamDidFinish(int32_t pp_error); // Once llc and ld nexes have been loaded and the two temporary files have // been created, this starts the translation. Translation starts two // subprocesses, one for llc and one for ld. @@ -180,12 +174,6 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { // Translated nexe file, produced by the linker. nacl::scoped_ptr<TempFile> temp_nexe_file_; - // Passed to the browser, which sets it to true if there is a translation - // cache hit. - PP_Bool is_cache_hit_; - - // Downloader for streaming translation - nacl::scoped_ptr<FileDownloader> streaming_downloader_; // Used to report information when errors (PPAPI or otherwise) are reported. ErrorInfo error_info_; 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 fff5382..7247f39 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc +++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc @@ -111,27 +111,15 @@ void PnaclTranslateThread::RunTranslate( } // Called from main thread to send bytes to the translator. -void PnaclTranslateThread::PutBytes(std::vector<char>* bytes, int count) { - PLUGIN_PRINTF(("PutBytes (this=%p, bytes=%p, size=%" NACL_PRIuS - ", count=%d)\n", - this, bytes, bytes ? bytes->size() : 0, count)); - size_t buffer_size = 0; +void PnaclTranslateThread::PutBytes(const void* bytes, int32_t count) { CHECK(bytes != NULL); - // Ensure that the buffer we send to the translation thread is the right size - // (count can be < the buffer size). This can be done without the lock. - buffer_size = bytes->size(); - bytes->resize(count); - NaClXMutexLock(&cond_mu_); - data_buffers_.push_back(std::vector<char>()); - bytes->swap(data_buffers_.back()); // Avoid copying the buffer data. - + data_buffers_.back().insert(data_buffers_.back().end(), + static_cast<const char*>(bytes), + static_cast<const char*>(bytes) + count); NaClXCondVarSignal(&buffer_cond_); NaClXMutexUnlock(&cond_mu_); - - // Ensure the buffer we send back to the coordinator is the expected size - bytes->resize(buffer_size); } void PnaclTranslateThread::EndStream() { 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 ed0c7d7..60c1cba 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h +++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h @@ -61,7 +61,7 @@ class PnaclTranslateThread { void AbortSubprocesses(); // Send bitcode bytes to the translator. Called from the main thread. - void PutBytes(std::vector<char>* data, int count); + void PutBytes(const void* data, int count); // Notify the translator that the end of the bitcode stream has been reached. // Called from the main thread. @@ -69,6 +69,9 @@ class PnaclTranslateThread { int64_t GetCompileTime() const { return compile_time_; } + // Returns true if RunTranslate() has been called, false otherwise. + bool started() const { return plugin_ != NULL; } + private: // Helper thread entry point for translation. Takes a pointer to // PnaclTranslateThread and calls DoTranslate(). diff --git a/ppapi/native_client/src/trusted/plugin/temporary_file.cc b/ppapi/native_client/src/trusted/plugin/temporary_file.cc index eee655f..7f550b9 100644 --- a/ppapi/native_client/src/trusted/plugin/temporary_file.cc +++ b/ppapi/native_client/src/trusted/plugin/temporary_file.cc @@ -18,20 +18,13 @@ namespace plugin { -TempFile::TempFile(Plugin* plugin) : plugin_(plugin), - internal_handle_(PP_kInvalidFileHandle) { -} +TempFile::TempFile(Plugin* plugin, PP_FileHandle handle) + : plugin_(plugin), + internal_handle_(handle) { } TempFile::~TempFile() { } int32_t TempFile::Open(bool writeable) { - // TODO(teravest): Clean up this Open() behavior; this is really confusing as - // written. - if (internal_handle_ == PP_kInvalidFileHandle) { - internal_handle_ = - plugin_->nacl_interface()->CreateTemporaryFile(plugin_->pp_instance()); - } - if (internal_handle_ == PP_kInvalidFileHandle) { PLUGIN_PRINTF(("TempFile::Open failed w/ PP_kInvalidFileHandle\n")); return PP_ERROR_FAILED; diff --git a/ppapi/native_client/src/trusted/plugin/temporary_file.h b/ppapi/native_client/src/trusted/plugin/temporary_file.h index 4bc8f71..a58879b 100644 --- a/ppapi/native_client/src/trusted/plugin/temporary_file.h +++ b/ppapi/native_client/src/trusted/plugin/temporary_file.h @@ -36,7 +36,7 @@ class Plugin; class TempFile { public: // Create a TempFile. - explicit TempFile(Plugin* plugin); + TempFile(Plugin* plugin, PP_FileHandle handle); ~TempFile(); // Opens a temporary file object and descriptor wrapper referring to the file. @@ -55,9 +55,6 @@ class TempFile { // and all wrappers. PP_FileHandle TakeFileHandle(); - // Used by GetNexeFd() to set the underlying internal handle. - PP_FileHandle* internal_handle() { return &internal_handle_; } - private: NACL_DISALLOW_COPY_AND_ASSIGN(TempFile); 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 f1fc368..c5e36d4 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 @@ -3322,11 +3322,6 @@ static PP_Bool Pnacl_M25_PPB_NaCl_Private_IsNonSFIModeEnabled(void) { return iface->IsNonSFIModeEnabled(); } -static int32_t Pnacl_M25_PPB_NaCl_Private_GetNexeFd(PP_Instance instance, const char* pexe_url, uint32_t abi_version, uint32_t opt_level, const char* headers, const char* extra_flags, PP_Bool* is_hit, PP_FileHandle* nexe_handle, struct PP_CompletionCallback* callback) { - const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; - return iface->GetNexeFd(instance, pexe_url, abi_version, opt_level, headers, extra_flags, is_hit, nexe_handle, *callback); -} - static void Pnacl_M25_PPB_NaCl_Private_ReportTranslationFinished(PP_Instance instance, PP_Bool success, int32_t opt_level, int64_t pexe_size, int64_t compile_time_us) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; iface->ReportTranslationFinished(instance, success, opt_level, pexe_size, compile_time_us); @@ -3477,6 +3472,11 @@ static void Pnacl_M25_PPB_NaCl_Private_SetPNaClStartTime(PP_Instance instance) { iface->SetPNaClStartTime(instance); } +static void Pnacl_M25_PPB_NaCl_Private_StreamPexe(PP_Instance instance, const char* pexe_url, int32_t opt_level, const struct PPP_PexeStreamHandler_1_0* stream_handler, void* stream_handler_user_data) { + const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; + iface->StreamPexe(instance, pexe_url, opt_level, stream_handler, stream_handler_user_data); +} + /* End wrapper methods for PPB_NaCl_Private_1_0 */ /* Begin wrapper methods for PPB_NetAddress_Private_0_1 */ @@ -4331,6 +4331,8 @@ static struct PP_Var Pnacl_M18_PPP_Instance_Private_GetInstanceObject(PP_Instanc /* End wrapper methods for PPP_Instance_Private_0_1 */ +/* Not generating wrapper methods for PPP_PexeStreamHandler_1_0 */ + /* Not generating wrapper interface for PPB_Audio_1_0 */ /* Not generating wrapper interface for PPB_Audio_1_1 */ @@ -5228,7 +5230,6 @@ static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = { .CreateTemporaryFile = (PP_FileHandle (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_CreateTemporaryFile, .GetNumberOfProcessors = (int32_t (*)(void))&Pnacl_M25_PPB_NaCl_Private_GetNumberOfProcessors, .IsNonSFIModeEnabled = (PP_Bool (*)(void))&Pnacl_M25_PPB_NaCl_Private_IsNonSFIModeEnabled, - .GetNexeFd = (int32_t (*)(PP_Instance instance, const char* pexe_url, uint32_t abi_version, uint32_t opt_level, const char* headers, const char* extra_flags, PP_Bool* is_hit, PP_FileHandle* nexe_handle, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_GetNexeFd, .ReportTranslationFinished = (void (*)(PP_Instance instance, PP_Bool success, int32_t opt_level, int64_t pexe_size, int64_t compile_time_us))&Pnacl_M25_PPB_NaCl_Private_ReportTranslationFinished, .DispatchEvent = (void (*)(PP_Instance instance, PP_NaClEventType event_type, const char* resource_url, PP_Bool length_is_computable, uint64_t loaded_bytes, uint64_t total_bytes))&Pnacl_M25_PPB_NaCl_Private_DispatchEvent, .ReportLoadSuccess = (void (*)(PP_Instance instance, uint64_t loaded_bytes, uint64_t total_bytes))&Pnacl_M25_PPB_NaCl_Private_ReportLoadSuccess, @@ -5258,7 +5259,8 @@ static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = { .ReportSelLdrStatus = (void (*)(PP_Instance instance, int32_t load_status, int32_t max_status))&Pnacl_M25_PPB_NaCl_Private_ReportSelLdrStatus, .LogTranslateTime = (void (*)(const char* histogram_name, int64_t time_us))&Pnacl_M25_PPB_NaCl_Private_LogTranslateTime, .OpenManifestEntry = (void (*)(PP_Instance instance, PP_Bool is_helper_process, const char* key, struct PP_NaClFileInfo* file_info, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_OpenManifestEntry, - .SetPNaClStartTime = (void (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_SetPNaClStartTime + .SetPNaClStartTime = (void (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_SetPNaClStartTime, + .StreamPexe = (void (*)(PP_Instance instance, const char* pexe_url, int32_t opt_level, const struct PPP_PexeStreamHandler_1_0* stream_handler, void* stream_handler_user_data))&Pnacl_M25_PPB_NaCl_Private_StreamPexe }; static const struct PPB_NetAddress_Private_0_1 Pnacl_Wrappers_PPB_NetAddress_Private_0_1 = { @@ -5481,6 +5483,8 @@ static const struct PPP_Instance_Private_0_1 Pnacl_Wrappers_PPP_Instance_Private .GetInstanceObject = &Pnacl_M18_PPP_Instance_Private_GetInstanceObject }; +/* Not generating wrapper interface for PPP_PexeStreamHandler_1_0 */ + static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Compositor_0_1 = { .iface_macro = PPB_COMPOSITOR_INTERFACE_0_1, .wrapped_iface = (const void *) &Pnacl_Wrappers_PPB_Compositor_0_1, |