OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client 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 WEB_RESOURCE_LOADER_H_ | |
6 #define WEB_RESOURCE_LOADER_H_ | |
7 | |
8 #include <ppapi/cpp/completion_callback.h> | |
9 #include <ppapi/cpp/url_loader.h> | |
10 #include <map> | |
11 #include <string> | |
12 | |
13 #include "threading/pthread_ext.h" | |
14 #include "threading/ref_count.h" | |
15 | |
16 namespace pp { | |
17 class Instance; | |
18 class URLRequestInfo; | |
19 } // namespace pp | |
20 | |
21 namespace url_io { | |
22 | |
23 class URLRequest; | |
24 | |
25 /// WebResourceLoader provides support for downloading resource data from a | |
26 /// given URL. It is usable from any thread and is thread safe. The only | |
27 /// retriction is that instance must be created on the main thread. To use | |
28 /// WebResourceLoader you must implement interface IDelegate and provide a | |
29 /// pointer to a delegate when creating the WebResourceLoader instance. | |
30 class WebResourceLoader { | |
31 public: | |
32 /// Interface IDelegate must be implemented by classes wishing to use | |
33 /// WebResourceLoader. | |
34 class Delegate { | |
35 public: | |
36 typedef WebResourceLoader Loader; | |
37 | |
38 virtual ~Delegate() = 0; | |
39 | |
40 /// Called when the URLResponseInfo has been received. You must call | |
41 /// WebResourceLoader::ReadMoreData after receiving the response info to | |
42 /// start downloading the resource. It is ok to call ReadMoreData from | |
43 /// within OnLoaderReceivedResponseInfo. | |
44 /// @param[in] loader The WebResourceLoader instance invoking this function. | |
45 virtual void OnLoaderReceivedResponseInfo(Loader* loader) = 0; | |
46 | |
47 /// Called when a block of web-resource data has been received. | |
48 /// @param[in] loader The WebResourceLoader instance invoking this function. | |
49 virtual void OnLoaderReceivedData(Loader* loader) = 0; | |
50 | |
51 /// Called after all the web-resource data has been received. | |
52 /// @param[in] loader The WebResourceLoader instance invoking this function. | |
53 virtual void OnLoaderCompletedDownload(Loader* loader) = 0; | |
54 | |
55 /// Called when an error occurs. | |
56 /// @param[in] error PPAPI error code (see pp_errors.h). | |
57 /// @param[in] loader The WebResourceLoader instance invoking this function. | |
58 virtual void OnLoaderError(int32_t error, Loader* loader) = 0; | |
59 | |
60 /// Called when the loader is done downloading data and is ready to be | |
61 /// closed, either at the end of a successful download or following an | |
62 /// error. If you plan on reusing the loader, you can simply close it with | |
63 /// WebResourceLoader::Close. If you do not need it any more, you can get | |
64 /// rid of it with WebResourceLoader::CloseAndDeleteSelf. Either of these | |
65 /// functions can be called from within OnLoaderDone. | |
66 /// @param[in] loader The WebResourceLoader instance invoking this function. | |
67 virtual void OnLoaderDone(Loader* loader) = 0; | |
68 }; | |
69 | |
70 /// A dictionary of <key, value> pairs for response-info http headers. | |
71 typedef std::map<std::string, std::string> HeaderDictionary; | |
72 | |
73 WebResourceLoader(pp::Instance* instance, Delegate* delegate); | |
74 | |
75 /// Call this function from any thread or from within an IDelegate function | |
76 /// to close and delete the WebResourceLoader instance. | |
77 void CloseAndDeleteSelf(); | |
78 | |
79 /// Initiate a download from the given URL. LoadURL will fail, with an assert | |
80 /// in debug mode, if a download is already in progress. | |
81 /// @param[in] url_request request configured with the desired download | |
82 /// parameters and URL. | |
83 void LoadURL(const URLRequest& url_request); | |
84 | |
85 /// WebResourceLoader doesn't automaticaly keep downloading data. Instead, | |
86 /// you must continually call ReadMoreData to get the next chunk of data until | |
87 /// WebResourceLoader calls Delegate function OnLoaderDownloadComplete. | |
88 /// @return true if the next download is successfully scheduled. | |
89 bool ReadMoreData(); | |
90 | |
91 /// Set the memory buffer to receive the next chunk of data. The size of the | |
92 /// buffer determines how much data WebResourceLoader will try to get before | |
93 /// calling Delegate::OnLoaderDataReceived. It is ok to set a new buffer for | |
94 /// each data-chunk download. It is also ok to call this function from within | |
95 /// Delegate::OnLoaderDataReceived. If no buffer is provided, a 4K internal | |
96 /// buffer is used. | |
97 /// @param[in] buffer pointer to memory buffer to receive the next chunk of | |
98 /// data. | |
99 /// @param[in] size size of buffer in bytes. | |
100 void set_content_buffer(uint8_t* buffer, int32_t size); | |
101 /// Get the current download buffer. Note: Do not attempt to read the buffer | |
102 /// while a ReadMoreData asynchronous call is in progress. Instead, wait until | |
103 /// the delegate is invoked. | |
104 /// @return pointer to the current download buffer. | |
105 const uint8_t* buffer() const { return buffer_; } | |
106 /// Get the size of the current download buffer. Note: Do not attempt to read | |
107 /// the data size while a ReadMoreData asynchronous call is in progress. | |
108 /// Instead, wait until the delegate is invoked. | |
109 /// @return size in bytes. | |
110 int32_t data_size() const { return data_size_; } | |
111 | |
112 /// Get the URL for the current download. This function should only be called | |
113 /// from the main thread. | |
114 /// @return URL string for the current download. | |
115 const std::string url() const; | |
116 /// Get the http status for the current download. This function should only | |
117 /// be called from the main thread. | |
118 /// @return http status code. | |
119 int32_t GetHttpStatus() const; | |
120 /// Get the URLResponseInfo object for the current download. Returns a | |
121 /// null object if the response has not yet been received. This function | |
122 /// should only be called from the main thread. | |
123 /// @return the URLResponseInfo object. | |
124 pp::URLResponseInfo GetResponseInfo() const; | |
125 /// Get the length of the content, as reported by the server, extracted from | |
126 /// the content-length parameter in the response info. | |
127 /// @return the content length in bytes. | |
128 int32_t GetContentLength() const; | |
129 | |
130 /// Return a dictionary of <key, value> pairs for the response headers. | |
131 /// Keys are in all-upper case. | |
132 /// @return dictionary of <key, value> header pairs. | |
133 const HeaderDictionary& response_headers() const { return response_headers_; } | |
134 | |
135 /// Close the current connection. It is ok to use the same loader to download | |
136 /// from several URLs. However, the current connection must be closed before | |
137 /// starting a new one. Close may only be called from the main thread. | |
138 void Close(); | |
139 | |
140 protected: | |
141 // Do not delete a WebResourceLoader instance directly. Call | |
142 // Call CloseAndDeleteSelf instead. | |
143 virtual ~WebResourceLoader(); | |
144 | |
145 private: | |
146 // WebResourceLoader uses a state machine to keep track of its internal state. | |
147 enum State { | |
148 kStateNotConnected = 0, // No active connection. | |
149 kStateConnecting, // Establishing a connection, waiting for response info. | |
150 kStateSuspended, // Suspended until ReadNextBlock is called. | |
151 kStateInvokedDelegate, // In a delegate-interface function. | |
152 kStateWillReadMoreData, // Read next block when returning from delegate. | |
153 kStateDownloading // Currently waiting for an asynch. data-read callback. | |
154 }; | |
155 | |
156 // We use a single completion callback with a dispatch op-code to distinguish | |
157 // between the various asynchronous operations. | |
158 enum CallbackOpCode { | |
159 kResponseInfoCallback, | |
160 kDataReceivedCallback | |
161 }; | |
162 | |
163 void CompletionCallbackFunc(int32_t result, CallbackOpCode op_code); | |
164 | |
165 void DoResponseInfoReceived(int32_t result); | |
166 void DoDataReceived(int32_t result); | |
167 void DoDownloadError(int32_t result); | |
168 | |
169 // Create a completion callback taking the given op-code. | |
170 pp::CompletionCallback MakeCallback(CallbackOpCode op_code); | |
171 | |
172 // Parse response headers into the header dictionary. | |
173 void ParseHeaders(pp::URLResponseInfo response); | |
174 | |
175 // Main-thread-only functions, suitable for callbacks. | |
176 void InternalReadMoreData(int32_t result); | |
177 void InternalLoadURL(int32_t result, const URLRequest& url_request); | |
178 | |
179 // Main-thread callback for CloseAndDeleteSelf. | |
180 static void DeleteOnMainThread(void* user_data, int32_t err); | |
181 | |
182 pp::CompletionCallbackFactory<WebResourceLoader, | |
183 ::threading::RefCount> factory_; | |
184 pp::Instance* instance_; | |
185 pp::URLLoader url_loader_; | |
186 | |
187 State state_; | |
188 mutable pthread_mutex_t state_mutex_; | |
189 | |
190 HeaderDictionary response_headers_; | |
191 | |
192 // Download buffer, either user provided, or as a pointer to internal_buffer_ | |
193 // otherwise. | |
194 uint8_t* buffer_; | |
195 int32_t buffer_size_; | |
196 int32_t data_size_; | |
197 | |
198 static const int32_t kInternalBufferSize = 4096; | |
199 uint8_t internal_buffer_[kInternalBufferSize]; | |
200 | |
201 Delegate* delegate_; | |
202 }; | |
203 | |
204 inline WebResourceLoader::Delegate::~Delegate() {} | |
205 | |
206 } // namespace url_io | |
207 | |
208 #endif // WEB_RESOURCE_LOADER_H_ | |
OLD | NEW |