Commit 45cba27e authored by teravest@chromium.org's avatar teravest@chromium.org

Pepper: Move StreamAsFile out of trusted plugin.

This removes a significant amount of code from the trusted plugin and
simplifies the callbacks that are used in PluginReverseInterface.

I was confused at first by the existing use of url_file_info_map_; it looks
like it was intended to serve as a cache for retrieved files, but I think the
files would be reopened every time, even if the file was already open. For
simplicity, I didn't try to add any caching behavior in this change.

Note that this changes progress events to be rate limited at 10ms per-file,
not 10ms per-plugin. It's a bit simpler to write this way, but I can
change that limit to be per-plugin if that makes more sense.

BUG=370556
R=bbudge@chromium.org

Review URL: https://codereview.chromium.org/294633003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@272550 0039d316-1c4b-4281-b951-d872f2087c98
parent dc0a1b27
...@@ -70,6 +70,12 @@ void FileDownloader::didFinishLoading( ...@@ -70,6 +70,12 @@ void FileDownloader::didFinishLoading(
blink::WebURLLoader* loader, blink::WebURLLoader* loader,
double finish_time, double finish_time,
int64_t total_encoded_data_length) { int64_t total_encoded_data_length) {
if (status_ == SUCCESS) {
// Seek back to the beginning of the file that was just written so it's
// easy for consumers to use.
if (base::SeekPlatformFile(file_, base::PLATFORM_FILE_FROM_BEGIN, 0) != 0)
status_ = FAILED;
}
status_cb_.Run(status_, http_status_code_); status_cb_.Run(status_, http_status_code_);
delete this; delete this;
} }
......
...@@ -282,6 +282,19 @@ blink::WebURLRequest CreateWebURLRequest(const blink::WebDocument& document, ...@@ -282,6 +282,19 @@ blink::WebURLRequest CreateWebURLRequest(const blink::WebDocument& document,
return request; return request;
} }
int32_t FileDownloaderToPepperError(FileDownloader::Status status) {
switch (status) {
case FileDownloader::SUCCESS:
return PP_OK;
case FileDownloader::ACCESS_DENIED:
return PP_ERROR_NOACCESS;
case FileDownloader::FAILED:
return PP_ERROR_FAILED;
// No default case, to catch unhandled Status values.
}
return PP_ERROR_FAILED;
}
// Launch NaCl's sel_ldr process. // Launch NaCl's sel_ldr process.
void LaunchSelLdr(PP_Instance instance, void LaunchSelLdr(PP_Instance instance,
PP_Bool main_service_runtime, PP_Bool main_service_runtime,
...@@ -886,18 +899,6 @@ PP_Var GetManifestBaseURL(PP_Instance instance) { ...@@ -886,18 +899,6 @@ PP_Var GetManifestBaseURL(PP_Instance instance) {
return ppapi::StringVar::StringToPPVar(gurl.spec()); return ppapi::StringVar::StringToPPVar(gurl.spec());
} }
PP_Bool ResolvesRelativeToPluginBaseURL(PP_Instance instance,
const char *url) {
NexeLoadManager* load_manager = GetNexeLoadManager(instance);
DCHECK(load_manager);
if (!load_manager)
return PP_FALSE;
const GURL& gurl = load_manager->plugin_base_url().Resolve(url);
if (!gurl.is_valid())
return PP_FALSE;
return PP_TRUE;
}
void ProcessNaClManifest(PP_Instance instance, const char* program_url) { void ProcessNaClManifest(PP_Instance instance, const char* program_url) {
nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
if (load_manager) if (load_manager)
...@@ -1387,22 +1388,9 @@ void DownloadNexeCompletion(const DownloadNexeRequest& request, ...@@ -1387,22 +1388,9 @@ void DownloadNexeCompletion(const DownloadNexeRequest& request,
PP_FileHandle* out_handle, PP_FileHandle* out_handle,
FileDownloader::Status status, FileDownloader::Status status,
int http_status) { int http_status) {
int32_t pp_error; int32_t pp_error = FileDownloaderToPepperError(status);
switch (status) { if (pp_error == PP_OK)
case FileDownloader::SUCCESS: *out_handle = target_file;
*out_handle = target_file;
pp_error = PP_OK;
break;
case FileDownloader::ACCESS_DENIED:
pp_error = PP_ERROR_NOACCESS;
break;
case FileDownloader::FAILED:
pp_error = PP_ERROR_FAILED;
break;
default:
NOTREACHED();
return;
}
int64_t bytes_read = -1; int64_t bytes_read = -1;
if (pp_error == PP_OK && target_file != base::kInvalidPlatformFileValue) { if (pp_error == PP_OK && target_file != base::kInvalidPlatformFileValue) {
...@@ -1431,6 +1419,97 @@ void DownloadNexeCompletion(const DownloadNexeRequest& request, ...@@ -1431,6 +1419,97 @@ void DownloadNexeCompletion(const DownloadNexeRequest& request,
request.callback.func(request.callback.user_data, pp_error); request.callback.func(request.callback.user_data, pp_error);
} }
void DownloadFileCompletion(base::PlatformFile file,
PP_NaClFileInfo* file_info,
PP_CompletionCallback callback,
FileDownloader::Status status,
int http_status) {
int32_t pp_error = FileDownloaderToPepperError(status);
if (pp_error == PP_OK) {
file_info->handle = file;
file_info->token_lo = 0;
file_info->token_hi = 0;
}
callback.func(callback.user_data, pp_error);
}
void DownloadFile(PP_Instance instance,
const char* url,
struct PP_NaClFileInfo* file_info,
struct PP_CompletionCallback callback) {
CHECK(url);
CHECK(file_info);
NexeLoadManager* load_manager = GetNexeLoadManager(instance);
DCHECK(load_manager);
if (!load_manager) {
ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
FROM_HERE,
base::Bind(callback.func, callback.user_data,
static_cast<int32_t>(PP_ERROR_FAILED)));
return;
}
// We have to ensure that this url resolves relative to the plugin base url
// before downloading it.
const GURL& test_gurl = load_manager->plugin_base_url().Resolve(url);
if (!test_gurl.is_valid()) {
ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
FROM_HERE,
base::Bind(callback.func, callback.user_data,
static_cast<int32_t>(PP_ERROR_FAILED)));
return;
}
// Try the fast path for retrieving the file first.
uint64_t file_token_lo = 0;
uint64_t file_token_hi = 0;
PP_FileHandle file_handle = OpenNaClExecutable(instance,
url,
&file_token_lo,
&file_token_hi);
if (file_handle != PP_kInvalidFileHandle) {
file_info->handle = file_handle;
file_info->token_lo = file_token_lo;
file_info->token_hi = file_token_hi;
ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
FROM_HERE,
base::Bind(callback.func, callback.user_data,
static_cast<int32_t>(PP_OK)));
return;
}
// The fast path didn't work, we'll fetch the file using URLLoader and write
// it to local storage.
base::PlatformFile target_file = CreateTemporaryFile(instance);
GURL gurl(url);
content::PepperPluginInstance* plugin_instance =
content::PepperPluginInstance::Get(instance);
if (!plugin_instance) {
ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
FROM_HERE,
base::Bind(callback.func, callback.user_data,
static_cast<int32_t>(PP_ERROR_FAILED)));
}
const blink::WebDocument& document =
plugin_instance->GetContainer()->element().document();
scoped_ptr<blink::WebURLLoader> url_loader(
CreateWebURLLoader(document, gurl));
blink::WebURLRequest url_request = CreateWebURLRequest(document, gurl);
ProgressEventRateLimiter* tracker = new ProgressEventRateLimiter(instance);
// FileDownloader deletes itself after invoking DownloadNexeCompletion.
FileDownloader* file_downloader = new FileDownloader(
url_loader.Pass(),
target_file,
base::Bind(&DownloadFileCompletion, target_file, file_info, callback),
base::Bind(&ProgressEventRateLimiter::ReportProgress,
base::Owned(tracker), url));
file_downloader->Load(url_request);
}
const PPB_NaCl_Private nacl_interface = { const PPB_NaCl_Private nacl_interface = {
&LaunchSelLdr, &LaunchSelLdr,
&StartPpapiProxy, &StartPpapiProxy,
...@@ -1443,7 +1522,6 @@ const PPB_NaCl_Private nacl_interface = { ...@@ -1443,7 +1522,6 @@ const PPB_NaCl_Private nacl_interface = {
&PPIsNonSFIModeEnabled, &PPIsNonSFIModeEnabled,
&GetNexeFd, &GetNexeFd,
&ReportTranslationFinished, &ReportTranslationFinished,
&OpenNaClExecutable,
&DispatchEvent, &DispatchEvent,
&ReportLoadSuccess, &ReportLoadSuccess,
&ReportLoadError, &ReportLoadError,
...@@ -1463,7 +1541,6 @@ const PPB_NaCl_Private nacl_interface = { ...@@ -1463,7 +1541,6 @@ const PPB_NaCl_Private nacl_interface = {
&GetNexeSize, &GetNexeSize,
&RequestNaClManifest, &RequestNaClManifest,
&GetManifestBaseURL, &GetManifestBaseURL,
&ResolvesRelativeToPluginBaseURL,
&ProcessNaClManifest, &ProcessNaClManifest,
&GetManifestURLArgument, &GetManifestURLArgument,
&DevInterfacesEnabled, &DevInterfacesEnabled,
...@@ -1474,7 +1551,8 @@ const PPB_NaCl_Private nacl_interface = { ...@@ -1474,7 +1551,8 @@ const PPB_NaCl_Private nacl_interface = {
&GetPNaClResourceInfo, &GetPNaClResourceInfo,
&GetCpuFeatureAttrs, &GetCpuFeatureAttrs,
&PostMessageToJavaScript, &PostMessageToJavaScript,
&DownloadNexe &DownloadNexe,
&DownloadFile
}; };
} // namespace } // namespace
......
...@@ -166,6 +166,16 @@ interface PPP_ManifestService { ...@@ -166,6 +166,16 @@ interface PPP_ManifestService {
[inout] mem_t callback_user_data); [inout] mem_t callback_user_data);
}; };
/* Corresponds to NaClFileInfo in
* native_client/src/trusted/validator/nacl_file_info.h */
struct PP_NaClFileInfo {
PP_FileHandle handle;
/* See NaClFileToken comment in nacl_file_info.h */
uint64_t token_lo;
uint64_t token_hi;
};
/* PPB_NaCl_Private */ /* PPB_NaCl_Private */
interface PPB_NaCl_Private { interface PPB_NaCl_Private {
/* Launches NaCl's sel_ldr process. Returns PP_EXTERNAL_PLUGIN_OK on success /* Launches NaCl's sel_ldr process. Returns PP_EXTERNAL_PLUGIN_OK on success
...@@ -281,16 +291,6 @@ interface PPB_NaCl_Private { ...@@ -281,16 +291,6 @@ interface PPB_NaCl_Private {
void ReportTranslationFinished([in] PP_Instance instance, void ReportTranslationFinished([in] PP_Instance instance,
[in] PP_Bool success); [in] PP_Bool success);
/* Opens a NaCl executable file in the application's extension directory
* corresponding to the file URL and returns a file descriptor, or an invalid
* handle on failure. |metadata| is left unchanged on failure.
*/
PP_FileHandle OpenNaClExecutable([in] PP_Instance instance,
[in] str_t file_url,
[out] uint64_t file_token_lo,
[out] uint64_t file_token_hi);
/* Dispatch a progress event on the DOM element where the given instance is /* Dispatch a progress event on the DOM element where the given instance is
* embedded. * embedded.
*/ */
...@@ -373,9 +373,6 @@ interface PPB_NaCl_Private { ...@@ -373,9 +373,6 @@ interface PPB_NaCl_Private {
PP_Var GetManifestBaseURL([in] PP_Instance instance); PP_Var GetManifestBaseURL([in] PP_Instance instance);
PP_Bool ResolvesRelativeToPluginBaseUrl([in] PP_Instance instance,
[in] str_t url);
/* Processes the NaCl manifest once it's been retrieved. /* Processes the NaCl manifest once it's been retrieved.
* TODO(teravest): Move the rest of the supporting logic out of the trusted * TODO(teravest): Move the rest of the supporting logic out of the trusted
* plugin. * plugin.
...@@ -436,4 +433,11 @@ interface PPB_NaCl_Private { ...@@ -436,4 +433,11 @@ interface PPB_NaCl_Private {
[out] uint64_t file_token_lo, [out] uint64_t file_token_lo,
[out] uint64_t file_token_hi, [out] uint64_t file_token_hi,
[in] PP_CompletionCallback callback); [in] PP_CompletionCallback callback);
/* Downloads a non-nexe file specified in the manifest, and sets |file_info|
* to corresponding information about the file. */
void DownloadFile([in] PP_Instance instance,
[in] str_t url,
[out] PP_NaClFileInfo file_info,
[in] PP_CompletionCallback callback);
}; };
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
/* From private/ppb_nacl_private.idl modified Wed May 21 13:23:26 2014. */ /* From private/ppb_nacl_private.idl modified Fri May 23 08:51:49 2014. */
#ifndef PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ #ifndef PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_
#define PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ #define PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_
...@@ -204,7 +204,30 @@ struct PPP_ManifestService_1_0 { ...@@ -204,7 +204,30 @@ struct PPP_ManifestService_1_0 {
}; };
typedef struct PPP_ManifestService_1_0 PPP_ManifestService; typedef struct PPP_ManifestService_1_0 PPP_ManifestService;
/**
* @}
*/
/**
* @addtogroup Structs
* @{
*/
/* Corresponds to NaClFileInfo in
* native_client/src/trusted/validator/nacl_file_info.h */
struct PP_NaClFileInfo {
PP_FileHandle handle;
/* See NaClFileToken comment in nacl_file_info.h */
uint64_t token_lo;
uint64_t token_hi;
};
/**
* @}
*/
/**
* @addtogroup Interfaces
* @{
*/
/* PPB_NaCl_Private */ /* PPB_NaCl_Private */
struct PPB_NaCl_Private_1_0 { struct PPB_NaCl_Private_1_0 {
/* Launches NaCl's sel_ldr process. Returns PP_EXTERNAL_PLUGIN_OK on success /* Launches NaCl's sel_ldr process. Returns PP_EXTERNAL_PLUGIN_OK on success
...@@ -309,14 +332,6 @@ struct PPB_NaCl_Private_1_0 { ...@@ -309,14 +332,6 @@ struct PPB_NaCl_Private_1_0 {
* the plugin.) * the plugin.)
*/ */
void (*ReportTranslationFinished)(PP_Instance instance, PP_Bool success); void (*ReportTranslationFinished)(PP_Instance instance, PP_Bool success);
/* Opens a NaCl executable file in the application's extension directory
* corresponding to the file URL and returns a file descriptor, or an invalid
* handle on failure. |metadata| is left unchanged on failure.
*/
PP_FileHandle (*OpenNaClExecutable)(PP_Instance instance,
const char* file_url,
uint64_t* file_token_lo,
uint64_t* file_token_hi);
/* Dispatch a progress event on the DOM element where the given instance is /* Dispatch a progress event on the DOM element where the given instance is
* embedded. * embedded.
*/ */
...@@ -377,8 +392,6 @@ struct PPB_NaCl_Private_1_0 { ...@@ -377,8 +392,6 @@ struct PPB_NaCl_Private_1_0 {
int32_t* manifest_id, int32_t* manifest_id,
struct PP_CompletionCallback callback); struct PP_CompletionCallback callback);
struct PP_Var (*GetManifestBaseURL)(PP_Instance instance); struct PP_Var (*GetManifestBaseURL)(PP_Instance instance);
PP_Bool (*ResolvesRelativeToPluginBaseUrl)(PP_Instance instance,
const char* url);
/* Processes the NaCl manifest once it's been retrieved. /* Processes the NaCl manifest once it's been retrieved.
* TODO(teravest): Move the rest of the supporting logic out of the trusted * TODO(teravest): Move the rest of the supporting logic out of the trusted
* plugin. * plugin.
...@@ -426,6 +439,12 @@ struct PPB_NaCl_Private_1_0 { ...@@ -426,6 +439,12 @@ struct PPB_NaCl_Private_1_0 {
uint64_t* file_token_lo, uint64_t* file_token_lo,
uint64_t* file_token_hi, uint64_t* file_token_hi,
struct PP_CompletionCallback callback); struct PP_CompletionCallback callback);
/* Downloads a non-nexe file specified in the manifest, and sets |file_info|
* to corresponding information about the file. */
void (*DownloadFile)(PP_Instance instance,
const char* url,
struct PP_NaClFileInfo* file_info,
struct PP_CompletionCallback callback);
}; };
typedef struct PPB_NaCl_Private_1_0 PPB_NaCl_Private; typedef struct PPB_NaCl_Private_1_0 PPB_NaCl_Private;
......
...@@ -30,26 +30,6 @@ struct NaClFileInfo NoFileInfo() { ...@@ -30,26 +30,6 @@ struct NaClFileInfo NoFileInfo() {
return info; return info;
} }
// Converts a PP_FileHandle to a POSIX file descriptor.
int32_t ConvertFileDescriptor(PP_FileHandle handle) {
PLUGIN_PRINTF(("ConvertFileDescriptor, handle=%d\n", handle));
#if NACL_WINDOWS
int32_t file_desc = NACL_NO_FILE_DESC;
// On Windows, valid handles are 32 bit unsigned integers so this is safe.
file_desc = reinterpret_cast<uintptr_t>(handle);
// Convert the Windows HANDLE from Pepper to a POSIX file descriptor.
int32_t posix_desc = _open_osfhandle(file_desc, _O_RDWR | _O_BINARY);
if (posix_desc == -1) {
// Close the Windows HANDLE if it can't be converted.
CloseHandle(reinterpret_cast<HANDLE>(file_desc));
return -1;
}
return posix_desc;
#else
return handle;
#endif
}
} // namespace } // namespace
namespace plugin { namespace plugin {
...@@ -175,37 +155,6 @@ bool FileDownloader::Open( ...@@ -175,37 +155,6 @@ bool FileDownloader::Open(
return true; return true;
} }
void FileDownloader::OpenFast(const nacl::string& url,
PP_FileHandle file_handle,
uint64_t file_token_lo, uint64_t file_token_hi) {
PLUGIN_PRINTF(("FileDownloader::OpenFast (url=%s)\n", url.c_str()));
file_info_.FreeResources();
CHECK(instance_ != NULL);
status_code_ = NACL_HTTP_STATUS_OK;
url_ = url;
mode_ = DOWNLOAD_NONE;
if (file_handle != PP_kInvalidFileHandle) {
NaClFileInfo tmp_info = NoFileInfo();
tmp_info.desc = ConvertFileDescriptor(file_handle, true);
tmp_info.file_token.lo = file_token_lo;
tmp_info.file_token.hi = file_token_hi;
file_info_.TakeOwnership(&tmp_info);
}
}
NaClFileInfo FileDownloader::GetFileInfo() {
NaClFileInfo info_to_return = NoFileInfo();
PLUGIN_PRINTF(("FileDownloader::GetFileInfo, this %p\n", this));
if (file_info_.get_desc() != -1) {
info_to_return = file_info_.Release();
}
PLUGIN_PRINTF(("FileDownloader::GetFileInfo -- returning %d\n",
info_to_return.desc));
return info_to_return;
}
bool FileDownloader::InitialResponseIsValid() { bool FileDownloader::InitialResponseIsValid() {
// Process the response, validating the headers to confirm successful loading. // Process the response, validating the headers to confirm successful loading.
url_response_ = url_loader_.GetResponseInfo(); url_response_ = url_loader_.GetResponseInfo();
......
...@@ -118,18 +118,6 @@ class FileDownloader { ...@@ -118,18 +118,6 @@ class FileDownloader {
// streaming is done. // streaming is done.
void FinishStreaming(const pp::CompletionCallback& callback); void FinishStreaming(const pp::CompletionCallback& callback);
// Bypasses downloading and takes a handle to the open file. To get the fd,
// call GetFileInfo().
void OpenFast(const nacl::string& url, PP_FileHandle file_handle,
uint64_t file_token_lo, uint64_t file_token_hi);
// Return a structure describing the file opened, including a file desc.
// If downloading and opening succeeded, this returns a valid read-only
// POSIX file descriptor. On failure, the return value is an invalid
// descriptor. The file descriptor is owned by this instance, so the
// delegate does not have to close it.
struct NaClFileInfo GetFileInfo();
// Returns the url passed to Open(). // Returns the url passed to Open().
const nacl::string& url() const { return url_; } const nacl::string& url() const { return url_; }
......
...@@ -358,8 +358,6 @@ Plugin::~Plugin() { ...@@ -358,8 +358,6 @@ Plugin::~Plugin() {
// Destroy the coordinator while the rest of the data is still there // Destroy the coordinator while the rest of the data is still there
pnacl_coordinator_.reset(NULL); pnacl_coordinator_.reset(NULL);
url_downloaders_.erase(url_downloaders_.begin(), url_downloaders_.end());
// Clean up accounting for our instance inside the NaCl interface. // Clean up accounting for our instance inside the NaCl interface.
if (manifest_id_ != -1) if (manifest_id_ != -1)
nacl_interface_->DestroyManifest(pp_instance(), manifest_id_); nacl_interface_->DestroyManifest(pp_instance(), manifest_id_);
...@@ -559,61 +557,16 @@ void Plugin::RequestNaClManifest(const nacl::string& url) { ...@@ -559,61 +557,16 @@ void Plugin::RequestNaClManifest(const nacl::string& url) {
open_callback.pp_completion_callback()); open_callback.pp_completion_callback());
} }
void Plugin::UrlDidOpenForStreamAsFile( void Plugin::StreamAsFile(const nacl::string& url,
int32_t pp_error, PP_NaClFileInfo* file_info,
FileDownloader* url_downloader,
NaClFileInfo* out_file_info,
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);
NaClFileInfo tmp_info(scoped_url_downloader->GetFileInfo());
NaClFileInfoAutoCloser *info = new NaClFileInfoAutoCloser(&tmp_info);
if (pp_error != PP_OK) {
callback.Run(pp_error);
delete info;
} else if (info->get_desc() > NACL_NO_FILE_DESC) {
*out_file_info = info->Release();
callback.Run(PP_OK);
} else {
callback.Run(PP_ERROR_FAILED);
delete info;
}
}
bool Plugin::StreamAsFile(const nacl::string& url,
NaClFileInfo* out_file_info,
const pp::CompletionCallback& callback) { const pp::CompletionCallback& callback) {
PLUGIN_PRINTF(("Plugin::StreamAsFile (url='%s')\n", url.c_str())); PLUGIN_PRINTF(("Plugin::StreamAsFile (url='%s')\n", url.c_str()));
FileDownloader* downloader = new FileDownloader(); nacl_interface_->DownloadFile(pp_instance(),
downloader->Initialize(this); url.c_str(),
url_downloaders_.insert(downloader); file_info,
callback.pp_completion_callback());
// Untrusted loads are always relative to the page's origin.
if (!GetNaClInterface()->ResolvesRelativeToPluginBaseUrl(pp_instance(),
url.c_str()))
return false;
// Try the fast path first. This will only block if the file is installed.
if (OpenURLFast(url, downloader)) {
UrlDidOpenForStreamAsFile(PP_OK, downloader, out_file_info, callback);
return true;
}
pp::CompletionCallback open_callback = callback_factory_.NewCallback(
&Plugin::UrlDidOpenForStreamAsFile, downloader, out_file_info, callback);
// If true, will always call the callback on success or failure.
return downloader->Open(url,
DOWNLOAD_TO_FILE,
open_callback,
true,
&UpdateDownloadProgress);
} }
void Plugin::ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes) { void Plugin::ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes) {
nacl_interface_->ReportLoadSuccess( nacl_interface_->ReportLoadSuccess(
pp_instance(), program_url_.c_str(), loaded_bytes, total_bytes); pp_instance(), program_url_.c_str(), loaded_bytes, total_bytes);
...@@ -632,55 +585,6 @@ void Plugin::ReportLoadAbort() { ...@@ -632,55 +585,6 @@ void Plugin::ReportLoadAbort() {
nacl_interface_->ReportLoadAbort(pp_instance()); nacl_interface_->ReportLoadAbort(pp_instance());
} }
void Plugin::UpdateDownloadProgress(
PP_Instance pp_instance,
PP_Resource pp_resource,
int64_t /*bytes_sent*/,
int64_t /*total_bytes_to_be_sent*/,
int64_t bytes_received,
int64_t total_bytes_to_be_received) {
Instance* instance = pp::Module::Get()->InstanceForPPInstance(pp_instance);
if (instance != NULL) {
Plugin* plugin = static_cast<Plugin*>(instance);
// Rate limit progress events to a maximum of 100 per second.
int64_t time = NaClGetTimeOfDayMicroseconds();
int64_t elapsed = time - plugin->time_of_last_progress_event_;
const int64_t kTenMilliseconds = 10000;
if (elapsed > kTenMilliseconds) {
plugin->time_of_last_progress_event_ = time;
// Find the URL loader that sent this notification.
const FileDownloader* file_downloader =
plugin->FindFileDownloader(pp_resource);
nacl::string url;
if (file_downloader)
url = file_downloader->url();
LengthComputable length_computable = (total_bytes_to_be_received >= 0) ?
LENGTH_IS_COMPUTABLE : LENGTH_IS_NOT_COMPUTABLE;
plugin->EnqueueProgressEvent(PP_NACL_EVENT_PROGRESS,
url,
length_computable,
bytes_received,
total_bytes_to_be_received);
}
}
}
const FileDownloader* Plugin::FindFileDownloader(
PP_Resource url_loader) const {
const FileDownloader* file_downloader = NULL;
std::set<FileDownloader*>::const_iterator it = url_downloaders_.begin();
while (it != url_downloaders_.end()) {
if (url_loader == (*it)->url_loader()) {
file_downloader = (*it);
break;
}
++it;
}
return file_downloader;
}
void Plugin::ReportSelLdrLoadStatus(int status) { void Plugin::ReportSelLdrLoadStatus(int status) {
HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status)); HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status));
} }
...@@ -708,23 +612,6 @@ void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type, ...@@ -708,23 +612,6 @@ void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type,
total_bytes); total_bytes);
} }
bool Plugin::OpenURLFast(const nacl::string& url,
FileDownloader* downloader) {
uint64_t file_token_lo = 0;
uint64_t file_token_hi = 0;
PP_FileHandle file_handle =
nacl_interface()->OpenNaClExecutable(pp_instance(),
url.c_str(),
&file_token_lo, &file_token_hi);
// We shouldn't hit this if the file URL is in an installed app.
if (file_handle == PP_kInvalidFileHandle)
return false;
// FileDownloader takes ownership of the file handle.
downloader->OpenFast(url, file_handle, file_token_lo, file_token_hi);
return true;
}
bool Plugin::DocumentCanRequest(const std::string& url) { bool Plugin::DocumentCanRequest(const std::string& url) {
CHECK(pp::Module::Get()->core()->IsMainThread()); CHECK(pp::Module::Get()->core()->IsMainThread());
CHECK(pp::URLUtil_Dev::Get() != NULL); CHECK(pp::URLUtil_Dev::Get() != NULL);
......
...@@ -50,6 +50,8 @@ namespace plugin { ...@@ -50,6 +50,8 @@ namespace plugin {
class ErrorInfo; class ErrorInfo;
class Manifest; class Manifest;
int32_t ConvertFileDescriptor(PP_FileHandle handle);
class Plugin : public pp::Instance { class Plugin : public pp::Instance {
public: public:
explicit Plugin(PP_Instance instance); explicit Plugin(PP_Instance instance);
...@@ -148,10 +150,11 @@ class Plugin : public pp::Instance { ...@@ -148,10 +150,11 @@ class Plugin : public pp::Instance {
// event. // event.
void DispatchProgressEvent(int32_t result); void DispatchProgressEvent(int32_t result);
// Requests a URL asynchronously resulting in a call to pp_callback with // Requests a URL asynchronously, resulting in a call to |callback| with
// a PP_Error indicating status. // an error code indicating status. On success, writes file information to
bool StreamAsFile(const nacl::string& url, // |file_info|.
NaClFileInfo *out_file_info, void StreamAsFile(const nacl::string& url,
PP_NaClFileInfo* file_info,
const pp::CompletionCallback& callback); const pp::CompletionCallback& callback);
// A helper function that indicates if |url| can be requested by the document // A helper function that indicates if |url| can be requested by the document
...@@ -247,17 +250,6 @@ class Plugin : public pp::Instance { ...@@ -247,17 +250,6 @@ class Plugin : public pp::Instance {
void HistogramStartupTimeSmall(const std::string& name, float dt); void HistogramStartupTimeSmall(const std::string& name, float dt);
void HistogramStartupTimeMedium(const std::string& name, float dt); void HistogramStartupTimeMedium(const std::string& name, float dt);
// Callback used when loading a URL for SRPC-based StreamAsFile().
void UrlDidOpenForStreamAsFile(int32_t pp_error,
FileDownloader* url_downloader,
NaClFileInfo* out_file_info,
pp::CompletionCallback pp_callback);
// Open an app file by requesting a file descriptor from the browser. This
// method first checks that the url is for an installed file before making the
// request so it won't slow down non-installed file downloads.
bool OpenURLFast(const nacl::string& url, FileDownloader* downloader);
void SetExitStatusOnMainThread(int32_t pp_error, int exit_status); void SetExitStatusOnMainThread(int32_t pp_error, int exit_status);
// Keep track of the NaCl module subprocess that was spun up in the plugin. // Keep track of the NaCl module subprocess that was spun up in the plugin.
...@@ -274,23 +266,6 @@ class Plugin : public pp::Instance { ...@@ -274,23 +266,6 @@ class Plugin : public pp::Instance {
nacl::scoped_ptr<PnaclCoordinator> pnacl_coordinator_; nacl::scoped_ptr<PnaclCoordinator> pnacl_coordinator_;
// Keep track of the FileDownloaders created to fetch urls.
std::set<FileDownloader*> url_downloaders_;
// Callback to receive .nexe and .dso download progress notifications.
static void UpdateDownloadProgress(
PP_Instance pp_instance,
PP_Resource pp_resource,
int64_t bytes_sent,
int64_t total_bytes_to_be_sent,
int64_t bytes_received,
int64_t total_bytes_to_be_received);
// Finds the file downloader which owns the given URL loader. This is used
// in UpdateDownloadProgress to map a url loader back to the URL being
// downloaded.
const FileDownloader* FindFileDownloader(PP_Resource url_loader) const;
int64_t time_of_last_progress_event_; int64_t time_of_last_progress_event_;
int exit_status_; int exit_status_;
......
...@@ -399,36 +399,29 @@ void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation( ...@@ -399,36 +399,29 @@ void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation(
// Callback is now delegated from p to open_cont. So, here we manually clear // Callback is now delegated from p to open_cont. So, here we manually clear
// complete callback. // complete callback.
p->callback = NULL; p->callback = NULL;
pp::CompletionCallback stream_cc = WeakRefNewCallback( pp::CompletionCallback stream_cc = WeakRefNewCallback(
anchor_, anchor_,
this, this,
&PluginReverseInterface::StreamAsFile_MainThreadContinuation, &PluginReverseInterface::StreamAsFile_MainThreadContinuation,
open_cont); open_cont);
if (!plugin_->StreamAsFile(mapped_url, p->file_info, stream_cc)) { plugin_->StreamAsFile(mapped_url, &open_cont->pp_file_info, stream_cc);
NaClLog(4, // p is deleted automatically.
"OpenManifestEntry_MainThreadContinuation: "
"StreamAsFile failed\n");
// Here, StreamAsFile is failed and stream_cc is not called.
// However, open_cont will be released only by the invocation.
// So, we manually call it here with error.
stream_cc.Run(PP_ERROR_FAILED);
return;
}
NaClLog(4, "OpenManifestEntry_MainThreadContinuation: StreamAsFile okay\n");
// p is deleted automatically
} }
void PluginReverseInterface::StreamAsFile_MainThreadContinuation( void PluginReverseInterface::StreamAsFile_MainThreadContinuation(
OpenManifestEntryResource* p, OpenManifestEntryResource* p,
int32_t result) { int32_t result) {
NaClLog(4, NaClLog(4, "Entered StreamAsFile_MainThreadContinuation\n");
"Entered StreamAsFile_MainThreadContinuation\n");
{ {
nacl::MutexLocker take(&mu_); nacl::MutexLocker take(&mu_);
if (result == PP_OK) { if (result == PP_OK) {
// We downloaded this file to temporary storage for this plugin; it's
// reasonable to provide a file descriptor with write access.
p->file_info->desc = ConvertFileDescriptor(p->pp_file_info.handle, false);
p->file_info->file_token.lo = p->pp_file_info.token_lo;
p->file_info->file_token.hi = p->pp_file_info.token_hi;
NaClLog(4, NaClLog(4,
"StreamAsFile_MainThreadContinuation: PP_OK, desc %d\n", "StreamAsFile_MainThreadContinuation: PP_OK, desc %d\n",
p->file_info->desc); p->file_info->desc);
......
...@@ -85,6 +85,7 @@ struct OpenManifestEntryResource { ...@@ -85,6 +85,7 @@ struct OpenManifestEntryResource {
std::string url; std::string url;
struct NaClFileInfo* file_info; struct NaClFileInfo* file_info;
PP_NaClFileInfo pp_file_info;
bool* op_complete_ptr; bool* op_complete_ptr;
OpenManifestEntryAsyncCallback* callback; OpenManifestEntryAsyncCallback* callback;
}; };
......
...@@ -3247,11 +3247,6 @@ static void Pnacl_M25_PPB_NaCl_Private_ReportTranslationFinished(PP_Instance ins ...@@ -3247,11 +3247,6 @@ static void Pnacl_M25_PPB_NaCl_Private_ReportTranslationFinished(PP_Instance ins
iface->ReportTranslationFinished(instance, success); iface->ReportTranslationFinished(instance, success);
} }
static PP_FileHandle Pnacl_M25_PPB_NaCl_Private_OpenNaClExecutable(PP_Instance instance, const char* file_url, uint64_t* file_token_lo, uint64_t* file_token_hi) {
const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
return iface->OpenNaClExecutable(instance, file_url, file_token_lo, file_token_hi);
}
static void Pnacl_M25_PPB_NaCl_Private_DispatchEvent(PP_Instance instance, PP_NaClEventType event_type, const char* resource_url, PP_Bool length_is_computable, uint64_t loaded_bytes, uint64_t total_bytes) { static void Pnacl_M25_PPB_NaCl_Private_DispatchEvent(PP_Instance instance, PP_NaClEventType event_type, const char* resource_url, PP_Bool length_is_computable, uint64_t loaded_bytes, uint64_t total_bytes) {
const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
iface->DispatchEvent(instance, event_type, resource_url, length_is_computable, loaded_bytes, total_bytes); iface->DispatchEvent(instance, event_type, resource_url, length_is_computable, loaded_bytes, total_bytes);
...@@ -3347,11 +3342,6 @@ static void Pnacl_M25_PPB_NaCl_Private_GetManifestBaseURL(struct PP_Var* _struct ...@@ -3347,11 +3342,6 @@ static void Pnacl_M25_PPB_NaCl_Private_GetManifestBaseURL(struct PP_Var* _struct
*_struct_result = iface->GetManifestBaseURL(instance); *_struct_result = iface->GetManifestBaseURL(instance);
} }
static PP_Bool Pnacl_M25_PPB_NaCl_Private_ResolvesRelativeToPluginBaseUrl(PP_Instance instance, const char* url) {
const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
return iface->ResolvesRelativeToPluginBaseUrl(instance, url);
}
static void Pnacl_M25_PPB_NaCl_Private_ProcessNaClManifest(PP_Instance instance, const char* program_url) { static void Pnacl_M25_PPB_NaCl_Private_ProcessNaClManifest(PP_Instance instance, const char* program_url) {
const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
iface->ProcessNaClManifest(instance, program_url); iface->ProcessNaClManifest(instance, program_url);
...@@ -3407,6 +3397,11 @@ static void Pnacl_M25_PPB_NaCl_Private_DownloadNexe(PP_Instance instance, const ...@@ -3407,6 +3397,11 @@ static void Pnacl_M25_PPB_NaCl_Private_DownloadNexe(PP_Instance instance, const
iface->DownloadNexe(instance, url, handle, file_token_lo, file_token_hi, *callback); iface->DownloadNexe(instance, url, handle, file_token_lo, file_token_hi, *callback);
} }
static void Pnacl_M25_PPB_NaCl_Private_DownloadFile(PP_Instance instance, const char* url, struct PP_NaClFileInfo* file_info, struct PP_CompletionCallback* callback) {
const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
iface->DownloadFile(instance, url, file_info, *callback);
}
/* End wrapper methods for PPB_NaCl_Private_1_0 */ /* End wrapper methods for PPB_NaCl_Private_1_0 */
/* Begin wrapper methods for PPB_NetAddress_Private_0_1 */ /* Begin wrapper methods for PPB_NetAddress_Private_0_1 */
...@@ -5136,7 +5131,6 @@ static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = { ...@@ -5136,7 +5131,6 @@ static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = {
.IsNonSFIModeEnabled = (PP_Bool (*)(void))&Pnacl_M25_PPB_NaCl_Private_IsNonSFIModeEnabled, .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, .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))&Pnacl_M25_PPB_NaCl_Private_ReportTranslationFinished, .ReportTranslationFinished = (void (*)(PP_Instance instance, PP_Bool success))&Pnacl_M25_PPB_NaCl_Private_ReportTranslationFinished,
.OpenNaClExecutable = (PP_FileHandle (*)(PP_Instance instance, const char* file_url, uint64_t* file_token_lo, uint64_t* file_token_hi))&Pnacl_M25_PPB_NaCl_Private_OpenNaClExecutable,
.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, .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, const char* url, uint64_t loaded_bytes, uint64_t total_bytes))&Pnacl_M25_PPB_NaCl_Private_ReportLoadSuccess, .ReportLoadSuccess = (void (*)(PP_Instance instance, const char* url, uint64_t loaded_bytes, uint64_t total_bytes))&Pnacl_M25_PPB_NaCl_Private_ReportLoadSuccess,
.ReportLoadError = (void (*)(PP_Instance instance, PP_NaClError error, const char* error_message, const char* console_message))&Pnacl_M25_PPB_NaCl_Private_ReportLoadError, .ReportLoadError = (void (*)(PP_Instance instance, PP_NaClError error, const char* error_message, const char* console_message))&Pnacl_M25_PPB_NaCl_Private_ReportLoadError,
...@@ -5156,7 +5150,6 @@ static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = { ...@@ -5156,7 +5150,6 @@ static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = {
.GetNexeSize = (int64_t (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetNexeSize, .GetNexeSize = (int64_t (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetNexeSize,
.RequestNaClManifest = (void (*)(PP_Instance instance, const char* manifest_url, int32_t* manifest_id, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_RequestNaClManifest, .RequestNaClManifest = (void (*)(PP_Instance instance, const char* manifest_url, int32_t* manifest_id, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_RequestNaClManifest,
.GetManifestBaseURL = (struct PP_Var (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetManifestBaseURL, .GetManifestBaseURL = (struct PP_Var (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetManifestBaseURL,
.ResolvesRelativeToPluginBaseUrl = (PP_Bool (*)(PP_Instance instance, const char* url))&Pnacl_M25_PPB_NaCl_Private_ResolvesRelativeToPluginBaseUrl,
.ProcessNaClManifest = (void (*)(PP_Instance instance, const char* program_url))&Pnacl_M25_PPB_NaCl_Private_ProcessNaClManifest, .ProcessNaClManifest = (void (*)(PP_Instance instance, const char* program_url))&Pnacl_M25_PPB_NaCl_Private_ProcessNaClManifest,
.GetManifestURLArgument = (struct PP_Var (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetManifestURLArgument, .GetManifestURLArgument = (struct PP_Var (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetManifestURLArgument,
.DevInterfacesEnabled = (PP_Bool (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_DevInterfacesEnabled, .DevInterfacesEnabled = (PP_Bool (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_DevInterfacesEnabled,
...@@ -5167,7 +5160,8 @@ static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = { ...@@ -5167,7 +5160,8 @@ static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = {
.GetPnaclResourceInfo = (PP_Bool (*)(PP_Instance instance, const char* filename, struct PP_Var* llc_tool_name, struct PP_Var* ld_tool_name))&Pnacl_M25_PPB_NaCl_Private_GetPnaclResourceInfo, .GetPnaclResourceInfo = (PP_Bool (*)(PP_Instance instance, const char* filename, struct PP_Var* llc_tool_name, struct PP_Var* ld_tool_name))&Pnacl_M25_PPB_NaCl_Private_GetPnaclResourceInfo,
.GetCpuFeatureAttrs = (struct PP_Var (*)(void))&Pnacl_M25_PPB_NaCl_Private_GetCpuFeatureAttrs, .GetCpuFeatureAttrs = (struct PP_Var (*)(void))&Pnacl_M25_PPB_NaCl_Private_GetCpuFeatureAttrs,
.PostMessageToJavaScript = (void (*)(PP_Instance instance, const char* message))&Pnacl_M25_PPB_NaCl_Private_PostMessageToJavaScript, .PostMessageToJavaScript = (void (*)(PP_Instance instance, const char* message))&Pnacl_M25_PPB_NaCl_Private_PostMessageToJavaScript,
.DownloadNexe = (void (*)(PP_Instance instance, const char* url, PP_FileHandle* handle, uint64_t* file_token_lo, uint64_t* file_token_hi, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_DownloadNexe .DownloadNexe = (void (*)(PP_Instance instance, const char* url, PP_FileHandle* handle, uint64_t* file_token_lo, uint64_t* file_token_hi, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_DownloadNexe,
.DownloadFile = (void (*)(PP_Instance instance, const char* url, struct PP_NaClFileInfo* file_info, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_DownloadFile
}; };
static const struct PPB_NetAddress_Private_0_1 Pnacl_Wrappers_PPB_NetAddress_Private_0_1 = { static const struct PPB_NetAddress_Private_0_1 Pnacl_Wrappers_PPB_NetAddress_Private_0_1 = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment