OLD | NEW |
| (Empty) |
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 "base/file_util.h" | |
6 #include "base/json/json_reader.h" | |
7 #include "base/json/json_writer.h" | |
8 #include "base/path_service.h" | |
9 #include "base/string_util.h" | |
10 #include "chrome/common/chrome_paths.h" | |
11 #include "chrome/common/render_messages.h" | |
12 #include "chrome/renderer/extensions/extension_process_bindings.h" | |
13 #include "chrome/renderer/extensions/renderer_extension_bindings.h" | |
14 #include "chrome/test/render_view_test.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
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 | |
30 class ExtensionAPIClientTest : public RenderViewTest { | |
31 protected: | |
32 virtual void SetUp() { | |
33 RenderViewTest::SetUp(); | |
34 | |
35 render_thread_.SetExtensionProcess(true); | |
36 render_thread_.sink().ClearMessages(); | |
37 LoadHTML("<body></body>"); | |
38 } | |
39 | |
40 std::string GetConsoleMessage() { | |
41 const IPC::Message* message = | |
42 render_thread_.sink().GetUniqueMessageMatching( | |
43 ViewHostMsg_AddMessageToConsole::ID); | |
44 ViewHostMsg_AddMessageToConsole::Param params; | |
45 if (message) { | |
46 ViewHostMsg_AddMessageToConsole::Read(message, ¶ms); | |
47 render_thread_.sink().ClearMessages(); | |
48 return WideToASCII(params.a); | |
49 } else { | |
50 return ""; | |
51 } | |
52 } | |
53 | |
54 // Don't call this directly. Use the macro ExpectJsFail. | |
55 void ExpectJsFailInternal(const std::string& js, const std::string& message) { | |
56 ExecuteJavaScript(js.c_str()); | |
57 EXPECT_EQ(message, GetConsoleMessage()); | |
58 render_thread_.sink().ClearMessages(); | |
59 } | |
60 | |
61 // Don't call this directly. Use the macro ExpectJsPass. | |
62 void ExpectJsPassInternal(const std::string& js, | |
63 const std::string& function, | |
64 const std::string& arg1) { | |
65 ExecuteJavaScript(js.c_str()); | |
66 const IPC::Message* request_msg = | |
67 render_thread_.sink().GetUniqueMessageMatching( | |
68 ViewHostMsg_ExtensionRequest::ID); | |
69 ASSERT_EQ("", GetConsoleMessage()) << js; | |
70 ASSERT_TRUE(request_msg) << js; | |
71 ViewHostMsg_ExtensionRequest::Param params; | |
72 ViewHostMsg_ExtensionRequest::Read(request_msg, ¶ms); | |
73 ASSERT_EQ(function.c_str(), params.a) << js; | |
74 | |
75 ASSERT_TRUE(params.b.IsType(Value::TYPE_LIST)); | |
76 ListValue* args = ¶ms.b; | |
77 | |
78 base::JSONReader reader; | |
79 scoped_ptr<Value> arg1_value(reader.JsonToValue(arg1, false, false)); | |
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; | |
90 render_thread_.sink().ClearMessages(); | |
91 } | |
92 }; | |
93 | |
94 // Tests that callback dispatching works correctly and that JSON is properly | |
95 // deserialized before handing off to the extension code. We use the createTab | |
96 // API here, but we could use any of them since they all dispatch callbacks the | |
97 // same way. | |
98 TEST_F(ExtensionAPIClientTest, CallbackDispatching) { | |
99 ExecuteJavaScript( | |
100 "function assert(truth, message) {" | |
101 " if (!truth) {" | |
102 " throw new Error(message);" | |
103 " }" | |
104 "}" | |
105 "function callback(result) {" | |
106 " assert(typeof result == 'object', 'result not object');" | |
107 " assert(JSON.stringify(result) == '{\"id\":1,\"index\":1,\"windowId\":1," | |
108 "\"selected\":true,\"incognito\":false," | |
109 "\"url\":\"http://www.google.com/\"}'," | |
110 " 'incorrect result');" | |
111 " console.log('pass')" | |
112 "}" | |
113 "chrome.tabs.create({}, callback);" | |
114 ); | |
115 | |
116 EXPECT_EQ("", GetConsoleMessage()); | |
117 | |
118 // Ok, we should have gotten a message to create a tab, grab the callback ID. | |
119 const IPC::Message* request_msg = | |
120 render_thread_.sink().GetUniqueMessageMatching( | |
121 ViewHostMsg_ExtensionRequest::ID); | |
122 ASSERT_TRUE(request_msg); | |
123 ViewHostMsg_ExtensionRequest::Param params; | |
124 ViewHostMsg_ExtensionRequest::Read(request_msg, ¶ms); | |
125 int callback_id = params.d; | |
126 ASSERT_GE(callback_id, 0); | |
127 | |
128 // Now send the callback a response | |
129 ExtensionProcessBindings::HandleResponse( | |
130 callback_id, true, "{\"id\":1,\"index\":1,\"windowId\":1,\"selected\":true," | |
131 "\"incognito\":false,\"url\":\"http://www.google.com/\"}", ""); | |
132 | |
133 // And verify that it worked | |
134 ASSERT_EQ("pass", GetConsoleMessage()); | |
135 } | |
136 | |
137 // The remainder of these tests exercise the client side of the various | |
138 // extension functions. We test both error and success conditions, but do not | |
139 // test errors exhaustively as json schema code is well tested by itself. | |
140 | |
141 // Window API tests | |
142 | |
143 TEST_F(ExtensionAPIClientTest, GetWindow) { | |
144 ExpectJsFail("chrome.windows.get(32, function(){}, 20);", | |
145 "Uncaught Error: Too many arguments."); | |
146 | |
147 ExpectJsFail("chrome.windows.get(32);", | |
148 "Uncaught Error: Parameter 1 is required."); | |
149 | |
150 ExpectJsFail("chrome.windows.get('abc', function(){});", | |
151 "Uncaught Error: Invalid value for argument 0. " | |
152 "Expected 'integer' but got 'string'."); | |
153 | |
154 ExpectJsFail("chrome.windows.get(1, 1);", | |
155 "Uncaught Error: Invalid value for argument 1. " | |
156 "Expected 'function' but got 'integer'."); | |
157 | |
158 ExpectJsPass("chrome.windows.get(2, function(){})", | |
159 "windows.get", "[2]"); | |
160 } | |
161 | |
162 // This test flakily crashes (http://crbug.com/22248) | |
163 TEST_F(ExtensionAPIClientTest, DISABLED_GetCurrentWindow) { | |
164 ExpectJsFail("chrome.windows.getCurrent(function(){}, 20);", | |
165 "Uncaught Error: Too many arguments."); | |
166 | |
167 ExpectJsFail("chrome.windows.getCurrent();", | |
168 "Uncaught Error: Parameter 0 is required."); | |
169 | |
170 ExpectJsFail("chrome.windows.getCurrent('abc');", | |
171 "Uncaught Error: Invalid value for argument 0. " | |
172 "Expected 'function' but got 'string'."); | |
173 | |
174 ExpectJsPass("chrome.windows.getCurrent(function(){})", | |
175 "windows.getCurrent", "null"); | |
176 } | |
177 | |
178 // This test flakily crashes (http://crbug.com/22248) | |
179 TEST_F(ExtensionAPIClientTest, DISABLED_GetLastFocusedWindow) { | |
180 ExpectJsFail("chrome.windows.getLastFocused(function(){}, 20);", | |
181 "Uncaught Error: Too many arguments."); | |
182 | |
183 ExpectJsFail("chrome.windows.getLastFocused();", | |
184 "Uncaught Error: Parameter 0 is required."); | |
185 | |
186 ExpectJsFail("chrome.windows.getLastFocused('abc');", | |
187 "Uncaught Error: Invalid value for argument 0. " | |
188 "Expected 'function' but got 'string'."); | |
189 | |
190 ExpectJsPass("chrome.windows.getLastFocused(function(){})", | |
191 "windows.getLastFocused", "null"); | |
192 } | |
193 | |
194 // This test flakily crashes (http://crbug.com/22248) | |
195 TEST_F(ExtensionAPIClientTest, DISABLED_GetAllWindows) { | |
196 ExpectJsFail("chrome.windows.getAll({populate: true}, function(){}, 20);", | |
197 "Uncaught Error: Too many arguments."); | |
198 | |
199 ExpectJsFail("chrome.windows.getAll(1, function(){});", | |
200 "Uncaught Error: Invalid value for argument 0. " | |
201 "Expected 'object' but got 'integer'."); | |
202 | |
203 ExpectJsPass("chrome.windows.getAll({populate:true}, function(){})", | |
204 "windows.getAll", "{\"populate\":true}"); | |
205 | |
206 ExpectJsPass("chrome.windows.getAll(null, function(){})", | |
207 "windows.getAll", "null"); | |
208 | |
209 ExpectJsPass("chrome.windows.getAll({}, function(){})", | |
210 "windows.getAll", "{}"); | |
211 | |
212 ExpectJsPass("chrome.windows.getAll(undefined, function(){})", | |
213 "windows.getAll", "null"); | |
214 } | |
215 | |
216 // Flaky on Windows. http://crosbug.com/46217 | |
217 #if defined(OS_WIN) | |
218 #define MAYBE_CreateWindow FLAKY_CreateWindow | |
219 #else | |
220 #define MAYBE_CreateWindow CreateWindow | |
221 #endif | |
222 TEST_F(ExtensionAPIClientTest, MAYBE_CreateWindow) { | |
223 ExpectJsFail("chrome.windows.create({url: 1}, function(){});", | |
224 "Uncaught Error: Invalid value for argument 0. Property " | |
225 "'url': Expected 'string' but got 'integer'."); | |
226 ExpectJsFail("chrome.windows.create({left: 'foo'}, function(){});", | |
227 "Uncaught Error: Invalid value for argument 0. Property " | |
228 "'left': Expected 'integer' but got 'string'."); | |
229 ExpectJsFail("chrome.windows.create({top: 'foo'}, function(){});", | |
230 "Uncaught Error: Invalid value for argument 0. Property " | |
231 "'top': Expected 'integer' but got 'string'."); | |
232 ExpectJsFail("chrome.windows.create({width: 'foo'}, function(){});", | |
233 "Uncaught Error: Invalid value for argument 0. Property " | |
234 "'width': Expected 'integer' but got 'string'."); | |
235 ExpectJsFail("chrome.windows.create({height: 'foo'}, function(){});", | |
236 "Uncaught Error: Invalid value for argument 0. Property " | |
237 "'height': Expected 'integer' but got 'string'."); | |
238 ExpectJsFail("chrome.windows.create({foo: 42}, function(){});", | |
239 "Uncaught Error: Invalid value for argument 0. Property " | |
240 "'foo': Unexpected property."); | |
241 | |
242 ExpectJsPass("chrome.windows.create({" | |
243 " url:'http://www.google.com/'," | |
244 " left:0," | |
245 " top: 10," | |
246 " width:100," | |
247 " height:200" | |
248 "})", | |
249 "windows.create", | |
250 "[{\"url\":\"http://www.google.com/\"," | |
251 "\"left\":0," | |
252 "\"top\":10," | |
253 "\"width\":100," | |
254 "\"height\":200}]"); | |
255 } | |
256 | |
257 TEST_F(ExtensionAPIClientTest, UpdateWindow) { | |
258 ExpectJsFail("chrome.windows.update(null);", | |
259 "Uncaught Error: Parameter 0 is required."); | |
260 ExpectJsFail("chrome.windows.update(42, {left: 'foo'});", | |
261 "Uncaught Error: Invalid value for argument 1. Property " | |
262 "'left': Expected 'integer' but got 'string'."); | |
263 ExpectJsFail("chrome.windows.update(42, {top: 'foo'});", | |
264 "Uncaught Error: Invalid value for argument 1. Property " | |
265 "'top': Expected 'integer' but got 'string'."); | |
266 ExpectJsFail("chrome.windows.update(42, {height: false});", | |
267 "Uncaught Error: Invalid value for argument 1. Property " | |
268 "'height': Expected 'integer' but got 'boolean'."); | |
269 ExpectJsFail("chrome.windows.update(42, {width: false});", | |
270 "Uncaught Error: Invalid value for argument 1. Property " | |
271 "'width': Expected 'integer' but got 'boolean'."); | |
272 ExpectJsFail("chrome.windows.update(42, {foo: false});", | |
273 "Uncaught Error: Invalid value for argument 1. Property " | |
274 "'foo': Unexpected property."); | |
275 | |
276 ExpectJsPass("chrome.windows.update(42, {" | |
277 " width:100," | |
278 " height:200" | |
279 "})", | |
280 "windows.update", | |
281 "[42," | |
282 "{\"width\":100," | |
283 "\"height\":200}]"); | |
284 } | |
285 | |
286 TEST_F(ExtensionAPIClientTest, RemoveWindow) { | |
287 ExpectJsFail("chrome.windows.remove(32, function(){}, 20);", | |
288 "Uncaught Error: Too many arguments."); | |
289 | |
290 ExpectJsFail("chrome.windows.remove('abc', function(){});", | |
291 "Uncaught Error: Invalid value for argument 0. " | |
292 "Expected 'integer' but got 'string'."); | |
293 | |
294 ExpectJsFail("chrome.windows.remove(1, 1);", | |
295 "Uncaught Error: Invalid value for argument 1. " | |
296 "Expected 'function' but got 'integer'."); | |
297 | |
298 ExpectJsPass("chrome.windows.remove(2, function(){})", | |
299 "windows.remove", "[2]"); | |
300 | |
301 ExpectJsPass("chrome.windows.remove(2)", | |
302 "windows.remove", "[2]"); | |
303 } | |
304 | |
305 // Tab API tests | |
306 | |
307 TEST_F(ExtensionAPIClientTest, GetTab) { | |
308 ExpectJsFail("chrome.tabs.get(32, function(){}, 20);", | |
309 "Uncaught Error: Too many arguments."); | |
310 | |
311 ExpectJsFail("chrome.tabs.get(32);", | |
312 "Uncaught Error: Parameter 1 is required."); | |
313 | |
314 ExpectJsFail("chrome.tabs.get('abc', function(){});", | |
315 "Uncaught Error: Invalid value for argument 0. " | |
316 "Expected 'integer' but got 'string'."); | |
317 | |
318 ExpectJsFail("chrome.tabs.get(1, 1);", | |
319 "Uncaught Error: Invalid value for argument 1. " | |
320 "Expected 'function' but got 'integer'."); | |
321 | |
322 ExpectJsPass("chrome.tabs.get(2, function(){})", | |
323 "tabs.get", "[2]"); | |
324 } | |
325 | |
326 TEST_F(ExtensionAPIClientTest, GetCurrentTab) { | |
327 ExpectJsFail("chrome.tabs.getCurrent(function(){}, 20);", | |
328 "Uncaught Error: Too many arguments."); | |
329 | |
330 ExpectJsFail("chrome.tabs.getCurrent();", | |
331 "Uncaught Error: Parameter 0 is required."); | |
332 | |
333 ExpectJsFail("chrome.tabs.getCurrent('abc');", | |
334 "Uncaught Error: Invalid value for argument 0. " | |
335 "Expected 'function' but got 'string'."); | |
336 | |
337 ExpectJsPass("chrome.tabs.getCurrent(function(){})", | |
338 "tabs.getCurrent", "[]"); | |
339 } | |
340 | |
341 TEST_F(ExtensionAPIClientTest, DetectTabLanguage) { | |
342 ExpectJsFail("chrome.tabs.detectLanguage(32, function(){}, 20);", | |
343 "Uncaught Error: Too many arguments."); | |
344 | |
345 ExpectJsFail("chrome.tabs.detectLanguage('abc', function(){});", | |
346 "Uncaught Error: Invalid value for argument 0. " | |
347 "Expected 'integer' but got 'string'."); | |
348 | |
349 ExpectJsFail("chrome.tabs.detectLanguage(1, 1);", | |
350 "Uncaught Error: Invalid value for argument 1. " | |
351 "Expected 'function' but got 'integer'."); | |
352 | |
353 ExpectJsPass("chrome.tabs.detectLanguage(null, function(){})", | |
354 "tabs.detectLanguage", "[null]"); | |
355 } | |
356 | |
357 TEST_F(ExtensionAPIClientTest, GetSelectedTab) { | |
358 ExpectJsFail("chrome.tabs.getSelected(32, function(){}, 20);", | |
359 "Uncaught Error: Too many arguments."); | |
360 | |
361 ExpectJsFail("chrome.tabs.getSelected(32);", | |
362 "Uncaught Error: Parameter 1 is required."); | |
363 | |
364 ExpectJsFail("chrome.tabs.getSelected('abc', function(){});", | |
365 "Uncaught Error: Invalid value for argument 0. " | |
366 "Expected 'integer' but got 'string'."); | |
367 | |
368 ExpectJsFail("chrome.tabs.getSelected(1, 1);", | |
369 "Uncaught Error: Invalid value for argument 1. " | |
370 "Expected 'function' but got 'integer'."); | |
371 | |
372 ExpectJsPass("chrome.tabs.getSelected(2, function(){})", | |
373 "tabs.getSelected", "[2]"); | |
374 | |
375 ExpectJsPass("chrome.tabs.getSelected(null, function(){})", | |
376 "tabs.getSelected", "[null]"); | |
377 } | |
378 | |
379 | |
380 TEST_F(ExtensionAPIClientTest, GetAllTabsInWindow) { | |
381 ExpectJsFail("chrome.tabs.getAllInWindow(42, function(){}, 'asd');", | |
382 "Uncaught Error: Too many arguments."); | |
383 | |
384 ExpectJsFail("chrome.tabs.getAllInWindow(32);", | |
385 "Uncaught Error: Parameter 1 is required."); | |
386 | |
387 ExpectJsFail("chrome.tabs.getAllInWindow(1, 1);", | |
388 "Uncaught Error: Invalid value for argument 1. " | |
389 "Expected 'function' but got 'integer'."); | |
390 | |
391 ExpectJsFail("chrome.tabs.getAllInWindow('asd', function(){});", | |
392 "Uncaught Error: Invalid value for argument 0. " | |
393 "Expected 'integer' but got 'string'."); | |
394 | |
395 ExpectJsPass("chrome.tabs.getAllInWindow(32, function(){})", | |
396 "tabs.getAllInWindow", "[32]"); | |
397 | |
398 ExpectJsPass("chrome.tabs.getAllInWindow(undefined, function(){})", | |
399 "tabs.getAllInWindow", "[null]"); | |
400 } | |
401 | |
402 TEST_F(ExtensionAPIClientTest, CreateTab) { | |
403 ExpectJsFail("chrome.tabs.create({windowId: 'foo'}, function(){});", | |
404 "Uncaught Error: Invalid value for argument 0. Property " | |
405 "'windowId': Expected 'integer' but got 'string'."); | |
406 ExpectJsFail("chrome.tabs.create({url: 42}, function(){});", | |
407 "Uncaught Error: Invalid value for argument 0. Property " | |
408 "'url': Expected 'string' but got 'integer'."); | |
409 ExpectJsFail("chrome.tabs.create({foo: 42}, function(){});", | |
410 "Uncaught Error: Invalid value for argument 0. Property " | |
411 "'foo': Unexpected property."); | |
412 | |
413 ExpectJsPass("chrome.tabs.create({" | |
414 " url:'http://www.google.com/'," | |
415 " selected:true," | |
416 " index: 2," | |
417 " windowId:4" | |
418 "})", | |
419 "tabs.create", | |
420 "[{\"url\":\"http://www.google.com/\"," | |
421 "\"selected\":true," | |
422 "\"index\":2," | |
423 "\"windowId\":4}]"); | |
424 } | |
425 | |
426 TEST_F(ExtensionAPIClientTest, UpdateTab) { | |
427 ExpectJsFail("chrome.tabs.update(null);", | |
428 "Uncaught Error: Parameter 0 is required."); | |
429 ExpectJsFail("chrome.tabs.update(42, {selected: 'foo'});", | |
430 "Uncaught Error: Invalid value for argument 1. Property " | |
431 "'selected': Expected 'boolean' but got 'string'."); | |
432 ExpectJsFail("chrome.tabs.update(42, {url: 42});", | |
433 "Uncaught Error: Invalid value for argument 1. Property " | |
434 "'url': Expected 'string' but got 'integer'."); | |
435 | |
436 ExpectJsPass("chrome.tabs.update(42, {" | |
437 " url:'http://www.google.com/'," | |
438 " selected:true" | |
439 "})", | |
440 "tabs.update", | |
441 "[42," | |
442 "{\"url\":\"http://www.google.com/\"," | |
443 "\"selected\":true}]"); | |
444 } | |
445 | |
446 TEST_F(ExtensionAPIClientTest, MoveTab) { | |
447 ExpectJsFail("chrome.tabs.move(null);", | |
448 "Uncaught Error: Parameter 0 is required."); | |
449 ExpectJsFail("chrome.tabs.move(42, {index: 'foo'});", | |
450 "Uncaught Error: Invalid value for argument 1. Property " | |
451 "'index': Expected 'integer' but got 'string'."); | |
452 ExpectJsFail("chrome.tabs.move(42, {index: 3, windowId: 'foo'});", | |
453 "Uncaught Error: Invalid value for argument 1. Property " | |
454 "'windowId': Expected 'integer' but got 'string'."); | |
455 | |
456 ExpectJsPass("chrome.tabs.move(42, {" | |
457 " index:3," | |
458 " windowId:21" | |
459 "})", | |
460 "tabs.move", | |
461 "[42," | |
462 "{\"index\":3," | |
463 "\"windowId\":21}]"); | |
464 } | |
465 | |
466 TEST_F(ExtensionAPIClientTest, RemoveTab) { | |
467 ExpectJsFail("chrome.tabs.remove(32, function(){}, 20);", | |
468 "Uncaught Error: Too many arguments."); | |
469 | |
470 | |
471 ExpectJsFail("chrome.tabs.remove('abc', function(){});", | |
472 "Uncaught Error: Invalid value for argument 0. " | |
473 "Expected 'integer' but got 'string'."); | |
474 | |
475 ExpectJsFail("chrome.tabs.remove(1, 1);", | |
476 "Uncaught Error: Invalid value for argument 1. " | |
477 "Expected 'function' but got 'integer'."); | |
478 | |
479 ExpectJsPass("chrome.tabs.remove(2, function(){})", | |
480 "tabs.remove", "[2]"); | |
481 | |
482 ExpectJsPass("chrome.tabs.remove(2)", | |
483 "tabs.remove", "[2]"); | |
484 } | |
485 | |
486 TEST_F(ExtensionAPIClientTest, CaptureVisibleTab) { | |
487 ExpectJsFail("chrome.tabs.captureVisibleTab(0);", | |
488 "Uncaught Error: Parameter 2 is required."); | |
489 | |
490 ExpectJsFail("chrome.tabs.captureVisibleTab(0, null);", | |
491 "Uncaught Error: Parameter 2 is required."); | |
492 | |
493 ExpectJsFail("chrome.tabs.captureVisibleTab(null, {});", | |
494 "Uncaught Error: Parameter 2 is required."); | |
495 | |
496 ExpectJsFail("chrome.tabs.captureVisibleTab(function(){}, 0)", | |
497 "Uncaught Error: Invalid value for argument 0. " | |
498 "Expected 'integer' but got 'function'."); | |
499 | |
500 // Use old signiture. Check that a null value of the options paramenter | |
501 // is added. | |
502 ExpectJsPass("chrome.tabs.captureVisibleTab(null, function(img){});", | |
503 "tabs.captureVisibleTab", "[null, null]"); | |
504 | |
505 ExpectJsPass("chrome.tabs.captureVisibleTab(1, function(img){});", | |
506 "tabs.captureVisibleTab", "[1, null]"); | |
507 | |
508 ExpectJsPass("chrome.tabs.captureVisibleTab(null, null, function(img){});", | |
509 "tabs.captureVisibleTab", "[null, null]"); | |
510 | |
511 ExpectJsPass("chrome.tabs.captureVisibleTab(" | |
512 "null, undefined, function(img){});", | |
513 "tabs.captureVisibleTab", "[null, null]"); | |
514 | |
515 ExpectJsPass("chrome.tabs.captureVisibleTab(null, {}, function(img){});", | |
516 "tabs.captureVisibleTab", "[null, {}]"); | |
517 | |
518 ExpectJsFail("chrome.tabs.captureVisibleTab(null, 42, function(img){});", | |
519 "Uncaught Error: Invalid value for argument 1. " | |
520 "Expected 'object' but got 'integer'."); | |
521 | |
522 ExpectJsPass("chrome.tabs.captureVisibleTab(" | |
523 "null, {\"format\": \"jpeg\"}, function(img){});", | |
524 "tabs.captureVisibleTab", "[null, {\"format\": \"jpeg\"}]"); | |
525 | |
526 ExpectJsPass("chrome.tabs.captureVisibleTab(" | |
527 "null, {\"quality\": 100}, function(img){});", | |
528 "tabs.captureVisibleTab", "[null, {\"quality\": 100}]"); | |
529 | |
530 ExpectJsFail("chrome.tabs.captureVisibleTab(" | |
531 "null, {\"quality\": 101}, function(img){});", | |
532 "Uncaught Error: Invalid value for argument 1. " | |
533 "Property 'quality': Value must not be greater than 100."); | |
534 | |
535 ExpectJsFail("chrome.tabs.captureVisibleTab(" | |
536 "null, {'not_a_param': 'jpeg'}, function(img){});", | |
537 "Uncaught Error: Invalid value for argument 1. " | |
538 "Property 'not_a_param': Unexpected property."); | |
539 | |
540 ExpectJsFail("chrome.tabs.captureVisibleTab(" | |
541 "null, {'format': 'invalid'}, function(img){});", | |
542 "Uncaught Error: Invalid value for argument 1. " | |
543 "Property 'format': Value must be one of: [jpeg, png]."); | |
544 | |
545 ExpectJsFail("chrome.tabs.captureVisibleTab(" | |
546 "null, {'format': 42}, function(img){});", | |
547 "Uncaught Error: Invalid value for argument 1. " | |
548 "Property 'format': Value must be one of: [jpeg, png]."); | |
549 } | |
550 | |
551 // Bookmark API tests | |
552 // TODO(erikkay) add more variations here | |
553 | |
554 TEST_F(ExtensionAPIClientTest, CreateBookmark) { | |
555 ExpectJsFail( | |
556 "chrome.bookmarks.create({parentId:0, title:0}, function(){})", | |
557 "Uncaught Error: Invalid value for argument 0. " | |
558 "Property 'parentId': Expected 'string' but got 'integer', " | |
559 "Property 'title': Expected 'string' but got 'integer'."); | |
560 | |
561 ExpectJsPass( | |
562 "chrome.bookmarks.create({parentId:'0', title:'x'}, function(){})", | |
563 "bookmarks.create", | |
564 "[{\"parentId\":\"0\",\"title\":\"x\"}]"); | |
565 } | |
566 | |
567 TEST_F(ExtensionAPIClientTest, GetBookmarks) { | |
568 ExpectJsPass("chrome.bookmarks.get('0', function(){});", | |
569 "bookmarks.get", | |
570 "[\"0\"]"); | |
571 ExpectJsPass("chrome.bookmarks.get(['0','1','2','3'], function(){});", | |
572 "bookmarks.get", | |
573 "[[\"0\",\"1\",\"2\",\"3\"]]"); | |
574 ExpectJsFail("chrome.bookmarks.get(null, function(){});", | |
575 "Uncaught Error: Parameter 0 is required."); | |
576 // TODO(erikkay) This is succeeding, when it should fail. | |
577 // BUG=13719 | |
578 #if 0 | |
579 ExpectJsFail("chrome.bookmarks.get({}, function(){});", | |
580 "Uncaught Error: Invalid value for argument 0. " | |
581 "Expected 'array' but got 'object'."); | |
582 #endif | |
583 } | |
584 | |
585 TEST_F(ExtensionAPIClientTest, GetBookmarkChildren) { | |
586 ExpectJsPass("chrome.bookmarks.getChildren('42', function(){});", | |
587 "bookmarks.getChildren", | |
588 "[\"42\"]"); | |
589 } | |
590 | |
591 TEST_F(ExtensionAPIClientTest, GetBookmarkRecent) { | |
592 ExpectJsPass("chrome.bookmarks.getRecent(5, function(){});", | |
593 "bookmarks.getRecent", | |
594 "[5]"); | |
595 } | |
596 | |
597 TEST_F(ExtensionAPIClientTest, GetBookmarkTree) { | |
598 ExpectJsPass("chrome.bookmarks.getTree(function(){});", | |
599 "bookmarks.getTree", | |
600 "[]"); | |
601 } | |
602 | |
603 TEST_F(ExtensionAPIClientTest, SearchBookmarks) { | |
604 ExpectJsPass("chrome.bookmarks.search('hello',function(){});", | |
605 "bookmarks.search", | |
606 "[\"hello\"]"); | |
607 } | |
608 | |
609 TEST_F(ExtensionAPIClientTest, RemoveBookmark) { | |
610 ExpectJsPass("chrome.bookmarks.remove('42');", | |
611 "bookmarks.remove", | |
612 "[\"42\"]"); | |
613 } | |
614 | |
615 TEST_F(ExtensionAPIClientTest, RemoveBookmarkTree) { | |
616 ExpectJsPass("chrome.bookmarks.removeTree('42');", | |
617 "bookmarks.removeTree", | |
618 "[\"42\"]"); | |
619 } | |
620 | |
621 TEST_F(ExtensionAPIClientTest, MoveBookmark) { | |
622 ExpectJsPass("chrome.bookmarks.move('42',{parentId:'1',index:0});", | |
623 "bookmarks.move", | |
624 "[\"42\",{\"parentId\":\"1\",\"index\":0}]"); | |
625 } | |
626 | |
627 TEST_F(ExtensionAPIClientTest, SetBookmarkTitle) { | |
628 ExpectJsPass("chrome.bookmarks.update('42',{title:'x'});", | |
629 "bookmarks.update", | |
630 "[\"42\",{\"title\":\"x\"}]"); | |
631 } | |
632 | |
633 TEST_F(ExtensionAPIClientTest, EnablePageAction) { | |
634 // Basic old-school enablePageAction call. | |
635 ExpectJsPass("chrome.pageActions.enableForTab(" | |
636 "'dummy', {tabId: 0, url: 'http://foo/'});", | |
637 "pageActions.enableForTab", | |
638 "[\"dummy\",{\"tabId\":0,\"url\":\"http://foo/\"}]"); | |
639 // Try both optional parameters (title and iconId). | |
640 ExpectJsPass("chrome.pageActions.enableForTab(" | |
641 "'dummy', {tabId: 0, url: 'http://foo/'," | |
642 "title: 'a', iconId: 0});", | |
643 "pageActions.enableForTab", | |
644 "[\"dummy\",{\"tabId\":0,\"url\":\"http://foo/\"," | |
645 "\"title\":\"a\",\"iconId\":0}]"); | |
646 | |
647 // Now try disablePageAction. | |
648 ExpectJsPass("chrome.pageActions.disableForTab(" | |
649 "'dummy', {tabId: 0, url: 'http://foo/'});", | |
650 "pageActions.disableForTab", | |
651 "[\"dummy\",{\"tabId\":0,\"url\":\"http://foo/\"}]"); | |
652 } | |
653 | |
654 TEST_F(ExtensionAPIClientTest, ExpandToolstrip) { | |
655 ExpectJsPass("chrome.toolstrip.expand({height:100, url:'http://foo/'})", | |
656 "toolstrip.expand", | |
657 "[{\"height\":100,\"url\":\"http://foo/\"}]"); | |
658 ExpectJsPass("chrome.toolstrip.expand({height:100}, null)", | |
659 "toolstrip.expand", | |
660 "[{\"height\":100}]"); | |
661 ExpectJsPass("chrome.toolstrip.expand({height:100,url:'http://foo/'}, " | |
662 "function(){})", | |
663 "toolstrip.expand", | |
664 "[{\"height\":100,\"url\":\"http://foo/\"}]"); | |
665 | |
666 | |
667 ExpectJsFail("chrome.toolstrip.expand()", | |
668 "Uncaught Error: Parameter 0 is required."); | |
669 ExpectJsFail("chrome.toolstrip.expand(1)", | |
670 "Uncaught Error: Invalid value for argument 0. " | |
671 "Expected 'object' but got 'integer'."); | |
672 ExpectJsFail("chrome.toolstrip.expand({height:'100', url:'http://foo/'})", | |
673 "Uncaught Error: Invalid value for argument 0. " | |
674 "Property 'height': " | |
675 "Expected 'integer' but got 'string'."); | |
676 ExpectJsFail("chrome.toolstrip.expand({height:100,url:100})", | |
677 "Uncaught Error: Invalid value for argument 0. Property 'url': " | |
678 "Expected 'string' but got 'integer'."); | |
679 ExpectJsFail("chrome.toolstrip.expand({height:100,'url':'http://foo/'}, 32)", | |
680 "Uncaught Error: Invalid value for argument 1. " | |
681 "Expected 'function' but got 'integer'."); | |
682 } | |
683 | |
684 TEST_F(ExtensionAPIClientTest, CollapseToolstrip) { | |
685 ExpectJsPass("chrome.toolstrip.collapse({url:'http://foo/'})", | |
686 "toolstrip.collapse", | |
687 "[{\"url\":\"http://foo/\"}]"); | |
688 ExpectJsPass("chrome.toolstrip.collapse(null)", | |
689 "toolstrip.collapse", | |
690 "[null]"); | |
691 ExpectJsPass("chrome.toolstrip.collapse({url:'http://foo/'}, function(){})", | |
692 "toolstrip.collapse", | |
693 "[{\"url\":\"http://foo/\"}]"); | |
694 | |
695 ExpectJsFail("chrome.toolstrip.collapse(1)", | |
696 "Uncaught Error: Invalid value for argument 0. " | |
697 "Expected 'object' but got 'integer'."); | |
698 ExpectJsFail("chrome.toolstrip.collapse(100)", | |
699 "Uncaught Error: Invalid value for argument 0. " | |
700 "Expected 'object' but got 'integer'."); | |
701 ExpectJsFail("chrome.toolstrip.collapse({url:'http://foo/'}, 32)", | |
702 "Uncaught Error: Invalid value for argument 1. " | |
703 "Expected 'function' but got 'integer'."); | |
704 } | |
705 | |
706 // I18N API | |
707 TEST_F(ExtensionAPIClientTest, GetAcceptLanguages) { | |
708 ExpectJsFail("chrome.i18n.getAcceptLanguages(32, function(){})", | |
709 "Uncaught Error: Too many arguments."); | |
710 | |
711 ExpectJsFail("chrome.i18n.getAcceptLanguages()", | |
712 "Uncaught Error: Parameter 0 is required."); | |
713 | |
714 ExpectJsFail("chrome.i18n.getAcceptLanguages('abc')", | |
715 "Uncaught Error: Invalid value for argument 0. " | |
716 "Expected 'function' but got 'string'."); | |
717 | |
718 ExpectJsPass("chrome.i18n.getAcceptLanguages(function(){})", | |
719 "i18n.getAcceptLanguages", "[]"); | |
720 } | |
721 | |
722 // TODO(cira): re-enable when we get validation going for | |
723 // renderer_process_bindings.js | |
724 TEST_F(ExtensionAPIClientTest, DISABLED_GetL10nMessage) { | |
725 ExpectJsFail("chrome.i18n.getMessage()", | |
726 "Uncaught Error: Parameter 0 is required."); | |
727 | |
728 ExpectJsFail("chrome.i18n.getMessage(1)", | |
729 "Uncaught Error: Invalid value for argument 0. " | |
730 "Expected 'string' but got 'integer'."); | |
731 | |
732 ExpectJsFail("chrome.i18n.getMessage('name', [])", | |
733 "Uncaught Error: Invalid value for argument 1. Value does not " | |
734 "match any valid type choices."); | |
735 | |
736 ExpectJsFail("chrome.i18n.getMessage('name', ['p1', 'p2', 'p3', 'p4', 'p5', " | |
737 "'p6', 'p7', 'p8', 'p9', 'p10'])", | |
738 "Uncaught Error: Invalid value for argument 1. Value does not " | |
739 "match any valid type choices."); | |
740 } | |
OLD | NEW |