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_INL_H_ | |
6 #define WEB_RESOURCE_LOADER_INL_H_ | |
7 | |
8 #include "experimental/conways_life/web_resource_loader.h" | |
9 | |
10 #include <stdio.h> | |
11 #include <cassert> | |
12 #include <string> | |
13 #include "ppapi/c/pp_errors.h" | |
14 #include "ppapi/cpp/module.h" | |
15 #include "ppapi/cpp/url_loader.h" | |
16 #include "ppapi/cpp/url_request_info.h" | |
17 #include "ppapi/cpp/url_response_info.h" | |
18 | |
19 namespace life { | |
20 | |
21 template <class Delegate> | |
22 WebResourceLoader<Delegate>::WebResourceLoader(pp::Instance* instance, | |
23 Delegate* delegate) | |
24 : factory_(this), | |
25 instance_(instance), | |
26 url_loader_(*instance), | |
27 connected_(false), | |
28 buffer_(NULL), | |
29 buffer_size_(0), | |
30 data_size_(0), | |
31 delegate_(delegate) { | |
32 assert(delegate != NULL); | |
33 } | |
34 | |
35 template <class Delegate> | |
36 void WebResourceLoader<Delegate>::CloseAndDeleteSelf() { | |
37 // Can't close & delete this instance here. Instead, we schedule a main-thread | |
38 // callback to delete it later. | |
39 pp::CompletionCallback cc(DeleteOnMainThread, this); | |
40 pp::Module::Get()->core()->CallOnMainThread(0, cc, PP_OK); | |
41 } | |
42 | |
43 template <class Delegate> | |
44 WebResourceLoader<Delegate>::~WebResourceLoader() { | |
45 Close(); | |
46 } | |
47 | |
48 template <class Delegate> | |
49 void WebResourceLoader<Delegate>::LoadURL(const std::string& url) { | |
50 // Check that there is no pending request. | |
51 assert(!connected_); | |
52 assert(url_loader_.GetResponseInfo().is_null()); | |
53 // Only usable from main plugin thread. | |
54 pp::CompletionCallback cc = factory_.NewCallback( | |
55 &WebResourceLoader<Delegate>::StartDownload, std::string(url)); | |
56 pp::Module::Get()->core()->CallOnMainThread(0, cc, PP_OK); | |
57 } | |
58 | |
59 template <class Delegate> | |
60 const std::string WebResourceLoader<Delegate>::url() const { | |
61 pp::URLResponseInfo response = url_loader_.GetResponseInfo(); | |
62 return response.GetURL().AsString(); | |
63 } | |
64 | |
65 template <class Delegate> | |
66 int32_t WebResourceLoader<Delegate>::GetHttpStatus() const { | |
67 return GetResponseInfo().GetStatusCode(); | |
68 } | |
69 | |
70 template <class Delegate> | |
71 pp::URLResponseInfo WebResourceLoader<Delegate>::GetResponseInfo() const { | |
72 pp::URLResponseInfo response = url_loader_.GetResponseInfo(); | |
73 assert(!response.is_null()); | |
74 return response; | |
75 } | |
76 | |
77 template <class Delegate> | |
78 void WebResourceLoader<Delegate>::Close() { | |
79 assert(pp::Module::Get()->core()->IsMainThread()); | |
80 connected_ = false; | |
81 buffer_ = NULL; | |
82 buffer_size_ = 0; | |
83 data_size_ = 0; | |
84 } | |
85 | |
86 template <class Delegate> | |
87 void WebResourceLoader<Delegate>::CompletionCallbackFunc( | |
88 int32_t result, DispatchOpCode op_code) { | |
89 if (result < 0) { | |
90 // A negative value indicates an error. | |
91 delegate_->OnWebResourceLoaderError(result, this); | |
92 delegate_->OnWebResourceLoaderDone(this); | |
93 } else if (result == PP_OK && !connected_) { | |
94 assert(op_code == kUrlResponseInfoReady); | |
95 // If we're not yet connected and get result == PP_OK, then we received | |
96 // the http headers. | |
97 connected_ = true; | |
98 pp::URLResponseInfo response = url_loader_.GetResponseInfo(); | |
99 if (delegate_->OnWebResourceLoaderCallback(kUrlResponseInfoReady, this)) { | |
100 ReadNextDataBlock(); | |
101 } else { | |
102 delegate_->OnWebResourceLoaderDone(this); | |
103 } | |
104 } else { | |
105 assert(op_code == kDataReceived); | |
106 if (result == 0) { | |
107 // No more data; the download completed successfully. | |
108 data_size_ = 0; | |
109 delegate_->OnWebResourceLoaderCallback(kDownloadComplete, this); | |
110 delegate_->OnWebResourceLoaderDone(this); | |
111 } else { | |
112 // We received a block of data of size |result|. | |
113 data_size_ = result; | |
114 if (delegate_->OnWebResourceLoaderCallback(kDataReceived, this)) { | |
115 ReadNextDataBlock(); | |
116 } else { | |
117 delegate_->OnWebResourceLoaderDone(this); | |
118 } | |
119 } | |
120 } | |
121 } | |
122 | |
123 template <class Delegate> | |
124 pp::CompletionCallback WebResourceLoader<Delegate>::MakeCallback( | |
125 DispatchOpCode op_code) { | |
126 return factory_.NewCallback( | |
127 &WebResourceLoader<Delegate>::CompletionCallbackFunc, op_code); | |
128 } | |
129 | |
130 template <class Delegate> | |
131 void WebResourceLoader<Delegate>::InitializeRequest( | |
132 const std::string& url, | |
133 pp::URLRequestInfo* request) { | |
134 request->SetURL(url); | |
135 request->SetMethod("GET"); | |
136 request->SetFollowRedirects(true); | |
137 request->SetStreamToFile(false); | |
138 } | |
139 | |
140 template <class Delegate> | |
141 void WebResourceLoader<Delegate>::ReadNextDataBlock() { | |
142 // If a custom buffer has not been set or has been set to NULL, use the | |
143 // internal buffer. | |
144 if (buffer_ == NULL) { | |
145 buffer_ = internal_buffer_; | |
146 buffer_size_ = kInternalBufferSize; | |
147 } | |
148 // Get the next block of data. | |
149 pp::CompletionCallback cc = MakeCallback(kDataReceived); | |
150 int32_t rv = url_loader_.ReadResponseBody(buffer_, buffer_size_, cc); | |
151 if (rv != PP_OK_COMPLETIONPENDING) { | |
152 cc.Run(rv); | |
153 } | |
154 } | |
155 | |
156 template <class Delegate> | |
157 void WebResourceLoader<Delegate>::StartDownload(int32_t result, | |
158 const std::string& url) { | |
159 // Only usable from main plugin thread. | |
160 assert(pp::Module::Get()->core()->IsMainThread()); | |
161 | |
162 pp::CompletionCallback cc = MakeCallback(kUrlResponseInfoReady); | |
163 pp::URLRequestInfo request(instance_); | |
164 InitializeRequest(url, &request); | |
165 int32_t rv = url_loader_.Open(request, cc); | |
166 if (rv != PP_OK_COMPLETIONPENDING) { | |
167 // Getting here isn't necessarily an error. It indicates that the call to | |
168 // Open did not take place asynchronously. That can happen, for instance, | |
169 // when the resource data comes out of the cache. In any case, we simply | |
170 // invoke the callback 'manually.' | |
171 cc.Run(rv); | |
172 } | |
173 } | |
174 | |
175 template <class Delegate> | |
176 void WebResourceLoader<Delegate>::DeleteOnMainThread(void* user_data, | |
177 int32_t err) { | |
178 WebResourceLoader* loader = reinterpret_cast<WebResourceLoader*>(user_data); | |
179 if (loader != NULL) delete loader; | |
180 } | |
181 | |
182 } // namespace life | |
183 | |
184 #endif // WEB_RESOURCE_LOADER_INL_H_ | |
OLD | NEW |