1 // Copyright (c) 2010 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_test.h" 6 7 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_util.h" 9 #include "content/test/plugin/npapi_constants.h" 10 11 namespace NPAPIClient { 12 13 PluginTest::PluginTest(NPP id, NPNetscapeFuncs *host_functions) { 14 id_ = id; 15 id_->pdata = this; 16 host_functions_ = host_functions; 17 test_completed_ = false; 18 } 19 20 PluginTest::~PluginTest() {} 21 22 bool PluginTest::IsWindowless() const { return false; } 23 24 NPError PluginTest::New(uint16 mode, int16 argc, const char* argn[], 25 const char* argv[], NPSavedData* saved) { 26 test_name_ = this->GetArgValue("name", argc, argn, argv); 27 const char* id = this->GetArgValue("id", argc, argn, argv); 28 if (id) // NULL for NP_FULL 29 test_id_ = id; 30 return NPERR_NO_ERROR; 31 } 32 33 NPError PluginTest::Destroy() { 34 return NPERR_NO_ERROR; 35 } 36 37 NPError PluginTest::SetWindow(NPWindow* pNPWindow) { 38 return NPERR_NO_ERROR; 39 } 40 41 // It's a shame I have to implement URLEncode. But, using webkit's 42 // or using chrome's means a ball of string of dlls and dependencies that 43 // is very very long. After spending far too much time on it, 44 // I'll just encode it myself. Too bad Microsoft doesn't implement 45 // this in a reusable way either. Both webkit and chrome will 46 // end up using libicu, which is a string of dependencies we don't 47 // want. 48 49 inline unsigned char toHex(const unsigned char x) { 50 return x > 9 ? (x + 'A' - 10) : (x + '0'); 51 } 52 53 std::string URLEncode(const std::string &sIn) { 54 std::string sOut; 55 56 const size_t length = sIn.length(); 57 for (size_t idx = 0; idx < length;) { 58 const char ch = sIn.at(idx); 59 if (isalnum(ch)) { 60 sOut.append(1, ch); 61 } else if (isspace(ch) && ((ch != '\n') && (ch != '\r'))) { 62 sOut.append(1, '+'); 63 } else { 64 sOut.append(1, '%'); 65 sOut.append(1, toHex(ch>>4)); 66 sOut.append(1, toHex(ch%16)); 67 } 68 idx++; 69 } 70 return sOut; 71 } 72 73 void PluginTest::SignalTestCompleted() { 74 NPObject *window_obj = NULL; 75 host_functions_->getvalue(id_, NPNVWindowNPObject, &window_obj); 76 if (!window_obj) 77 return; 78 79 test_completed_ = true; 80 // To signal test completion, we expect a couple of 81 // javascript functions to be defined in the webpage 82 // which hosts this plugin: 83 // onSuccess(test_name, test_id) 84 // onFailure(test_name, test_id, error_message) 85 std::string script("javascript:"); 86 if (Succeeded()) { 87 script.append("onSuccess(\""); 88 script.append(test_name_); 89 script.append("\",\""); 90 script.append(test_id_); 91 script.append("\");"); 92 } else { 93 script.append("onFailure(\""); 94 script.append(test_name_); 95 script.append("\",\""); 96 script.append(test_id_); 97 script.append("\",\""); 98 script.append(test_status_); 99 script.append("\");"); 100 } 101 102 NPString script_string; 103 script_string.UTF8Characters = script.c_str(); 104 script_string.UTF8Length = static_cast<unsigned int>(script.length()); 105 106 NPVariant result_var; 107 host_functions_->evaluate(id_, window_obj, &script_string, &result_var); 108 } 109 110 const char *PluginTest::GetArgValue(const char *name, const int16 argc, 111 const char *argn[], const char *argv[]) { 112 for (int idx = 0; idx < argc; idx++) 113 if (base::strcasecmp(argn[idx], name) == 0) 114 return argv[idx]; 115 return NULL; 116 } 117 118 void PluginTest::SetError(const std::string &msg) { 119 test_status_.append(msg); 120 } 121 122 void PluginTest::ExpectStringLowerCaseEqual(const std::string &val1, 123 const std::string &val2) { 124 if (!LowerCaseEqualsASCII(val1, val2.c_str())) { 125 std::string err; 126 err = "Expected Equal for '"; 127 err.append(val1); 128 err.append("' and '"); 129 err.append(val2); 130 err.append("'"); 131 SetError(err); 132 } 133 } 134 135 void PluginTest::ExpectAsciiStringNotEqual(const char *val1, const char *val2) { 136 if (val1 == val2) { 137 std::string err; 138 err = "Expected Not Equal for '"; 139 err.append(val1); 140 err.append("' and '"); 141 err.append(val2); 142 err.append("'"); 143 SetError(err); 144 } 145 } 146 147 void PluginTest::ExpectIntegerEqual(int val1, int val2) { 148 if (val1 != val2) { 149 std::string err; 150 err = "Expected Equal for '"; 151 err.append(base::IntToString(val1)); 152 err.append("' and '"); 153 err.append(base::IntToString(val2)); 154 err.append("'"); 155 SetError(err); 156 } 157 } 158 159 NPError PluginTest::NewStream(NPMIMEType type, NPStream* stream, 160 NPBool seekable, uint16* stype) { 161 // There is no default action here. 162 return NPERR_NO_ERROR; 163 } 164 165 int32 PluginTest::WriteReady(NPStream *stream) { 166 // Take data in small chunks 167 return 4096; 168 } 169 170 int32 PluginTest::Write(NPStream *stream, int32 offset, int32 len, 171 void *buffer) { 172 // Pretend that we took all the data. 173 return len; 174 } 175 176 NPError PluginTest::DestroyStream(NPStream *stream, NPError reason) { 177 // There is no default action. 178 return NPERR_NO_ERROR; 179 } 180 181 void PluginTest::StreamAsFile(NPStream* stream, const char* fname) { 182 // There is no default action. 183 } 184 185 void PluginTest::URLNotify(const char* url, NPReason reason, void* data) { 186 // There is no default action 187 } 188 189 int16 PluginTest::HandleEvent(void* event) { 190 // There is no default action 191 return 0; 192 } 193 194 void PluginTest::URLRedirectNotify(const char* url, int32_t status, 195 void* notify_data) { 196 // There is no default action 197 } 198 199 } // namespace NPAPIClient 200