OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 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 "base/file_util.h" | 5 #include "base/file_util.h" |
6 #include "base/json/json_reader.h" | 6 #include "base/json/json_reader.h" |
| 7 #include "base/json/json_writer.h" |
7 #include "base/path_service.h" | 8 #include "base/path_service.h" |
8 #include "base/string_util.h" | 9 #include "base/string_util.h" |
9 #include "chrome/common/chrome_paths.h" | 10 #include "chrome/common/chrome_paths.h" |
10 #include "chrome/common/render_messages.h" | 11 #include "chrome/common/render_messages.h" |
11 #include "chrome/renderer/extensions/extension_process_bindings.h" | 12 #include "chrome/renderer/extensions/extension_process_bindings.h" |
12 #include "chrome/renderer/extensions/renderer_extension_bindings.h" | 13 #include "chrome/renderer/extensions/renderer_extension_bindings.h" |
13 #include "chrome/test/render_view_test.h" | 14 #include "chrome/test/render_view_test.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
15 | 16 |
| 17 // Make failures easier to locate by using SCOPED_TRACE() to print out the line |
| 18 // number of a failing call to ExtensionAPIClientTest::ExpectJs(Pass|Fail) . |
| 19 // Sadly, a #define is the only reasonable way to get the line number. |
| 20 #define ExpectJsFail(js, expected_failure_message) { \ |
| 21 SCOPED_TRACE(js); \ |
| 22 ExpectJsFailInternal(js, expected_failure_message); \ |
| 23 } |
| 24 |
| 25 #define ExpectJsPass(js, function, arg1) { \ |
| 26 SCOPED_TRACE(js); \ |
| 27 ExpectJsPassInternal(js, function, arg1); \ |
| 28 } |
| 29 |
16 class ExtensionAPIClientTest : public RenderViewTest { | 30 class ExtensionAPIClientTest : public RenderViewTest { |
17 protected: | 31 protected: |
18 virtual void SetUp() { | 32 virtual void SetUp() { |
19 RenderViewTest::SetUp(); | 33 RenderViewTest::SetUp(); |
20 | 34 |
21 render_thread_.sink().ClearMessages(); | 35 render_thread_.sink().ClearMessages(); |
22 LoadHTML("<body></body>"); | 36 LoadHTML("<body></body>"); |
23 } | 37 } |
24 | 38 |
25 std::string GetConsoleMessage() { | 39 std::string GetConsoleMessage() { |
26 const IPC::Message* message = | 40 const IPC::Message* message = |
27 render_thread_.sink().GetUniqueMessageMatching( | 41 render_thread_.sink().GetUniqueMessageMatching( |
28 ViewHostMsg_AddMessageToConsole::ID); | 42 ViewHostMsg_AddMessageToConsole::ID); |
29 ViewHostMsg_AddMessageToConsole::Param params; | 43 ViewHostMsg_AddMessageToConsole::Param params; |
30 if (message) { | 44 if (message) { |
31 ViewHostMsg_AddMessageToConsole::Read(message, ¶ms); | 45 ViewHostMsg_AddMessageToConsole::Read(message, ¶ms); |
32 render_thread_.sink().ClearMessages(); | 46 render_thread_.sink().ClearMessages(); |
33 return WideToASCII(params.a); | 47 return WideToASCII(params.a); |
34 } else { | 48 } else { |
35 return ""; | 49 return ""; |
36 } | 50 } |
37 } | 51 } |
38 | 52 |
39 void ExpectJsFail(const std::string& js, const std::string& message) { | 53 // Don't call this directly. Use the macro ExpectJsFail. |
| 54 void ExpectJsFailInternal(const std::string& js, const std::string& message) { |
40 ExecuteJavaScript(js.c_str()); | 55 ExecuteJavaScript(js.c_str()); |
41 EXPECT_EQ(message, GetConsoleMessage()); | 56 EXPECT_EQ(message, GetConsoleMessage()); |
42 render_thread_.sink().ClearMessages(); | 57 render_thread_.sink().ClearMessages(); |
43 } | 58 } |
44 | 59 |
45 void ExpectJsPass(const std::string& js, | 60 // Don't call this directly. Use the macro ExpectJsPass. |
46 const std::string& function, | 61 void ExpectJsPassInternal(const std::string& js, |
47 const std::string& arg1) { | 62 const std::string& function, |
| 63 const std::string& arg1) { |
48 ExecuteJavaScript(js.c_str()); | 64 ExecuteJavaScript(js.c_str()); |
49 const IPC::Message* request_msg = | 65 const IPC::Message* request_msg = |
50 render_thread_.sink().GetUniqueMessageMatching( | 66 render_thread_.sink().GetUniqueMessageMatching( |
51 ViewHostMsg_ExtensionRequest::ID); | 67 ViewHostMsg_ExtensionRequest::ID); |
52 ASSERT_EQ("", GetConsoleMessage()) << js; | 68 ASSERT_EQ("", GetConsoleMessage()) << js; |
53 ASSERT_TRUE(request_msg) << js; | 69 ASSERT_TRUE(request_msg) << js; |
54 ViewHostMsg_ExtensionRequest::Param params; | 70 ViewHostMsg_ExtensionRequest::Param params; |
55 ViewHostMsg_ExtensionRequest::Read(request_msg, ¶ms); | 71 ViewHostMsg_ExtensionRequest::Read(request_msg, ¶ms); |
56 ASSERT_EQ(function.c_str(), params.a) << js; | 72 ASSERT_EQ(function.c_str(), params.a) << js; |
57 | 73 |
58 Value* args = NULL; | 74 Value* args = NULL; |
59 ASSERT_TRUE(params.b.IsType(Value::TYPE_LIST)); | 75 ASSERT_TRUE(params.b.IsType(Value::TYPE_LIST)); |
60 ASSERT_TRUE(static_cast<const ListValue*>(¶ms.b)->Get(0, &args)); | 76 ASSERT_TRUE(static_cast<const ListValue*>(¶ms.b)->Get(0, &args)); |
61 | 77 |
62 base::JSONReader reader; | 78 base::JSONReader reader; |
63 scoped_ptr<Value> arg1_value(reader.JsonToValue(arg1, false, false)); | 79 scoped_ptr<Value> arg1_value(reader.JsonToValue(arg1, false, false)); |
64 ASSERT_TRUE(args->Equals(arg1_value.get())) << js; | 80 ASSERT_TRUE(arg1_value.get()) |
| 81 << "Failed to parse expected result as JSON: " << arg1; |
| 82 |
| 83 std::string args_as_string; |
| 84 base::JSONWriter::Write(args, false, &args_as_string); |
| 85 |
| 86 ASSERT_TRUE(args->Equals(arg1_value.get())) |
| 87 << js |
| 88 << "\n Expected "<< arg1 |
| 89 << "\n Actual: "<< args_as_string; |
65 render_thread_.sink().ClearMessages(); | 90 render_thread_.sink().ClearMessages(); |
66 } | 91 } |
67 }; | 92 }; |
68 | 93 |
69 // Tests that callback dispatching works correctly and that JSON is properly | 94 // Tests that callback dispatching works correctly and that JSON is properly |
70 // deserialized before handing off to the extension code. We use the createTab | 95 // deserialized before handing off to the extension code. We use the createTab |
71 // API here, but we could use any of them since they all dispatch callbacks the | 96 // API here, but we could use any of them since they all dispatch callbacks the |
72 // same way. | 97 // same way. |
73 TEST_F(ExtensionAPIClientTest, CallbackDispatching) { | 98 TEST_F(ExtensionAPIClientTest, CallbackDispatching) { |
74 ExecuteJavaScript( | 99 ExecuteJavaScript( |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 | 455 |
431 ExpectJsPass("chrome.tabs.remove(2, function(){})", | 456 ExpectJsPass("chrome.tabs.remove(2, function(){})", |
432 "tabs.remove", "2"); | 457 "tabs.remove", "2"); |
433 | 458 |
434 ExpectJsPass("chrome.tabs.remove(2)", | 459 ExpectJsPass("chrome.tabs.remove(2)", |
435 "tabs.remove", "2"); | 460 "tabs.remove", "2"); |
436 } | 461 } |
437 | 462 |
438 TEST_F(ExtensionAPIClientTest, CaptureVisibleTab) { | 463 TEST_F(ExtensionAPIClientTest, CaptureVisibleTab) { |
439 ExpectJsFail("chrome.tabs.captureVisibleTab(0);", | 464 ExpectJsFail("chrome.tabs.captureVisibleTab(0);", |
440 "Uncaught Error: Parameter 1 is required."); | 465 "Uncaught Error: Parameter 2 is required."); |
| 466 |
| 467 ExpectJsFail("chrome.tabs.captureVisibleTab(0, null);", |
| 468 "Uncaught Error: Parameter 2 is required."); |
| 469 |
| 470 ExpectJsFail("chrome.tabs.captureVisibleTab(null, {});", |
| 471 "Uncaught Error: Parameter 2 is required."); |
441 | 472 |
442 ExpectJsFail("chrome.tabs.captureVisibleTab(function(){}, 0)", | 473 ExpectJsFail("chrome.tabs.captureVisibleTab(function(){}, 0)", |
443 "Uncaught Error: Invalid value for argument 0. " | 474 "Uncaught Error: Invalid value for argument 0. " |
444 "Expected 'integer' but got 'function'."); | 475 "Expected 'integer' but got 'function'."); |
445 | 476 |
446 ExpectJsPass("chrome.tabs.captureVisibleTab(null, function(img){});", | 477 // Use old signiture. Check that a null value of the options paramenter |
447 "tabs.captureVisibleTab", "null"); | 478 // is added. |
| 479 ExpectJsPass("chrome.tabs.captureVisibleTab(null, function(img){});", |
| 480 "tabs.captureVisibleTab", "[null, null]"); |
| 481 |
| 482 ExpectJsPass("chrome.tabs.captureVisibleTab(1, function(img){});", |
| 483 "tabs.captureVisibleTab", "[1, null]"); |
| 484 |
| 485 ExpectJsPass("chrome.tabs.captureVisibleTab(null, null, function(img){});", |
| 486 "tabs.captureVisibleTab", "[null, null]"); |
| 487 |
| 488 ExpectJsPass("chrome.tabs.captureVisibleTab(" |
| 489 "null, undefined, function(img){});", |
| 490 "tabs.captureVisibleTab", "[null, null]"); |
| 491 |
| 492 ExpectJsPass("chrome.tabs.captureVisibleTab(null, {}, function(img){});", |
| 493 "tabs.captureVisibleTab", "[null, {}]"); |
| 494 |
| 495 ExpectJsFail("chrome.tabs.captureVisibleTab(null, 42, function(img){});", |
| 496 "Uncaught Error: Invalid value for argument 1. " |
| 497 "Expected 'object' but got 'integer'."); |
| 498 |
| 499 ExpectJsPass("chrome.tabs.captureVisibleTab(" |
| 500 "null, {\"format\": \"jpeg\"}, function(img){});", |
| 501 "tabs.captureVisibleTab", "[null, {\"format\": \"jpeg\"}]"); |
| 502 |
| 503 ExpectJsPass("chrome.tabs.captureVisibleTab(" |
| 504 "null, {\"quality\": 100}, function(img){});", |
| 505 "tabs.captureVisibleTab", "[null, {\"quality\": 100}]"); |
| 506 |
| 507 ExpectJsFail("chrome.tabs.captureVisibleTab(" |
| 508 "null, {\"quality\": 101}, function(img){});", |
| 509 "Uncaught Error: Invalid value for argument 1. " |
| 510 "Property 'quality': Value must not be greater than 100."); |
| 511 |
| 512 ExpectJsFail("chrome.tabs.captureVisibleTab(" |
| 513 "null, {'not_a_param': 'jpeg'}, function(img){});", |
| 514 "Uncaught Error: Invalid value for argument 1. " |
| 515 "Property 'not_a_param': Unexpected property."); |
| 516 |
| 517 ExpectJsFail("chrome.tabs.captureVisibleTab(" |
| 518 "null, {'format': 'invalid'}, function(img){});", |
| 519 "Uncaught Error: Invalid value for argument 1. " |
| 520 "Property 'format': Value must be one of: [jpeg, png]."); |
| 521 |
| 522 ExpectJsFail("chrome.tabs.captureVisibleTab(" |
| 523 "null, {'format': 42}, function(img){});", |
| 524 "Uncaught Error: Invalid value for argument 1. " |
| 525 "Property 'format': Value must be one of: [jpeg, png]."); |
448 } | 526 } |
449 | 527 |
450 // Bookmark API tests | 528 // Bookmark API tests |
451 // TODO(erikkay) add more variations here | 529 // TODO(erikkay) add more variations here |
452 | 530 |
453 TEST_F(ExtensionAPIClientTest, CreateBookmark) { | 531 TEST_F(ExtensionAPIClientTest, CreateBookmark) { |
454 ExpectJsFail( | 532 ExpectJsFail( |
455 "chrome.bookmarks.create({parentId:0, title:0}, function(){})", | 533 "chrome.bookmarks.create({parentId:0, title:0}, function(){})", |
456 "Uncaught Error: Invalid value for argument 0. " | 534 "Uncaught Error: Invalid value for argument 0. " |
457 "Property 'parentId': Expected 'string' but got 'integer', " | 535 "Property 'parentId': Expected 'string' but got 'integer', " |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 | 708 |
631 ExpectJsFail("chrome.i18n.getMessage('name', [])", | 709 ExpectJsFail("chrome.i18n.getMessage('name', [])", |
632 "Uncaught Error: Invalid value for argument 1. Value does not " | 710 "Uncaught Error: Invalid value for argument 1. Value does not " |
633 "match any valid type choices."); | 711 "match any valid type choices."); |
634 | 712 |
635 ExpectJsFail("chrome.i18n.getMessage('name', ['p1', 'p2', 'p3', 'p4', 'p5', " | 713 ExpectJsFail("chrome.i18n.getMessage('name', ['p1', 'p2', 'p3', 'p4', 'p5', " |
636 "'p6', 'p7', 'p8', 'p9', 'p10'])", | 714 "'p6', 'p7', 'p8', 'p9', 'p10'])", |
637 "Uncaught Error: Invalid value for argument 1. Value does not " | 715 "Uncaught Error: Invalid value for argument 1. Value does not " |
638 "match any valid type choices."); | 716 "match any valid type choices."); |
639 } | 717 } |
OLD | NEW |