Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(305)

Side by Side Diff: ppapi/tests/test_message_handler.cc

Issue 605593002: PPAPI: Support sending browser-hosted resources synchronously Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix content_browsertests Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ppapi/tests/test_message_handler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/tests/test_message_handler.h" 5 #include "ppapi/tests/test_message_handler.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <map> 9 #include <map>
10 #include <sstream> 10 #include <sstream>
11 #include <vector>
11 12
12 #include "ppapi/c/pp_var.h" 13 #include "ppapi/c/pp_var.h"
13 #include "ppapi/c/ppb_file_io.h" 14 #include "ppapi/c/ppb_file_io.h"
14 #include "ppapi/c/ppb_messaging.h" 15 #include "ppapi/c/ppb_messaging.h"
15 #include "ppapi/c/ppp_message_handler.h" 16 #include "ppapi/c/ppp_message_handler.h"
16 #include "ppapi/cpp/completion_callback.h" 17 #include "ppapi/cpp/completion_callback.h"
17 #include "ppapi/cpp/file_io.h" 18 #include "ppapi/cpp/file_io.h"
18 #include "ppapi/cpp/file_ref.h" 19 #include "ppapi/cpp/file_ref.h"
19 #include "ppapi/cpp/file_system.h" 20 #include "ppapi/cpp/file_system.h"
20 #include "ppapi/cpp/instance.h" 21 #include "ppapi/cpp/instance.h"
(...skipping 16 matching lines...) Expand all
37 38
38 REGISTER_TEST_CASE(MessageHandler); 39 REGISTER_TEST_CASE(MessageHandler);
39 40
40 namespace { 41 namespace {
41 42
42 // Created and destroyed on the main thread. All public methods should be called 43 // Created and destroyed on the main thread. All public methods should be called
43 // on the main thread. Most data members are only accessed on the main thread. 44 // on the main thread. Most data members are only accessed on the main thread.
44 // (Though it handles messages on the background thread). 45 // (Though it handles messages on the background thread).
45 class MyMessageHandler : public pp::MessageHandler { 46 class MyMessageHandler : public pp::MessageHandler {
46 public: 47 public:
47 explicit MyMessageHandler(TestingInstance* instance, 48 MyMessageHandler(TestingInstance* instance, const pp::MessageLoop& loop)
48 const pp::MessageLoop& loop)
49 : testing_instance_(instance), 49 : testing_instance_(instance),
50 message_handler_loop_(loop), 50 message_handler_loop_(loop),
51 is_registered_(false), 51 is_registered_(false),
52 test_finished_event_(instance->pp_instance()), 52 test_finished_event_(instance->pp_instance()),
53 destroy_event_(instance->pp_instance()), 53 destroy_event_(instance->pp_instance()),
54 async_message_received_(instance->pp_instance()) { 54 finished_message_received_(instance->pp_instance()) {
55 AssertOnMainThread(); 55 AssertOnMainThread();
56 } 56 }
57 void Register() { 57 void Register() {
58 AssertOnMainThread(); 58 AssertOnMainThread();
59 assert(!is_registered_); 59 assert(!is_registered_);
60 int32_t result = 60 int32_t result =
61 testing_instance_->RegisterMessageHandler(this, message_handler_loop_); 61 testing_instance_->RegisterMessageHandler(this, message_handler_loop_);
62 if (result == PP_OK) { 62 if (result == PP_OK) {
63 is_registered_ = true; 63 is_registered_ = true;
64 } else { 64 } else {
(...skipping 24 matching lines...) Expand all
89 assert(!is_registered_); 89 assert(!is_registered_);
90 destroy_event_.Wait(); 90 destroy_event_.Wait();
91 destroy_event_.Reset(); 91 destroy_event_.Reset();
92 // Now that we know Destroy() has been called, we know errors_ isn't being 92 // Now that we know Destroy() has been called, we know errors_ isn't being
93 // written on the MessageHandler thread anymore. So we can safely read it 93 // written on the MessageHandler thread anymore. So we can safely read it
94 // here on the main thread (since destroy_event_ gave us a memory barrier). 94 // here on the main thread (since destroy_event_ gave us a memory barrier).
95 std::string temp_errors; 95 std::string temp_errors;
96 errors_.swap(temp_errors); 96 errors_.swap(temp_errors);
97 return temp_errors; 97 return temp_errors;
98 } 98 }
99 pp::Var WaitForAsyncMessage() { 99 void WaitForAsyncMessages(std::vector<pp::Var>* out_vec) {
100 async_message_received_.Wait(); 100 finished_message_received_.Wait();
101 pp::Var var_to_return = last_async_message_received_; 101 out_vec->swap(async_messages_received_);
102 last_async_message_received_ = pp::Var(); 102 finished_message_received_.Reset();
103 async_message_received_.Reset();
104 return var_to_return;
105 } 103 }
106 private: 104 private:
107 static void AssertOnMainThread() { 105 static void AssertOnMainThread() {
108 assert(pp::MessageLoop::GetForMainThread() == 106 assert(pp::MessageLoop::GetForMainThread() ==
109 pp::MessageLoop::GetCurrent()); 107 pp::MessageLoop::GetCurrent());
110 } 108 }
111 void AddError(const std::string& error) { 109 void AddError(const std::string& error) {
112 if (!error.empty()) { 110 if (!error.empty()) {
113 if (!errors_.empty()) 111 if (!errors_.empty())
114 errors_ += "<p>"; 112 errors_ += "<p>";
115 errors_ += error; 113 errors_ += error;
116 } 114 }
117 } 115 }
118 virtual void HandleMessage(pp::InstanceHandle instance, const pp::Var& var) { 116 virtual void HandleMessage(pp::InstanceHandle instance, const pp::Var& var) {
119 if (pp::MessageLoop::GetCurrent() != message_handler_loop_) 117 if (pp::MessageLoop::GetCurrent() != message_handler_loop_)
120 AddError("HandleMessage was called on the wrong thread!"); 118 AddError("HandleMessage was called on the wrong thread!");
121 if (instance.pp_instance() != testing_instance_->pp_instance()) 119 if (instance.pp_instance() != testing_instance_->pp_instance())
122 AddError("HandleMessage was passed the wrong instance!"); 120 AddError("HandleMessage was passed the wrong instance!");
123 if (var.is_string() && var.AsString() == "FINISHED_TEST") { 121 if (var.is_string() && var.AsString() == "FINISHED_TEST") {
124 test_finished_event_.Signal(); 122 test_finished_event_.Signal();
123 } else if (var.is_string() && var.AsString() == "FINISHED_WAITING") {
124 finished_message_received_.Signal();
125 } else { 125 } else {
126 // Any client causing a message to arrive must wait for the message 126 async_messages_received_.push_back(var);
127 // before continuing. See WaitForAsyncMessage().
128 assert(last_async_message_received_.is_undefined());
129 last_async_message_received_ = var;
130 async_message_received_.Signal();
131 } 127 }
132 } 128 }
133 129
134 virtual pp::Var HandleBlockingMessage(pp::InstanceHandle instance, 130 virtual pp::Var HandleBlockingMessage(pp::InstanceHandle instance,
135 const pp::Var& var) { 131 const pp::Var& var) {
136 if (pp::MessageLoop::GetCurrent() != message_handler_loop_) 132 if (pp::MessageLoop::GetCurrent() != message_handler_loop_)
137 AddError("HandleBlockingMessage was called on the wrong thread!"); 133 AddError("HandleBlockingMessage was called on the wrong thread!");
138 if (instance.pp_instance() != testing_instance_->pp_instance()) 134 if (instance.pp_instance() != testing_instance_->pp_instance())
139 AddError("HandleBlockingMessage was passed the wrong instance!"); 135 AddError("HandleBlockingMessage was passed the wrong instance!");
140 136
(...skipping 30 matching lines...) Expand all
171 // is_registered_ is only read/written on the main thread. 167 // is_registered_ is only read/written on the main thread.
172 bool is_registered_; 168 bool is_registered_;
173 169
174 // errors_ is written on the MessageHandler thread. When Destroy() is 170 // errors_ is written on the MessageHandler thread. When Destroy() is
175 // called, we stop writing to errors_ and signal destroy_event_. This causes 171 // called, we stop writing to errors_ and signal destroy_event_. This causes
176 // a memory barrier, so it's safe to read errors_ after that. 172 // a memory barrier, so it's safe to read errors_ after that.
177 std::string errors_; 173 std::string errors_;
178 NestedEvent test_finished_event_; 174 NestedEvent test_finished_event_;
179 NestedEvent destroy_event_; 175 NestedEvent destroy_event_;
180 176
181 pp::Var last_async_message_received_; 177 std::vector<pp::Var> async_messages_received_;
182 NestedEvent async_message_received_; 178 NestedEvent finished_message_received_;
183 179
184 // Undefined & private to disallow copy and assign. 180 // Undefined & private to disallow copy and assign.
185 MyMessageHandler(const MyMessageHandler&); 181 MyMessageHandler(const MyMessageHandler&);
186 MyMessageHandler& operator=(const MyMessageHandler&); 182 MyMessageHandler& operator=(const MyMessageHandler&);
187 }; 183 };
188 184
189 void FakeHandleMessage(PP_Instance instance, 185 void FakeHandleMessage(PP_Instance instance,
190 void* user_data, 186 void* user_data,
191 const PP_Var* message_data) {} 187 const PP_Var* message_data) {}
192 void FakeHandleBlockingMessage(PP_Instance instance, 188 void FakeHandleBlockingMessage(PP_Instance instance,
(...skipping 20 matching lines...) Expand all
213 pp::Module::Get()->GetBrowserInterface(PPB_MESSAGING_INTERFACE_1_2)); 209 pp::Module::Get()->GetBrowserInterface(PPB_MESSAGING_INTERFACE_1_2));
214 return ppb_messaging_if_ && 210 return ppb_messaging_if_ &&
215 CheckTestingInterface() && 211 CheckTestingInterface() &&
216 handler_thread_.Start(); 212 handler_thread_.Start();
217 } 213 }
218 214
219 void TestMessageHandler::RunTests(const std::string& filter) { 215 void TestMessageHandler::RunTests(const std::string& filter) {
220 RUN_TEST(RegisterErrorConditions, filter); 216 RUN_TEST(RegisterErrorConditions, filter);
221 RUN_TEST(PostMessageAndAwaitResponse, filter); 217 RUN_TEST(PostMessageAndAwaitResponse, filter);
222 RUN_TEST(Exceptions, filter); 218 RUN_TEST(Exceptions, filter);
219 RUN_TEST(BrowserHostedResources, filter);
223 } 220 }
224 221
225 void TestMessageHandler::HandleMessage(const pp::Var& message_data) { 222 void TestMessageHandler::HandleMessage(const pp::Var& message_data) {
226 if (instance()->current_test_name() == "Exceptions") { 223 if (instance()->current_test_name() == "Exceptions") {
227 // For TestPostMessageAndAwaitResponse(), all messages should go to the 224 // For TestPostMessageAndAwaitResponse(), all messages should go to the
228 // background thread message handler. 225 // background thread message handler.
229 assert(false); 226 assert(false);
230 } else { 227 } else {
231 // Any subtest causing a message to arrive here must wait for it before 228 // Any subtest causing a message to arrive here must wait for it before
232 // continuing. See WaitForMessage(). 229 // continuing. See WaitForMessage().
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 handler.Unregister(); 296 handler.Unregister();
300 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy()); 297 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy());
301 298
302 PASS(); 299 PASS();
303 } 300 }
304 301
305 std::string TestMessageHandler::TestExceptions() { 302 std::string TestMessageHandler::TestExceptions() {
306 MyMessageHandler handler(instance(), 303 MyMessageHandler handler(instance(),
307 handler_thread_.message_loop()); 304 handler_thread_.message_loop());
308 { 305 {
309 // First, try sending a blocking message when there is no handler 306 // First try sending a blocking message when there is no handler
310 // registered. It should throw an exception. 307 // registered. It should throw an exception.
311 std::string js_code( 308 std::string js_code(
312 "var plugin = document.getElementById('plugin');\n" 309 "var plugin = document.getElementById('plugin');\n"
313 "var caught_exception = false;\n" 310 "var caught_exception = false;\n"
314 "try {\n" 311 "try {\n"
315 " plugin.postMessageAndAwaitResponse('Hello!');\n" 312 " plugin.postMessageAndAwaitResponse('Hello!');\n"
316 "} catch (err) {\n" 313 "} catch (err) {\n"
317 " caught_exception = true;\n" 314 " caught_exception = true;\n"
318 "}\n" 315 "}\n"
319 "plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n"); 316 "plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n");
320 instance_->EvalScript(js_code); 317 instance_->EvalScript(js_code);
321 // Note that we want to wait for the Instance to get the SUCCESS/FAIL 318 // Note that we want to wait for the Instance to get the SUCCESS/FAIL
322 // message here. |message_handler| is not yet registered, so the message 319 // message here. |message_handler| is not yet registered, so the message
323 // goes to the instance instead. 320 // goes to the instance instead.
324 pp::Var msg = WaitForMessage(); 321 pp::Var msg = WaitForMessage();
325 ASSERT_TRUE(msg.is_string()); 322 ASSERT_TRUE(msg.is_string());
326 ASSERT_EQ("SUCCESS", msg.AsString()); 323 ASSERT_EQ("SUCCESS", msg.AsString());
327 } 324 }
328 handler.Register(); 325 handler.Register();
329 { 326 {
330 // Now that a handler is registered, try requesting and sending a 327 // Try passing different numbers of arguments; only 1 argument is allowed.
331 // FileSystem. It should throw an exception. The file system is opened 328 // Other numbers should throw an exception.
332 // asynchronously. What *should* happen is that it opens successfully, then 329 std::string js_code(
333 // we try to send it via postMessageAndAwaitResponse, which fails with an 330 "var plugin = document.getElementById('plugin');\n"
334 // exception. The test could fail either because the filesystem doesn't 331 "var caught_exception = false;\n"
335 // open or because postMessageAndAwaitResponse doesn't throw an exception. 332 "try {\n"
333 " plugin.postMessageAndAwaitResponse();\n"
334 "} catch (err) {\n"
335 " caught_exception = true;\n"
336 "}\n"
337 "plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n"
338 "try {\n"
339 " plugin.postMessageAndAwaitResponse('hello', 5);\n"
340 "} catch (err) {\n"
341 " caught_exception = true;\n"
342 "}\n"
343 "plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n"
344 "plugin.postMessage('FINISHED_WAITING');\n");
345 instance_->EvalScript(js_code);
346 std::vector<pp::Var> messages;
347 handler.WaitForAsyncMessages(&messages);
348 ASSERT_EQ(2u, messages.size());
349 ASSERT_EQ("SUCCESS", messages[0].AsString());
350 ASSERT_EQ("SUCCESS", messages[1].AsString());
351 }
352 handler.Unregister();
353 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy());
354
355 PASS();
356 }
357
358 std::string TestMessageHandler::TestBrowserHostedResources() {
359 MyMessageHandler handler(instance(),
360 handler_thread_.message_loop());
361 handler.Register();
362 {
363 // Try requesting and sending a FileSystem. It should throw an exception.
364 // The file system is opened asynchronously. Once it opens successfully,
365 // then we send it via postMessage and postMessageAndAwaitResponse. We try
366 // both to make sure that the ordering is correct.
336 std::string js_code( 367 std::string js_code(
337 "var plugin = document.getElementById('plugin');\n" 368 "var plugin = document.getElementById('plugin');\n"
338 "function gotFileSystem(fs) {\n" 369 "function gotFileSystem(fs) {\n"
339 " var caught_exception = false;\n" 370 " var caught_exception = false;\n"
340 " try {\n" 371 " try {\n"
341 " plugin.postMessageAndAwaitResponse(fs);\n" 372 " plugin.postMessage(fs);"
373 " plugin.postMessage(fs);"
374 " plugin.postMessage(fs);"
375 " plugin.postMessage(fs);"
376 " var result = plugin.postMessageAndAwaitResponse(fs);\n"
342 " } catch (err) {\n" 377 " } catch (err) {\n"
343 " caught_exception = true;\n" 378 " caught_exception = true;\n"
344 " }\n" 379 " }\n" //TODO(dmichael): Really test that the filesystem is right
345 " plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n" 380 // ...and FileRef?
381 " plugin.postMessage(result.toString() == fs.toString() ?"
382 " 'SUCCESS' : result.toString());\n"
383 " plugin.postMessage('FINISHED_WAITING');\n"
346 "}\n" 384 "}\n"
347 "function fileSystemError() {\n" 385 "function fileSystemError() {\n"
348 " plugin.postMessage('Failed to open filesystem');\n" 386 " plugin.postMessage('Failed to open filesystem');\n"
349 "}\n" 387 "}\n"
350 "window.webkitRequestFileSystem(\n" 388 "window.webkitRequestFileSystem(\n"
351 " window.Temporary, 1024, gotFileSystem, fileSystemError)\n"); 389 " window.Temporary, 1024, gotFileSystem, fileSystemError)\n");
352 instance_->EvalScript(js_code); 390 instance_->EvalScript(js_code);
353 pp::Var msg = handler.WaitForAsyncMessage(); 391 std::vector<pp::Var> messages;
354 ASSERT_EQ(PP_VARTYPE_STRING, msg.pp_var().type); 392 handler.WaitForAsyncMessages(&messages);
355 ASSERT_EQ("SUCCESS", msg.AsString()); 393 ASSERT_EQ(5u, messages.size());
394 ASSERT_EQ("SUCCESS", messages.back().AsString());
356 } 395 }
357 handler.Unregister(); 396 handler.Unregister();
358 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy()); 397 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy());
359 398
360 PASS(); 399 PASS();
361 } 400 }
362 401
402
363 pp::Var TestMessageHandler::WaitForMessage() { 403 pp::Var TestMessageHandler::WaitForMessage() {
364 message_received_.Wait(); 404 message_received_.Wait();
365 pp::Var var_to_return = last_message_; 405 pp::Var var_to_return = last_message_;
366 last_message_ = pp::Var(); 406 last_message_ = pp::Var();
367 message_received_.Reset(); 407 message_received_.Reset();
368 return var_to_return; 408 return var_to_return;
369 } 409 }
370 410
OLDNEW
« no previous file with comments | « ppapi/tests/test_message_handler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698