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