1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_FILE_DOWNLOADER_H_ 6 #define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_FILE_DOWNLOADER_H_ 7 8 #include <deque> 9 10 #include "native_client/src/include/nacl_macros.h" 11 #include "native_client/src/include/nacl_string.h" 12 #include "native_client/src/public/nacl_file_info.h" 13 #include "ppapi/c/private/ppb_nacl_private.h" 14 #include "ppapi/cpp/file_io.h" 15 #include "ppapi/cpp/instance.h" 16 #include "ppapi/cpp/url_loader.h" 17 #include "ppapi/cpp/url_response_info.h" 18 #include "ppapi/native_client/src/trusted/plugin/callback_source.h" 19 #include "ppapi/utility/completion_callback_factory.h" 20 21 namespace plugin { 22 23 class Plugin; 24 25 typedef enum { 26 DOWNLOAD_TO_BUFFER_AND_STREAM = 0, 27 DOWNLOAD_NONE 28 } DownloadMode; 29 30 typedef std::vector<char>* FileStreamData; 31 typedef CallbackSource<FileStreamData> StreamCallbackSource; 32 typedef pp::CompletionCallbackWithOutput<FileStreamData> StreamCallback; 33 34 // A class that wraps PPAPI URLLoader and FileIO functionality for downloading 35 // the url into a file and providing an open file descriptor. 36 class FileDownloader { 37 public: 38 explicit FileDownloader(Plugin* instance); 39 ~FileDownloader() {} 40 41 // Issues a GET on |url| to start downloading the response into a file, 42 // and finish streaming it. |callback| will be run after streaming is 43 // done or if an error prevents streaming from completing. 44 // Returns true when callback is scheduled to be called on success or failure. 45 // Returns false if callback is NULL, or if the PPB_FileIO_Trusted interface 46 // is not available. 47 // If |record_progress| is true, then download progress will be recorded, 48 // and can be polled through GetDownloadProgress(). 49 // If |progress_callback| is not NULL and |record_progress| is true, 50 // then the callback will be invoked for every progress update received 51 // by the loader. 52 53 // Similar to Open(), but used for streaming the |url| data directly to the 54 // caller without writing to a temporary file. The callbacks provided by 55 // |stream_callback_source| are expected to copy the data before returning. 56 // |callback| is called once the response headers are received, 57 // and streaming must be completed separately via BeginStreaming(). 58 bool OpenStream(const nacl::string& url, 59 const pp::CompletionCallback& callback, 60 StreamCallbackSource* stream_callback_source); 61 62 // Finish streaming the response body for a URL request started by either 63 // OpenStream(). Runs the given |callback| when streaming is done. 64 void BeginStreaming(const pp::CompletionCallback& callback); 65 66 // Once the GET request has finished, and the contents of the file 67 // represented by |url_| are available, |full_url_| is the full URL including 68 // the scheme, host and full path. 69 // Returns an empty string before the GET request has finished. 70 const nacl::string& full_url() const { return full_url_; } 71 72 // GetDownloadProgress() returns the current download progress, which is 73 // meaningful after Open() has been called. Progress only refers to the 74 // response body and does not include the headers. 75 // 76 // This data is only available if the |record_progress| true in the 77 // Open() call. If progress is being recorded, then |bytes_received| 78 // will be set to the number of bytes received thus far, 79 // and |total_bytes_to_be_received| will be set to the total number 80 // of bytes to be received. The total bytes to be received may be unknown, 81 // in which case |total_bytes_to_be_received| will be set to -1. 82 bool GetDownloadProgress(int64_t* bytes_received, 83 int64_t* total_bytes_to_be_received) const; 84 85 int status_code() const { return status_code_; } 86 nacl::string GetResponseHeaders() const; 87 88 void set_request_headers(const nacl::string& extra_request_headers) { 89 extra_request_headers_ = extra_request_headers; 90 } 91 92 private: 93 NACL_DISALLOW_COPY_AND_ASSIGN(FileDownloader); 94 95 // For DOWNLOAD_TO_BUFFER_AND_STREAM, the process is very similar: 96 // 1) Ask the browser to start streaming |url_| to an internal buffer. 97 // 2) Ask the browser to finish streaming to |temp_buffer_| on success. 98 // 3) Wait for streaming to finish, passing the data directly to the user. 99 // Each step is done asynchronously using callbacks. We create callbacks 100 // through a factory to take advantage of ref-counting. 101 // The public Open*() functions start step 1), and the public BeginStreaming 102 // function proceeds to step 2) and 3). 103 bool InitialResponseIsValid(); 104 void URLLoadStartNotify(int32_t pp_error); 105 void URLReadBodyNotify(int32_t pp_error); 106 107 Plugin* instance_; 108 nacl::string full_url_; 109 110 nacl::string extra_request_headers_; 111 pp::URLResponseInfo url_response_; 112 pp::CompletionCallback file_open_notify_callback_; 113 pp::CompletionCallback stream_finish_callback_; 114 pp::URLLoader url_loader_; 115 pp::CompletionCallbackFactory<FileDownloader> callback_factory_; 116 int32_t status_code_; 117 DownloadMode mode_; 118 static const uint32_t kTempBufferSize = 16384; 119 std::vector<char> temp_buffer_; 120 StreamCallbackSource* data_stream_callback_source_; 121 }; 122 123 } // namespace plugin 124 125 #endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_FILE_DOWNLOADER_H_ 126