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.
7 embedder.baseGuestURL = '';
8 embedder.emptyGuestURL = '';
9 embedder.windowOpenGuestURL = '';
10 embedder.noReferrerGuestURL = '';
11 embedder.redirectGuestURL = '';
12 embedder.redirectGuestURLDest = '';
13 embedder.closeSocketURL = '';
16 embedder.setUp_ = function(config) {
17 if (!config || !config.testServer) {
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);
41 embedder.test.testList[testName]();
44 // Creates a <webview> tag in document.body and returns the reference to it.
45 // It also sets a dummy src. The dummy src is significant because this makes
46 // sure that the <object> shim is created (asynchronously at this point) for the
47 // <webview> tag. This makes the <webview> tag ready for add/removeEventListener
49 util.createWebViewTagInDOM = function(partitionName) {
50 var webview = document.createElement('webview');
51 webview.style.width = '300px';
52 webview.style.height = '200px';
53 var urlDummy = 'data:text/html,<body>Initial dummy guest</body>';
54 webview.setAttribute('src', urlDummy);
55 webview.setAttribute('partition', partitionName);
56 document.body.appendChild(webview);
61 embedder.test.succeed = function() {
62 chrome.test.sendMessage('TEST_PASSED');
65 embedder.test.fail = function() {
66 chrome.test.sendMessage('TEST_FAILED');
69 embedder.test.assertEq = function(a, b) {
71 console.log('assertion failed: ' + a + ' != ' + b);
76 embedder.test.assertTrue = function(condition) {
78 console.log('assertion failed: true != ' + condition);
83 embedder.test.assertFalse = function(condition) {
85 console.log('assertion failed: false != ' + condition);
92 // This test verifies that if a browser plugin is in autosize mode before
93 // navigation then the guest starts auto-sized.
94 function testAutosizeBeforeNavigation() {
95 var webview = document.createElement('webview');
97 webview.setAttribute('autosize', 'true');
98 webview.setAttribute('minwidth', 200);
99 webview.setAttribute('maxwidth', 210);
100 webview.setAttribute('minheight', 100);
101 webview.setAttribute('maxheight', 110);
103 webview.addEventListener('sizechanged', function(e) {
104 embedder.test.assertEq(0, e.oldWidth);
105 embedder.test.assertEq(0, e.oldHeight);
106 embedder.test.assertTrue(e.newWidth >= 200 && e.newWidth <= 210);
107 embedder.test.assertTrue(e.newHeight >= 100 && e.newHeight <= 110);
108 embedder.test.succeed();
111 webview.setAttribute('src', 'data:text/html,webview test sizechanged event');
112 document.body.appendChild(webview);
115 // Makes sure 'sizechanged' event is fired only if autosize attribute is
117 // After loading <webview> without autosize attribute and a size, say size1,
118 // we set autosize attribute and new min size with size2. We would get (only
119 // one) sizechanged event with size1 as old size and size2 as new size.
120 function testAutosizeAfterNavigation() {
121 var webview = document.createElement('webview');
124 var sizeChangeHandler = function(e) {
127 // This would be triggered after we set autosize attribute.
128 embedder.test.assertEq(50, e.oldWidth);
129 embedder.test.assertEq(100, e.oldHeight);
130 embedder.test.assertTrue(e.newWidth >= 60 && e.newWidth <= 70);
131 embedder.test.assertTrue(e.newHeight >= 110 && e.newHeight <= 120);
133 // Remove autosize attribute and expect webview to return to its
135 webview.removeAttribute('autosize');
139 embedder.test.assertEq(50, e.newWidth);
140 embedder.test.assertEq(100, e.newHeight);
142 embedder.test.succeed();
145 window.console.log('Unexpected sizechanged event, step = ' + step);
146 embedder.test.fail();
153 webview.addEventListener('sizechanged', sizeChangeHandler);
155 webview.addEventListener('loadstop', function(e) {
156 webview.setAttribute('autosize', true);
157 webview.setAttribute('minwidth', 60);
158 webview.setAttribute('maxwidth', 70);
159 webview.setAttribute('minheight', 110);
160 webview.setAttribute('maxheight', 120);
163 webview.style.width = '50px';
164 webview.style.height = '100px';
165 webview.setAttribute('src', 'data:text/html,webview test sizechanged event');
166 document.body.appendChild(webview);
169 // This test verifies that autosize works when some of the parameters are unset.
170 function testAutosizeWithPartialAttributes() {
171 window.console.log('testAutosizeWithPartialAttributes');
172 var webview = document.createElement('webview');
175 var sizeChangeHandler = function(e) {
176 window.console.log('sizeChangeHandler, new: ' +
177 e.newWidth + ' X ' + e.newHeight);
181 embedder.test.assertEq(300, e.newWidth);
182 embedder.test.assertEq(200, e.newHeight);
184 // Change the min size to cause a relayout.
185 webview.minwidth = 500;
188 embedder.test.assertTrue(e.newWidth >= webview.minwidth);
189 embedder.test.assertTrue(e.newWidth <= webview.maxwidth);
191 // Tests when minwidth > maxwidth, minwidth = maxwidth.
192 // i.e. minwidth is essentially 700.
193 webview.minwidth = 800;
197 embedder.test.assertEq(700, e.newWidth);
198 embedder.test.assertTrue(e.newHeight >= 200);
199 embedder.test.assertTrue(e.newHeight <= 600);
201 embedder.test.succeed();
204 window.console.log('Unexpected sizechanged event, step = ' + step);
205 embedder.test.fail();
212 webview.addEventListener('sizechanged', sizeChangeHandler);
214 webview.addEventListener('loadstop', function(e) {
215 webview.minwidth = 300;
216 webview.maxwidth = 700;
217 webview.minheight = 200;
218 webview.maxheight = 600;
219 webview.autosize = true;
222 webview.style.width = '640px';
223 webview.style.height = '480px';
224 webview.setAttribute('src', 'data:text/html,webview check autosize');
225 document.body.appendChild(webview);
228 // This test verifies that all autosize attributes can be removed
229 // without crashing the plugin, or throwing errors.
230 function testAutosizeRemoveAttributes() {
231 var webview = document.createElement('webview');
234 var sizeChangeHandler = function(e) {
237 // This is the sizechanged event for autosize.
239 // Remove attributes.
240 webview.removeAttribute('minwidth');
241 webview.removeAttribute('maxwidth');
242 webview.removeAttribute('minheight');
243 webview.removeAttribute('maxheight');
244 webview.removeAttribute('autosize');
246 // We'd get one more sizechanged event after we turn off
248 webview.style.width = '500px';
249 webview.style.height = '500px';
252 embedder.test.succeed();
259 webview.addEventListener('loadstop', function(e) {
260 webview.minwidth = 300;
261 webview.maxwidth = 700;
262 webview.minheight = 600;
263 webview.maxheight = 400;
264 webview.autosize = true;
267 webview.addEventListener('sizechanged', sizeChangeHandler);
269 webview.style.width = '640px';
270 webview.style.height = '480px';
271 webview.setAttribute('src', 'data:text/html,webview check autosize');
272 document.body.appendChild(webview);
275 function testAPIMethodExistence() {
276 var apiMethodsToCheck = [
287 var webview = document.createElement('webview');
288 webview.setAttribute('partition', arguments.callee.name);
289 webview.addEventListener('loadstop', function(e) {
290 for (var i = 0; i < apiMethodsToCheck.length; ++i) {
291 embedder.test.assertEq('function',
292 typeof webview[apiMethodsToCheck[i]]);
295 // Check contentWindow.
296 embedder.test.assertEq('object', typeof webview.contentWindow);
297 embedder.test.assertEq('function',
298 typeof webview.contentWindow.postMessage);
299 embedder.test.succeed();
301 webview.setAttribute('src', 'data:text/html,webview check api');
302 document.body.appendChild(webview);
305 // This test verifies that the loadstop event fires when loading a webview
306 // accessible resource from a partition that is privileged.
307 function testChromeExtensionURL() {
308 var localResource = chrome.runtime.getURL('guest.html');
309 var webview = document.createElement('webview');
310 // foobar is a privileged partition according to the manifest file.
311 webview.partition = 'foobar';
312 webview.addEventListener('loadabort', function(e) {
313 embedder.test.fail();
315 webview.addEventListener('loadstop', function(e) {
316 embedder.test.succeed();
318 webview.setAttribute('src', localResource);
319 document.body.appendChild(webview);
322 // This test verifies that the loadstop event fires when loading a webview
323 // accessible resource from a partition that is privileged if the src URL
324 // is not fully qualified.
325 function testChromeExtensionRelativePath() {
326 var webview = document.createElement('webview');
327 // foobar is a privileged partition according to the manifest file.
328 webview.partition = 'foobar';
329 webview.addEventListener('loadabort', function(e) {
330 embedder.test.fail();
332 webview.addEventListener('loadstop', function(e) {
333 embedder.test.succeed();
335 webview.setAttribute('src', 'guest.html');
336 document.body.appendChild(webview);
339 // This tests verifies that webview fires a loadabort event instead of crashing
340 // the browser if we attempt to navigate to a chrome-extension: URL with an
341 // extension ID that does not exist.
342 function testInvalidChromeExtensionURL() {
343 var invalidResource = 'chrome-extension://abc123/guest.html';
344 var webview = document.createElement('webview');
345 // foobar is a privileged partition according to the manifest file.
346 webview.partition = 'foobar';
347 webview.addEventListener('loadabort', function(e) {
348 embedder.test.succeed();
350 webview.setAttribute('src', invalidResource);
351 document.body.appendChild(webview);
354 function testWebRequestAPIExistence() {
355 var apiPropertiesToCheck = [
356 // Declarative WebRequest API.
361 'onBeforeSendHeaders',
370 var webview = document.createElement('webview');
371 webview.setAttribute('partition', arguments.callee.name);
372 webview.addEventListener('loadstop', function(e) {
373 for (var i = 0; i < apiPropertiesToCheck.length; ++i) {
374 embedder.test.assertEq('object',
375 typeof webview.request[apiPropertiesToCheck[i]]);
376 embedder.test.assertEq(
378 typeof webview.request[apiPropertiesToCheck[i]].addListener);
379 embedder.test.assertEq(
381 typeof webview.request[apiPropertiesToCheck[i]].addRules);
382 embedder.test.assertEq(
384 typeof webview.request[apiPropertiesToCheck[i]].getRules);
385 embedder.test.assertEq(
387 typeof webview.request[apiPropertiesToCheck[i]].removeRules);
389 embedder.test.succeed();
391 webview.setAttribute('src', 'data:text/html,webview check api');
392 document.body.appendChild(webview);
395 // This test verifies that the loadstart, loadstop, and exit events fire as
397 function testEventName() {
398 var webview = document.createElement('webview');
399 webview.setAttribute('partition', arguments.callee.name);
401 webview.addEventListener('loadstart', function(evt) {
402 embedder.test.assertEq('loadstart', evt.type);
405 webview.addEventListener('loadstop', function(evt) {
406 embedder.test.assertEq('loadstop', evt.type);
410 webview.addEventListener('exit', function(evt) {
411 embedder.test.assertEq('exit', evt.type);
412 embedder.test.succeed();
415 webview.setAttribute('src', 'data:text/html,trigger navigation');
416 document.body.appendChild(webview);
419 function testOnEventProperties() {
420 var sequence = ['first', 'second', 'third', 'fourth'];
421 var webview = document.createElement('webview');
422 function createHandler(id) {
424 embedder.test.assertEq(id, sequence.shift());
428 webview.addEventListener('loadstart', createHandler('first'));
429 webview.addEventListener('loadstart', createHandler('second'));
430 webview.onloadstart = createHandler('third');
431 webview.addEventListener('loadstart', createHandler('fourth'));
432 webview.addEventListener('loadstop', function(evt) {
433 embedder.test.assertEq(0, sequence.length);
435 // Test that setting another 'onloadstart' handler replaces the previous
437 sequence = ['first', 'second', 'fourth'];
438 webview.onloadstart = function() {
439 embedder.test.assertEq(0, sequence.length);
440 embedder.test.succeed();
443 webview.setAttribute('src', 'data:text/html,next navigation');
446 webview.setAttribute('src', 'data:text/html,trigger navigation');
447 document.body.appendChild(webview);
450 // Tests that the 'loadprogress' event is triggered correctly.
451 function testLoadProgressEvent() {
452 var webview = document.createElement('webview');
455 webview.addEventListener('loadstop', function(evt) {
456 embedder.test.assertEq(1, progress);
457 embedder.test.succeed();
460 webview.addEventListener('loadprogress', function(evt) {
461 progress = evt.progress;
464 webview.setAttribute('src', 'data:text/html,trigger navigation');
465 document.body.appendChild(webview);
468 // This test registers two listeners on an event (loadcommit) and removes
469 // the <webview> tag when the first listener fires.
470 // Current expected behavior is that the second event listener will still
471 // fire without crashing.
472 function testDestroyOnEventListener() {
473 var webview = util.createWebViewTagInDOM(arguments.callee.name);
474 var url = 'data:text/html,<body>Destroy test</body>';
476 var loadCommitCount = 0;
477 function loadCommitCommon(e) {
478 embedder.test.assertEq('loadcommit', e.type);
482 if (loadCommitCount == 1) {
483 setTimeout(function() {
484 embedder.test.succeed();
486 } else if (loadCommitCount > 2) {
487 embedder.test.fail();
491 // The test starts from here, by setting the src to |url|.
492 webview.addEventListener('loadcommit', function(e) {
493 webview.parentNode.removeChild(webview);
496 webview.addEventListener('loadcommit', function(e) {
499 webview.setAttribute('src', url);
502 // This test registers two event listeners on a same event (loadcommit).
503 // Each of the listener tries to change some properties on the event param,
504 // which should not be possible.
505 function testCannotMutateEventName() {
506 var webview = util.createWebViewTagInDOM(arguments.callee.name);
507 var url = 'data:text/html,<body>Two</body>';
509 var loadCommitACalled = false;
510 var loadCommitBCalled = false;
512 var maybeFinishTest = function(e) {
513 if (loadCommitACalled && loadCommitBCalled) {
514 embedder.test.assertEq('loadcommit', e.type);
515 embedder.test.succeed();
519 var onLoadCommitA = function(e) {
521 embedder.test.assertEq('loadcommit', e.type);
522 embedder.test.assertTrue(e.isTopLevel);
523 embedder.test.assertFalse(loadCommitACalled);
524 loadCommitACalled = true;
525 // Try mucking with properities inside |e|.
530 var onLoadCommitB = function(e) {
532 embedder.test.assertEq('loadcommit', e.type);
533 embedder.test.assertTrue(e.isTopLevel);
534 embedder.test.assertFalse(loadCommitBCalled);
535 loadCommitBCalled = true;
536 // Try mucking with properities inside |e|.
542 // The test starts from here, by setting the src to |url|. Event
543 // listener registration works because we already have a (dummy) src set
544 // on the <webview> tag.
545 webview.addEventListener('loadcommit', onLoadCommitA);
546 webview.addEventListener('loadcommit', onLoadCommitB);
547 webview.setAttribute('src', url);
550 // This test verifies that setting the partition attribute after the src has
551 // been set raises an exception.
552 function testPartitionRaisesException() {
553 var webview = document.createElement('webview');
554 webview.setAttribute('partition', arguments.callee.name);
555 webview.setAttribute('src', 'data:text/html,trigger navigation');
556 document.body.appendChild(webview);
557 setTimeout(function() {
559 webview.partition = 'illegal';
560 embedder.test.fail();
562 embedder.test.succeed();
567 function testExecuteScriptFail() {
568 var webview = document.createElement('webview');
569 document.body.appendChild(webview);
570 setTimeout(function() {
572 webview.executeScript(
573 {code:'document.body.style.backgroundColor = "red";'},
575 embedder.test.fail();
578 embedder.test.succeed();
583 function testExecuteScript() {
584 var webview = document.createElement('webview');
585 webview.setAttribute('partition', arguments.callee.name);
586 webview.addEventListener('loadstop', function() {
587 webview.executeScript(
588 {code:'document.body.style.backgroundColor = "red";'},
590 embedder.test.assertEq(1, results.length);
591 embedder.test.assertEq('red', results[0]);
592 embedder.test.succeed();
595 webview.setAttribute('src', 'data:text/html,trigger navigation');
596 document.body.appendChild(webview);
599 // This test calls terminate() on guest after it has already been
600 // terminated. This makes sure we ignore the call gracefully.
601 function testTerminateAfterExit() {
602 var webview = document.createElement('webview');
603 webview.setAttribute('partition', arguments.callee.name);
604 var loadstopSucceedsTest = false;
605 webview.addEventListener('loadstop', function(evt) {
606 embedder.test.assertEq('loadstop', evt.type);
607 if (loadstopSucceedsTest) {
608 embedder.test.succeed();
615 webview.addEventListener('exit', function(evt) {
616 embedder.test.assertEq('exit', evt.type);
617 // Call terminate again.
619 // Load another page. The test would pass when loadstop is called on
620 // this second page. This would hopefully catch if call to
621 // webview.terminate() caused a browser crash.
622 setTimeout(function() {
623 loadstopSucceedsTest = true;
624 webview.setAttribute('src', 'data:text/html,test second page');
628 webview.setAttribute('src', 'data:text/html,test terminate() crash.');
629 document.body.appendChild(webview);
632 // This test verifies that multiple consecutive changes to the <webview> src
633 // attribute will cause a navigation.
634 function testNavOnConsecutiveSrcAttributeChanges() {
635 var testPage1 = 'data:text/html,test page 1';
636 var testPage2 = 'data:text/html,test page 2';
637 var testPage3 = 'data:text/html,test page 3';
638 var webview = new WebView();
639 webview.partition = arguments.callee.name;
640 var loadCommitCount = 0;
641 webview.addEventListener('loadcommit', function(e) {
642 if (e.url == testPage3) {
643 embedder.test.succeed();
646 if (loadCommitCount > 3) {
647 embedder.test.fail();
650 document.body.appendChild(webview);
651 webview.src = testPage1;
652 webview.src = testPage2;
653 webview.src = testPage3;
656 // This test verifies that we can set the <webview> src multiple times and the
657 // changes will cause a navigation.
658 function testNavOnSrcAttributeChange() {
659 var testPage1 = 'data:text/html,test page 1';
660 var testPage2 = 'data:text/html,test page 2';
661 var testPage3 = 'data:text/html,test page 3';
662 var tests = [testPage1, testPage2, testPage3];
663 var webview = new WebView();
664 webview.partition = arguments.callee.name;
665 var loadCommitCount = 0;
666 webview.addEventListener('loadcommit', function(evt) {
667 var success = tests.indexOf(evt.url) > -1;
668 embedder.test.assertTrue(success);
670 if (loadCommitCount == tests.length) {
671 embedder.test.succeed();
672 } else if (loadCommitCount > tests.length) {
673 embedder.test.fail();
675 webview.src = tests[loadCommitCount];
678 webview.src = tests[0];
679 document.body.appendChild(webview);
682 // This test verifies that assigning the src attribute the same value it had
683 // prior to a crash spawns off a new guest process.
684 function testAssignSrcAfterCrash() {
685 var webview = document.createElement('webview');
686 webview.setAttribute('partition', arguments.callee.name);
687 var terminated = false;
688 webview.addEventListener('loadstop', function(evt) {
693 // The guest has recovered after being terminated.
694 embedder.test.succeed();
696 webview.addEventListener('exit', function(evt) {
698 webview.setAttribute('src', 'data:text/html,test page');
700 webview.setAttribute('src', 'data:text/html,test page');
701 document.body.appendChild(webview);
704 // This test verifies that <webview> reloads the page if the src attribute is
705 // assigned the same value.
706 function testReassignSrcAttribute() {
707 var dataUrl = 'data:text/html,test page';
708 var webview = new WebView();
709 webview.partition = arguments.callee.name;
711 var loadStopCount = 0;
712 webview.addEventListener('loadstop', function(evt) {
713 embedder.test.assertEq(dataUrl, webview.getAttribute('src'));
715 console.log('[' + loadStopCount + '] loadstop called');
716 if (loadStopCount == 3) {
717 embedder.test.succeed();
718 } else if (loadStopCount > 3) {
719 embedder.test.fail();
721 webview.src = dataUrl;
724 webview.src = dataUrl;
725 document.body.appendChild(webview);
728 // This test verifies that <webview> restores the src attribute if it is
729 // removed after navigation.
730 function testRemoveSrcAttribute() {
731 var dataUrl = 'data:text/html,test page';
732 var webview = document.createElement('webview');
733 webview.setAttribute('partition', arguments.callee.name);
734 var terminated = false;
735 webview.addEventListener('loadstop', function(evt) {
736 webview.removeAttribute('src');
737 setTimeout(function() {
738 embedder.test.assertEq(dataUrl, webview.getAttribute('src'));
739 embedder.test.succeed();
742 webview.setAttribute('src', dataUrl);
743 document.body.appendChild(webview);
746 // This test verifies that it is not possible to instantiate a browser plugin
747 // directly within an app.
748 function testBrowserPluginNotAllowed() {
749 var container = document.getElementById('object-container');
751 embedder.test.fail('Container for object not found.');
754 container.innerHTML = '<object type="application/browser-plugin"' +
755 ' id="object-plugin"' +
756 ' src="data:text/html,<body>You should not see this</body>">' +
758 var objectElement = document.getElementById('object-plugin');
759 // Check that bindings are not registered.
760 embedder.test.assertTrue(
761 objectElement['-internal-attach'] === undefined);
762 embedder.test.succeed();
765 function testPluginLoadPermission() {
766 var pluginIdentifier = 'unknown platform';
767 if (navigator.platform.match(/linux/i))
768 pluginIdentifier = 'libppapi_tests.so';
769 else if (navigator.platform.match(/win32/i))
770 pluginIdentifier = 'ppapi_tests.dll';
771 else if (navigator.platform.match(/mac/i))
772 pluginIdentifier = 'ppapi_tests.plugin';
774 var webview = document.createElement('webview');
775 webview.addEventListener('permissionrequest', function(e) {
777 embedder.test.assertEq('loadplugin', e.permission);
778 embedder.test.assertEq(pluginIdentifier, e.name);
779 embedder.test.assertEq(pluginIdentifier, e.identifier);
780 embedder.test.assertEq('function', typeof e.request.allow);
781 embedder.test.assertEq('function', typeof e.request.deny);
782 embedder.test.succeed();
784 webview.setAttribute('src', 'data:text/html,<body>' +
785 '<embed type="application/x-ppapi-tests">' +
787 document.body.appendChild(webview);
790 // This test verifies that new window attachment functions as expected.
791 function testNewWindow() {
792 var webview = document.createElement('webview');
793 webview.addEventListener('newwindow', function(e) {
795 var newwebview = document.createElement('webview');
796 newwebview.addEventListener('loadstop', function(evt) {
797 // If the new window finishes loading, the test is successful.
798 embedder.test.succeed();
800 document.body.appendChild(newwebview);
801 // Attach the new window to the new <webview>.
802 e.window.attach(newwebview);
804 webview.setAttribute('src', embedder.windowOpenGuestURL);
805 document.body.appendChild(webview);
808 // This test verifies "first-call-wins" semantics. That is, the first call
809 // to perform an action on the new window takes the action and all
810 // subsequent calls throw an exception.
811 function testNewWindowTwoListeners() {
812 var webview = document.createElement('webview');
814 webview.addEventListener('newwindow', function(e) {
816 var newwebview = document.createElement('webview');
817 document.body.appendChild(newwebview);
819 e.window.attach(newwebview);
821 embedder.test.fail();
824 webview.addEventListener('newwindow', function(e) {
829 embedder.test.succeed();
832 webview.setAttribute('src', embedder.windowOpenGuestURL);
833 document.body.appendChild(webview);
836 // This test verifies that the attach can be called inline without
837 // preventing default.
838 function testNewWindowNoPreventDefault() {
839 var webview = document.createElement('webview');
840 webview.addEventListener('newwindow', function(e) {
841 var newwebview = document.createElement('webview');
842 document.body.appendChild(newwebview);
843 // Attach the new window to the new <webview>.
845 e.window.attach(newwebview);
846 embedder.test.succeed();
848 embedder.test.fail();
851 webview.setAttribute('src', embedder.windowOpenGuestURL);
852 document.body.appendChild(webview);
855 function testNewWindowNoReferrerLink() {
856 var webview = document.createElement('webview');
857 webview.addEventListener('newwindow', function(e) {
859 var newwebview = document.createElement('webview');
860 newwebview.addEventListener('loadstop', function(evt) {
861 // If the new window finishes loading, the test is successful.
862 embedder.test.succeed();
864 document.body.appendChild(newwebview);
865 // Attach the new window to the new <webview>.
866 e.window.attach(newwebview);
868 webview.setAttribute('src', embedder.noReferrerGuestURL);
869 document.body.appendChild(webview);
872 // This test verifies that the load event fires when the a new page is
874 // TODO(fsamuel): Add a test to verify that subframe loads within a guest
875 // do not fire the 'contentload' event.
876 function testContentLoadEvent() {
877 var webview = document.createElement('webview');
878 webview.addEventListener('contentload', function(e) {
879 embedder.test.succeed();
881 webview.setAttribute('src', 'data:text/html,trigger navigation');
882 document.body.appendChild(webview);
885 // This test verifies that the WebRequest API onBeforeRequest event fires on
887 function testWebRequestAPI() {
888 var webview = new WebView();
889 webview.request.onBeforeRequest.addListener(function(e) {
890 embedder.test.succeed();
891 }, { urls: ['<all_urls>']}) ;
892 webview.src = embedder.windowOpenGuestURL;
893 document.body.appendChild(webview);
896 // This test verifies that the basic use cases of the declarative WebRequest API
897 // work as expected. This test demonstrates that rules can be added prior to
898 // navigation and attachment.
899 // 1. It adds a rule to block URLs that contain guest.
900 // 2. It attempts to navigate to a guest.html page.
901 // 3. It detects the appropriate loadabort message.
902 // 4. It removes the rule blocking the page and reloads.
903 // 5. The page loads successfully.
904 function testDeclarativeWebRequestAPI() {
906 var webview = new WebView();
909 new chrome.webViewRequest.RequestMatcher(
911 url: { urlContains: 'guest' }
916 new chrome.webViewRequest.CancelRequest()
919 webview.request.onRequest.addRules([rule]);
920 webview.addEventListener('loadabort', function(e) {
921 embedder.test.assertEq(1, step);
922 embedder.test.assertEq('ERR_BLOCKED_BY_CLIENT', e.reason);
924 webview.request.onRequest.removeRules();
927 webview.addEventListener('loadcommit', function(e) {
928 embedder.test.assertEq(2, step);
929 embedder.test.succeed();
931 webview.src = embedder.emptyGuestURL;
932 document.body.appendChild(webview);
935 // This test verifies that the WebRequest API onBeforeRequest event fires on
936 // clients*.google.com URLs.
937 function testWebRequestAPIGoogleProperty() {
938 var webview = new WebView();
939 webview.request.onBeforeRequest.addListener(function(e) {
940 embedder.test.succeed();
941 return {cancel: true};
942 }, { urls: ['<all_urls>']}, ['blocking']) ;
943 webview.src = 'http://clients6.google.com';
944 document.body.appendChild(webview);
947 // This test verifies that the WebRequest event listener for onBeforeRequest
948 // survives reparenting of the <webview>.
949 function testWebRequestListenerSurvivesReparenting() {
950 var webview = new WebView();
952 webview.request.onBeforeRequest.addListener(function(e) {
954 embedder.test.succeed();
956 }, { urls: ['<all_urls>']});
957 var onLoadStop = function(e) {
958 webview.removeEventListener('loadstop', onLoadStop);
959 webview.parentNode.removeChild(webview);
960 var container = document.getElementById('object-container');
962 embedder.test.fail('Container for object not found.');
965 container.appendChild(webview);
967 webview.addEventListener('loadstop', onLoadStop);
968 webview.src = embedder.emptyGuestURL;
969 document.body.appendChild(webview);
972 // This test verifies that getProcessId is defined and returns a non-zero
973 // value corresponding to the processId of the guest process.
974 function testGetProcessId() {
975 var webview = document.createElement('webview');
976 webview.setAttribute('src', 'data:text/html,trigger navigation');
977 var firstLoad = function() {
978 webview.removeEventListener('loadstop', firstLoad);
979 embedder.test.assertTrue(webview.getProcessId() > 0);
980 embedder.test.succeed();
982 webview.addEventListener('loadstop', firstLoad);
983 document.body.appendChild(webview);
986 // This test verifies that the loadstart event fires at the beginning of a load
987 // and the loadredirect event fires when a redirect occurs.
988 function testLoadStartLoadRedirect() {
989 var webview = document.createElement('webview');
990 var loadstartCalled = false;
991 webview.setAttribute('src', embedder.redirectGuestURL);
992 webview.addEventListener('loadstart', function(e) {
993 embedder.test.assertTrue(e.isTopLevel);
994 embedder.test.assertEq(embedder.redirectGuestURL, e.url);
995 loadstartCalled = true;
997 webview.addEventListener('loadredirect', function(e) {
998 embedder.test.assertTrue(e.isTopLevel);
999 embedder.test.assertEq(embedder.redirectGuestURL,
1000 e.oldUrl.replace('127.0.0.1', 'localhost'));
1001 embedder.test.assertEq(embedder.redirectGuestURLDest,
1002 e.newUrl.replace('127.0.0.1', 'localhost'));
1003 if (loadstartCalled) {
1004 embedder.test.succeed();
1006 embedder.test.fail();
1009 document.body.appendChild(webview);
1012 // This test verifies that the loadabort event fires when loading a webview
1013 // accessible resource from a partition that is not privileged.
1014 function testLoadAbortChromeExtensionURLWrongPartition() {
1015 var localResource = chrome.runtime.getURL('guest.html');
1016 var webview = document.createElement('webview');
1017 webview.addEventListener('loadabort', function(e) {
1018 embedder.test.assertEq('ERR_ADDRESS_UNREACHABLE', e.reason);
1019 embedder.test.succeed();
1021 webview.addEventListener('loadstop', function(e) {
1022 embedder.test.fail();
1024 webview.setAttribute('src', localResource);
1025 document.body.appendChild(webview);
1028 // This test verifies that the loadabort event fires as expected and with the
1029 // appropriate fields when an empty response is returned.
1030 function testLoadAbortEmptyResponse() {
1031 var webview = document.createElement('webview');
1032 webview.addEventListener('loadabort', function(e) {
1033 embedder.test.assertEq('ERR_EMPTY_RESPONSE', e.reason);
1034 embedder.test.succeed();
1036 webview.setAttribute('src', embedder.closeSocketURL);
1037 document.body.appendChild(webview);
1040 // This test verifies that the loadabort event fires as expected when an illegal
1041 // chrome URL is provided.
1042 function testLoadAbortIllegalChromeURL() {
1043 var webview = document.createElement('webview');
1044 var onFirstLoadStop = function(e) {
1045 webview.removeEventListener('loadstop', onFirstLoadStop);
1046 webview.setAttribute('src', 'chrome://newtab');
1048 webview.addEventListener('loadstop', onFirstLoadStop);
1049 webview.addEventListener('loadabort', function(e) {
1050 embedder.test.assertEq('ERR_ABORTED', e.reason);
1051 embedder.test.succeed();
1053 webview.setAttribute('src', 'about:blank');
1054 document.body.appendChild(webview);
1057 function testLoadAbortIllegalFileURL() {
1058 var webview = document.createElement('webview');
1059 webview.addEventListener('loadabort', function(e) {
1060 embedder.test.assertEq('ERR_ABORTED', e.reason);
1061 embedder.test.succeed();
1063 webview.setAttribute('src', 'file://foo');
1064 document.body.appendChild(webview);
1067 function testLoadAbortIllegalJavaScriptURL() {
1068 var webview = document.createElement('webview');
1069 webview.addEventListener('loadabort', function(e) {
1070 embedder.test.assertEq('ERR_ABORTED', e.reason);
1071 embedder.test.succeed();
1073 webview.setAttribute('src', 'javascript:void(document.bgColor="#0000FF")');
1074 document.body.appendChild(webview);
1077 // This test verifies that the reload method on webview functions as expected.
1078 function testReload() {
1079 var triggerNavUrl = 'data:text/html,trigger navigation';
1080 var webview = document.createElement('webview');
1082 var loadCommitCount = 0;
1083 webview.addEventListener('loadstop', function(e) {
1084 if (loadCommitCount < 2) {
1086 } else if (loadCommitCount == 2) {
1087 embedder.test.succeed();
1089 embedder.test.fail();
1092 webview.addEventListener('loadcommit', function(e) {
1093 embedder.test.assertEq(triggerNavUrl, e.url);
1094 embedder.test.assertTrue(e.isTopLevel);
1098 webview.setAttribute('src', triggerNavUrl);
1099 document.body.appendChild(webview);
1102 // This test verifies that a <webview> is torn down gracefully when removed from
1105 window.removeWebviewOnExitDoCrash = null;
1107 function testRemoveWebviewOnExit() {
1108 var triggerNavUrl = 'data:text/html,trigger navigation';
1109 var webview = document.createElement('webview');
1111 webview.addEventListener('loadstop', function(e) {
1112 chrome.test.sendMessage('guest-loaded');
1115 window.removeWebviewOnExitDoCrash = function() {
1116 webview.terminate();
1119 webview.addEventListener('exit', function(e) {
1120 // We expected to be killed.
1121 if (e.reason != 'killed') {
1122 console.log('EXPECTED TO BE KILLED!');
1125 webview.parentNode.removeChild(webview);
1128 // Trigger a navigation to create a guest process.
1129 webview.setAttribute('src', embedder.emptyGuestURL);
1130 document.body.appendChild(webview);
1133 function testRemoveWebviewAfterNavigation() {
1134 var webview = new WebView();
1135 document.body.appendChild(webview);
1136 webview.src = 'data:text/html,trigger navigation';
1137 document.body.removeChild(webview);
1138 setTimeout(function() {
1139 embedder.test.succeed();
1143 function testNavigationToExternalProtocol() {
1144 var webview = document.createElement('webview');
1145 webview.addEventListener('loadstop', function(e) {
1146 webview.addEventListener('loadabort', function(e) {
1147 embedder.test.assertEq('ERR_UNKNOWN_URL_SCHEME', e.reason);
1148 embedder.test.succeed();
1150 webview.executeScript({
1151 code: 'window.location.href = "tel:+12223334444";'
1152 }, function(results) {});
1154 webview.setAttribute('src', 'data:text/html,navigate to external protocol');
1155 document.body.appendChild(webview);
1158 function testResizeWebviewResizesContent() {
1159 var webview = new WebView();
1160 webview.src = 'about:blank';
1161 webview.addEventListener('loadstop', function(e) {
1162 webview.executeScript(
1163 {file: 'inject_resize_test.js'},
1165 window.console.log('The resize test has been injected into webview.');
1168 webview.executeScript(
1169 {file: 'inject_comm_channel.js'},
1171 window.console.log('The guest script for a two-way comm channel has ' +
1172 'been injected into webview.');
1173 // Establish a communication channel with the guest.
1174 var msg = ['connect'];
1175 webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1179 window.addEventListener('message', function(e) {
1180 var data = JSON.parse(e.data);
1181 if (data[0] == 'connected') {
1182 console.log('A communication channel has been established with webview.');
1183 console.log('Resizing <webview> width from 300px to 400px.');
1184 webview.style.width = '400px';
1187 if (data[0] == 'resize') {
1188 var width = data[1];
1189 var height = data[2];
1190 embedder.test.assertEq(400, width);
1191 embedder.test.assertEq(300, height);
1192 embedder.test.succeed();
1195 console.log('Unexpected message: \'' + data[0] + '\'');
1196 embedder.test.fail();
1198 document.body.appendChild(webview);
1201 function testPostMessageCommChannel() {
1202 var webview = new WebView();
1203 webview.src = 'about:blank';
1204 webview.addEventListener('loadstop', function(e) {
1205 webview.executeScript(
1206 {file: 'inject_comm_channel.js'},
1208 window.console.log('The guest script for a two-way comm channel has ' +
1209 'been injected into webview.');
1210 // Establish a communication channel with the guest.
1211 var msg = ['connect'];
1212 webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1216 window.addEventListener('message', function(e) {
1217 var data = JSON.parse(e.data);
1218 if (data[0] == 'connected') {
1219 console.log('A communication channel has been established with webview.');
1220 embedder.test.succeed();
1223 console.log('Unexpected message: \'' + data[0] + '\'');
1224 embedder.test.fail();
1226 document.body.appendChild(webview);
1229 function testScreenshotCapture() {
1230 var webview = document.createElement('webview');
1232 webview.addEventListener('loadstop', function(e) {
1233 webview.captureVisibleRegion(null, function(dataUrl) {
1235 var expectedUrl = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/' +
1236 '2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLE' +
1237 'BYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFB' +
1238 'QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCABkAGQ' +
1239 'DASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAA' +
1240 'AgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM' +
1241 '2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3' +
1242 'R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8j' +
1243 'JytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAA' +
1244 'AAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBU' +
1245 'QdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERU' +
1246 'ZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqO' +
1247 'kpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3' +
1248 '+Pn6/9oADAMBAAIRAxEAPwD50ooor8MP9UwooooAKKKKACiiigAooooAKKKKACiii' +
1249 'gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiig' +
1250 'AooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigA' +
1251 'ooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAo' +
1252 'oooAKKKKACiiigAooooAKKKKACiiigD/2Q==';
1253 embedder.test.assertEq(expectedUrl, dataUrl);
1254 embedder.test.succeed();
1258 webview.style.width = '100px';
1259 webview.style.height = '100px';
1260 webview.setAttribute('src',
1261 'data:text/html,<body style="background-color: red"></body>');
1262 document.body.appendChild(webview);
1265 embedder.test.testList = {
1266 'testAutosizeAfterNavigation': testAutosizeAfterNavigation,
1267 'testAutosizeBeforeNavigation': testAutosizeBeforeNavigation,
1268 'testAutosizeRemoveAttributes': testAutosizeRemoveAttributes,
1269 'testAutosizeWithPartialAttributes': testAutosizeWithPartialAttributes,
1270 'testAPIMethodExistence': testAPIMethodExistence,
1271 'testChromeExtensionURL': testChromeExtensionURL,
1272 'testChromeExtensionRelativePath': testChromeExtensionRelativePath,
1273 'testInvalidChromeExtensionURL': testInvalidChromeExtensionURL,
1274 'testWebRequestAPIExistence': testWebRequestAPIExistence,
1275 'testEventName': testEventName,
1276 'testOnEventProperties': testOnEventProperties,
1277 'testLoadProgressEvent': testLoadProgressEvent,
1278 'testDestroyOnEventListener': testDestroyOnEventListener,
1279 'testCannotMutateEventName': testCannotMutateEventName,
1280 'testPartitionRaisesException': testPartitionRaisesException,
1281 'testExecuteScriptFail': testExecuteScriptFail,
1282 'testExecuteScript': testExecuteScript,
1283 'testTerminateAfterExit': testTerminateAfterExit,
1284 'testAssignSrcAfterCrash': testAssignSrcAfterCrash,
1285 'testNavOnConsecutiveSrcAttributeChanges':
1286 testNavOnConsecutiveSrcAttributeChanges,
1287 'testNavOnSrcAttributeChange': testNavOnSrcAttributeChange,
1288 'testReassignSrcAttribute': testReassignSrcAttribute,
1289 'testRemoveSrcAttribute': testRemoveSrcAttribute,
1290 'testBrowserPluginNotAllowed': testBrowserPluginNotAllowed,
1291 'testPluginLoadPermission': testPluginLoadPermission,
1292 'testNewWindow': testNewWindow,
1293 'testNewWindowTwoListeners': testNewWindowTwoListeners,
1294 'testNewWindowNoPreventDefault': testNewWindowNoPreventDefault,
1295 'testNewWindowNoReferrerLink': testNewWindowNoReferrerLink,
1296 'testContentLoadEvent': testContentLoadEvent,
1297 'testDeclarativeWebRequestAPI': testDeclarativeWebRequestAPI,
1298 'testWebRequestAPI': testWebRequestAPI,
1299 'testWebRequestAPIGoogleProperty': testWebRequestAPIGoogleProperty,
1300 'testWebRequestListenerSurvivesReparenting':
1301 testWebRequestListenerSurvivesReparenting,
1302 'testGetProcessId': testGetProcessId,
1303 'testLoadStartLoadRedirect': testLoadStartLoadRedirect,
1304 'testLoadAbortChromeExtensionURLWrongPartition':
1305 testLoadAbortChromeExtensionURLWrongPartition,
1306 'testLoadAbortEmptyResponse': testLoadAbortEmptyResponse,
1307 'testLoadAbortIllegalChromeURL': testLoadAbortIllegalChromeURL,
1308 'testLoadAbortIllegalFileURL': testLoadAbortIllegalFileURL,
1309 'testLoadAbortIllegalJavaScriptURL': testLoadAbortIllegalJavaScriptURL,
1310 'testNavigationToExternalProtocol': testNavigationToExternalProtocol,
1311 'testReload': testReload,
1312 'testRemoveWebviewOnExit': testRemoveWebviewOnExit,
1313 'testRemoveWebviewAfterNavigation': testRemoveWebviewAfterNavigation,
1314 'testResizeWebviewResizesContent': testResizeWebviewResizesContent,
1315 'testPostMessageCommChannel': testPostMessageCommChannel,
1316 'testScreenshotCapture' : testScreenshotCapture
1319 onload = function() {
1320 chrome.test.getConfig(function(config) {
1321 embedder.setUp_(config);
1322 chrome.test.sendMessage("Launched");