OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Native Client 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 "native_client/tests/ppapi_geturl/module.h" |
| 6 |
| 7 #include <stdio.h> |
| 8 #include <stdlib.h> |
| 9 #include <string.h> |
| 10 |
| 11 #include <string> |
| 12 |
| 13 #include "native_client/src/include/nacl_macros.h" |
| 14 #include "native_client/src/include/portability.h" |
| 15 #include "native_client/src/shared/platform/nacl_check.h" |
| 16 #include "native_client/src/untrusted/ppapi/nacl_file.h" |
| 17 #include "native_client/tests/ppapi_geturl/nacl_file_main.h" |
| 18 #include "native_client/tests/ppapi_geturl/url_load_request.h" |
| 19 |
| 20 #include "ppapi/c/pp_completion_callback.h" |
| 21 #include "ppapi/c/pp_errors.h" |
| 22 #include "ppapi/c/pp_var.h" |
| 23 #include "ppapi/c/ppp_instance.h" |
| 24 #include "ppapi/c/ppp_messaging.h" |
| 25 |
| 26 #if !defined(__native_client__) |
| 27 int32_t LoadUrl(PP_Instance /*instance*/, const char* /*url*/, |
| 28 PP_CompletionCallback /*callback*/) { return PP_OK; } |
| 29 #endif |
| 30 |
| 31 namespace { |
| 32 |
| 33 // These constants need to match their corresponding JavaScript values in |
| 34 // ppapi_geturl.html. The JavaScript variables are all upper-case; for example |
| 35 // kTrueStringValue corresponds to TRUE_STRING_VALUE. |
| 36 const char* const kLoadUrlMethodId = "loadUrl"; |
| 37 const char* const kTrueStringValue = "1"; |
| 38 const char* const kFalseStringValue = "0"; |
| 39 static const char kArgumentSeparator = '|'; |
| 40 |
| 41 // A helper function to convert a bool to a string, used when assembling |
| 42 // messages posted back to the browser. |true| is converted to "1", |false| to |
| 43 // "0". |
| 44 const std::string BoolToString(bool bool_value) { |
| 45 return bool_value ? kTrueStringValue : kFalseStringValue; |
| 46 } |
| 47 |
| 48 PPP_Instance instance_interface; |
| 49 PPP_Messaging messaging_interface; |
| 50 Module* singleton_ = NULL; |
| 51 |
| 52 void RunTests(void* user_data) { |
| 53 int* count = reinterpret_cast<int*>(user_data); |
| 54 *count -= 1; |
| 55 if (*count == 0) |
| 56 test_nacl_file(); |
| 57 } |
| 58 } // namespace |
| 59 |
| 60 void HTMLLoaded(void* user_data, int32_t result) { |
| 61 CHECK(PP_OK == result); |
| 62 printf("--- HTMLLoaded() SUCCESS: completion callback got PP_OK\n"); |
| 63 RunTests(user_data); |
| 64 } |
| 65 |
| 66 void RobotLoaded(void* user_data, int32_t result) { |
| 67 CHECK(PP_ERROR_NOACCESS == result); |
| 68 printf("--- RobotLoaded() SUCCESS: unable to LoadUrl on cross-domain\n"); |
| 69 RunTests(user_data); |
| 70 } |
| 71 |
| 72 void NonExistLoaded(void* user_data, int32_t result) { |
| 73 CHECK(PP_ERROR_FAILED == result); |
| 74 printf("--- NonExistLoaded() SUCCESS: callback got PP_ERROR_FAILED\n"); |
| 75 RunTests(user_data); |
| 76 } |
| 77 |
| 78 PP_Bool Instance_DidCreate(PP_Instance pp_instance, |
| 79 uint32_t /*argc*/, |
| 80 const char* /*argn*/[], |
| 81 const char* /*argv*/[]) { |
| 82 printf("--- Instance_DidCreate\n"); |
| 83 int* url_count = new int(3); |
| 84 PP_CompletionCallback html_cb = |
| 85 PP_MakeCompletionCallback(HTMLLoaded, url_count); |
| 86 int32_t result = LoadUrl(pp_instance, "ppapi_geturl_success.html", html_cb); |
| 87 |
| 88 PP_CompletionCallback robot_cb = |
| 89 PP_MakeCompletionCallback(RobotLoaded, url_count); |
| 90 result = LoadUrl(pp_instance, "http://www.google.com/robots.txt", robot_cb); |
| 91 |
| 92 PP_CompletionCallback non_exist_cb = |
| 93 PP_MakeCompletionCallback(NonExistLoaded, url_count); |
| 94 result = LoadUrl(pp_instance, "ppapi_nonexistent_url.html", non_exist_cb); |
| 95 |
| 96 return PP_TRUE; |
| 97 } |
| 98 |
| 99 void Instance_DidDestroy(PP_Instance /*instance*/) { |
| 100 printf("--- Instance_DidDestroy\n"); |
| 101 } |
| 102 |
| 103 void Instance_DidChangeView(PP_Instance /*pp_instance*/, |
| 104 const PP_Rect* /*position*/, |
| 105 const PP_Rect* /*clip*/) { |
| 106 } |
| 107 |
| 108 void Instance_DidChangeFocus(PP_Instance /*pp_instance*/, |
| 109 PP_Bool /*has_focus*/) { |
| 110 } |
| 111 |
| 112 PP_Bool Instance_HandleDocumentLoad(PP_Instance /*pp_instance*/, |
| 113 PP_Resource /*pp_url_loader*/) { |
| 114 return PP_FALSE; |
| 115 } |
| 116 |
| 117 void Messaging_HandleMessage(PP_Instance instance, struct PP_Var var_message) { |
| 118 if (var_message.type != PP_VARTYPE_STRING) |
| 119 return; |
| 120 std::string message = Module::Get()->VarToStr(var_message); |
| 121 printf("--- Messaging_HandleMessage(%s)\n", message.c_str()); |
| 122 // Look for the "loadUrl" message. The expected string format looks like: |
| 123 // loadUrl|<url>|<stream_as_file> |
| 124 // loadUrl is a string literal |
| 125 // <url> is the URL used to make the GET request in UrlLoader |
| 126 // <stream_as_file> represent Boolean true if it's a '1' or false if it's |
| 127 // anything else. |
| 128 if (message.find(kLoadUrlMethodId) != 0) |
| 129 return; |
| 130 |
| 131 size_t url_pos = message.find_first_of(kArgumentSeparator); |
| 132 if (url_pos == std::string::npos || url_pos + 1 >= message.length()) |
| 133 return; |
| 134 |
| 135 size_t as_file_pos = message.find_first_of(kArgumentSeparator, url_pos + 1); |
| 136 if (as_file_pos == std::string::npos || as_file_pos + 1 >= message.length()) |
| 137 return; |
| 138 |
| 139 size_t url_length = as_file_pos - url_pos; |
| 140 if (url_length == 0) |
| 141 return; |
| 142 std::string url = message.substr(url_pos + 1, url_length - 1); |
| 143 |
| 144 // If the second argument is a '1', assume it means |stream_as_file| is |
| 145 // true. Anything else means |stream_as_file| is false. |
| 146 bool stream_as_file = message.compare(as_file_pos + 1, |
| 147 1, |
| 148 kTrueStringValue) == 0; |
| 149 |
| 150 printf("--- Messaging_HandleMessage(method='%s', " |
| 151 "url='%s', " |
| 152 "stream_as_file='%s')\n", |
| 153 message.c_str(), |
| 154 url.c_str(), |
| 155 stream_as_file ? "true" : "false"); |
| 156 fflush(stdout); |
| 157 |
| 158 UrlLoadRequest* url_load_request = new UrlLoadRequest(instance); |
| 159 if (NULL == url_load_request) { |
| 160 Module::Get()->ReportResult(instance, |
| 161 url.c_str(), |
| 162 stream_as_file, |
| 163 "LoadUrl: memory allocation failed", |
| 164 false); |
| 165 return; |
| 166 } |
| 167 // On success or failure url_load_request will call ReportResult(). |
| 168 // This is the time to clean it up. |
| 169 url_load_request->set_delete_this_after_report(); |
| 170 url_load_request->Load(stream_as_file, url); |
| 171 } |
| 172 |
| 173 Module* Module::Create(PP_Module module_id, |
| 174 PPB_GetInterface get_browser_interface) { |
| 175 if (NULL == singleton_) { |
| 176 singleton_ = new Module(module_id, get_browser_interface); |
| 177 } |
| 178 return singleton_; |
| 179 } |
| 180 |
| 181 Module* Module::Get() { |
| 182 return singleton_; |
| 183 } |
| 184 |
| 185 void Module::Free() { |
| 186 delete singleton_; |
| 187 singleton_ = NULL; |
| 188 } |
| 189 |
| 190 Module::Module(PP_Module module_id, PPB_GetInterface get_browser_interface) |
| 191 : module_id_(module_id), |
| 192 get_browser_interface_(get_browser_interface), |
| 193 ppb_core_interface_(NULL), |
| 194 ppb_messaging_interface_(NULL), |
| 195 ppb_var_interface_(NULL) { |
| 196 printf("--- Module::Module\n"); |
| 197 memset(&instance_interface, 0, sizeof(instance_interface)); |
| 198 instance_interface.DidCreate = Instance_DidCreate; |
| 199 instance_interface.DidDestroy = Instance_DidDestroy; |
| 200 instance_interface.DidChangeView = Instance_DidChangeView; |
| 201 instance_interface.DidChangeFocus = Instance_DidChangeFocus; |
| 202 instance_interface.HandleDocumentLoad = Instance_HandleDocumentLoad; |
| 203 |
| 204 memset(&messaging_interface, 0, sizeof(messaging_interface)); |
| 205 messaging_interface.HandleMessage = Messaging_HandleMessage; |
| 206 |
| 207 ppb_core_interface_ = |
| 208 static_cast<const PPB_Core*>( |
| 209 GetBrowserInterface(PPB_CORE_INTERFACE)); |
| 210 ppb_messaging_interface_ = |
| 211 static_cast<const PPB_Messaging*>( |
| 212 GetBrowserInterface(PPB_MESSAGING_INTERFACE)); |
| 213 ppb_var_interface_ = |
| 214 static_cast<const PPB_Var*>( |
| 215 GetBrowserInterface(PPB_VAR_INTERFACE)); |
| 216 } |
| 217 |
| 218 const void* Module::GetPluginInterface(const char* interface_name) { |
| 219 printf("--- Module::GetPluginInterface(%s)\n", interface_name); |
| 220 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) |
| 221 return &instance_interface; |
| 222 if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) |
| 223 return &messaging_interface; |
| 224 return NULL; |
| 225 } |
| 226 |
| 227 const void* Module::GetBrowserInterface(const char* interface_name) { |
| 228 if (NULL == get_browser_interface_) |
| 229 return NULL; |
| 230 return (*get_browser_interface_)(interface_name); |
| 231 } |
| 232 |
| 233 char* Module::VarToCStr(const PP_Var& var) { |
| 234 Module* module = Get(); |
| 235 if (NULL == module) |
| 236 return NULL; |
| 237 const PPB_Var* ppb_var = module->ppb_var_interface(); |
| 238 if (NULL == ppb_var) |
| 239 return NULL; |
| 240 uint32_t len = 0; |
| 241 const char* pp_str = ppb_var->VarToUtf8(var, &len); |
| 242 if (NULL == pp_str) |
| 243 return NULL; |
| 244 char* str = static_cast<char*>(malloc(len + 1)); |
| 245 if (NULL == str) |
| 246 return NULL; |
| 247 memcpy(str, pp_str, len); |
| 248 str[len] = 0; |
| 249 return str; |
| 250 } |
| 251 |
| 252 std::string Module::VarToStr(const PP_Var& var) { |
| 253 std::string str; |
| 254 char* cstr = VarToCStr(var); |
| 255 if (NULL != cstr) { |
| 256 str = cstr; |
| 257 free(cstr); |
| 258 } |
| 259 return str; |
| 260 } |
| 261 |
| 262 PP_Var Module::StrToVar(const char* str) { |
| 263 Module* module = Get(); |
| 264 if (NULL == module) |
| 265 return PP_MakeUndefined(); |
| 266 const PPB_Var* ppb_var = module->ppb_var_interface(); |
| 267 if (NULL != ppb_var) |
| 268 return ppb_var->VarFromUtf8(module->module_id(), str, strlen(str)); |
| 269 return PP_MakeUndefined(); |
| 270 } |
| 271 |
| 272 PP_Var Module::StrToVar(const std::string& str) { |
| 273 return Module::StrToVar(str.c_str()); |
| 274 } |
| 275 |
| 276 std::string Module::ErrorCodeToStr(int32_t error_code) { |
| 277 switch (error_code) { |
| 278 case PP_OK: return "PP_OK"; |
| 279 case PP_OK_COMPLETIONPENDING: return "PP_OK_COMPLETIONPENDING"; |
| 280 case PP_ERROR_FAILED: return "PP_ERROR_FAILED"; |
| 281 case PP_ERROR_ABORTED: return "PP_ERROR_ABORTED"; |
| 282 case PP_ERROR_BADARGUMENT: return "PP_ERROR_BADARGUMENT"; |
| 283 case PP_ERROR_BADRESOURCE: return "PP_ERROR_BADRESOURCE"; |
| 284 case PP_ERROR_NOINTERFACE: return "PP_ERROR_NOINTERFACE"; |
| 285 case PP_ERROR_NOACCESS: return "PP_ERROR_NOACCESS"; |
| 286 case PP_ERROR_NOMEMORY: return "PP_ERROR_NOMEMORY"; |
| 287 case PP_ERROR_NOSPACE: return "PP_ERROR_NOSPACE"; |
| 288 case PP_ERROR_NOQUOTA: return "PP_ERROR_NOQUOTA"; |
| 289 case PP_ERROR_INPROGRESS: return "PP_ERROR_INPROGRESS"; |
| 290 case PP_ERROR_FILENOTFOUND: return "PP_ERROR_FILENOTFOUND"; |
| 291 case PP_ERROR_FILEEXISTS: return "PP_ERROR_FILEEXISTS"; |
| 292 case PP_ERROR_FILETOOBIG: return "PP_ERROR_FILETOOBIG"; |
| 293 case PP_ERROR_FILECHANGED: return "PP_ERROR_FILECHANGED"; |
| 294 case PP_ERROR_TIMEDOUT: return "PP_ERROR_TIMEDOUT"; |
| 295 } |
| 296 return "N/A"; |
| 297 } |
| 298 |
| 299 void Module::ReportResult(PP_Instance pp_instance, |
| 300 const char* url, |
| 301 bool as_file, |
| 302 const char* text, |
| 303 bool success) { |
| 304 printf("--- ReportResult('%s', as_file=%d, '%s', success=%d)\n", |
| 305 url, as_file, text, success); |
| 306 // Post a message with the results back to the browser. |
| 307 std::string result(url); |
| 308 result += kArgumentSeparator; |
| 309 result += BoolToString(as_file); |
| 310 result += kArgumentSeparator; |
| 311 result += text; |
| 312 result += kArgumentSeparator; |
| 313 result += BoolToString(success); |
| 314 printf("--- ReportResult posts result string:\n\t%s\n", result.c_str()); |
| 315 struct PP_Var var_result = StrToVar(result); |
| 316 ppb_messaging_interface()->PostMessage(pp_instance, var_result); |
| 317 // If the message was created using VarFromUtf8() it needs to be released. |
| 318 // See the comments about VarFromUtf8() in ppapi/c/ppb_var.h for more |
| 319 // information. |
| 320 if (var_result.type == PP_VARTYPE_STRING) { |
| 321 ppb_var_interface()->Release(var_result); |
| 322 } |
| 323 } |
OLD | NEW |