15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/test/plugin/plugin_test.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/test/plugin/npapi_constants.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace NPAPIClient {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginTest::PluginTest(NPP id, NPNetscapeFuncs *host_functions) {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id_ = id;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id_->pdata = this;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host_functions_ = host_functions;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_completed_ = false;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginTest::~PluginTest() {}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginTest::IsWindowless() const { return false; }
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPError PluginTest::New(uint16 mode, int16 argc, const char* argn[],
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const char* argv[], NPSavedData* saved) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_name_ = this->GetArgValue("name", argc, argn, argv);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* id = this->GetArgValue("id", argc, argn, argv);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id)  // NULL for NP_FULL
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_id_ = id;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NPERR_NO_ERROR;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPError PluginTest::Destroy() {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NPERR_NO_ERROR;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPError PluginTest::SetWindow(NPWindow* pNPWindow) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NPERR_NO_ERROR;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It's a shame I have to implement URLEncode.  But, using webkit's
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or using chrome's means a ball of string of dlls and dependencies that
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is very very long.  After spending far too much time on it,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// I'll just encode it myself.  Too bad Microsoft doesn't implement
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this in a reusable way either.  Both webkit and chrome will
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// end up using libicu, which is a string of dependencies we don't
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// want.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline unsigned char toHex(const unsigned char x) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return x > 9 ? (x + 'A' - 10) : (x + '0');
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string URLEncode(const std::string &sIn) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sOut;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t length = sIn.length();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t idx = 0; idx < length;) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char ch = sIn.at(idx);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (isalnum(ch)) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sOut.append(1, ch);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (isspace(ch) && ((ch != '\n') && (ch != '\r'))) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sOut.append(1, '+');
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sOut.append(1, '%');
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sOut.append(1, toHex(ch>>4));
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sOut.append(1, toHex(ch%16));
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    idx++;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sOut;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginTest::SignalTestCompleted() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObject *window_obj = NULL;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host_functions_->getvalue(id_, NPNVWindowNPObject, &window_obj);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!window_obj)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_completed_ = true;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // To signal test completion, we expect a couple of
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // javascript functions to be defined in the webpage
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which hosts this plugin:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    onSuccess(test_name, test_id)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    onFailure(test_name, test_id, error_message)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string script("javascript:");
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (Succeeded()) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append("onSuccess(\"");
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append(test_name_);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append("\",\"");
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append(test_id_);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append("\");");
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append("onFailure(\"");
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append(test_name_);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append("\",\"");
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append(test_id_);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append("\",\"");
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append(test_status_);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script.append("\");");
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPString script_string;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  script_string.UTF8Characters = script.c_str();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  script_string.UTF8Length = static_cast<unsigned int>(script.length());
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPVariant result_var;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host_functions_->evaluate(id_, window_obj, &script_string, &result_var);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char *PluginTest::GetArgValue(const char *name, const int16 argc,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const char *argn[], const char *argv[]) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int idx = 0; idx < argc; idx++)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (base::strcasecmp(argn[idx], name) == 0)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return argv[idx];
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginTest::SetError(const std::string &msg) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_status_.append(msg);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginTest::ExpectStringLowerCaseEqual(const std::string &val1,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const std::string &val2) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!LowerCaseEqualsASCII(val1, val2.c_str())) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string err;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = "Expected Equal for '";
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append(val1);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append("' and '");
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append(val2);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append("'");
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetError(err);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginTest::ExpectAsciiStringNotEqual(const char *val1, const char *val2) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (val1 == val2) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string err;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = "Expected Not Equal for '";
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append(val1);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append("' and '");
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append(val2);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append("'");
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetError(err);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginTest::ExpectIntegerEqual(int val1, int val2) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (val1 != val2) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string err;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = "Expected Equal for '";
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append(base::IntToString(val1));
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append("' and '");
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append(base::IntToString(val2));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err.append("'");
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetError(err);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPError PluginTest::NewStream(NPMIMEType type, NPStream* stream,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              NPBool seekable, uint16* stype) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no default action here.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NPERR_NO_ERROR;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32 PluginTest::WriteReady(NPStream *stream) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Take data in small chunks
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 4096;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32 PluginTest::Write(NPStream *stream, int32 offset, int32 len,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           void *buffer) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pretend that we took all the data.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return len;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPError PluginTest::DestroyStream(NPStream *stream, NPError reason) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no default action.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NPERR_NO_ERROR;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginTest::StreamAsFile(NPStream* stream, const char* fname) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no default action.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginTest::URLNotify(const char* url, NPReason reason, void* data) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no default action
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int16 PluginTest::HandleEvent(void* event) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no default action
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginTest::URLRedirectNotify(const char* url, int32_t status,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   void* notify_data) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no default action
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace NPAPIClient
200