Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / test / data / web_view / apitest / main.js
blob0ea11fa2bc97e0aaf052ad8d200c5eecf2054b67
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 var embedder = {};
7 // TODO(lfg) Move these functions to a common js.
8 embedder.setUp_ = function(config) {
9   if (!config || !config.testServer) {
10     return;
11   }
12   embedder.baseGuestURL = 'http://localhost:' + config.testServer.port;
13   embedder.closeSocketURL = embedder.baseGuestURL + '/close-socket';
14   embedder.emptyGuestURL = embedder.baseGuestURL + '/empty_guest.html';
15   embedder.noReferrerGuestURL =
16       embedder.baseGuestURL + '/guest_noreferrer.html';
17   embedder.detectUserAgentURL = embedder.baseGuestURL + '/detect-user-agent';
18   embedder.redirectGuestURL = embedder.baseGuestURL + '/server-redirect';
19   embedder.redirectGuestURLDest =
20       embedder.baseGuestURL + '/guest_redirect.html';
21   embedder.windowOpenGuestURL = embedder.baseGuestURL + '/guest.html';
24 window.runTest = function(testName) {
25   if (!embedder.test.testList[testName]) {
26     window.console.warn('Incorrect testName: ' + testName);
27     embedder.test.fail();
28     return;
29   }
31   // Run the test.
32   embedder.test.testList[testName]();
35 embedder.test = {};
37 embedder.test.assertEq = function(a, b) {
38   if (a != b) {
39     window.console.warn('assertion failed: ' + a + ' != ' + b);
40     embedder.test.fail();
41   }
44 embedder.test.assertFalse = function(condition) {
45   if (condition) {
46     window.console.warn('assertion failed: false != ' + condition);
47     embedder.test.fail();
48   }
51 embedder.test.assertTrue = function(condition) {
52   if (!condition) {
53     window.console.warn('assertion failed: true != ' + condition);
54     embedder.test.fail();
55   }
58 embedder.test.fail = function() {
59   chrome.test.sendMessage('TEST_FAILED');
62 embedder.test.succeed = function() {
63   chrome.test.sendMessage('TEST_PASSED');
67 // Tests begin.
69 // This test verifies that the allowtransparency property cannot be changed
70 // once set. The attribute can only be deleted.
71 function testAllowTransparencyAttribute() {
72   var webview = document.createElement('webview');
73   webview.src = 'data:text/html,webview test';
74   embedder.test.assertFalse(webview.hasAttribute('allowtransparency'));
75   embedder.test.assertFalse(webview.allowtransparency);
76   webview.allowtransparency = true;
78   webview.addEventListener('loadstop', function(e) {
79     embedder.test.assertTrue(webview.hasAttribute('allowtransparency'));
80     embedder.test.assertTrue(webview.allowtransparency);
81     webview.allowtransparency = false;
82     embedder.test.assertFalse(webview.hasAttribute('allowtransparency'));
83     embedder.test.assertFalse(webview.allowtransparency);
84     webview.allowtransparency = '';
85     embedder.test.assertFalse(webview.hasAttribute('allowtransparency'));
86     embedder.test.assertFalse(webview.allowtransparency);
87     webview.allowtransparency = 'some string';
88     embedder.test.assertTrue(webview.hasAttribute('allowtransparency'));
89     embedder.test.assertTrue(webview.allowtransparency);
90     embedder.test.succeed();
91   });
93   document.body.appendChild(webview);
96 function testAPIMethodExistence() {
97   var apiMethodsToCheck = [
98     'back',
99     'find',
100     'forward',
101     'canGoBack',
102     'canGoForward',
103     'clearData',
104     'getProcessId',
105     'getZoom',
106     'go',
107     'print',
108     'reload',
109     'setZoom',
110     'stop',
111     'stopFinding',
112     'terminate',
113     'executeScript',
114     'insertCSS',
115     'getUserAgent',
116     'isUserAgentOverridden',
117     'setUserAgentOverride'
118   ];
119   var webview = document.createElement('webview');
120   webview.setAttribute('partition', arguments.callee.name);
121   webview.addEventListener('loadstop', function(e) {
122     for (var i = 0; i < apiMethodsToCheck.length; ++i) {
123       embedder.test.assertEq('function',
124                              typeof webview[apiMethodsToCheck[i]]);
125     }
127     // Check contentWindow.
128     embedder.test.assertEq('object', typeof webview.contentWindow);
129     embedder.test.assertEq('function',
130                            typeof webview.contentWindow.postMessage);
131     embedder.test.succeed();
132   });
133   webview.setAttribute('src', 'data:text/html,webview check api');
134   document.body.appendChild(webview);
137 // This test verifies that assigning the src attribute the same value it had
138 // prior to a crash spawns off a new guest process.
139 function testAssignSrcAfterCrash() {
140   var webview = document.createElement('webview');
141   webview.setAttribute('partition', arguments.callee.name);
142   var terminated = false;
143   webview.addEventListener('loadstop', function(evt) {
144     if (!terminated) {
145       webview.terminate();
146       return;
147     }
148     // The guest has recovered after being terminated.
149     embedder.test.succeed();
150   });
151   webview.addEventListener('exit', function(evt) {
152     terminated = true;
153     webview.setAttribute('src', 'data:text/html,test page');
154   });
155   webview.setAttribute('src', 'data:text/html,test page');
156   document.body.appendChild(webview);
159 // Makes sure 'sizechanged' event is fired only if autosize attribute is
160 // specified.
161 // After loading <webview> without autosize attribute and a size, say size1,
162 // we set autosize attribute and new min size with size2. We would get (only
163 // one) sizechanged event with size1 as old size and size2 as new size.
164 function testAutosizeAfterNavigation() {
165   var webview = document.createElement('webview');
167   var step = 1;
168   var autosizeWidth = -1;
169   var autosizeHeight = -1;
170   var sizeChangeHandler = function(e) {
171     switch (step) {
172       case 1:
173         // This would be triggered after we set autosize attribute.
174         embedder.test.assertEq(50, e.oldWidth);
175         embedder.test.assertEq(100, e.oldHeight);
176         embedder.test.assertTrue(e.newWidth >= 60 && e.newWidth <= 70);
177         embedder.test.assertTrue(e.newHeight >= 110 && e.newHeight <= 120);
179         // Remove autosize attribute and expect webview to retain the same size.
180         autosizeWidth = e.newWidth;
181         autosizeHeight = e.newHeight;
182         webview.removeAttribute('autosize');
183         break;
184       case 2:
185         // Expect the autosized size.
186         embedder.test.assertEq(autosizeWidth, e.newWidth);
187         embedder.test.assertEq(autosizeHeight, e.newHeight);
189         embedder.test.succeed();
190         break;
191       default:
192         window.console.log('Unexpected sizechanged event, step = ' + step);
193         embedder.test.fail();
194         break;
195     }
197     ++step;
198   };
200   webview.addEventListener('sizechanged', sizeChangeHandler);
202   webview.addEventListener('loadstop', function(e) {
203     webview.setAttribute('autosize', true);
204     webview.setAttribute('minwidth', 60);
205     webview.setAttribute('maxwidth', 70);
206     webview.setAttribute('minheight', 110);
207     webview.setAttribute('maxheight', 120);
208   });
210   webview.style.width = '50px';
211   webview.style.height = '100px';
212   webview.setAttribute('src', 'data:text/html,webview test sizechanged event');
213   document.body.appendChild(webview);
216 // This test verifies that if a browser plugin is in autosize mode before
217 // navigation then the guest starts auto-sized.
218 function testAutosizeBeforeNavigation() {
219   var webview = document.createElement('webview');
221   webview.setAttribute('autosize', 'true');
222   webview.setAttribute('minwidth', 200);
223   webview.setAttribute('maxwidth', 210);
224   webview.setAttribute('minheight', 100);
225   webview.setAttribute('maxheight', 110);
227   webview.addEventListener('sizechanged', function(e) {
228     embedder.test.assertTrue(e.newWidth >= 200 && e.newWidth <= 210);
229     embedder.test.assertTrue(e.newHeight >= 100 && e.newHeight <= 110);
230     embedder.test.succeed();
231   });
233   webview.setAttribute('src', 'data:text/html,webview test sizechanged event');
234   document.body.appendChild(webview);
237 // This test verifies that a lengthy page with autosize enabled will report
238 // the correct height in the sizechanged event.
239 function testAutosizeHeight() {
240   var webview = document.createElement('webview');
242   webview.autosize = true;
243   webview.minwidth = 200;
244   webview.maxwidth = 210;
245   webview.minheight = 40;
246   webview.maxheight = 200;
248   var step = 1;
249   webview.addEventListener('sizechanged', function(e) {
250     switch (step) {
251       case 1:
252         embedder.test.assertEq(200, e.newHeight);
253         // Change the maxheight to verify that we see the change.
254         webview.maxheight = 50;
255         break;
256       case 2:
257         embedder.test.assertEq(200, e.oldHeight);
258         embedder.test.assertEq(50, e.newHeight);
259         embedder.test.succeed();
260         break;
261       default:
262         window.console.log('Unexpected sizechanged event, step = ' + step);
263         embedder.test.fail();
264         break;
265     }
266     ++step;
267   });
269   webview.src = 'data:text/html,' +
270                 'a<br/>b<br/>c<br/>d<br/>e<br/>f<br/>' +
271                 'a<br/>b<br/>c<br/>d<br/>e<br/>f<br/>' +
272                 'a<br/>b<br/>c<br/>d<br/>e<br/>f<br/>' +
273                 'a<br/>b<br/>c<br/>d<br/>e<br/>f<br/>' +
274                 'a<br/>b<br/>c<br/>d<br/>e<br/>f<br/>';
275   document.body.appendChild(webview);
278 // This test verifies that all autosize attributes can be removed
279 // without crashing the plugin, or throwing errors.
280 function testAutosizeRemoveAttributes() {
281   var webview = document.createElement('webview');
283   var step = 1;
284   var sizeChangeHandler = function(e) {
285     switch (step) {
286       case 1:
287         // This is the sizechanged event for autosize.
289         // Remove attributes.
290         webview.removeAttribute('minwidth');
291         webview.removeAttribute('maxwidth');
292         webview.removeAttribute('minheight');
293         webview.removeAttribute('maxheight');
294         webview.removeAttribute('autosize');
296         // We'd get one more sizechanged event after we turn off
297         // autosize.
298         webview.style.width = '500px';
299         webview.style.height = '500px';
300         break;
301       case 2:
302         embedder.test.succeed();
303         break;
304     }
306     ++step;
307   };
309   webview.addEventListener('loadstop', function(e) {
310     webview.minwidth = 300;
311     webview.maxwidth = 700;
312     webview.minheight = 600;
313     webview.maxheight = 400;
314     webview.autosize = true;
315   });
317   webview.addEventListener('sizechanged', sizeChangeHandler);
319   webview.style.width = '640px';
320   webview.style.height = '480px';
321   webview.setAttribute('src', 'data:text/html,webview check autosize');
322   document.body.appendChild(webview);
325 // This test verifies that autosize works when some of the parameters are unset.
326 function testAutosizeWithPartialAttributes() {
327   window.console.log('testAutosizeWithPartialAttributes');
328   var webview = document.createElement('webview');
330   var step = 1;
331   var sizeChangeHandler = function(e) {
332     window.console.log('sizeChangeHandler, new: ' +
333                        e.newWidth + ' X ' + e.newHeight);
334     switch (step) {
335       case 1:
336         // Expect 300x200.
337         embedder.test.assertEq(300, e.newWidth);
338         embedder.test.assertEq(200, e.newHeight);
340         // Change the min size to cause a relayout.
341         webview.minwidth = 500;
342         break;
343       case 2:
344         embedder.test.assertTrue(e.newWidth >= webview.minwidth);
345         embedder.test.assertTrue(e.newWidth <= webview.maxwidth);
347         // Tests when minwidth > maxwidth, minwidth = maxwidth.
348         // i.e. minwidth is essentially 700.
349         webview.minwidth = 800;
350         break;
351       case 3:
352         // Expect 700X?
353         embedder.test.assertEq(700, e.newWidth);
354         embedder.test.assertTrue(e.newHeight >= 200);
355         embedder.test.assertTrue(e.newHeight <= 600);
357         embedder.test.succeed();
358         break;
359       default:
360         window.console.log('Unexpected sizechanged event, step = ' + step);
361         embedder.test.fail();
362         break;
363     }
365     ++step;
366   };
368   webview.addEventListener('sizechanged', sizeChangeHandler);
370   webview.addEventListener('loadstop', function(e) {
371     webview.minwidth = 300;
372     webview.maxwidth = 700;
373     webview.minheight = 200;
374     webview.maxheight = 600;
375     webview.autosize = true;
376   });
378   webview.style.width = '640px';
379   webview.style.height = '480px';
380   webview.setAttribute('src', 'data:text/html,webview check autosize');
381   document.body.appendChild(webview);
384 // This test registers two event listeners on a same event (loadcommit).
385 // Each of the listener tries to change some properties on the event param,
386 // which should not be possible.
387 function testCannotMutateEventName() {
388   var webview = document.createElement('webview');
389   var url = 'data:text/html,<body>Two</body>';
390   var loadCommitACalled = false;
391   var loadCommitBCalled = false;
393   var maybeFinishTest = function(e) {
394     if (loadCommitACalled && loadCommitBCalled) {
395       embedder.test.assertEq('loadcommit', e.type);
396       embedder.test.succeed();
397     }
398   };
400   var onLoadCommitA = function(e) {
401     if (e.url == url) {
402       embedder.test.assertEq('loadcommit', e.type);
403       embedder.test.assertTrue(e.isTopLevel);
404       embedder.test.assertFalse(loadCommitACalled);
405       loadCommitACalled = true;
406       // Try mucking with properities inside |e|.
407       e.type = 'modified';
408       maybeFinishTest(e);
409     }
410   };
411   var onLoadCommitB = function(e) {
412     if (e.url == url) {
413       embedder.test.assertEq('loadcommit', e.type);
414       embedder.test.assertTrue(e.isTopLevel);
415       embedder.test.assertFalse(loadCommitBCalled);
416       loadCommitBCalled = true;
417       // Try mucking with properities inside |e|.
418       e.type = 'modified';
419       maybeFinishTest(e);
420     }
421   };
423   // The test starts from here, by setting the src to |url|. Event
424   // listener registration works because we already have a (dummy) src set
425   // on the <webview> tag.
426   webview.addEventListener('loadcommit', onLoadCommitA);
427   webview.addEventListener('loadcommit', onLoadCommitB);
428   webview.setAttribute('src', url);
429   document.body.appendChild(webview);
432 // This test verifies that the loadstop event fires when loading a webview
433 // accessible resource from a partition that is privileged if the src URL
434 // is not fully qualified.
435 function testChromeExtensionRelativePath() {
436   var webview = document.createElement('webview');
437   // foobar is a privileged partition according to the manifest file.
438   webview.partition = 'foobar';
439   webview.addEventListener('loadabort', function(e) {
440     embedder.test.fail();
441   });
442   webview.addEventListener('loadstop', function(e) {
443     embedder.test.succeed();
444   });
445   webview.setAttribute('src', 'guest_with_inline_script.html');
446   document.body.appendChild(webview);
449 // This test verifies that the loadstop event fires when loading a webview
450 // accessible resource from a partition that is privileged.
451 function testChromeExtensionURL() {
452   var localResource = chrome.runtime.getURL('guest_with_inline_script.html');
453   var webview = document.createElement('webview');
454   // foobar is a privileged partition according to the manifest file.
455   webview.partition = 'foobar';
456   webview.addEventListener('loadabort', function(e) {
457     embedder.test.fail();
458   });
459   webview.addEventListener('loadstop', function(e) {
460     embedder.test.succeed();
461   });
462   webview.setAttribute('src', localResource);
463   document.body.appendChild(webview);
466 // This test verifies that the load event fires when the a new page is
467 // loaded.
468 // TODO(fsamuel): Add a test to verify that subframe loads within a guest
469 // do not fire the 'contentload' event.
470 function testContentLoadEvent() {
471   var webview = document.createElement('webview');
472   webview.addEventListener('contentload', function(e) {
473     embedder.test.succeed();
474   });
475   webview.setAttribute('src', 'data:text/html,trigger navigation');
476   document.body.appendChild(webview);
479 // This test verifies that the basic use cases of the declarative WebRequest API
480 // work as expected. This test demonstrates that rules can be added prior to
481 // navigation and attachment.
482 // 1. It adds a rule to block URLs that contain guest.
483 // 2. It attempts to navigate to a guest.html page.
484 // 3. It detects the appropriate loadabort message.
485 // 4. It removes the rule blocking the page and reloads.
486 // 5. The page loads successfully.
487 function testDeclarativeWebRequestAPI() {
488   var step = 1;
489   var webview = new WebView();
490   var rule = {
491     conditions: [
492       new chrome.webViewRequest.RequestMatcher(
493         {
494           url: { urlContains: 'guest' }
495         }
496       )
497     ],
498     actions: [
499       new chrome.webViewRequest.CancelRequest()
500     ]
501   };
502   webview.request.onRequest.addRules([rule]);
503   webview.addEventListener('loadabort', function(e) {
504     embedder.test.assertEq(1, step);
505     embedder.test.assertEq('ERR_BLOCKED_BY_CLIENT', e.reason);
506     step = 2;
507     webview.request.onRequest.removeRules();
508     webview.reload();
509   });
510   webview.addEventListener('loadstop', function(e) {
511     embedder.test.assertEq(2, step);
512     embedder.test.succeed();
513   });
514   webview.src = embedder.emptyGuestURL;
515   document.body.appendChild(webview);
518 function testDeclarativeWebRequestAPISendMessage() {
519   var webview = new WebView();
520   window.console.log(embedder.emptyGuestURL);
521   var rule = {
522     conditions: [
523       new chrome.webViewRequest.RequestMatcher(
524         {
525           url: { urlContains: 'guest' }
526         }
527       )
528     ],
529     actions: [
530       new chrome.webViewRequest.SendMessageToExtension({ message: 'bleep' })
531     ]
532   };
533   webview.request.onRequest.addRules([rule]);
534   webview.request.onMessage.addListener(function(e) {
535     embedder.test.assertEq('bleep', e.message);
536     embedder.test.succeed();
537   });
538   webview.src = embedder.emptyGuestURL;
539   document.body.appendChild(webview);
542 // This test registers two listeners on an event (loadcommit) and removes
543 // the <webview> tag when the first listener fires.
544 // Current expected behavior is that the second event listener will still
545 // fire without crashing.
546 function testDestroyOnEventListener() {
547   var webview = document.createElement('webview');
548   var url = 'data:text/html,<body>Destroy test</body>';
550   var loadCommitCount = 0;
551   function loadCommitCommon(e) {
552     embedder.test.assertEq('loadcommit', e.type);
553     if (url != e.url)
554       return;
555     ++loadCommitCount;
556     if (loadCommitCount == 2) {
557       // Pass in a timeout so that we can catch if any additional loadcommit
558       // occurs.
559       setTimeout(function() {
560         embedder.test.succeed();
561       }, 0);
562     } else if (loadCommitCount > 2) {
563       embedder.test.fail();
564     }
565   };
567   // The test starts from here, by setting the src to |url|.
568   webview.addEventListener('loadcommit', function(e) {
569     window.console.log('loadcommit1');
570     webview.parentNode.removeChild(webview);
571     loadCommitCommon(e);
572   });
573   webview.addEventListener('loadcommit', function(e) {
574     window.console.log('loadcommit2');
575     loadCommitCommon(e);
576   });
577   webview.setAttribute('src', url);
578   document.body.appendChild(webview);
581 // Tests that a <webview> that starts with "display: none" style loads
582 // properly.
583 function testDisplayNoneWebviewLoad() {
584   var webview = document.createElement('webview');
585   var visible = false;
586   webview.style.display = 'none';
587   // foobar is a privileged partition according to the manifest file.
588   webview.partition = 'foobar';
589   webview.addEventListener('loadabort', function(e) {
590     embedder.test.fail();
591   });
592   webview.addEventListener('loadstop', function(e) {
593     embedder.test.assertTrue(visible);
594     embedder.test.succeed();
595   });
596   // Set the .src while we are "display: none".
597   webview.setAttribute('src', 'about:blank');
598   document.body.appendChild(webview);
600   setTimeout(function() {
601     visible = true;
602     // This should trigger loadstop.
603     webview.style.display = '';
604   }, 0);
607 function testDisplayNoneWebviewRemoveChild() {
608   var webview = document.createElement('webview');
609   var visibleAndInDOM = false;
610   webview.style.display = 'none';
611   // foobar is a privileged partition according to the manifest file.
612   webview.partition = 'foobar';
613   webview.addEventListener('loadabort', function(e) {
614     embedder.test.fail();
615   });
616   webview.addEventListener('loadstop', function(e) {
617     embedder.test.assertTrue(visibleAndInDOM);
618     embedder.test.succeed();
619   });
620   // Set the .src while we are "display: none".
621   webview.setAttribute('src', 'about:blank');
622   document.body.appendChild(webview);
624   setTimeout(function() {
625     webview.parentNode.removeChild(webview);
626     webview.style.display = '';
627     visibleAndInDOM = true;
628     // This should trigger loadstop.
629     document.body.appendChild(webview);
630   }, 0);
633 // This test verifies that the loadstart, loadstop, and exit events fire as
634 // expected.
635 function testEventName() {
636   var webview = document.createElement('webview');
637   webview.setAttribute('partition', arguments.callee.name);
639   webview.addEventListener('loadstart', function(evt) {
640     embedder.test.assertEq('loadstart', evt.type);
641   });
643   webview.addEventListener('loadstop', function(evt) {
644     embedder.test.assertEq('loadstop', evt.type);
645     webview.terminate();
646   });
648   webview.addEventListener('exit', function(evt) {
649     embedder.test.assertEq('exit', evt.type);
650     embedder.test.succeed();
651   });
653   webview.setAttribute('src', 'data:text/html,trigger navigation');
654   document.body.appendChild(webview);
657 function testExecuteScript() {
658   var webview = document.createElement('webview');
659   webview.addEventListener('loadstop', function() {
660     webview.executeScript(
661       {code:'document.body.style.backgroundColor = "red";'},
662       function(results) {
663         embedder.test.assertEq(1, results.length);
664         embedder.test.assertEq('red', results[0]);
665         embedder.test.succeed();
666       });
667   });
668   webview.setAttribute('src', 'data:text/html,trigger navigation');
669   document.body.appendChild(webview);
672 function testExecuteScriptFail() {
673   var webview = document.createElement('webview');
674   document.body.appendChild(webview);
675   setTimeout(function() {
676     webview.executeScript(
677         {code:'document.body.style.backgroundColor = "red";'},
678         function(results) {
679           embedder.test.fail();
680         });
681     setTimeout(function() {
682       embedder.test.succeed();
683     }, 0);
684   }, 0);
687 // This test verifies that the call to executeScript will fail and return null
688 // if the webview has been navigated between the time the call was made and the
689 // time it arrives in the guest process.
690 function testExecuteScriptIsAbortedWhenWebViewSourceIsChanged() {
691   var webview = document.createElement('webview');
692   webview.addEventListener('loadstop', function onLoadStop(e) {
693     window.console.log('2. Inject script to trigger a guest-initiated ' +
694         'navigation.');
695     var navUrl = 'data:text/html,trigger nav';
696     webview.executeScript({
697       code: 'window.location.href = "' + navUrl + '";'
698     });
700     window.console.log('3. Listening for the load that will be started as a ' +
701         'result of 2.');
702     webview.addEventListener('loadstart', function onLoadStart(e) {
703       embedder.test.assertEq('about:blank', webview.src);
704       window.console.log('4. Attempting to inject script into about:blank. ' +
705           'This is expected to fail.');
706       webview.executeScript(
707         { code: 'document.body.style.backgroundColor = "red";' },
708         function(results) {
709           window.console.log(
710               '5. Verify that executeScript has, indeed, failed.');
711           embedder.test.assertEq(null, results);
712           embedder.test.assertEq(navUrl, webview.src);
713           embedder.test.succeed();
714         }
715       );
716       webview.removeEventListener('loadstart', onLoadStart);
717     });
718     webview.removeEventListener('loadstop', onLoadStop);
719   });
721   window.console.log('1. Performing initial navigation.');
722   webview.setAttribute('src', 'about:blank');
723   document.body.appendChild(webview);
726 function testFindAPI() {
727   var webview = new WebView();
728   webview.src = 'data:text/html,Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
729       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
730       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
731       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
732       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
733       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
734       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
735       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
736       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
737       'Dog dog dog Dog dog dogcatDog dogDogdog<br><br>' +
738       '<a href="about:blank">Click here!</a>';
740   var loadstopListener2 = function(e) {
741     embedder.test.assertEq(webview.src, "about:blank");
742     embedder.test.succeed();
743   }
745   var loadstopListener1 = function(e) {
746     // Test find results.
747     webview.find("dog", {}, function(results) {
748       callbackTest = true;
749       embedder.test.assertEq(results.numberOfMatches, 100);
750       embedder.test.assertTrue(results.selectionRect.width > 0);
751       embedder.test.assertTrue(results.selectionRect.height > 0);
753       // Test finding next active matches.
754       webview.find("dog");
755       webview.find("dog");
756       webview.find("dog");
757       webview.find("dog");
758       webview.find("dog", {}, function(results) {
759         embedder.test.assertEq(results.activeMatchOrdinal, 6);
760         webview.find("dog", {backward: true});
761         webview.find("dog", {backward: true}, function(results) {
762           // Test the |backward| find option.
763           embedder.test.assertEq(results.activeMatchOrdinal, 4);
765           // Test the |matchCase| find option.
766           webview.find("Dog", {matchCase: true}, function(results) {
767             embedder.test.assertEq(results.numberOfMatches, 40);
769             // Test canceling find requests.
770             webview.find("dog");
771             webview.stopFinding();
772             webview.find("dog");
773             webview.find("cat");
775             // Test find results when looking for something that isn't there.
776             webview.find("fish", {}, function(results) {
777               embedder.test.assertEq(results.numberOfMatches, 0);
778               embedder.test.assertEq(results.activeMatchOrdinal, 0);
779               embedder.test.assertEq(results.selectionRect.left, 0);
780               embedder.test.assertEq(results.selectionRect.top, 0);
781               embedder.test.assertEq(results.selectionRect.width, 0);
782               embedder.test.assertEq(results.selectionRect.height, 0);
784               // Test following a link with stopFinding().
785               webview.removeEventListener('loadstop', loadstopListener1);
786               webview.addEventListener('loadstop', loadstopListener2);
787               webview.find("click here!", {}, function() {
788                 webview.stopFinding("activate");
789               });
790             });
791           });
792         });
793       });
794     });
795   };
797   webview.addEventListener('loadstop', loadstopListener1);
798   document.body.appendChild(webview);
801 function testFindAPI_findupdate() {
802   var webview = new WebView();
803   webview.src = 'data:text/html,Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
804       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
805       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
806       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
807       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
808       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
809       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
810       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
811       'Dog dog dog Dog dog dogcatDog dogDogdog<br>' +
812       'Dog dog dog Dog dog dogcatDog dogDogdog<br><br>' +
813       '<a href="about:blank">Click here!</a>';
814   var canceledTest = false;
815   webview.addEventListener('loadstop', function(e) {
816     // Test the |findupdate| event.
817     webview.addEventListener('findupdate', function(e) {
818       if (e.activeMatchOrdinal > 0) {
819         // embedder.test.assertTrue(e.numberOfMatches >= e.activeMatchOrdinal)
820         // This currently fails because of http://crbug.com/342445 .
821         embedder.test.assertTrue(e.selectionRect.width > 0);
822         embedder.test.assertTrue(e.selectionRect.height > 0);
823       }
825       if (e.finalUpdate) {
826         if (e.canceled) {
827           canceledTest = true;
828         } else {
829           embedder.test.assertEq(e.searchText, "dog");
830           embedder.test.assertEq(e.numberOfMatches, 100);
831           embedder.test.assertEq(e.activeMatchOrdinal, 1);
832           embedder.test.assertTrue(canceledTest);
833           embedder.test.succeed();
834         }
835       }
836     });
837     wv.find("dog");
838     wv.find("cat");
839     wv.find("dog");
840   });
842   document.body.appendChild(webview);
845 // This test verifies that getProcessId is defined and returns a non-zero
846 // value corresponding to the processId of the guest process.
847 function testGetProcessId() {
848   var webview = document.createElement('webview');
849   webview.setAttribute('src', 'data:text/html,trigger navigation');
850   var firstLoad = function() {
851     webview.removeEventListener('loadstop', firstLoad);
852     embedder.test.assertTrue(webview.getProcessId() > 0);
853     embedder.test.succeed();
854   };
855   webview.addEventListener('loadstop', firstLoad);
856   document.body.appendChild(webview);
859 function testHiddenBeforeNavigation() {
860   var webview = document.createElement('webview');
861   webview.style.visibility = 'hidden';
863   var postMessageHandler = function(e) {
864     var data = JSON.parse(e.data);
865     window.removeEventListener('message', postMessageHandler);
866     if (data[0] == 'visibilityState-response') {
867       embedder.test.assertEq('hidden', data[1]);
868       embedder.test.succeed();
869     } else {
870       window.console.warn('Unexpected message: ' + data);
871       embedder.test.fail();
872     }
873   };
875   webview.addEventListener('loadstop', function(e) {
876     window.console.warn('webview.loadstop');
877     window.addEventListener('message', postMessageHandler);
878     webview.addEventListener('consolemessage', function(e) {
879       window.console.warn('g: ' + e.message);
880     });
882     webview.executeScript(
883       {file: 'inject_hidden_test.js'},
884       function(results) {
885         if (!results || !results.length) {
886           window.console.warn('Failed to inject script: inject_hidden_test.js');
887           embedder.test.fail();
888           return;
889         }
891         window.console.warn('script injection success');
892         webview.contentWindow.postMessage(
893             JSON.stringify(['visibilityState-request']), '*');
894       });
895   });
897   webview.setAttribute('src', 'data:text/html,<html><body></body></html>');
898   document.body.appendChild(webview);
901 // Makes sure inline scripts works inside guest that was loaded from
902 // accessible_resources.
903 function testInlineScriptFromAccessibleResources() {
904   var webview = document.createElement('webview');
905   // foobar is a privileged partition according to the manifest file.
906   webview.partition = 'foobar';
907   webview.addEventListener('loadabort', function(e) {
908     embedder.test.fail();
909   });
910   webview.addEventListener('consolemessage', function(e) {
911     window.console.log('consolemessage: ' + e.message);
912     if (e.message == 'guest_with_inline_script.html: Inline script ran') {
913       embedder.test.succeed();
914     }
915   });
916   webview.setAttribute('src', 'guest_with_inline_script.html');
917   document.body.appendChild(webview);
920 // This tests verifies that webview fires a loadabort event instead of crashing
921 // the browser if we attempt to navigate to a chrome-extension: URL with an
922 // extension ID that does not exist.
923 function testInvalidChromeExtensionURL() {
924   var invalidResource = 'chrome-extension://abc123/guest.html';
925   var webview = document.createElement('webview');
926   // foobar is a privileged partition according to the manifest file.
927   webview.partition = 'foobar';
928   webview.addEventListener('loadabort', function(e) {
929     embedder.test.succeed();
930   });
931   webview.setAttribute('src', invalidResource);
932   document.body.appendChild(webview);
935 // This test verifies that the loadabort event fires when loading a webview
936 // accessible resource from a partition that is not privileged.
937 function testLoadAbortChromeExtensionURLWrongPartition() {
938   var localResource = chrome.runtime.getURL('guest.html');
939   var webview = document.createElement('webview');
940   webview.addEventListener('loadabort', function(e) {
941     embedder.test.assertEq('ERR_ADDRESS_UNREACHABLE', e.reason);
942     embedder.test.succeed();
943   });
944   webview.addEventListener('loadstop', function(e) {
945     embedder.test.fail();
946   });
947   webview.setAttribute('src', localResource);
948   document.body.appendChild(webview);
951 // This test verifies that the loadabort event fires as expected and with the
952 // appropriate fields when an empty response is returned.
953 function testLoadAbortEmptyResponse() {
954   var webview = document.createElement('webview');
955   webview.addEventListener('loadabort', function(e) {
956     embedder.test.assertEq('ERR_EMPTY_RESPONSE', e.reason);
957     embedder.test.succeed();
958   });
959   webview.setAttribute('src', embedder.closeSocketURL);
960   document.body.appendChild(webview);
963 // This test verifies that the loadabort event fires as expected when an illegal
964 // chrome URL is provided.
965 function testLoadAbortIllegalChromeURL() {
966   var webview = document.createElement('webview');
967   webview.addEventListener('loadabort', function(e) {
968     embedder.test.assertEq('ERR_DISALLOWED_URL_SCHEME', e.reason);
969   });
970   webview.addEventListener('loadstop', function(e)  {
971     embedder.test.assertEq('about:blank', webview.src);
972     embedder.test.succeed();
973   });
974   webview.src = 'chrome://newtab';
975   document.body.appendChild(webview);
978 function testLoadAbortIllegalFileURL() {
979   var webview = document.createElement('webview');
980   webview.addEventListener('loadabort', function(e) {
981     embedder.test.assertEq('ERR_DISALLOWED_URL_SCHEME', e.reason);
982   });
983   webview.addEventListener('loadstop', function(e) {
984     embedder.test.assertEq('about:blank', webview.src);
985     embedder.test.succeed();
986   });
987   webview.src = 'file://foo';
988   document.body.appendChild(webview);
991 function testLoadAbortIllegalJavaScriptURL() {
992   var webview = document.createElement('webview');
993   webview.addEventListener('loadabort', function(e) {
994     embedder.test.assertEq('ERR_DISALLOWED_URL_SCHEME', e.reason);
995   });
996   webview.addEventListener('loadstop', function(e) {
997     embedder.test.assertEq('about:blank', webview.src);
998     embedder.test.succeed();
999   });
1000   webview.setAttribute('src', 'javascript:void(document.bgColor="#0000FF")');
1001   document.body.appendChild(webview);
1004 // Verifies that navigating to invalid URL (e.g. 'http:') doesn't cause a crash.
1005 function testLoadAbortInvalidNavigation() {
1006   var webview = document.createElement('webview');
1007   webview.addEventListener('loadabort', function(e) {
1008     embedder.test.assertEq('ERR_INVALID_URL', e.reason);
1009     embedder.test.assertEq('', e.url);
1010   });
1011   webview.addEventListener('loadstop', function(e) {
1012     embedder.test.assertEq('about:blank', webview.src);
1013     embedder.test.succeed();
1014   });
1015   webview.addEventListener('exit', function(e) {
1016     // We should not crash.
1017     embedder.test.fail();
1018   });
1019   webview.src = 'http:';
1020   document.body.appendChild(webview);
1023 // Verifies that navigation to a URL that is valid but not web-safe or
1024 // pseudo-scheme fires loadabort and doesn't cause a crash.
1025 function testLoadAbortNonWebSafeScheme() {
1026   var webview = document.createElement('webview');
1027   var chromeGuestURL = 'chrome-guest://abc123/';
1028   webview.addEventListener('loadabort', function(e) {
1029     embedder.test.assertEq('ERR_DISALLOWED_URL_SCHEME', e.reason);
1030     embedder.test.assertEq(chromeGuestURL, e.url);
1031   });
1032   webview.addEventListener('loadstop', function(e) {
1033     embedder.test.assertEq('about:blank', webview.src);
1034     embedder.test.succeed();
1035   });
1036   webview.addEventListener('exit', function(e) {
1037     // We should not crash.
1038     embedder.test.fail();
1039   });
1040   webview.src = chromeGuestURL;
1041   document.body.appendChild(webview);
1044 // Tests that the 'loadprogress' event is triggered correctly.
1045 function testLoadProgressEvent() {
1046   var webview = document.createElement('webview');
1047   var progress = 0;
1049   webview.addEventListener('loadstop', function(evt) {
1050     embedder.test.assertEq(1, progress);
1051     embedder.test.succeed();
1052   });
1054   webview.addEventListener('loadprogress', function(evt) {
1055     progress = evt.progress;
1056   });
1058   webview.setAttribute('src', 'data:text/html,trigger navigation');
1059   document.body.appendChild(webview);
1062 // This test verifies that the loadstart event fires at the beginning of a load
1063 // and the loadredirect event fires when a redirect occurs.
1064 function testLoadStartLoadRedirect() {
1065   var webview = document.createElement('webview');
1066   var loadstartCalled = false;
1067   webview.setAttribute('src', embedder.redirectGuestURL);
1068   webview.addEventListener('loadstart', function(e) {
1069     embedder.test.assertTrue(e.isTopLevel);
1070     embedder.test.assertEq(embedder.redirectGuestURL, e.url);
1071     loadstartCalled = true;
1072   });
1073   webview.addEventListener('loadredirect', function(e) {
1074     embedder.test.assertTrue(e.isTopLevel);
1075     embedder.test.assertEq(embedder.redirectGuestURL,
1076         e.oldUrl.replace('127.0.0.1', 'localhost'));
1077     embedder.test.assertEq(embedder.redirectGuestURLDest,
1078         e.newUrl.replace('127.0.0.1', 'localhost'));
1079     if (loadstartCalled) {
1080       embedder.test.succeed();
1081     } else {
1082       embedder.test.fail();
1083     }
1084   });
1085   document.body.appendChild(webview);
1088 function testNavigationToExternalProtocol() {
1089   var webview = document.createElement('webview');
1090   webview.addEventListener('loadstop', function(e) {
1091     webview.addEventListener('loadabort', function(e) {
1092       embedder.test.assertEq('ERR_UNKNOWN_URL_SCHEME', e.reason);
1093       embedder.test.succeed();
1094     });
1095     webview.executeScript({
1096       code: 'window.location.href = "tel:+12223334444";'
1097     }, function(results) {});
1098   });
1099   webview.setAttribute('src', 'data:text/html,navigate to external protocol');
1100   document.body.appendChild(webview);
1103 // This test ensures if the guest isn't there and we resize the guest (from JS),
1104 // it remembers the size correctly.
1105 function testNavigateAfterResize() {
1106   var webview = document.createElement('webview');
1108   var postMessageHandler = function(e) {
1109     var data = JSON.parse(e.data);
1110     webview.removeEventListener('message', postMessageHandler);
1111     if (data[0] == 'dimension-response') {
1112       var actualWidth = data[1];
1113       var actualHeight = data[2];
1114       embedder.test.assertEq(100, actualWidth);
1115       embedder.test.assertEq(125, actualHeight);
1116       embedder.test.succeed();
1117     }
1118   };
1119   window.addEventListener('message', postMessageHandler);
1121   webview.addEventListener('consolemessage', function(e) {
1122     window.console.warn('guest log: ' + e.message);
1123   });
1125   webview.addEventListener('loadstop', function(e) {
1126     webview.executeScript(
1127       {file: 'navigate_after_resize.js'},
1128       function(results) {
1129         if (!results || !results.length) {
1130           window.console.warn('Failed to inject navigate_after_resize.js');
1131           embedder.test.fail();
1132           return;
1133         }
1134         var msg = ['dimension-request'];
1135         webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1136       });
1137   });
1139   // First set size.
1140   webview.style.width = '100px';
1141   webview.style.height = '125px';
1143   // Then navigate.
1144   webview.src = 'about:blank';
1145   document.body.appendChild(webview);
1148 // This test verifies that multiple consecutive changes to the <webview> src
1149 // attribute will cause a navigation.
1150 function testNavOnConsecutiveSrcAttributeChanges() {
1151   var testPage1 = 'data:text/html,test page 1';
1152   var testPage2 = 'data:text/html,test page 2';
1153   var testPage3 = 'data:text/html,test page 3';
1154   var webview = document.createElement('webview');
1155   webview.partition = arguments.callee.name;
1156   var loadCommitCount = 0;
1157   webview.addEventListener('loadcommit', function(e) {
1158     if (e.url == testPage3) {
1159       embedder.test.succeed();
1160     }
1161     loadCommitCount++;
1162     if (loadCommitCount > 3) {
1163       embedder.test.fail();
1164     }
1165   });
1166   document.body.appendChild(webview);
1167   webview.src = testPage1;
1168   webview.src = testPage2;
1169   webview.src = testPage3;
1172 // This test verifies that we can set the <webview> src multiple times and the
1173 // changes will cause a navigation.
1174 function testNavOnSrcAttributeChange() {
1175   var testPage1 = 'data:text/html,test page 1';
1176   var testPage2 = 'data:text/html,test page 2';
1177   var testPage3 = 'data:text/html,test page 3';
1178   var tests = [testPage1, testPage2, testPage3];
1179   var webview = document.createElement('webview');
1180   webview.partition = arguments.callee.name;
1181   var loadCommitCount = 0;
1182   webview.addEventListener('loadcommit', function(evt) {
1183     var success = tests.indexOf(evt.url) > -1;
1184     embedder.test.assertTrue(success);
1185     ++loadCommitCount;
1186     if (loadCommitCount == tests.length) {
1187       embedder.test.succeed();
1188     } else if (loadCommitCount > tests.length) {
1189       embedder.test.fail();
1190     } else {
1191       webview.src = tests[loadCommitCount];
1192     }
1193   });
1194   webview.src = tests[0];
1195   document.body.appendChild(webview);
1198 // This test verifies that new window attachment functions as expected.
1199 function testNewWindow() {
1200   var webview = document.createElement('webview');
1201   webview.addEventListener('newwindow', function(e) {
1202     e.preventDefault();
1203     var newwebview = document.createElement('webview');
1204     newwebview.addEventListener('loadstop', function(evt) {
1205       // If the new window finishes loading, the test is successful.
1206       embedder.test.succeed();
1207     });
1208     document.body.appendChild(newwebview);
1209     // Attach the new window to the new <webview>.
1210     e.window.attach(newwebview);
1211   });
1212   webview.setAttribute('src', embedder.windowOpenGuestURL);
1213   document.body.appendChild(webview);
1216 // This test verifies that the attach can be called inline without
1217 // preventing default.
1218 function testNewWindowNoPreventDefault() {
1219   var webview = document.createElement('webview');
1220   webview.addEventListener('newwindow', function(e) {
1221     var newwebview = document.createElement('webview');
1222     document.body.appendChild(newwebview);
1223     // Attach the new window to the new <webview>.
1224     try {
1225       e.window.attach(newwebview);
1226       embedder.test.succeed();
1227     } catch (err) {
1228       embedder.test.fail();
1229     }
1230   });
1231   webview.setAttribute('src', embedder.windowOpenGuestURL);
1232   document.body.appendChild(webview);
1235 function testNewWindowNoReferrerLink() {
1236   var webview = document.createElement('webview');
1237   webview.addEventListener('newwindow', function(e) {
1238     e.preventDefault();
1239     var newwebview = document.createElement('webview');
1240     newwebview.addEventListener('loadstop', function(evt) {
1241       // If the new window finishes loading, the test is successful.
1242       embedder.test.succeed();
1243     });
1244     document.body.appendChild(newwebview);
1245     // Attach the new window to the new <webview>.
1246     e.window.attach(newwebview);
1247   });
1248   webview.setAttribute('src', embedder.noReferrerGuestURL);
1249   document.body.appendChild(webview);
1252 // This test verifies "first-call-wins" semantics. That is, the first call
1253 // to perform an action on the new window takes the action and all
1254 // subsequent calls throw an exception.
1255 function testNewWindowTwoListeners() {
1256   var webview = document.createElement('webview');
1257   var error = false;
1258   webview.addEventListener('newwindow', function(e) {
1259     e.preventDefault();
1260     var newwebview = document.createElement('webview');
1261     document.body.appendChild(newwebview);
1262     try {
1263       e.window.attach(newwebview);
1264     } catch (err) {
1265       embedder.test.fail();
1266     }
1267   });
1268   webview.addEventListener('newwindow', function(e) {
1269     e.preventDefault();
1270     try {
1271       e.window.discard();
1272     } catch (err) {
1273       embedder.test.succeed();
1274     }
1275   });
1276   webview.setAttribute('src', embedder.windowOpenGuestURL);
1277   document.body.appendChild(webview);
1280 function testOnEventProperties() {
1281   var sequence = ['first', 'second', 'third', 'fourth'];
1282   var webview = document.createElement('webview');
1283   function createHandler(id) {
1284     return function(e) {
1285       embedder.test.assertEq(id, sequence.shift());
1286     };
1287   }
1289   webview.addEventListener('loadstart', createHandler('first'));
1290   webview.addEventListener('loadstart', createHandler('second'));
1291   webview.onloadstart = createHandler('third');
1292   webview.addEventListener('loadstart', createHandler('fourth'));
1293   webview.addEventListener('loadstop', function(evt) {
1294     embedder.test.assertEq(0, sequence.length);
1296     // Test that setting another 'onloadstart' handler replaces the previous
1297     // handler.
1298     sequence = ['first', 'second', 'fourth'];
1299     webview.onloadstart = function() {
1300       embedder.test.assertEq(0, sequence.length);
1301       embedder.test.succeed();
1302     };
1304     webview.setAttribute('src', 'data:text/html,next navigation');
1305   });
1307   webview.setAttribute('src', 'data:text/html,trigger navigation');
1308   document.body.appendChild(webview);
1311 // This test verifies that the partion attribute cannot be changed after the src
1312 // has been set.
1313 function testPartitionChangeAfterNavigation() {
1314   var webview = document.createElement('webview');
1315   var partitionAttribute = arguments.callee.name;
1316   webview.setAttribute('partition', partitionAttribute);
1318   var loadstopHandler = function(e) {
1319     webview.partition = 'illegal';
1320     embedder.test.assertEq(partitionAttribute, webview.partition);
1321     embedder.test.succeed();
1322   };
1323   webview.addEventListener('loadstop', loadstopHandler);
1325   webview.setAttribute('src', 'data:text/html,trigger navigation');
1326   document.body.appendChild(webview);
1329 // This test verifies that removing partition attribute after navigation does
1330 // not work, i.e. the partition remains the same.
1331 function testPartitionRemovalAfterNavigationFails() {
1332   var webview = document.createElement('webview');
1334   var partition = 'testme';
1335   webview.setAttribute('partition', partition);
1337   var loadstopHandler = function(e) {
1338     // Removing after navigation should not change the partition.
1339     webview.removeAttribute('partition');
1340     embedder.test.assertEq('testme', webview.partition);
1341     embedder.test.succeed();
1342   };
1343   webview.addEventListener('loadstop', loadstopHandler);
1345   webview.setAttribute('src', 'data:text/html,<html><body>guest</body></html>');
1346   document.body.appendChild(webview);
1349 // This test verifies that <webview> reloads the page if the src attribute is
1350 // assigned the same value.
1351 function testReassignSrcAttribute() {
1352   var dataUrl = 'data:text/html,test page';
1353   var webview = document.createElement('webview');
1354   webview.partition = arguments.callee.name;
1356   var loadStopCount = 0;
1357   webview.addEventListener('loadstop', function(evt) {
1358     embedder.test.assertEq(dataUrl, webview.getAttribute('src'));
1359     ++loadStopCount;
1360     console.log('[' + loadStopCount + '] loadstop called');
1361     if (loadStopCount == 3) {
1362       embedder.test.succeed();
1363     } else if (loadStopCount > 3) {
1364       embedder.test.fail();
1365     } else {
1366       webview.src = dataUrl;
1367     }
1368   });
1369   webview.src = dataUrl;
1370   document.body.appendChild(webview);
1373 // This test verifies that the reload method on webview functions as expected.
1374 function testReload() {
1375   var triggerNavUrl = 'data:text/html,trigger navigation';
1376   var webview = document.createElement('webview');
1378   var loadCommitCount = 0;
1379   webview.addEventListener('loadstop', function(e) {
1380     if (loadCommitCount < 2) {
1381       webview.reload();
1382     } else if (loadCommitCount == 2) {
1383       embedder.test.succeed();
1384     } else {
1385       embedder.test.fail();
1386     }
1387   });
1388   webview.addEventListener('loadcommit', function(e) {
1389     embedder.test.assertEq(triggerNavUrl, e.url);
1390     embedder.test.assertTrue(e.isTopLevel);
1391     loadCommitCount++;
1392   });
1394   webview.setAttribute('src', triggerNavUrl);
1395   document.body.appendChild(webview);
1398 // This test verifies that the reload method on webview functions as expected.
1399 function testReloadAfterTerminate() {
1400   var triggerNavUrl = 'data:text/html,trigger navigation';
1401   var webview = document.createElement('webview');
1403   var step = 1;
1404   webview.addEventListener('loadstop', function(e) {
1405     switch (step) {
1406       case 1:
1407         webview.terminate();
1408         break;
1409       case 2:
1410         setTimeout(function() { embedder.test.succeed(); }, 0);
1411         break;
1412       default:
1413         window.console.log('Unexpected loadstop event, step = ' + step);
1414         embedder.test.fail();
1415         break;
1416     }
1417     ++step;
1418   });
1420   webview.addEventListener('exit', function(e) {
1421     // Trigger a focus state change of the guest to test for
1422     // http://crbug.com/413874.
1423     webview.blur();
1424     webview.focus();
1425     setTimeout(function() { webview.reload(); }, 0);
1426   });
1428   webview.src = triggerNavUrl;
1429   document.body.appendChild(webview);
1432 // This test verifies that <webview> restores the src attribute if it is
1433 // removed after navigation.
1434 function testRemoveSrcAttribute() {
1435   var dataUrl = 'data:text/html,test page';
1436   var webview = document.createElement('webview');
1437   webview.setAttribute('partition', arguments.callee.name);
1438   var terminated = false;
1439   webview.addEventListener('loadstop', function(evt) {
1440     webview.removeAttribute('src');
1441     setTimeout(function() {
1442       embedder.test.assertEq(dataUrl, webview.getAttribute('src'));
1443       embedder.test.succeed();
1444     }, 0);
1445   });
1446   webview.setAttribute('src', dataUrl);
1447   document.body.appendChild(webview);
1450 function testRemoveWebviewAfterNavigation() {
1451   var webview = document.createElement('webview');
1452   document.body.appendChild(webview);
1453   webview.src = 'data:text/html,trigger navigation';
1454   document.body.removeChild(webview);
1455   setTimeout(function() {
1456     embedder.test.succeed();
1457   }, 0);
1460 // This test verifies that a <webview> is torn down gracefully when removed from
1461 // the DOM on exit.
1462 window.removeWebviewOnExitDoCrash = null;
1463 function testRemoveWebviewOnExit() {
1464   var triggerNavUrl = 'data:text/html,trigger navigation';
1465   var webview = document.createElement('webview');
1467   webview.addEventListener('loadstop', function(e) {
1468     chrome.test.sendMessage('guest-loaded');
1469   });
1471   window.removeWebviewOnExitDoCrash = function() {
1472     webview.terminate();
1473   };
1475   webview.addEventListener('exit', function(e) {
1476     // We expected to be killed.
1477     if (e.reason != 'killed') {
1478       return;
1479     }
1480     webview.parentNode.removeChild(webview);
1481   });
1483   // Trigger a navigation to create a guest process.
1484   webview.setAttribute('src', embedder.emptyGuestURL);
1485   document.body.appendChild(webview);
1488 function testResizeWebviewResizesContent() {
1489   var webview = document.createElement('webview');
1490   webview.src = 'about:blank';
1491   webview.addEventListener('loadstop', function(e) {
1492     webview.executeScript(
1493       {file: 'inject_resize_test.js'},
1494       function(results) {
1495         window.console.log('The resize test has been injected into webview.');
1496       }
1497     );
1498     webview.executeScript(
1499       {file: 'inject_comm_channel.js'},
1500       function(results) {
1501         window.console.log('The guest script for a two-way comm channel has ' +
1502             'been injected into webview.');
1503         // Establish a communication channel with the guest.
1504         var msg = ['connect'];
1505         webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1506       }
1507     );
1508   });
1509   window.addEventListener('message', function(e) {
1510     var data = JSON.parse(e.data);
1511     if (data[0] == 'connected') {
1512       console.log('A communication channel has been established with webview.');
1513       console.log('Resizing <webview> width from 300px to 400px.');
1514       webview.style.width = '400px';
1515       return;
1516     }
1517     if (data[0] == 'resize') {
1518       var width = data[1];
1519       var height = data[2];
1520       embedder.test.assertEq(400, width);
1521       embedder.test.assertEq(300, height);
1522       embedder.test.succeed();
1523       return;
1524     }
1525     console.log('Unexpected message: \'' + data[0]  + '\'');
1526     embedder.test.fail();
1527   });
1528   document.body.appendChild(webview);
1531 // This test calls terminate() on guest after it has already been
1532 // terminated. This makes sure we ignore the call gracefully.
1533 function testTerminateAfterExit() {
1534   var webview = document.createElement('webview');
1535   webview.setAttribute('partition', arguments.callee.name);
1536   var loadstopSucceedsTest = false;
1537   webview.addEventListener('loadstop', function(evt) {
1538     embedder.test.assertEq('loadstop', evt.type);
1539     if (loadstopSucceedsTest) {
1540       embedder.test.succeed();
1541       return;
1542     }
1544     webview.terminate();
1545   });
1547   webview.addEventListener('exit', function(evt) {
1548     embedder.test.assertEq('exit', evt.type);
1549     // Call terminate again.
1550     webview.terminate();
1551     // Load another page. The test would pass when loadstop is called on
1552     // this second page. This would hopefully catch if call to
1553     // webview.terminate() caused a browser crash.
1554     setTimeout(function() {
1555       loadstopSucceedsTest = true;
1556       webview.setAttribute('src', 'data:text/html,test second page');
1557     }, 0);
1558   });
1560   webview.setAttribute('src', 'data:text/html,test terminate() crash.');
1561   document.body.appendChild(webview);
1564 // This test verifies that the WebRequest API onBeforeRequest event fires on
1565 // webview.
1566 function testWebRequestAPI() {
1567   var webview = new WebView();
1568   webview.request.onBeforeRequest.addListener(function(e) {
1569     embedder.test.succeed();
1570   }, { urls: ['<all_urls>']}) ;
1571   webview.src = embedder.windowOpenGuestURL;
1572   document.body.appendChild(webview);
1575 // This test verifies that the WebRequest API onBeforeSendHeaders event fires on
1576 // webview and supports headers. This tests verifies that we can modify HTTP
1577 // headers via the WebRequest API and those modified headers will be sent to the
1578 // HTTP server.
1579 function testWebRequestAPIWithHeaders() {
1580   var webview = new WebView();
1581   var requestFilter = {
1582     urls: ['<all_urls>']
1583   };
1584   var extraInfoSpec = ['requestHeaders', 'blocking'];
1585   webview.request.onBeforeSendHeaders.addListener(function(details) {
1586     var headers = details.requestHeaders;
1587     for( var i = 0, l = headers.length; i < l; ++i ) {
1588       if (headers[i].name == 'User-Agent') {
1589         headers[i].value = 'foobar';
1590         break;
1591       }
1592     }
1593     var blockingResponse = {};
1594     blockingResponse.requestHeaders = headers;
1595     return blockingResponse;
1596   }, requestFilter, extraInfoSpec);
1598   var loadstartCalled = false;
1599   webview.addEventListener('loadstart', function(e) {
1600     embedder.test.assertTrue(e.isTopLevel);
1601     embedder.test.assertEq(embedder.detectUserAgentURL, e.url);
1602     loadstartCalled = true;
1603   });
1605   webview.addEventListener('loadredirect', function(e) {
1606     embedder.test.assertTrue(e.isTopLevel);
1607     embedder.test.assertEq(embedder.detectUserAgentURL,
1608         e.oldUrl.replace('127.0.0.1', 'localhost'));
1609     embedder.test.assertEq(embedder.redirectGuestURLDest,
1610         e.newUrl.replace('127.0.0.1', 'localhost'));
1611     if (loadstartCalled) {
1612       embedder.test.succeed();
1613     } else {
1614       embedder.test.fail();
1615     }
1616   });
1617   webview.src = embedder.detectUserAgentURL;
1618   document.body.appendChild(webview);
1621 function testWebRequestAPIExistence() {
1622   var apiPropertiesToCheck = [
1623     // Declarative WebRequest API.
1624     'onMessage',
1625     'onRequest',
1626     // WebRequest API.
1627     'onBeforeRequest',
1628     'onBeforeSendHeaders',
1629     'onSendHeaders',
1630     'onHeadersReceived',
1631     'onAuthRequired',
1632     'onBeforeRedirect',
1633     'onResponseStarted',
1634     'onCompleted',
1635     'onErrorOccurred'
1636   ];
1637   var webview = document.createElement('webview');
1638   webview.setAttribute('partition', arguments.callee.name);
1639   webview.addEventListener('loadstop', function(e) {
1640     for (var i = 0; i < apiPropertiesToCheck.length; ++i) {
1641       embedder.test.assertEq('object',
1642                              typeof webview.request[apiPropertiesToCheck[i]]);
1643       embedder.test.assertEq(
1644           'function',
1645           typeof webview.request[apiPropertiesToCheck[i]].addListener);
1646       embedder.test.assertEq(
1647           'function',
1648           typeof webview.request[apiPropertiesToCheck[i]].addRules);
1649       embedder.test.assertEq(
1650           'function',
1651           typeof webview.request[apiPropertiesToCheck[i]].getRules);
1652       embedder.test.assertEq(
1653           'function',
1654           typeof webview.request[apiPropertiesToCheck[i]].removeRules);
1655     }
1657     // Try to overwrite webview.request, shall not succeed.
1658     webview.request = '123';
1659     embedder.test.assertTrue(typeof webview.request !== 'string');
1661     embedder.test.succeed();
1662   });
1663   webview.setAttribute('src', 'data:text/html,webview check api');
1664   document.body.appendChild(webview);
1667 // This test verifies that the WebRequest API onBeforeRequest event fires on
1668 // clients*.google.com URLs.
1669 function testWebRequestAPIGoogleProperty() {
1670   var webview = new WebView();
1671   webview.request.onBeforeRequest.addListener(function(e) {
1672     embedder.test.succeed();
1673     return {cancel: true};
1674   }, { urls: ['<all_urls>']}, ['blocking']) ;
1675   webview.src = 'http://clients6.google.com';
1676   document.body.appendChild(webview);
1679 // Tests end.
1681 embedder.test.testList = {
1682   'testAllowTransparencyAttribute': testAllowTransparencyAttribute,
1683   'testAPIMethodExistence': testAPIMethodExistence,
1684   'testAssignSrcAfterCrash': testAssignSrcAfterCrash,
1685   'testAutosizeAfterNavigation': testAutosizeAfterNavigation,
1686   'testAutosizeBeforeNavigation': testAutosizeBeforeNavigation,
1687   'testAutosizeHeight': testAutosizeHeight,
1688   'testAutosizeRemoveAttributes': testAutosizeRemoveAttributes,
1689   'testAutosizeWithPartialAttributes': testAutosizeWithPartialAttributes,
1690   'testCannotMutateEventName': testCannotMutateEventName,
1691   'testChromeExtensionRelativePath': testChromeExtensionRelativePath,
1692   'testChromeExtensionURL': testChromeExtensionURL,
1693   'testContentLoadEvent': testContentLoadEvent,
1694   'testDeclarativeWebRequestAPI': testDeclarativeWebRequestAPI,
1695   'testDeclarativeWebRequestAPISendMessage':
1696       testDeclarativeWebRequestAPISendMessage,
1697   'testDestroyOnEventListener': testDestroyOnEventListener,
1698   'testDisplayNoneWebviewLoad': testDisplayNoneWebviewLoad,
1699   'testDisplayNoneWebviewRemoveChild': testDisplayNoneWebviewRemoveChild,
1700   'testEventName': testEventName,
1701   'testExecuteScript': testExecuteScript,
1702   'testExecuteScriptFail': testExecuteScriptFail,
1703   'testExecuteScriptIsAbortedWhenWebViewSourceIsChanged':
1704       testExecuteScriptIsAbortedWhenWebViewSourceIsChanged,
1705   'testFindAPI': testFindAPI,
1706   'testFindAPI_findupdate': testFindAPI,
1707   'testGetProcessId': testGetProcessId,
1708   'testHiddenBeforeNavigation': testHiddenBeforeNavigation,
1709   'testInlineScriptFromAccessibleResources':
1710       testInlineScriptFromAccessibleResources,
1711   'testInvalidChromeExtensionURL': testInvalidChromeExtensionURL,
1712   'testLoadAbortChromeExtensionURLWrongPartition':
1713       testLoadAbortChromeExtensionURLWrongPartition,
1714   'testLoadAbortEmptyResponse': testLoadAbortEmptyResponse,
1715   'testLoadAbortIllegalChromeURL': testLoadAbortIllegalChromeURL,
1716   'testLoadAbortIllegalFileURL': testLoadAbortIllegalFileURL,
1717   'testLoadAbortIllegalJavaScriptURL': testLoadAbortIllegalJavaScriptURL,
1718   'testLoadAbortInvalidNavigation': testLoadAbortInvalidNavigation,
1719   'testLoadAbortNonWebSafeScheme': testLoadAbortNonWebSafeScheme,
1720   'testLoadProgressEvent': testLoadProgressEvent,
1721   'testLoadStartLoadRedirect': testLoadStartLoadRedirect,
1722   'testNavigateAfterResize': testNavigateAfterResize,
1723   'testNavigationToExternalProtocol': testNavigationToExternalProtocol,
1724   'testNavOnConsecutiveSrcAttributeChanges':
1725       testNavOnConsecutiveSrcAttributeChanges,
1726   'testNavOnSrcAttributeChange': testNavOnSrcAttributeChange,
1727   'testNewWindow': testNewWindow,
1728   'testNewWindowNoPreventDefault': testNewWindowNoPreventDefault,
1729   'testNewWindowNoReferrerLink': testNewWindowNoReferrerLink,
1730   'testNewWindowTwoListeners': testNewWindowTwoListeners,
1731   'testOnEventProperties': testOnEventProperties,
1732   'testPartitionChangeAfterNavigation': testPartitionChangeAfterNavigation,
1733   'testPartitionRemovalAfterNavigationFails':
1734       testPartitionRemovalAfterNavigationFails,
1735   'testReassignSrcAttribute': testReassignSrcAttribute,
1736   'testReload': testReload,
1737   'testReloadAfterTerminate': testReloadAfterTerminate,
1738   'testRemoveSrcAttribute': testRemoveSrcAttribute,
1739   'testRemoveWebviewAfterNavigation': testRemoveWebviewAfterNavigation,
1740   'testRemoveWebviewOnExit': testRemoveWebviewOnExit,
1741   'testResizeWebviewResizesContent': testResizeWebviewResizesContent,
1742   'testTerminateAfterExit': testTerminateAfterExit,
1743   'testWebRequestAPI': testWebRequestAPI,
1744   'testWebRequestAPIWithHeaders': testWebRequestAPIWithHeaders,
1745   'testWebRequestAPIExistence': testWebRequestAPIExistence,
1746   'testWebRequestAPIGoogleProperty': testWebRequestAPIGoogleProperty
1749 onload = function() {
1750   chrome.test.getConfig(function(config) {
1751     embedder.setUp_(config);
1752     chrome.test.sendMessage('LAUNCHED');
1753   });