Move Browser Plugin loadabort tests from content_browsertests to browser_tests.
[chromium-blink-merge.git] / chrome / test / data / extensions / platform_apps / web_view / shim / main.js
blob908bdf0ce8cec32e6cbcabefaab1c2f3c129702e
1 // Copyright (c) 2012 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.
5 var util = {};
6 var embedder = {};
7 embedder.baseGuestURL = '';
8 embedder.emptyGuestURL = '';
9 embedder.windowOpenGuestURL = '';
10 embedder.noReferrerGuestURL = '';
11 embedder.redirectGuestURL = '';
12 embedder.redirectGuestURLDest = '';
13 embedder.closeSocketURL = '';
14 embedder.tests = {};
16 embedder.setUp_ = function(config) {
17   if (!config || !config.testServer) {
18     return;
19   }
20   embedder.baseGuestURL = 'http://localhost:' + config.testServer.port;
21   embedder.emptyGuestURL = embedder.baseGuestURL +
22       '/extensions/platform_apps/web_view/shim/empty_guest.html';
23   embedder.windowOpenGuestURL = embedder.baseGuestURL +
24       '/extensions/platform_apps/web_view/shim/guest.html';
25   embedder.noReferrerGuestURL = embedder.baseGuestURL +
26       '/extensions/platform_apps/web_view/shim/guest_noreferrer.html';
27   embedder.redirectGuestURL = embedder.baseGuestURL + '/server-redirect';
28   embedder.redirectGuestURLDest = embedder.baseGuestURL +
29       '/extensions/platform_apps/web_view/shim/guest_redirect.html';
30   embedder.closeSocketURL = embedder.baseGuestURL + '/close-socket';
33 window.runTest = function(testName) {
34   if (!embedder.test.testList[testName]) {
35     console.log('Incorrect testName: ' + testName);
36     embedder.test.fail();
37     return;
38   }
40   // Run the test.
41   embedder.test.testList[testName]();
44 var LOG = function(msg) {
45   window.console.log(msg);
48 // Creates a <webview> tag in document.body and returns the reference to it.
49 // It also sets a dummy src. The dummy src is significant because this makes
50 // sure that the <object> shim is created (asynchronously at this point) for the
51 // <webview> tag. This makes the <webview> tag ready for add/removeEventListener
52 // calls.
53 util.createWebViewTagInDOM = function(partitionName) {
54   var webview = document.createElement('webview');
55   webview.style.width = '300px';
56   webview.style.height = '200px';
57   var urlDummy = 'data:text/html,<body>Initial dummy guest</body>';
58   webview.setAttribute('src', urlDummy);
59   webview.setAttribute('partition', partitionName);
60   document.body.appendChild(webview);
61   return webview;
64 embedder.test = {};
65 embedder.test.succeed = function() {
66   chrome.test.sendMessage('TEST_PASSED');
69 embedder.test.fail = function() {
70   chrome.test.sendMessage('TEST_FAILED');
73 embedder.test.assertEq = function(a, b) {
74   if (a != b) {
75     console.log('assertion failed: ' + a + ' != ' + b);
76     embedder.test.fail();
77   }
80 embedder.test.assertTrue = function(condition) {
81   if (!condition) {
82     console.log('assertion failed: true != ' + condition);
83     embedder.test.fail();
84   }
87 embedder.test.assertFalse = function(condition) {
88   if (condition) {
89     console.log('assertion failed: false != ' + condition);
90     embedder.test.fail();
91   }
94 // Tests begin.
96 // This test verifies that if a browser plugin is in autosize mode before
97 // navigation then the guest starts auto-sized.
98 function testAutosizeBeforeNavigation() {
99   var webview = document.createElement('webview');
101   webview.setAttribute('autosize', 'true');
102   webview.setAttribute('minwidth', 200);
103   webview.setAttribute('maxwidth', 210);
104   webview.setAttribute('minheight', 100);
105   webview.setAttribute('maxheight', 110);
107   webview.addEventListener('sizechanged', function(e) {
108     embedder.test.assertEq(0, e.oldWidth);
109     embedder.test.assertEq(0, e.oldHeight);
110     embedder.test.assertTrue(e.newWidth >= 200 && e.newWidth <= 210);
111     embedder.test.assertTrue(e.newHeight >= 100 && e.newHeight <= 110);
112     embedder.test.succeed();
113   });
115   webview.setAttribute('src', 'data:text/html,webview test sizechanged event');
116   document.body.appendChild(webview);
119 // Makes sure 'sizechanged' event is fired only if autosize attribute is
120 // specified.
121 // After loading <webview> without autosize attribute and a size, say size1,
122 // we set autosize attribute and new min size with size2. We would get (only
123 // one) sizechanged event with size1 as old size and size2 as new size.
124 function testAutosizeAfterNavigation() {
125   var webview = document.createElement('webview');
127   var step = 1;
128   var sizeChangeHandler = function(e) {
129     switch (step) {
130       case 1:
131         // This would be triggered after we set autosize attribute.
132         embedder.test.assertEq(50, e.oldWidth);
133         embedder.test.assertEq(100, e.oldHeight);
134         embedder.test.assertTrue(e.newWidth >= 60 && e.newWidth <= 70);
135         embedder.test.assertTrue(e.newHeight >= 110 && e.newHeight <= 120);
137         // Remove autosize attribute and expect webview to return to its
138         // original size.
139         webview.removeAttribute('autosize');
140         break;
141       case 2:
142         // Expect 50x100.
143         embedder.test.assertEq(50, e.newWidth);
144         embedder.test.assertEq(100, e.newHeight);
146         embedder.test.succeed();
147         break;
148       default:
149         window.console.log('Unexpected sizechanged event, step = ' + step);
150         embedder.test.fail();
151         break;
152     }
154     ++step;
155   };
157   webview.addEventListener('sizechanged', sizeChangeHandler);
159   webview.addEventListener('loadstop', function(e) {
160     webview.setAttribute('autosize', true);
161     webview.setAttribute('minwidth', 60);
162     webview.setAttribute('maxwidth', 70);
163     webview.setAttribute('minheight', 110);
164     webview.setAttribute('maxheight', 120);
165   });
167   webview.style.width = '50px';
168   webview.style.height = '100px';
169   webview.setAttribute('src', 'data:text/html,webview test sizechanged event');
170   document.body.appendChild(webview);
173 // This test verifies that autosize works when some of the parameters are unset.
174 function testAutosizeWithPartialAttributes() {
175   window.console.log('testAutosizeWithPartialAttributes');
176   var webview = document.createElement('webview');
178   var step = 1;
179   var sizeChangeHandler = function(e) {
180     window.console.log('sizeChangeHandler, new: ' +
181                        e.newWidth + ' X ' + e.newHeight);
182     switch (step) {
183       case 1:
184         // Expect 300x200.
185         embedder.test.assertEq(300, e.newWidth);
186         embedder.test.assertEq(200, e.newHeight);
188         // Change the min size to cause a relayout.
189         webview.minwidth = 500;
190         break;
191       case 2:
192         embedder.test.assertTrue(e.newWidth >= webview.minwidth);
193         embedder.test.assertTrue(e.newWidth <= webview.maxwidth);
195         // Tests when minwidth > maxwidth, minwidth = maxwidth.
196         // i.e. minwidth is essentially 700.
197         webview.minwidth = 800;
198         break;
199       case 3:
200         // Expect 700X?
201         embedder.test.assertEq(700, e.newWidth);
202         embedder.test.assertTrue(e.newHeight >= 200);
203         embedder.test.assertTrue(e.newHeight <= 600);
205         embedder.test.succeed();
206         break;
207       default:
208         window.console.log('Unexpected sizechanged event, step = ' + step);
209         embedder.test.fail();
210         break;
211     }
213     ++step;
214   };
216   webview.addEventListener('sizechanged', sizeChangeHandler);
218   webview.addEventListener('loadstop', function(e) {
219     webview.minwidth = 300;
220     webview.maxwidth = 700;
221     webview.minheight = 200;
222     webview.maxheight = 600;
223     webview.autosize = true;
224   });
226   webview.style.width = '640px';
227   webview.style.height = '480px';
228   webview.setAttribute('src', 'data:text/html,webview check autosize');
229   document.body.appendChild(webview);
232 // This test verifies that all autosize attributes can be removed
233 // without crashing the plugin, or throwing errors.
234 function testAutosizeRemoveAttributes() {
235   var webview = document.createElement('webview');
237   var step = 1;
238   var sizeChangeHandler = function(e) {
239     switch (step) {
240       case 1:
241         // This is the sizechanged event for autosize.
243         // Remove attributes.
244         webview.removeAttribute('minwidth');
245         webview.removeAttribute('maxwidth');
246         webview.removeAttribute('minheight');
247         webview.removeAttribute('maxheight');
248         webview.removeAttribute('autosize');
250         // We'd get one more sizechanged event after we turn off
251         // autosize.
252         webview.style.width = '500px';
253         webview.style.height = '500px';
254         break;
255       case 2:
256         embedder.test.succeed();
257         break;
258     }
260     ++step;
261   };
263   webview.addEventListener('loadstop', function(e) {
264     webview.minwidth = 300;
265     webview.maxwidth = 700;
266     webview.minheight = 600;
267     webview.maxheight = 400;
268     webview.autosize = true;
269   });
271   webview.addEventListener('sizechanged', sizeChangeHandler);
273   webview.style.width = '640px';
274   webview.style.height = '480px';
275   webview.setAttribute('src', 'data:text/html,webview check autosize');
276   document.body.appendChild(webview);
279 function testAPIMethodExistence() {
280   var apiMethodsToCheck = [
281     'back',
282     'canGoBack',
283     'canGoForward',
284     'forward',
285     'getProcessId',
286     'go',
287     'reload',
288     'stop',
289     'terminate'
290   ];
291   var webview = document.createElement('webview');
292   webview.setAttribute('partition', arguments.callee.name);
293   webview.addEventListener('loadstop', function(e) {
294     for (var i = 0; i < apiMethodsToCheck.length; ++i) {
295       embedder.test.assertEq('function',
296                            typeof webview[apiMethodsToCheck[i]]);
297     }
299     // Check contentWindow.
300     embedder.test.assertEq('object', typeof webview.contentWindow);
301     embedder.test.assertEq('function',
302                          typeof webview.contentWindow.postMessage);
303     embedder.test.succeed();
304   });
305   webview.setAttribute('src', 'data:text/html,webview check api');
306   document.body.appendChild(webview);
309 // This test verifies that the loadstop event fires when loading a webview
310 // accessible resource from a partition that is privileged.
311 function testChromeExtensionURL() {
312   var localResource = chrome.runtime.getURL('guest_with_inline_script.html');
313   var webview = document.createElement('webview');
314   // foobar is a privileged partition according to the manifest file.
315   webview.partition = 'foobar';
316   webview.addEventListener('loadabort', function(e) {
317     embedder.test.fail();
318   });
319   webview.addEventListener('loadstop', function(e) {
320     embedder.test.succeed();
321   });
322   webview.setAttribute('src', localResource);
323   document.body.appendChild(webview);
326 // This test verifies that the loadstop event fires when loading a webview
327 // accessible resource from a partition that is privileged if the src URL
328 // is not fully qualified.
329 function testChromeExtensionRelativePath() {
330   var webview = document.createElement('webview');
331   // foobar is a privileged partition according to the manifest file.
332   webview.partition = 'foobar';
333   webview.addEventListener('loadabort', function(e) {
334     embedder.test.fail();
335   });
336   webview.addEventListener('loadstop', function(e) {
337     embedder.test.succeed();
338   });
339   webview.setAttribute('src', 'guest_with_inline_script.html');
340   document.body.appendChild(webview);
343 // Makes sure inline scripts works inside guest that was loaded from
344 // accessible_resources.
345 function testInlineScriptFromAccessibleResources() {
346   var webview = document.createElement('webview');
347   // foobar is a privileged partition according to the manifest file.
348   webview.partition = 'foobar';
349   webview.addEventListener('loadabort', function(e) {
350     embedder.test.fail();
351   });
352   webview.addEventListener('consolemessage', function(e) {
353     window.console.log('consolemessage: ' + e.message);
354     if (e.message == 'guest_with_inline_script.html: Inline script ran') {
355       embedder.test.succeed();
356     }
357   });
358   webview.setAttribute('src', 'guest_with_inline_script.html');
359   document.body.appendChild(webview);
362 // This tests verifies that webview fires a loadabort event instead of crashing
363 // the browser if we attempt to navigate to a chrome-extension: URL with an
364 // extension ID that does not exist.
365 function testInvalidChromeExtensionURL() {
366   var invalidResource = 'chrome-extension://abc123/guest.html';
367   var webview = document.createElement('webview');
368   // foobar is a privileged partition according to the manifest file.
369   webview.partition = 'foobar';
370   webview.addEventListener('loadabort', function(e) {
371     embedder.test.succeed();
372   });
373   webview.setAttribute('src', invalidResource);
374   document.body.appendChild(webview);
377 function testWebRequestAPIExistence() {
378   var apiPropertiesToCheck = [
379     // Declarative WebRequest API.
380     'onMessage',
381     'onRequest',
382     // WebRequest API.
383     'onBeforeRequest',
384     'onBeforeSendHeaders',
385     'onSendHeaders',
386     'onHeadersReceived',
387     'onAuthRequired',
388     'onBeforeRedirect',
389     'onResponseStarted',
390     'onCompleted',
391     'onErrorOccurred'
392   ];
393   var webview = document.createElement('webview');
394   webview.setAttribute('partition', arguments.callee.name);
395   webview.addEventListener('loadstop', function(e) {
396     for (var i = 0; i < apiPropertiesToCheck.length; ++i) {
397       embedder.test.assertEq('object',
398                              typeof webview.request[apiPropertiesToCheck[i]]);
399       embedder.test.assertEq(
400           'function',
401           typeof webview.request[apiPropertiesToCheck[i]].addListener);
402       embedder.test.assertEq(
403           'function',
404           typeof webview.request[apiPropertiesToCheck[i]].addRules);
405       embedder.test.assertEq(
406           'function',
407           typeof webview.request[apiPropertiesToCheck[i]].getRules);
408       embedder.test.assertEq(
409           'function',
410           typeof webview.request[apiPropertiesToCheck[i]].removeRules);
411     }
413     // Try to overwrite webview.request, shall not succeed.
414     webview.request = '123';
415     embedder.test.assertTrue(typeof webview.request !== 'string');
417     embedder.test.succeed();
418   });
419   webview.setAttribute('src', 'data:text/html,webview check api');
420   document.body.appendChild(webview);
423 // This test verifies that the loadstart, loadstop, and exit events fire as
424 // expected.
425 function testEventName() {
426   var webview = document.createElement('webview');
427   webview.setAttribute('partition', arguments.callee.name);
429   webview.addEventListener('loadstart', function(evt) {
430     embedder.test.assertEq('loadstart', evt.type);
431   });
433   webview.addEventListener('loadstop', function(evt) {
434     embedder.test.assertEq('loadstop', evt.type);
435     webview.terminate();
436   });
438   webview.addEventListener('exit', function(evt) {
439     embedder.test.assertEq('exit', evt.type);
440     embedder.test.succeed();
441   });
443   webview.setAttribute('src', 'data:text/html,trigger navigation');
444   document.body.appendChild(webview);
447 function testOnEventProperties() {
448   var sequence = ['first', 'second', 'third', 'fourth'];
449   var webview = document.createElement('webview');
450   function createHandler(id) {
451     return function(e) {
452       embedder.test.assertEq(id, sequence.shift());
453     };
454   }
456   webview.addEventListener('loadstart', createHandler('first'));
457   webview.addEventListener('loadstart', createHandler('second'));
458   webview.onloadstart = createHandler('third');
459   webview.addEventListener('loadstart', createHandler('fourth'));
460   webview.addEventListener('loadstop', function(evt) {
461     embedder.test.assertEq(0, sequence.length);
463     // Test that setting another 'onloadstart' handler replaces the previous
464     // handler.
465     sequence = ['first', 'second', 'fourth'];
466     webview.onloadstart = function() {
467       embedder.test.assertEq(0, sequence.length);
468       embedder.test.succeed();
469     };
471     webview.setAttribute('src', 'data:text/html,next navigation');
472   });
474   webview.setAttribute('src', 'data:text/html,trigger navigation');
475   document.body.appendChild(webview);
478 // Tests that the 'loadprogress' event is triggered correctly.
479 function testLoadProgressEvent() {
480   var webview = document.createElement('webview');
481   var progress = 0;
483   webview.addEventListener('loadstop', function(evt) {
484     embedder.test.assertEq(1, progress);
485     embedder.test.succeed();
486   });
488   webview.addEventListener('loadprogress', function(evt) {
489     progress = evt.progress;
490   });
492   webview.setAttribute('src', 'data:text/html,trigger navigation');
493   document.body.appendChild(webview);
496 // This test registers two listeners on an event (loadcommit) and removes
497 // the <webview> tag when the first listener fires.
498 // Current expected behavior is that the second event listener will still
499 // fire without crashing.
500 function testDestroyOnEventListener() {
501   var webview = util.createWebViewTagInDOM(arguments.callee.name);
502   var url = 'data:text/html,<body>Destroy test</body>';
504   var loadCommitCount = 0;
505   function loadCommitCommon(e) {
506     embedder.test.assertEq('loadcommit', e.type);
507     if (url != e.url)
508       return;
509     ++loadCommitCount;
510     if (loadCommitCount == 1) {
511       setTimeout(function() {
512         embedder.test.succeed();
513       }, 0);
514     } else if (loadCommitCount > 2) {
515       embedder.test.fail();
516     }
517   };
519   // The test starts from here, by setting the src to |url|.
520   webview.addEventListener('loadcommit', function(e) {
521     webview.parentNode.removeChild(webview);
522     loadCommitCommon(e);
523   });
524   webview.addEventListener('loadcommit', function(e) {
525     loadCommitCommon(e);
526   });
527   webview.setAttribute('src', url);
530 // This test registers two event listeners on a same event (loadcommit).
531 // Each of the listener tries to change some properties on the event param,
532 // which should not be possible.
533 function testCannotMutateEventName() {
534   var webview = util.createWebViewTagInDOM(arguments.callee.name);
535   var url = 'data:text/html,<body>Two</body>';
537   var loadCommitACalled = false;
538   var loadCommitBCalled = false;
540   var maybeFinishTest = function(e) {
541     if (loadCommitACalled && loadCommitBCalled) {
542       embedder.test.assertEq('loadcommit', e.type);
543       embedder.test.succeed();
544     }
545   };
547   var onLoadCommitA = function(e) {
548     if (e.url == url) {
549       embedder.test.assertEq('loadcommit', e.type);
550       embedder.test.assertTrue(e.isTopLevel);
551       embedder.test.assertFalse(loadCommitACalled);
552       loadCommitACalled = true;
553       // Try mucking with properities inside |e|.
554       e.type = 'modified';
555       maybeFinishTest(e);
556     }
557   };
558   var onLoadCommitB = function(e) {
559     if (e.url == url) {
560       embedder.test.assertEq('loadcommit', e.type);
561       embedder.test.assertTrue(e.isTopLevel);
562       embedder.test.assertFalse(loadCommitBCalled);
563       loadCommitBCalled = true;
564       // Try mucking with properities inside |e|.
565       e.type = 'modified';
566       maybeFinishTest(e);
567     }
568   };
570   // The test starts from here, by setting the src to |url|. Event
571   // listener registration works because we already have a (dummy) src set
572   // on the <webview> tag.
573   webview.addEventListener('loadcommit', onLoadCommitA);
574   webview.addEventListener('loadcommit', onLoadCommitB);
575   webview.setAttribute('src', url);
578 // This test verifies that setting the partition attribute after the src has
579 // been set raises an exception.
580 function testPartitionRaisesException() {
581   var webview = document.createElement('webview');
582   webview.setAttribute('partition', arguments.callee.name);
583   webview.setAttribute('src', 'data:text/html,trigger navigation');
584   document.body.appendChild(webview);
585   setTimeout(function() {
586     try {
587       webview.partition = 'illegal';
588       embedder.test.fail();
589     } catch (e) {
590       embedder.test.succeed();
591     }
592   }, 0);
595 function testExecuteScriptFail() {
596   var webview = document.createElement('webview');
597   document.body.appendChild(webview);
598   setTimeout(function() {
599     try {
600     webview.executeScript(
601       {code:'document.body.style.backgroundColor = "red";'},
602       function(results) {
603         embedder.test.fail();
604       });
605     } catch (e) {
606       embedder.test.succeed();
607     }
608   }, 0);
611 function testExecuteScript() {
612   var webview = document.createElement('webview');
613   webview.setAttribute('partition', arguments.callee.name);
614   webview.addEventListener('loadstop', function() {
615     webview.executeScript(
616       {code:'document.body.style.backgroundColor = "red";'},
617       function(results) {
618         embedder.test.assertEq(1, results.length);
619         embedder.test.assertEq('red', results[0]);
620         embedder.test.succeed();
621       });
622   });
623   webview.setAttribute('src', 'data:text/html,trigger navigation');
624   document.body.appendChild(webview);
627 // This test verifies that the call of executeScript will fail and return null
628 // if the webview has been navigated to another source.
629 function testExecuteScriptIsAbortedWhenWebViewSourceIsChanged() {
630   var webview = document.createElement('webview');
631   var initial = true;
632   var navigationOccur = false;
633   var newSrc = 'data:text/html,trigger navigation';
634   webview.addEventListener('loadstart', function() {
635     if (initial) {
636       webview.setAttribute('src', newSrc);
637       navigationOccur = true;
638     }
639     initial = false;
640   });
641   webview.addEventListener('loadstop', function() {
642     webview.executeScript(
643       {code:'document.body.style.backgroundColor = "red";'},
644       function(results) {
645         if (navigationOccur) {
646           // Expect a null results because the executeScript failed;
647           // return "red", otherwise.
648           embedder.test.assertEq(null, results);
649           embedder.test.succeed();
650         }
651         navigationOccur = false;
652       }
653     );
654   });
655   webview.setAttribute('src', "about:blank");
656   document.body.appendChild(webview);
659 // This test calls terminate() on guest after it has already been
660 // terminated. This makes sure we ignore the call gracefully.
661 function testTerminateAfterExit() {
662   var webview = document.createElement('webview');
663   webview.setAttribute('partition', arguments.callee.name);
664   var loadstopSucceedsTest = false;
665   webview.addEventListener('loadstop', function(evt) {
666     embedder.test.assertEq('loadstop', evt.type);
667     if (loadstopSucceedsTest) {
668       embedder.test.succeed();
669       return;
670     }
672     webview.terminate();
673   });
675   webview.addEventListener('exit', function(evt) {
676     embedder.test.assertEq('exit', evt.type);
677     // Call terminate again.
678     webview.terminate();
679     // Load another page. The test would pass when loadstop is called on
680     // this second page. This would hopefully catch if call to
681     // webview.terminate() caused a browser crash.
682     setTimeout(function() {
683       loadstopSucceedsTest = true;
684       webview.setAttribute('src', 'data:text/html,test second page');
685     }, 0);
686   });
688   webview.setAttribute('src', 'data:text/html,test terminate() crash.');
689   document.body.appendChild(webview);
692 // This test verifies that multiple consecutive changes to the <webview> src
693 // attribute will cause a navigation.
694 function testNavOnConsecutiveSrcAttributeChanges() {
695   var testPage1 = 'data:text/html,test page 1';
696   var testPage2 = 'data:text/html,test page 2';
697   var testPage3 = 'data:text/html,test page 3';
698   var webview = new WebView();
699   webview.partition = arguments.callee.name;
700   var loadCommitCount = 0;
701   webview.addEventListener('loadcommit', function(e) {
702     if (e.url == testPage3) {
703       embedder.test.succeed();
704     }
705     loadCommitCount++;
706     if (loadCommitCount > 3) {
707       embedder.test.fail();
708     }
709   });
710   document.body.appendChild(webview);
711   webview.src = testPage1;
712   webview.src = testPage2;
713   webview.src = testPage3;
716 // This test verifies that we can set the <webview> src multiple times and the
717 // changes will cause a navigation.
718 function testNavOnSrcAttributeChange() {
719   var testPage1 = 'data:text/html,test page 1';
720   var testPage2 = 'data:text/html,test page 2';
721   var testPage3 = 'data:text/html,test page 3';
722   var tests = [testPage1, testPage2, testPage3];
723   var webview = new WebView();
724   webview.partition = arguments.callee.name;
725   var loadCommitCount = 0;
726   webview.addEventListener('loadcommit', function(evt) {
727     var success = tests.indexOf(evt.url) > -1;
728     embedder.test.assertTrue(success);
729     ++loadCommitCount;
730     if (loadCommitCount == tests.length) {
731       embedder.test.succeed();
732     } else if (loadCommitCount > tests.length) {
733       embedder.test.fail();
734     } else {
735       webview.src = tests[loadCommitCount];
736     }
737   });
738   webview.src = tests[0];
739   document.body.appendChild(webview);
742 // This test verifies that assigning the src attribute the same value it had
743 // prior to a crash spawns off a new guest process.
744 function testAssignSrcAfterCrash() {
745   var webview = document.createElement('webview');
746   webview.setAttribute('partition', arguments.callee.name);
747   var terminated = false;
748   webview.addEventListener('loadstop', function(evt) {
749     if (!terminated) {
750       webview.terminate();
751       return;
752     }
753     // The guest has recovered after being terminated.
754     embedder.test.succeed();
755   });
756   webview.addEventListener('exit', function(evt) {
757     terminated = true;
758     webview.setAttribute('src', 'data:text/html,test page');
759   });
760   webview.setAttribute('src', 'data:text/html,test page');
761   document.body.appendChild(webview);
764 // This test verifies that <webview> reloads the page if the src attribute is
765 // assigned the same value.
766 function testReassignSrcAttribute() {
767   var dataUrl = 'data:text/html,test page';
768   var webview = new WebView();
769   webview.partition = arguments.callee.name;
771   var loadStopCount = 0;
772   webview.addEventListener('loadstop', function(evt) {
773     embedder.test.assertEq(dataUrl, webview.getAttribute('src'));
774     ++loadStopCount;
775     console.log('[' + loadStopCount + '] loadstop called');
776     if (loadStopCount == 3) {
777       embedder.test.succeed();
778     } else if (loadStopCount > 3) {
779       embedder.test.fail();
780     } else {
781       webview.src = dataUrl;
782     }
783   });
784   webview.src = dataUrl;
785   document.body.appendChild(webview);
788 // This test verifies that <webview> restores the src attribute if it is
789 // removed after navigation.
790 function testRemoveSrcAttribute() {
791   var dataUrl = 'data:text/html,test page';
792   var webview = document.createElement('webview');
793   webview.setAttribute('partition', arguments.callee.name);
794   var terminated = false;
795   webview.addEventListener('loadstop', function(evt) {
796     webview.removeAttribute('src');
797     setTimeout(function() {
798       embedder.test.assertEq(dataUrl, webview.getAttribute('src'));
799       embedder.test.succeed();
800     }, 0);
801   });
802   webview.setAttribute('src', dataUrl);
803   document.body.appendChild(webview);
806 // This test verifies that it is not possible to instantiate a browser plugin
807 // directly within an app.
808 function testBrowserPluginNotAllowed() {
809   var container = document.getElementById('object-container');
810   if (!container) {
811     embedder.test.fail('Container for object not found.');
812     return;
813   }
814   container.innerHTML = '<object type="application/browser-plugin"' +
815       ' id="object-plugin"' +
816       ' src="data:text/html,<body>You should not see this</body>">' +
817       '</object>';
818   var objectElement = document.getElementById('object-plugin');
819   // Check that bindings are not registered.
820   embedder.test.assertTrue(
821       objectElement['-internal-attach'] === undefined);
822   embedder.test.succeed();
825 function testPluginLoadPermission() {
826   var pluginIdentifier = 'unknown platform';
827   if (navigator.platform.match(/linux/i))
828     pluginIdentifier = 'libppapi_tests.so';
829   else if (navigator.platform.match(/win32/i))
830     pluginIdentifier = 'ppapi_tests.dll';
831   else if (navigator.platform.match(/mac/i))
832     pluginIdentifier = 'ppapi_tests.plugin';
834   var webview = document.createElement('webview');
835   webview.addEventListener('permissionrequest', function(e) {
836     e.preventDefault();
837     embedder.test.assertEq('loadplugin', e.permission);
838     embedder.test.assertEq(pluginIdentifier, e.name);
839     embedder.test.assertEq(pluginIdentifier, e.identifier);
840     embedder.test.assertEq('function', typeof e.request.allow);
841     embedder.test.assertEq('function', typeof e.request.deny);
842     embedder.test.succeed();
843   });
844   webview.setAttribute('src', 'data:text/html,<body>' +
845                               '<embed type="application/x-ppapi-tests">' +
846                               '</embed></body>');
847   document.body.appendChild(webview);
850 // This test verifies that new window attachment functions as expected.
851 function testNewWindow() {
852   var webview = document.createElement('webview');
853   webview.addEventListener('newwindow', function(e) {
854     e.preventDefault();
855     var newwebview = document.createElement('webview');
856     newwebview.addEventListener('loadstop', function(evt) {
857       // If the new window finishes loading, the test is successful.
858       embedder.test.succeed();
859     });
860     document.body.appendChild(newwebview);
861     // Attach the new window to the new <webview>.
862     e.window.attach(newwebview);
863   });
864   webview.setAttribute('src', embedder.windowOpenGuestURL);
865   document.body.appendChild(webview);
868 // This test verifies "first-call-wins" semantics. That is, the first call
869 // to perform an action on the new window takes the action and all
870 // subsequent calls throw an exception.
871 function testNewWindowTwoListeners() {
872   var webview = document.createElement('webview');
873   var error = false;
874   webview.addEventListener('newwindow', function(e) {
875     e.preventDefault();
876     var newwebview = document.createElement('webview');
877     document.body.appendChild(newwebview);
878     try {
879       e.window.attach(newwebview);
880     } catch (err) {
881       embedder.test.fail();
882     }
883   });
884   webview.addEventListener('newwindow', function(e) {
885     e.preventDefault();
886     try {
887       e.window.discard();
888     } catch (err) {
889       embedder.test.succeed();
890     }
891   });
892   webview.setAttribute('src', embedder.windowOpenGuestURL);
893   document.body.appendChild(webview);
896 // This test verifies that the attach can be called inline without
897 // preventing default.
898 function testNewWindowNoPreventDefault() {
899   var webview = document.createElement('webview');
900   webview.addEventListener('newwindow', function(e) {
901     var newwebview = document.createElement('webview');
902     document.body.appendChild(newwebview);
903     // Attach the new window to the new <webview>.
904     try {
905       e.window.attach(newwebview);
906       embedder.test.succeed();
907     } catch (err) {
908       embedder.test.fail();
909     }
910   });
911   webview.setAttribute('src', embedder.windowOpenGuestURL);
912   document.body.appendChild(webview);
915 function testNewWindowNoReferrerLink() {
916   var webview = document.createElement('webview');
917   webview.addEventListener('newwindow', function(e) {
918     e.preventDefault();
919     var newwebview = document.createElement('webview');
920     newwebview.addEventListener('loadstop', function(evt) {
921       // If the new window finishes loading, the test is successful.
922       embedder.test.succeed();
923     });
924     document.body.appendChild(newwebview);
925     // Attach the new window to the new <webview>.
926     e.window.attach(newwebview);
927   });
928   webview.setAttribute('src', embedder.noReferrerGuestURL);
929   document.body.appendChild(webview);
932 // This test verifies that the load event fires when the a new page is
933 // loaded.
934 // TODO(fsamuel): Add a test to verify that subframe loads within a guest
935 // do not fire the 'contentload' event.
936 function testContentLoadEvent() {
937   var webview = document.createElement('webview');
938   webview.addEventListener('contentload', function(e) {
939     embedder.test.succeed();
940   });
941   webview.setAttribute('src', 'data:text/html,trigger navigation');
942   document.body.appendChild(webview);
945 // This test verifies that the WebRequest API onBeforeRequest event fires on
946 // webview.
947 function testWebRequestAPI() {
948   var webview = new WebView();
949   webview.request.onBeforeRequest.addListener(function(e) {
950     embedder.test.succeed();
951   }, { urls: ['<all_urls>']}) ;
952   webview.src = embedder.windowOpenGuestURL;
953   document.body.appendChild(webview);
956 // This test verifies that the basic use cases of the declarative WebRequest API
957 // work as expected. This test demonstrates that rules can be added prior to
958 // navigation and attachment.
959 // 1. It adds a rule to block URLs that contain guest.
960 // 2. It attempts to navigate to a guest.html page.
961 // 3. It detects the appropriate loadabort message.
962 // 4. It removes the rule blocking the page and reloads.
963 // 5. The page loads successfully.
964 function testDeclarativeWebRequestAPI() {
965   var step = 1;
966   var webview = new WebView();
967   var rule = {
968     conditions: [
969       new chrome.webViewRequest.RequestMatcher(
970         {
971           url: { urlContains: 'guest' }
972         }
973       )
974     ],
975     actions: [
976       new chrome.webViewRequest.CancelRequest()
977     ]
978   };
979   webview.request.onRequest.addRules([rule]);
980   webview.addEventListener('loadabort', function(e) {
981     embedder.test.assertEq(1, step);
982     embedder.test.assertEq('ERR_BLOCKED_BY_CLIENT', e.reason);
983     step = 2;
984     webview.request.onRequest.removeRules();
985     webview.reload();
986   });
987   webview.addEventListener('loadcommit', function(e) {
988     embedder.test.assertEq(2, step);
989     embedder.test.succeed();
990   });
991   webview.src = embedder.emptyGuestURL;
992   document.body.appendChild(webview);
995 // This test verifies that the WebRequest API onBeforeRequest event fires on
996 // clients*.google.com URLs.
997 function testWebRequestAPIGoogleProperty() {
998   var webview = new WebView();
999   webview.request.onBeforeRequest.addListener(function(e) {
1000     embedder.test.succeed();
1001     return {cancel: true};
1002   }, { urls: ['<all_urls>']}, ['blocking']) ;
1003   webview.src = 'http://clients6.google.com';
1004   document.body.appendChild(webview);
1007 // This test verifies that the WebRequest event listener for onBeforeRequest
1008 // survives reparenting of the <webview>.
1009 function testWebRequestListenerSurvivesReparenting() {
1010   var webview = new WebView();
1011   var count = 0;
1012   webview.request.onBeforeRequest.addListener(function(e) {
1013     if (++count == 2) {
1014       embedder.test.succeed();
1015     }
1016   }, { urls: ['<all_urls>']});
1017   var onLoadStop =  function(e) {
1018     webview.removeEventListener('loadstop', onLoadStop);
1019     webview.parentNode.removeChild(webview);
1020     var container = document.getElementById('object-container');
1021     if (!container) {
1022       embedder.test.fail('Container for object not found.');
1023       return;
1024     }
1025     container.appendChild(webview);
1026   };
1027   webview.addEventListener('loadstop', onLoadStop);
1028   webview.src = embedder.emptyGuestURL;
1029   document.body.appendChild(webview);
1032 // This test verifies that getProcessId is defined and returns a non-zero
1033 // value corresponding to the processId of the guest process.
1034 function testGetProcessId() {
1035   var webview = document.createElement('webview');
1036   webview.setAttribute('src', 'data:text/html,trigger navigation');
1037   var firstLoad = function() {
1038     webview.removeEventListener('loadstop', firstLoad);
1039     embedder.test.assertTrue(webview.getProcessId() > 0);
1040     embedder.test.succeed();
1041   };
1042   webview.addEventListener('loadstop', firstLoad);
1043   document.body.appendChild(webview);
1046 // This test verifies that the loadstart event fires at the beginning of a load
1047 // and the loadredirect event fires when a redirect occurs.
1048 function testLoadStartLoadRedirect() {
1049   var webview = document.createElement('webview');
1050   var loadstartCalled = false;
1051   webview.setAttribute('src', embedder.redirectGuestURL);
1052   webview.addEventListener('loadstart', function(e) {
1053     embedder.test.assertTrue(e.isTopLevel);
1054     embedder.test.assertEq(embedder.redirectGuestURL, e.url);
1055     loadstartCalled = true;
1056   });
1057   webview.addEventListener('loadredirect', function(e) {
1058     embedder.test.assertTrue(e.isTopLevel);
1059     embedder.test.assertEq(embedder.redirectGuestURL,
1060         e.oldUrl.replace('127.0.0.1', 'localhost'));
1061     embedder.test.assertEq(embedder.redirectGuestURLDest,
1062         e.newUrl.replace('127.0.0.1', 'localhost'));
1063     if (loadstartCalled) {
1064       embedder.test.succeed();
1065     } else {
1066       embedder.test.fail();
1067     }
1068   });
1069   document.body.appendChild(webview);
1072 // This test verifies that the loadabort event fires when loading a webview
1073 // accessible resource from a partition that is not privileged.
1074 function testLoadAbortChromeExtensionURLWrongPartition() {
1075   var localResource = chrome.runtime.getURL('guest.html');
1076   var webview = document.createElement('webview');
1077   webview.addEventListener('loadabort', function(e) {
1078     embedder.test.assertEq('ERR_ADDRESS_UNREACHABLE', e.reason);
1079     embedder.test.succeed();
1080   });
1081   webview.addEventListener('loadstop', function(e) {
1082     embedder.test.fail();
1083   });
1084   webview.setAttribute('src', localResource);
1085   document.body.appendChild(webview);
1088 // This test verifies that the loadabort event fires as expected and with the
1089 // appropriate fields when an empty response is returned.
1090 function testLoadAbortEmptyResponse() {
1091   var webview = document.createElement('webview');
1092   webview.addEventListener('loadabort', function(e) {
1093     embedder.test.assertEq('ERR_EMPTY_RESPONSE', e.reason);
1094     embedder.test.succeed();
1095   });
1096   webview.setAttribute('src', embedder.closeSocketURL);
1097   document.body.appendChild(webview);
1100 // This test verifies that the loadabort event fires as expected when an illegal
1101 // chrome URL is provided.
1102 function testLoadAbortIllegalChromeURL() {
1103   var webview = document.createElement('webview');
1104   var onFirstLoadStop = function(e) {
1105     webview.removeEventListener('loadstop', onFirstLoadStop);
1106     webview.setAttribute('src', 'chrome://newtab');
1107   };
1108   webview.addEventListener('loadstop', onFirstLoadStop);
1109   webview.addEventListener('loadabort', function(e) {
1110     embedder.test.assertEq('ERR_ABORTED', e.reason);
1111     embedder.test.succeed();
1112   });
1113   webview.setAttribute('src', 'about:blank');
1114   document.body.appendChild(webview);
1117 function testLoadAbortIllegalFileURL() {
1118   var webview = document.createElement('webview');
1119   webview.addEventListener('loadabort', function(e) {
1120     embedder.test.assertEq('ERR_ABORTED', e.reason);
1121     embedder.test.succeed();
1122   });
1123   webview.setAttribute('src', 'file://foo');
1124   document.body.appendChild(webview);
1127 function testLoadAbortIllegalJavaScriptURL() {
1128   var webview = document.createElement('webview');
1129   webview.addEventListener('loadabort', function(e) {
1130     embedder.test.assertEq('ERR_ABORTED', e.reason);
1131     embedder.test.succeed();
1132   });
1133   webview.setAttribute('src', 'javascript:void(document.bgColor="#0000FF")');
1134   document.body.appendChild(webview);
1137 // Verifies that navigating to invalid URL (e.g. 'http:') doesn't cause a crash.
1138 function testLoadAbortInvalidNavigation() {
1139   var webview = document.createElement('webview');
1140   var validSchemeWithEmptyURL = 'http:';
1141   webview.addEventListener('loadabort', function(e) {
1142     embedder.test.assertEq('ERR_ABORTED', e.reason);
1143     embedder.test.assertEq('', e.url);
1144     embedder.test.succeed();
1145   });
1146   webview.addEventListener('exit', function(e) {
1147     // We should not crash.
1148     embedder.test.fail();
1149   });
1150   webview.setAttribute('src', validSchemeWithEmptyURL);
1151   document.body.appendChild(webview);
1154 // Verifies that navigation to a URL that is valid but not web-safe or
1155 // pseudo-scheme fires loadabort and doesn't cause a crash.
1156 function testLoadAbortNonWebSafeScheme() {
1157   var webview = document.createElement('webview');
1158   var chromeGuestURL = 'chrome-guest://abc123';
1159   webview.addEventListener('loadabort', function(e) {
1160     embedder.test.assertEq('ERR_ABORTED', e.reason);
1161     embedder.test.assertEq('chrome-guest://abc123/', e.url);
1162     embedder.test.succeed();
1163   });
1164   webview.addEventListener('exit', function(e) {
1165     // We should not crash.
1166     embedder.test.fail();
1167   });
1168   webview.setAttribute('src', chromeGuestURL);
1169   document.body.appendChild(webview);
1172 // This test verifies that the reload method on webview functions as expected.
1173 function testReload() {
1174   var triggerNavUrl = 'data:text/html,trigger navigation';
1175   var webview = document.createElement('webview');
1177   var loadCommitCount = 0;
1178   webview.addEventListener('loadstop', function(e) {
1179     if (loadCommitCount < 2) {
1180       webview.reload();
1181     } else if (loadCommitCount == 2) {
1182       embedder.test.succeed();
1183     } else {
1184       embedder.test.fail();
1185     }
1186   });
1187   webview.addEventListener('loadcommit', function(e) {
1188     embedder.test.assertEq(triggerNavUrl, e.url);
1189     embedder.test.assertTrue(e.isTopLevel);
1190     loadCommitCount++;
1191   });
1193   webview.setAttribute('src', triggerNavUrl);
1194   document.body.appendChild(webview);
1197 // This test verifies that a <webview> is torn down gracefully when removed from
1198 // the DOM on exit.
1200 window.removeWebviewOnExitDoCrash = null;
1202 function testRemoveWebviewOnExit() {
1203   var triggerNavUrl = 'data:text/html,trigger navigation';
1204   var webview = document.createElement('webview');
1206   webview.addEventListener('loadstop', function(e) {
1207     chrome.test.sendMessage('guest-loaded');
1208   });
1210   window.removeWebviewOnExitDoCrash = function() {
1211     webview.terminate();
1212   };
1214   webview.addEventListener('exit', function(e) {
1215     // We expected to be killed.
1216     if (e.reason != 'killed') {
1217       console.log('EXPECTED TO BE KILLED!');
1218       return;
1219     }
1220     webview.parentNode.removeChild(webview);
1221   });
1223   // Trigger a navigation to create a guest process.
1224   webview.setAttribute('src', embedder.emptyGuestURL);
1225   document.body.appendChild(webview);
1228 function testRemoveWebviewAfterNavigation() {
1229   var webview = new WebView();
1230   document.body.appendChild(webview);
1231   webview.src = 'data:text/html,trigger navigation';
1232   document.body.removeChild(webview);
1233   setTimeout(function() {
1234     embedder.test.succeed();
1235   }, 0);
1238 function testNavigationToExternalProtocol() {
1239   var webview = document.createElement('webview');
1240   webview.addEventListener('loadstop', function(e) {
1241     webview.addEventListener('loadabort', function(e) {
1242       embedder.test.assertEq('ERR_UNKNOWN_URL_SCHEME', e.reason);
1243       embedder.test.succeed();
1244     });
1245     webview.executeScript({
1246       code: 'window.location.href = "tel:+12223334444";'
1247     }, function(results) {});
1248   });
1249   webview.setAttribute('src', 'data:text/html,navigate to external protocol');
1250   document.body.appendChild(webview);
1253 // This test ensures if the guest isn't there and we resize the guest (from JS),
1254 // it remembers the size correctly.
1255 function testNavigateAfterResize() {
1256   var webview = new WebView();
1258   var postMessageHandler = function(e) {
1259     var data = JSON.parse(e.data);
1260     LOG('postMessageHandler: ' + data);
1261     webview.removeEventListener('message', postMessageHandler);
1262     if (data[0] == 'dimension-response') {
1263       var actualWidth = data[1];
1264       var actualHeight = data[2];
1265       LOG('actualWidth: ' + actualWidth + ', actualHeight: ' + actualHeight);
1266       embedder.test.assertEq(100, actualWidth);
1267       embedder.test.assertEq(125, actualHeight);
1268       embedder.test.succeed();
1269     }
1270   };
1271   window.addEventListener('message', postMessageHandler);
1273   webview.addEventListener('consolemessage', function(e) {
1274     LOG('guest log: ' + e.message);
1275   });
1277   webview.addEventListener('loadstop', function(e) {
1278     webview.executeScript(
1279       {file: 'navigate_after_resize.js'},
1280       function(results) {
1281         if (!results || !results.length) {
1282           LOG('Failed to inject navigate_after_resize.js');
1283           embedder.test.fail();
1284           return;
1285         }
1286         LOG('Inject success: navigate_after_resize.js');
1287         var msg = ['dimension-request'];
1288         webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1289       });
1290   });
1292   // First set size.
1293   webview.style.width = '100px';
1294   webview.style.height = '125px';
1296   // Then navigate.
1297   webview.src = 'about:blank';
1298   document.body.appendChild(webview);
1301 function testResizeWebviewResizesContent() {
1302   var webview = new WebView();
1303   webview.src = 'about:blank';
1304   webview.addEventListener('loadstop', function(e) {
1305     webview.executeScript(
1306       {file: 'inject_resize_test.js'},
1307       function(results) {
1308         window.console.log('The resize test has been injected into webview.');
1309       }
1310     );
1311     webview.executeScript(
1312       {file: 'inject_comm_channel.js'},
1313       function(results) {
1314         window.console.log('The guest script for a two-way comm channel has ' +
1315             'been injected into webview.');
1316         // Establish a communication channel with the guest.
1317         var msg = ['connect'];
1318         webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1319       }
1320     );
1321   });
1322   window.addEventListener('message', function(e) {
1323     var data = JSON.parse(e.data);
1324     if (data[0] == 'connected') {
1325       console.log('A communication channel has been established with webview.');
1326       console.log('Resizing <webview> width from 300px to 400px.');
1327       webview.style.width = '400px';
1328       return;
1329     }
1330     if (data[0] == 'resize') {
1331       var width = data[1];
1332       var height = data[2];
1333       embedder.test.assertEq(400, width);
1334       embedder.test.assertEq(300, height);
1335       embedder.test.succeed();
1336       return;
1337     }
1338     console.log('Unexpected message: \'' + data[0]  + '\'');
1339     embedder.test.fail();
1340   });
1341   document.body.appendChild(webview);
1344 function testPostMessageCommChannel() {
1345   var webview = new WebView();
1346   webview.src = 'about:blank';
1347   webview.addEventListener('loadstop', function(e) {
1348     webview.executeScript(
1349       {file: 'inject_comm_channel.js'},
1350       function(results) {
1351         window.console.log('The guest script for a two-way comm channel has ' +
1352             'been injected into webview.');
1353         // Establish a communication channel with the guest.
1354         var msg = ['connect'];
1355         webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1356       }
1357     );
1358   });
1359   window.addEventListener('message', function(e) {
1360     var data = JSON.parse(e.data);
1361     if (data[0] == 'connected') {
1362       console.log('A communication channel has been established with webview.');
1363       embedder.test.succeed();
1364       return;
1365     }
1366     console.log('Unexpected message: \'' + data[0]  + '\'');
1367     embedder.test.fail();
1368   });
1369   document.body.appendChild(webview);
1372 function testScreenshotCapture() {
1373   var webview = document.createElement('webview');
1375   webview.addEventListener('loadstop', function(e) {
1376     webview.captureVisibleRegion(null, function(dataUrl) {
1377       // 100x100 red box.
1378       var expectedUrl = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/' +
1379           '2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLE' +
1380           'BYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFB' +
1381           'QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCABkAGQ' +
1382           'DASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAA' +
1383           'AgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM' +
1384           '2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3' +
1385           'R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8j' +
1386           'JytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAA' +
1387           'AAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBU' +
1388           'QdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERU' +
1389           'ZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqO' +
1390           'kpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3' +
1391           '+Pn6/9oADAMBAAIRAxEAPwD50ooor8MP9UwooooAKKKKACiiigAooooAKKKKACiii' +
1392           'gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiig' +
1393           'AooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigA' +
1394           'ooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAo' +
1395           'oooAKKKKACiiigAooooAKKKKACiiigD/2Q==';
1396       embedder.test.assertEq(expectedUrl, dataUrl);
1397       embedder.test.succeed();
1398     });
1399   });
1401   webview.style.width = '100px';
1402   webview.style.height = '100px';
1403   webview.setAttribute('src',
1404       'data:text/html,<body style="background-color: red"></body>');
1405   document.body.appendChild(webview);
1408 function testZoomAPI() {
1409   var webview = new WebView();
1410   webview.src = 'about:blank';
1411   webview.addEventListener('loadstop', function(e) {
1412     // getZoom() should work initially.
1413     webview.getZoom(function(zoomFactor) {
1414       embedder.test.assertFalse(zoomFactor == undefined);
1415     });
1417     // Two consecutive calls to getZoom() should return the same result.
1418     var zoomFactor1;
1419     webview.getZoom(function(zoomFactor) {
1420       zoomFactor1 = zoomFactor;
1421     });
1422     webview.getZoom(function(zoomFactor) {
1423       embedder.test.assertEq(zoomFactor1, zoomFactor);
1424     });
1426     // Test setZoom()'s callback.
1427     var callbackTest = false;
1428     webview.setZoom(0.95, function() {
1429       callbackTest = true;
1430     });
1432     // getZoom() should return the same zoom factor as is set in setZoom().
1433     webview.setZoom(1.53);
1434     webview.getZoom(function(zoomFactor) {
1435       embedder.test.assertEq(zoomFactor, 1.53);
1436     });
1437     webview.setZoom(0.835847);
1438     webview.getZoom(function(zoomFactor) {
1439       embedder.test.assertEq(zoomFactor, 0.835847);
1440     });
1441     webview.setZoom(0.3795);
1442     webview.getZoom(function(zoomFactor) {
1443       embedder.test.assertEq(zoomFactor, 0.3795);
1444     });
1446     // setZoom() should really zoom the page (thus changing window.innerWidth).
1447     webview.setZoom(0.45, function() {
1448       webview.executeScript({code: 'window.innerWidth'},
1449         function(result) {
1450           var width1 = result[0];
1451           webview.setZoom(1.836);
1452           webview.executeScript({code: 'window.innerWidth'},
1453             function(result) {
1454               var width2 = result[0];
1455               embedder.test.assertTrue(width2 < width1);
1456               webview.setZoom(0.73);
1457               webview.executeScript({code: 'window.innerWidth'},
1458                 function(result) {
1459                   var width3 = result[0];
1460                   embedder.test.assertTrue(width3 < width1);
1461                   embedder.test.assertTrue(width2 < width3);
1463                   // Test the onzoomchange event.
1464                   webview.addEventListener('zoomchange', function(e) {
1465                     embedder.test.assertEq(event.oldZoomFactor, 0.73);
1466                     embedder.test.assertEq(event.newZoomFactor, 0.25325);
1468                     embedder.test.assertTrue(callbackTest);
1470                     embedder.test.succeed();
1471                   });
1472                   webview.setZoom(0.25325);
1473                 }
1474               );
1475             }
1476           );
1477         }
1478       );
1479     });
1480   });
1481   document.body.appendChild(webview);
1484 function testFindAPI() {
1485   var webview = new WebView();
1486   webview.src = 'data:text/html,Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1487       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1488       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1489       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1490       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1491       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1492       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1493       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1494       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1495       'Dog dog dog Dog dog dogcatDog dogDogdog.<br><br>' +
1496       '<a href="about:blank">Click here!</a>';
1498   var loadstopListener2 = function(e) {
1499     embedder.test.assertEq(webview.src, "about:blank");
1500     embedder.test.succeed();
1501   }
1503   var loadstopListener1 = function(e) {
1504     // Test find results.
1505     webview.find("dog", {}, function(results) {
1506       callbackTest = true;
1507       embedder.test.assertEq(results.numberOfMatches, 100);
1508       embedder.test.assertTrue(results.selectionRect.width > 0);
1509       embedder.test.assertTrue(results.selectionRect.height > 0);
1511       // Test finding next active matches.
1512       webview.find("dog");
1513       webview.find("dog");
1514       webview.find("dog");
1515       webview.find("dog");
1516       webview.find("dog", {}, function(results) {
1517         embedder.test.assertEq(results.activeMatchOrdinal, 6);
1518         webview.find("dog", {backward: true});
1519         webview.find("dog", {backward: true}, function(results) {
1520           // Test the |backward| find option.
1521           embedder.test.assertEq(results.activeMatchOrdinal, 4);
1523           // Test the |matchCase| find option.
1524           webview.find("Dog", {matchCase: true}, function(results) {
1525             embedder.test.assertEq(results.numberOfMatches, 40);
1527             // Test canceling find requests.
1528             webview.find("dog");
1529             webview.stopFinding();
1530             webview.find("dog");
1531             webview.find("cat");
1533             // Test find results when looking for something that isn't there.
1534             webview.find("fish", {}, function(results) {
1535               embedder.test.assertEq(results.numberOfMatches, 0);
1536               embedder.test.assertEq(results.activeMatchOrdinal, 0);
1537               embedder.test.assertEq(results.selectionRect.left, 0);
1538               embedder.test.assertEq(results.selectionRect.top, 0);
1539               embedder.test.assertEq(results.selectionRect.width, 0);
1540               embedder.test.assertEq(results.selectionRect.height, 0);
1542               // Test following a link with stopFinding().
1543               webview.removeEventListener('loadstop', loadstopListener1);
1544               webview.addEventListener('loadstop', loadstopListener2);
1545               webview.find("click here!", {}, function() {
1546                 webview.stopFinding("activate");
1547               });
1548             });
1549           });
1550         });
1551       });
1552     });
1553   };
1555   webview.addEventListener('loadstop', loadstopListener1);
1556   document.body.appendChild(webview);
1559 function testFindAPI_findupdate() {
1560   var webview = new WebView();
1561   webview.src = 'data:text/html,Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1562       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1563       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1564       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1565       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1566       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1567       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1568       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1569       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
1570       'Dog dog dog Dog dog dogcatDog dogDogdog.<br><br>' +
1571       '<a href="about:blank">Click here!</a>';
1572   var canceledTest = false;
1573   webview.addEventListener('loadstop', function(e) {
1574     // Test the |findupdate| event.
1575     webview.addEventListener('findupdate', function(e) {
1576       if (e.activeMatchOrdinal > 0) {
1577         // embedder.test.assertTrue(e.numberOfMatches >= e.activeMatchOrdinal)
1578         // This currently fails because of http://crbug.com/342445 .
1579         embedder.test.assertTrue(e.selectionRect.width > 0);
1580         embedder.test.assertTrue(e.selectionRect.height > 0);
1581       }
1583       if (e.finalUpdate) {
1584         if (e.canceled) {
1585           canceledTest = true;
1586         } else {
1587           embedder.test.assertEq(e.searchText, "dog");
1588           embedder.test.assertEq(e.numberOfMatches, 100);
1589           embedder.test.assertEq(e.activeMatchOrdinal, 1);
1590           embedder.test.assertTrue(canceledTest);
1591           embedder.test.succeed();
1592         }
1593       }
1594     });
1595     wv.find("dog");
1596     wv.find("cat");
1597     wv.find("dog");
1598   });
1600   document.body.appendChild(webview);
1603 embedder.test.testList = {
1604   'testAutosizeAfterNavigation': testAutosizeAfterNavigation,
1605   'testAutosizeBeforeNavigation': testAutosizeBeforeNavigation,
1606   'testAutosizeRemoveAttributes': testAutosizeRemoveAttributes,
1607   'testAutosizeWithPartialAttributes': testAutosizeWithPartialAttributes,
1608   'testAPIMethodExistence': testAPIMethodExistence,
1609   'testChromeExtensionURL': testChromeExtensionURL,
1610   'testChromeExtensionRelativePath': testChromeExtensionRelativePath,
1611   'testInlineScriptFromAccessibleResources':
1612       testInlineScriptFromAccessibleResources,
1613   'testInvalidChromeExtensionURL': testInvalidChromeExtensionURL,
1614   'testWebRequestAPIExistence': testWebRequestAPIExistence,
1615   'testEventName': testEventName,
1616   'testOnEventProperties': testOnEventProperties,
1617   'testLoadProgressEvent': testLoadProgressEvent,
1618   'testDestroyOnEventListener': testDestroyOnEventListener,
1619   'testCannotMutateEventName': testCannotMutateEventName,
1620   'testPartitionRaisesException': testPartitionRaisesException,
1621   'testExecuteScriptFail': testExecuteScriptFail,
1622   'testExecuteScript': testExecuteScript,
1623   'testExecuteScriptIsAbortedWhenWebViewSourceIsChanged':
1624       testExecuteScriptIsAbortedWhenWebViewSourceIsChanged,
1625   'testTerminateAfterExit': testTerminateAfterExit,
1626   'testAssignSrcAfterCrash': testAssignSrcAfterCrash,
1627   'testNavOnConsecutiveSrcAttributeChanges':
1628       testNavOnConsecutiveSrcAttributeChanges,
1629   'testNavOnSrcAttributeChange': testNavOnSrcAttributeChange,
1630   'testReassignSrcAttribute': testReassignSrcAttribute,
1631   'testRemoveSrcAttribute': testRemoveSrcAttribute,
1632   'testBrowserPluginNotAllowed': testBrowserPluginNotAllowed,
1633   'testPluginLoadPermission': testPluginLoadPermission,
1634   'testNewWindow': testNewWindow,
1635   'testNewWindowTwoListeners': testNewWindowTwoListeners,
1636   'testNewWindowNoPreventDefault': testNewWindowNoPreventDefault,
1637   'testNewWindowNoReferrerLink': testNewWindowNoReferrerLink,
1638   'testContentLoadEvent': testContentLoadEvent,
1639   'testDeclarativeWebRequestAPI': testDeclarativeWebRequestAPI,
1640   'testWebRequestAPI': testWebRequestAPI,
1641   'testWebRequestAPIGoogleProperty': testWebRequestAPIGoogleProperty,
1642   'testWebRequestListenerSurvivesReparenting':
1643       testWebRequestListenerSurvivesReparenting,
1644   'testGetProcessId': testGetProcessId,
1645   'testLoadStartLoadRedirect': testLoadStartLoadRedirect,
1646   'testLoadAbortChromeExtensionURLWrongPartition':
1647       testLoadAbortChromeExtensionURLWrongPartition,
1648   'testLoadAbortEmptyResponse': testLoadAbortEmptyResponse,
1649   'testLoadAbortIllegalChromeURL': testLoadAbortIllegalChromeURL,
1650   'testLoadAbortIllegalFileURL': testLoadAbortIllegalFileURL,
1651   'testLoadAbortIllegalJavaScriptURL': testLoadAbortIllegalJavaScriptURL,
1652   'testLoadAbortInvalidNavigation': testLoadAbortInvalidNavigation,
1653   'testLoadAbortNonWebSafeScheme': testLoadAbortNonWebSafeScheme,
1654   'testNavigateAfterResize': testNavigateAfterResize,
1655   'testNavigationToExternalProtocol': testNavigationToExternalProtocol,
1656   'testReload': testReload,
1657   'testRemoveWebviewOnExit': testRemoveWebviewOnExit,
1658   'testRemoveWebviewAfterNavigation': testRemoveWebviewAfterNavigation,
1659   'testResizeWebviewResizesContent': testResizeWebviewResizesContent,
1660   'testPostMessageCommChannel': testPostMessageCommChannel,
1661   'testScreenshotCapture' : testScreenshotCapture,
1662   'testZoomAPI' : testZoomAPI,
1663   'testFindAPI': testFindAPI,
1664   'testFindAPI_findupdate': testFindAPI
1667 onload = function() {
1668   chrome.test.getConfig(function(config) {
1669     embedder.setUp_(config);
1670     chrome.test.sendMessage("Launched");
1671   });