OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 #include "content/test/plugin/plugin_geturl_test.h" | |
6 | |
7 #include <stdio.h> | |
8 | |
9 #include "base/basictypes.h" | |
10 #include "base/files/file_util.h" | |
11 #include "base/strings/string_number_conversions.h" | |
12 #include "base/strings/string_util.h" | |
13 #include "base/strings/utf_string_conversions.h" | |
14 | |
15 // url for "self". The %22%22 is to make a statement for javascript to | |
16 // evaluate and return. | |
17 #define SELF_URL "javascript:window.location+\"\"" | |
18 | |
19 // The identifier for the self url stream. | |
20 #define SELF_URL_STREAM_ID 1 | |
21 | |
22 // The identifier for the fetched url stream. | |
23 #define FETCHED_URL_STREAM_ID 2 | |
24 | |
25 // url for testing GetURL with a bogus URL. | |
26 #define BOGUS_URL "bogoproto:///x:/asdf.xysdhffieasdf.asdhj/" | |
27 | |
28 // url for testing redirect notifications sent to plugins. | |
29 #define REDIRECT_SRC_URL \ | |
30 "http://mock.http/npapi/plugin_read_page_redirect_src.html" | |
31 | |
32 // The notification id for the redirect notification url that we will cancel. | |
33 #define REDIRECT_SRC_URL_NOTIFICATION_CANCEL_ID 4 | |
34 | |
35 // The notification id for the redirect notification url that we will accept. | |
36 #define REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID 5 | |
37 | |
38 // The identifier for the bogus url stream. | |
39 #define BOGUS_URL_STREAM_ID 3 | |
40 | |
41 // The maximum chunk size of stream data. | |
42 #define STREAM_CHUNK 197 | |
43 | |
44 namespace NPAPIClient { | |
45 | |
46 PluginGetURLTest::PluginGetURLTest(NPP id, NPNetscapeFuncs *host_functions) | |
47 : PluginTest(id, host_functions), | |
48 tests_started_(false), | |
49 tests_in_progress_(0), | |
50 test_file_(NULL), | |
51 expect_404_response_(false), | |
52 npn_evaluate_context_(false), | |
53 handle_url_redirects_(false), | |
54 received_url_redirect_cancel_notification_(false), | |
55 received_url_redirect_allow_notification_(false), | |
56 check_cookies_(false) { | |
57 } | |
58 | |
59 PluginGetURLTest::~PluginGetURLTest() {} | |
60 | |
61 NPError PluginGetURLTest::New(uint16 mode, int16 argc, const char* argn[], | |
62 const char* argv[], NPSavedData* saved) { | |
63 const char* page_not_found_url = GetArgValue("page_not_found_url", argc, | |
64 argn, argv); | |
65 if (page_not_found_url) { | |
66 page_not_found_url_ = page_not_found_url; | |
67 expect_404_response_ = true; | |
68 } | |
69 | |
70 const char* fail_write_url = GetArgValue("fail_write_url", argc, | |
71 argn, argv); | |
72 if (fail_write_url) { | |
73 fail_write_url_ = fail_write_url; | |
74 } | |
75 | |
76 const char* referrer_target_url = GetArgValue("ref_target", argc, | |
77 argn, argv); | |
78 if (referrer_target_url) { | |
79 referrer_target_url_ = referrer_target_url; | |
80 } | |
81 | |
82 if (!base::strcasecmp(GetArgValue("name", argc, argn, argv), | |
83 "geturlredirectnotify")) { | |
84 handle_url_redirects_ = true; | |
85 } | |
86 | |
87 NPError error = PluginTest::New(mode, argc, argn, argv, saved); | |
88 | |
89 // The above sets test_name(). | |
90 if (test_name() == "cookies") | |
91 check_cookies_ = true; | |
92 | |
93 return error; | |
94 } | |
95 | |
96 NPError PluginGetURLTest::SetWindow(NPWindow* pNPWindow) { | |
97 #if !defined(OS_MACOSX) | |
98 if (pNPWindow->window == NULL) | |
99 return NPERR_NO_ERROR; | |
100 #endif | |
101 | |
102 if (!tests_started_) { | |
103 tests_started_ = true; | |
104 | |
105 tests_in_progress_++; | |
106 | |
107 if (expect_404_response_) { | |
108 HostFunctions()->geturl(id(), page_not_found_url_.c_str(), NULL); | |
109 return NPERR_NO_ERROR; | |
110 } else if (!fail_write_url_.empty()) { | |
111 HostFunctions()->geturl(id(), fail_write_url_.c_str(), NULL); | |
112 return NPERR_NO_ERROR; | |
113 } else if (!referrer_target_url_.empty()) { | |
114 HostFunctions()->pushpopupsenabledstate(id(), true); | |
115 HostFunctions()->geturl(id(), referrer_target_url_.c_str(), "_blank"); | |
116 HostFunctions()->poppopupsenabledstate(id()); | |
117 return NPERR_NO_ERROR; | |
118 } else if (handle_url_redirects_) { | |
119 HostFunctions()->geturlnotify( | |
120 id(), REDIRECT_SRC_URL, NULL, | |
121 reinterpret_cast<void*>(REDIRECT_SRC_URL_NOTIFICATION_CANCEL_ID)); | |
122 return NPERR_NO_ERROR; | |
123 } else if (check_cookies_) { | |
124 HostFunctions()->geturlnotify( | |
125 id(), | |
126 "plugin_ref_target_page.html", | |
127 NULL, | |
128 reinterpret_cast<void*>(SELF_URL_STREAM_ID)); | |
129 return NPERR_NO_ERROR; | |
130 } | |
131 | |
132 std::string url = SELF_URL; | |
133 HostFunctions()->geturlnotify(id(), url.c_str(), NULL, | |
134 reinterpret_cast<void*>(SELF_URL_STREAM_ID)); | |
135 | |
136 tests_in_progress_++; | |
137 std::string bogus_url = BOGUS_URL; | |
138 HostFunctions()->geturlnotify(id(), bogus_url.c_str(), NULL, | |
139 reinterpret_cast<void*>(BOGUS_URL_STREAM_ID)); | |
140 } | |
141 return NPERR_NO_ERROR; | |
142 } | |
143 | |
144 NPError PluginGetURLTest::NewStream(NPMIMEType type, NPStream* stream, | |
145 NPBool seekable, uint16* stype) { | |
146 if (stream == NULL) { | |
147 SetError("NewStream got null stream"); | |
148 return NPERR_INVALID_PARAM; | |
149 } | |
150 | |
151 if (test_completed()) { | |
152 return PluginTest::NewStream(type, stream, seekable, stype); | |
153 } | |
154 | |
155 if (!referrer_target_url_.empty()) { | |
156 return NPERR_NO_ERROR; | |
157 } | |
158 | |
159 static_assert(sizeof(unsigned long) <= sizeof(stream->notifyData), | |
160 "cast validity check"); | |
161 | |
162 if (expect_404_response_) { | |
163 NPObject *window_obj = NULL; | |
164 HostFunctions()->getvalue(id(), NPNVWindowNPObject, &window_obj); | |
165 if (!window_obj) { | |
166 SetError("Failed to get NPObject for plugin instance2"); | |
167 SignalTestCompleted(); | |
168 return NPERR_NO_ERROR; | |
169 } | |
170 | |
171 std::string script = "javascript:document.title=\"OK\""; | |
172 NPString script_string; | |
173 script_string.UTF8Characters = script.c_str(); | |
174 script_string.UTF8Length = static_cast<unsigned int>(script.length()); | |
175 NPVariant result_var; | |
176 | |
177 npn_evaluate_context_ = true; | |
178 HostFunctions()->evaluate(id(), window_obj, &script_string, &result_var); | |
179 npn_evaluate_context_ = false; | |
180 return NPERR_NO_ERROR; | |
181 } | |
182 | |
183 if (!fail_write_url_.empty() || check_cookies_) { | |
184 return NPERR_NO_ERROR; | |
185 } | |
186 | |
187 | |
188 unsigned long stream_id = reinterpret_cast<unsigned long>( | |
189 stream->notifyData); | |
190 | |
191 switch (stream_id) { | |
192 case SELF_URL_STREAM_ID: | |
193 break; | |
194 case FETCHED_URL_STREAM_ID: | |
195 { | |
196 std::string filename = self_url_; | |
197 if (filename.find("file:///", 0) != 0) { | |
198 SetError("Test expects a file-url."); | |
199 break; | |
200 } | |
201 | |
202 // TODO(evanm): use the net:: functions to convert file:// URLs to | |
203 // on-disk file paths. But it probably doesn't actually matter in | |
204 // this test. | |
205 | |
206 #if defined(OS_WIN) | |
207 filename = filename.substr(8); // remove "file:///" | |
208 // Assume an ASCII path on Windows. | |
209 base::FilePath path = base::FilePath(base::ASCIIToUTF16(filename)); | |
210 #else | |
211 filename = filename.substr(7); // remove "file://" | |
212 base::FilePath path = base::FilePath(filename); | |
213 #endif | |
214 | |
215 test_file_ = base::OpenFile(path, "r"); | |
216 if (!test_file_) { | |
217 SetError("Could not open source file"); | |
218 } | |
219 } | |
220 break; | |
221 case BOGUS_URL_STREAM_ID: | |
222 SetError("Unexpected NewStream for BOGUS_URL"); | |
223 break; | |
224 case REDIRECT_SRC_URL_NOTIFICATION_CANCEL_ID: | |
225 SetError("Should not redirect to URL when plugin denied it."); | |
226 break; | |
227 case REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID: | |
228 break; | |
229 default: | |
230 SetError("Unexpected NewStream callback"); | |
231 break; | |
232 } | |
233 return NPERR_NO_ERROR; | |
234 } | |
235 | |
236 int32 PluginGetURLTest::WriteReady(NPStream *stream) { | |
237 if (test_completed()) { | |
238 return PluginTest::WriteReady(stream); | |
239 } | |
240 | |
241 if (!referrer_target_url_.empty() || check_cookies_) { | |
242 return STREAM_CHUNK; | |
243 } | |
244 | |
245 static_assert(sizeof(unsigned long) <= sizeof(stream->notifyData), | |
246 "cast validity check"); | |
247 unsigned long stream_id = reinterpret_cast<unsigned long>( | |
248 stream->notifyData); | |
249 if (stream_id == BOGUS_URL_STREAM_ID) | |
250 SetError("Received WriteReady for BOGUS_URL"); | |
251 | |
252 return STREAM_CHUNK; | |
253 } | |
254 | |
255 int32 PluginGetURLTest::Write(NPStream *stream, int32 offset, int32 len, | |
256 void *buffer) { | |
257 if (test_completed()) { | |
258 return PluginTest::Write(stream, offset, len, buffer); | |
259 } | |
260 | |
261 if (!fail_write_url_.empty()) { | |
262 SignalTestCompleted(); | |
263 return -1; | |
264 } | |
265 | |
266 if (!referrer_target_url_.empty() || check_cookies_) { | |
267 return len; | |
268 } | |
269 | |
270 if (stream == NULL) { | |
271 SetError("Write got null stream"); | |
272 return -1; | |
273 } | |
274 if (len < 0 || len > STREAM_CHUNK) { | |
275 SetError("Write got bogus stream chunk size"); | |
276 return -1; | |
277 } | |
278 | |
279 static_assert(sizeof(unsigned long) <= sizeof(stream->notifyData), | |
280 "cast validity check"); | |
281 unsigned long stream_id = reinterpret_cast<unsigned long>( | |
282 stream->notifyData); | |
283 switch (stream_id) { | |
284 case SELF_URL_STREAM_ID: | |
285 self_url_.append(static_cast<char*>(buffer), len); | |
286 break; | |
287 case FETCHED_URL_STREAM_ID: | |
288 { | |
289 char read_buffer[STREAM_CHUNK]; | |
290 int32 bytes = | |
291 static_cast<int32>(fread(read_buffer, 1, len, test_file_)); | |
292 // Technically, fread could return fewer than len | |
293 // bytes. But this is not likely. | |
294 if (bytes != len) | |
295 SetError("Did not read correct bytelength from source file"); | |
296 if (memcmp(read_buffer, buffer, len)) | |
297 SetError("Content mismatch between data and source!"); | |
298 } | |
299 break; | |
300 case BOGUS_URL_STREAM_ID: | |
301 SetError("Unexpected write callback for BOGUS_URL"); | |
302 break; | |
303 case REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID: | |
304 break; | |
305 default: | |
306 SetError("Unexpected write callback"); | |
307 break; | |
308 } | |
309 // Pretend that we took all the data. | |
310 return len; | |
311 } | |
312 | |
313 | |
314 NPError PluginGetURLTest::DestroyStream(NPStream *stream, NPError reason) { | |
315 if (test_completed()) { | |
316 return PluginTest::DestroyStream(stream, reason); | |
317 } | |
318 | |
319 if (stream == NULL) { | |
320 SetError("NewStream got null stream"); | |
321 return NPERR_INVALID_PARAM; | |
322 } | |
323 | |
324 static_assert(sizeof(unsigned long) <= sizeof(stream->notifyData), | |
325 "cast validity check"); | |
326 | |
327 if (expect_404_response_) { | |
328 if (npn_evaluate_context_) { | |
329 SetError("Received destroyStream in the context of NPN_Evaluate."); | |
330 } | |
331 | |
332 SignalTestCompleted(); | |
333 return NPERR_NO_ERROR; | |
334 } | |
335 | |
336 if (!referrer_target_url_.empty()) { | |
337 return NPERR_NO_ERROR; | |
338 } | |
339 | |
340 if (check_cookies_) { | |
341 SignalTestCompleted(); | |
342 return NPERR_NO_ERROR; | |
343 } | |
344 | |
345 unsigned long stream_id = | |
346 reinterpret_cast<unsigned long>(stream->notifyData); | |
347 switch (stream_id) { | |
348 case SELF_URL_STREAM_ID: | |
349 // don't care | |
350 break; | |
351 case REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID: | |
352 break; | |
353 case FETCHED_URL_STREAM_ID: | |
354 { | |
355 char read_buffer[STREAM_CHUNK]; | |
356 size_t bytes = fread(read_buffer, 1, sizeof(read_buffer), test_file_); | |
357 if (bytes != 0) | |
358 SetError("Data and source mismatch on length"); | |
359 base::CloseFile(test_file_); | |
360 } | |
361 break; | |
362 default: | |
363 SetError("Unexpected NewStream callback"); | |
364 break; | |
365 } | |
366 return NPERR_NO_ERROR; | |
367 } | |
368 | |
369 void PluginGetURLTest::StreamAsFile(NPStream* stream, const char* fname) { | |
370 if (stream == NULL) { | |
371 SetError("NewStream got null stream"); | |
372 return; | |
373 } | |
374 | |
375 static_assert(sizeof(unsigned long) <= sizeof(stream->notifyData), | |
376 "cast validity check"); | |
377 unsigned long stream_id = | |
378 reinterpret_cast<unsigned long>(stream->notifyData); | |
379 switch (stream_id) { | |
380 case SELF_URL_STREAM_ID: | |
381 // don't care | |
382 break; | |
383 default: | |
384 SetError("Unexpected NewStream callback"); | |
385 break; | |
386 } | |
387 } | |
388 | |
389 void PluginGetURLTest::URLNotify(const char* url, NPReason reason, void* data) { | |
390 if (!tests_in_progress_) { | |
391 SetError("URLNotify received after tests completed"); | |
392 return; | |
393 } | |
394 | |
395 if (!url) { | |
396 SetError("URLNotify received NULL url"); | |
397 return; | |
398 } | |
399 | |
400 if (check_cookies_) | |
401 return; | |
402 | |
403 static_assert(sizeof(unsigned long) <= sizeof(data), "cast validity check"); | |
404 unsigned long stream_id = reinterpret_cast<unsigned long>(data); | |
405 switch (stream_id) { | |
406 case SELF_URL_STREAM_ID: | |
407 if (strcmp(url, SELF_URL) != 0) | |
408 SetError("URLNotify reported incorrect url for SELF_URL"); | |
409 | |
410 // We have our stream url. Go fetch it. | |
411 HostFunctions()->geturlnotify(id(), self_url_.c_str(), NULL, | |
412 reinterpret_cast<void*>(FETCHED_URL_STREAM_ID)); | |
413 break; | |
414 case FETCHED_URL_STREAM_ID: | |
415 if (!url || strcmp(url, self_url_.c_str()) != 0) | |
416 SetError("URLNotify reported incorrect url for FETCHED_URL"); | |
417 tests_in_progress_--; | |
418 break; | |
419 case BOGUS_URL_STREAM_ID: | |
420 if (reason != NPRES_NETWORK_ERR) { | |
421 std::string err = "BOGUS_URL received unexpected URLNotify status: "; | |
422 err.append(base::IntToString(reason)); | |
423 SetError(err); | |
424 } | |
425 tests_in_progress_--; | |
426 break; | |
427 case REDIRECT_SRC_URL_NOTIFICATION_CANCEL_ID: { | |
428 if (!received_url_redirect_cancel_notification_) { | |
429 SetError("Failed to receive URLRedirect notification for cancel"); | |
430 } | |
431 if (reason != NPRES_NETWORK_ERR) { | |
432 SetError("Redirected URL didn't get canceled"); | |
433 } | |
434 break; | |
435 } | |
436 case REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID: { | |
437 if (!received_url_redirect_allow_notification_) { | |
438 SetError("Failed to receive URLRedirect notification for allow"); | |
439 } | |
440 if (reason != NPRES_DONE) { | |
441 SetError("Redirected URL didn't complete successfully"); | |
442 } | |
443 tests_in_progress_--; | |
444 break; | |
445 } | |
446 default: | |
447 SetError("Unexpected NewStream callback"); | |
448 break; | |
449 } | |
450 | |
451 if (tests_in_progress_ == 0) | |
452 SignalTestCompleted(); | |
453 } | |
454 | |
455 void PluginGetURLTest::URLRedirectNotify(const char* url, | |
456 int32_t status, | |
457 void* notify_data) { | |
458 unsigned long stream_id = reinterpret_cast<unsigned long>(notify_data); | |
459 if (stream_id == REDIRECT_SRC_URL_NOTIFICATION_CANCEL_ID) { | |
460 if (!base::strcasecmp(url, | |
461 "http://mock.http/npapi/plugin_read_page.html")) { | |
462 received_url_redirect_cancel_notification_ = true; | |
463 // Disallow redirect notification. | |
464 HostFunctions()->urlredirectresponse(id(), notify_data, false); | |
465 | |
466 // Now start a request that we will allow to redirect. | |
467 HostFunctions()->geturlnotify( | |
468 id(), REDIRECT_SRC_URL, NULL, | |
469 reinterpret_cast<void*>(REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID)); | |
470 } | |
471 } else if (stream_id == REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID) { | |
472 received_url_redirect_allow_notification_ = true; | |
473 HostFunctions()->urlredirectresponse(id(), notify_data, true); | |
474 } | |
475 } | |
476 | |
477 } // namespace NPAPIClient | |
OLD | NEW |