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.
5 #include "content/test/plugin/plugin_geturl_test.h"
9 #include "base/basictypes.h"
10 #include "base/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"
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+\"\""
19 // The identifier for the self url stream.
20 #define SELF_URL_STREAM_ID 1
22 // The identifier for the fetched url stream.
23 #define FETCHED_URL_STREAM_ID 2
25 // url for testing GetURL with a bogus URL.
26 #define BOGUS_URL "bogoproto:///x:/asdf.xysdhffieasdf.asdhj/"
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"
32 // The notification id for the redirect notification url that we will cancel.
33 #define REDIRECT_SRC_URL_NOTIFICATION_CANCEL_ID 4
35 // The notification id for the redirect notification url that we will accept.
36 #define REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID 5
38 // The identifier for the bogus url stream.
39 #define BOGUS_URL_STREAM_ID 3
41 // The maximum chunk size of stream data.
42 #define STREAM_CHUNK 197
44 namespace NPAPIClient
{
46 PluginGetURLTest::PluginGetURLTest(NPP id
, NPNetscapeFuncs
*host_functions
)
47 : PluginTest(id
, host_functions
),
48 tests_started_(false),
49 tests_in_progress_(0),
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) {
59 PluginGetURLTest::~PluginGetURLTest() {}
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
,
65 if (page_not_found_url
) {
66 page_not_found_url_
= page_not_found_url
;
67 expect_404_response_
= true;
70 const char* fail_write_url
= GetArgValue("fail_write_url", argc
,
73 fail_write_url_
= fail_write_url
;
76 const char* referrer_target_url
= GetArgValue("ref_target", argc
,
78 if (referrer_target_url
) {
79 referrer_target_url_
= referrer_target_url
;
82 if (!base::strcasecmp(GetArgValue("name", argc
, argn
, argv
),
83 "geturlredirectnotify")) {
84 handle_url_redirects_
= true;
87 NPError error
= PluginTest::New(mode
, argc
, argn
, argv
, saved
);
89 // The above sets test_name().
90 if (test_name() == "cookies")
91 check_cookies_
= true;
96 NPError
PluginGetURLTest::SetWindow(NPWindow
* pNPWindow
) {
97 #if !defined(OS_MACOSX)
98 if (pNPWindow
->window
== NULL
)
99 return NPERR_NO_ERROR
;
102 if (!tests_started_
) {
103 tests_started_
= true;
105 tests_in_progress_
++;
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(
126 "plugin_ref_target_page.html",
128 reinterpret_cast<void*>(SELF_URL_STREAM_ID
));
129 return NPERR_NO_ERROR
;
132 std::string url
= SELF_URL
;
133 HostFunctions()->geturlnotify(id(), url
.c_str(), NULL
,
134 reinterpret_cast<void*>(SELF_URL_STREAM_ID
));
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
));
141 return NPERR_NO_ERROR
;
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
;
151 if (test_completed()) {
152 return PluginTest::NewStream(type
, stream
, seekable
, stype
);
155 if (!referrer_target_url_
.empty()) {
156 return NPERR_NO_ERROR
;
159 COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream
->notifyData
),
160 cast_validity_check
);
162 if (expect_404_response_
) {
163 NPObject
*window_obj
= NULL
;
164 HostFunctions()->getvalue(id(), NPNVWindowNPObject
, &window_obj
);
166 SetError("Failed to get NPObject for plugin instance2");
167 SignalTestCompleted();
168 return NPERR_NO_ERROR
;
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
;
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
;
183 if (!fail_write_url_
.empty() || check_cookies_
) {
184 return NPERR_NO_ERROR
;
188 unsigned long stream_id
= reinterpret_cast<unsigned long>(
192 case SELF_URL_STREAM_ID
:
194 case FETCHED_URL_STREAM_ID
:
196 std::string filename
= self_url_
;
197 if (filename
.find("file:///", 0) != 0) {
198 SetError("Test expects a file-url.");
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
207 filename
= filename
.substr(8); // remove "file:///"
208 // Assume an ASCII path on Windows.
209 base::FilePath path
= base::FilePath(base::ASCIIToWide(filename
));
211 filename
= filename
.substr(7); // remove "file://"
212 base::FilePath path
= base::FilePath(filename
);
215 test_file_
= base::OpenFile(path
, "r");
217 SetError("Could not open source file");
221 case BOGUS_URL_STREAM_ID
:
222 SetError("Unexpected NewStream for BOGUS_URL");
224 case REDIRECT_SRC_URL_NOTIFICATION_CANCEL_ID
:
225 SetError("Should not redirect to URL when plugin denied it.");
227 case REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID
:
230 SetError("Unexpected NewStream callback");
233 return NPERR_NO_ERROR
;
236 int32
PluginGetURLTest::WriteReady(NPStream
*stream
) {
237 if (test_completed()) {
238 return PluginTest::WriteReady(stream
);
241 if (!referrer_target_url_
.empty() || check_cookies_
) {
245 COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream
->notifyData
),
246 cast_validity_check
);
247 unsigned long stream_id
= reinterpret_cast<unsigned long>(
249 if (stream_id
== BOGUS_URL_STREAM_ID
)
250 SetError("Received WriteReady for BOGUS_URL");
255 int32
PluginGetURLTest::Write(NPStream
*stream
, int32 offset
, int32 len
,
257 if (test_completed()) {
258 return PluginTest::Write(stream
, offset
, len
, buffer
);
261 if (!fail_write_url_
.empty()) {
262 SignalTestCompleted();
266 if (!referrer_target_url_
.empty() || check_cookies_
) {
270 if (stream
== NULL
) {
271 SetError("Write got null stream");
274 if (len
< 0 || len
> STREAM_CHUNK
) {
275 SetError("Write got bogus stream chunk size");
279 COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream
->notifyData
),
280 cast_validity_check
);
281 unsigned long stream_id
= reinterpret_cast<unsigned long>(
284 case SELF_URL_STREAM_ID
:
285 self_url_
.append(static_cast<char*>(buffer
), len
);
287 case FETCHED_URL_STREAM_ID
:
289 char read_buffer
[STREAM_CHUNK
];
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.
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!");
300 case BOGUS_URL_STREAM_ID
:
301 SetError("Unexpected write callback for BOGUS_URL");
303 case REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID
:
306 SetError("Unexpected write callback");
309 // Pretend that we took all the data.
314 NPError
PluginGetURLTest::DestroyStream(NPStream
*stream
, NPError reason
) {
315 if (test_completed()) {
316 return PluginTest::DestroyStream(stream
, reason
);
319 if (stream
== NULL
) {
320 SetError("NewStream got null stream");
321 return NPERR_INVALID_PARAM
;
324 COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream
->notifyData
),
325 cast_validity_check
);
327 if (expect_404_response_
) {
328 if (npn_evaluate_context_
) {
329 SetError("Received destroyStream in the context of NPN_Evaluate.");
332 SignalTestCompleted();
333 return NPERR_NO_ERROR
;
336 if (!referrer_target_url_
.empty()) {
337 return NPERR_NO_ERROR
;
340 if (check_cookies_
) {
341 SignalTestCompleted();
342 return NPERR_NO_ERROR
;
345 unsigned long stream_id
=
346 reinterpret_cast<unsigned long>(stream
->notifyData
);
348 case SELF_URL_STREAM_ID
:
351 case REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID
:
353 case FETCHED_URL_STREAM_ID
:
355 char read_buffer
[STREAM_CHUNK
];
356 size_t bytes
= fread(read_buffer
, 1, sizeof(read_buffer
), test_file_
);
358 SetError("Data and source mismatch on length");
359 base::CloseFile(test_file_
);
363 SetError("Unexpected NewStream callback");
366 return NPERR_NO_ERROR
;
369 void PluginGetURLTest::StreamAsFile(NPStream
* stream
, const char* fname
) {
370 if (stream
== NULL
) {
371 SetError("NewStream got null stream");
375 COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream
->notifyData
),
376 cast_validity_check
);
377 unsigned long stream_id
=
378 reinterpret_cast<unsigned long>(stream
->notifyData
);
380 case SELF_URL_STREAM_ID
:
384 SetError("Unexpected NewStream callback");
389 void PluginGetURLTest::URLNotify(const char* url
, NPReason reason
, void* data
) {
390 if (!tests_in_progress_
) {
391 SetError("URLNotify received after tests completed");
396 SetError("URLNotify received NULL url");
403 COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(data
), cast_validity_check
);
404 unsigned long stream_id
= reinterpret_cast<unsigned long>(data
);
406 case SELF_URL_STREAM_ID
:
407 if (strcmp(url
, SELF_URL
) != 0)
408 SetError("URLNotify reported incorrect url for SELF_URL");
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
));
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_
--;
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
));
425 tests_in_progress_
--;
427 case REDIRECT_SRC_URL_NOTIFICATION_CANCEL_ID
: {
428 if (!received_url_redirect_cancel_notification_
) {
429 SetError("Failed to receive URLRedirect notification for cancel");
431 if (reason
!= NPRES_NETWORK_ERR
) {
432 SetError("Redirected URL didn't get canceled");
436 case REDIRECT_SRC_URL_NOTIFICATION_ALLOW_ID
: {
437 if (!received_url_redirect_allow_notification_
) {
438 SetError("Failed to receive URLRedirect notification for allow");
440 if (reason
!= NPRES_DONE
) {
441 SetError("Redirected URL didn't complete successfully");
443 tests_in_progress_
--;
447 SetError("Unexpected NewStream callback");
451 if (tests_in_progress_
== 0)
452 SignalTestCompleted();
455 void PluginGetURLTest::URLRedirectNotify(const char* url
,
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);
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
));
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);
477 } // namespace NPAPIClient