Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / extensions / test / data / web_view / apitest / main.js
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.
4
5 var embedder = {};
6
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';
22 };
23
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   }
30
31   // Run the test.
32   embedder.test.testList[testName]();
33 };
34
35 embedder.test = {};
36
37 embedder.test.assertEq = function(a, b) {
38   if (a != b) {
39     window.console.warn('assertion failed: ' + a + ' != ' + b);
40     embedder.test.fail();
41   }
42 };
43
44 embedder.test.assertFalse = function(condition) {
45   if (condition) {
46     window.console.warn('assertion failed: false != ' + condition);
47     embedder.test.fail();
48   }
49 };
50
51 embedder.test.assertTrue = function(condition) {
52   if (!condition) {
53     window.console.warn('assertion failed: true != ' + condition);
54     embedder.test.fail();
55   }
56 };
57
58 embedder.test.fail = function() {
59   chrome.test.sendMessage('TEST_FAILED');
60 };
61
62 embedder.test.succeed = function() {
63   chrome.test.sendMessage('TEST_PASSED');
64 };
65
66
67 // Tests begin.
68
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;
77
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   });
92
93   document.body.appendChild(webview);
94 }
95
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     }
126
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);
135 }
136
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);
157 }
158
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');
166
167   var step = 1;
168   var sizeChangeHandler = function(e) {
169     switch (step) {
170       case 1:
171         // This would be triggered after we set autosize attribute.
172         embedder.test.assertEq(50, e.oldWidth);
173         embedder.test.assertEq(100, e.oldHeight);
174         embedder.test.assertTrue(e.newWidth >= 60 && e.newWidth <= 70);
175         embedder.test.assertTrue(e.newHeight >= 110 && e.newHeight <= 120);
176
177         // Remove autosize attribute and expect webview to return to its
178         // original size.
179         webview.removeAttribute('autosize');
180         break;
181       case 2:
182         // Expect 50x100.
183         embedder.test.assertEq(50, e.newWidth);
184         embedder.test.assertEq(100, e.newHeight);
185
186         embedder.test.succeed();
187         break;
188       default:
189         window.console.log('Unexpected sizechanged event, step = ' + step);
190         embedder.test.fail();
191         break;
192     }
193
194     ++step;
195   };
196
197   webview.addEventListener('sizechanged', sizeChangeHandler);
198
199   webview.addEventListener('loadstop', function(e) {
200     webview.setAttribute('autosize', true);
201     webview.setAttribute('minwidth', 60);
202     webview.setAttribute('maxwidth', 70);
203     webview.setAttribute('minheight', 110);
204     webview.setAttribute('maxheight', 120);
205   });
206
207   webview.style.width = '50px';
208   webview.style.height = '100px';
209   webview.setAttribute('src', 'data:text/html,webview test sizechanged event');
210   document.body.appendChild(webview);
211 }
212
213 // This test verifies that if a browser plugin is in autosize mode before
214 // navigation then the guest starts auto-sized.
215 function testAutosizeBeforeNavigation() {
216   var webview = document.createElement('webview');
217
218   webview.setAttribute('autosize', 'true');
219   webview.setAttribute('minwidth', 200);
220   webview.setAttribute('maxwidth', 210);
221   webview.setAttribute('minheight', 100);
222   webview.setAttribute('maxheight', 110);
223
224   webview.addEventListener('sizechanged', function(e) {
225     embedder.test.assertEq(0, e.oldWidth);
226     embedder.test.assertEq(0, e.oldHeight);
227     embedder.test.assertTrue(e.newWidth >= 200 && e.newWidth <= 210);
228     embedder.test.assertTrue(e.newHeight >= 100 && e.newHeight <= 110);
229     embedder.test.succeed();
230   });
231
232   webview.setAttribute('src', 'data:text/html,webview test sizechanged event');
233   document.body.appendChild(webview);
234 }
235
236 // This test verifies that a lengthy page with autosize enabled will report
237 // the correct height in the sizechanged event.
238 function testAutosizeHeight() {
239   var webview = document.createElement('webview');
240
241   webview.autosize = true;
242   webview.minwidth = 200;
243   webview.maxwidth = 210;
244   webview.minheight = 40;
245   webview.maxheight = 200;
246
247   var step = 1;
248   webview.addEventListener('sizechanged', function(e) {
249     switch (step) {
250       case 1:
251         embedder.test.assertEq(0, e.oldHeight);
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   });
268
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);
276 }
277
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');
282
283   var step = 1;
284   var sizeChangeHandler = function(e) {
285     switch (step) {
286       case 1:
287         // This is the sizechanged event for autosize.
288
289         // Remove attributes.
290         webview.removeAttribute('minwidth');
291         webview.removeAttribute('maxwidth');
292         webview.removeAttribute('minheight');
293         webview.removeAttribute('maxheight');
294         webview.removeAttribute('autosize');
295
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     }
305
306     ++step;
307   };
308
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   });
316
317   webview.addEventListener('sizechanged', sizeChangeHandler);
318
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);
323 }
324
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');
329
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);
339
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);
346
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);
356
357         embedder.test.succeed();
358         break;
359       default:
360         window.console.log('Unexpected sizechanged event, step = ' + step);
361         embedder.test.fail();
362         break;
363     }
364
365     ++step;
366   };
367
368   webview.addEventListener('sizechanged', sizeChangeHandler);
369
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   });
377
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);
382 }
383
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;
392
393   var maybeFinishTest = function(e) {
394     if (loadCommitACalled && loadCommitBCalled) {
395       embedder.test.assertEq('loadcommit', e.type);
396       embedder.test.succeed();
397     }
398   };
399
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   };
422
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);
430 }
431
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);
447 }
448
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);
464 }
465
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);
477 }
478
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);
516 }
517
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);
540 }
541
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>';
549
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   };
566
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);
579 }
580
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);
599
600   setTimeout(function() {
601     visible = true;
602     // This should trigger loadstop.
603     webview.style.display = '';
604   }, 0);
605 }
606
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);
623
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);
631 }
632
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);
638
639   webview.addEventListener('loadstart', function(evt) {
640     embedder.test.assertEq('loadstart', evt.type);
641   });
642
643   webview.addEventListener('loadstop', function(evt) {
644     embedder.test.assertEq('loadstop', evt.type);
645     webview.terminate();
646   });
647
648   webview.addEventListener('exit', function(evt) {
649     embedder.test.assertEq('exit', evt.type);
650     embedder.test.succeed();
651   });
652
653   webview.setAttribute('src', 'data:text/html,trigger navigation');
654   document.body.appendChild(webview);
655 }
656
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);
670 }
671
672 function testExecuteScriptFail() {
673   var webview = document.createElement('webview');
674   try {
675     webview.executeScript(
676         {code: 'document.body.style.backgroundColor = "red";'},
677         function(results) { embedder.test.fail(); });
678   }
679   catch (e) {
680     embedder.test.succeed();
681   }
682 }
683
684 // This test verifies that the call of executeScript will fail and return null
685 // if the webview has been navigated to another source.
686 function testExecuteScriptIsAbortedWhenWebViewSourceIsChanged() {
687   var webview = document.createElement('webview');
688   var initial = true;
689   var navigationOccur = false;
690   var newSrc = 'data:text/html,trigger navigation';
691   webview.addEventListener('loadstart', function() {
692     if (initial) {
693       webview.setAttribute('src', newSrc);
694       navigationOccur = true;
695     }
696     initial = false;
697   });
698   webview.addEventListener('loadstop', function() {
699     webview.executeScript(
700       {code:'document.body.style.backgroundColor = "red";'},
701       function(results) {
702         if (navigationOccur) {
703           // Expect a null results because the executeScript failed;
704           // return "red", otherwise.
705           embedder.test.assertEq(null, results);
706           embedder.test.succeed();
707         }
708         navigationOccur = false;
709       }
710     );
711   });
712   webview.setAttribute('src', "about:blank");
713   document.body.appendChild(webview);
714 }
715
716 function testFindAPI() {
717   var webview = new WebView();
718   webview.src = 'data:text/html,Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
719       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
720       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
721       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
722       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
723       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
724       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
725       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
726       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
727       'Dog dog dog Dog dog dogcatDog dogDogdog.<br><br>' +
728       '<a href="about:blank">Click here!</a>';
729
730   var loadstopListener2 = function(e) {
731     embedder.test.assertEq(webview.src, "about:blank");
732     embedder.test.succeed();
733   }
734
735   var loadstopListener1 = function(e) {
736     // Test find results.
737     webview.find("dog", {}, function(results) {
738       callbackTest = true;
739       embedder.test.assertEq(results.numberOfMatches, 100);
740       embedder.test.assertTrue(results.selectionRect.width > 0);
741       embedder.test.assertTrue(results.selectionRect.height > 0);
742
743       // Test finding next active matches.
744       webview.find("dog");
745       webview.find("dog");
746       webview.find("dog");
747       webview.find("dog");
748       webview.find("dog", {}, function(results) {
749         embedder.test.assertEq(results.activeMatchOrdinal, 6);
750         webview.find("dog", {backward: true});
751         webview.find("dog", {backward: true}, function(results) {
752           // Test the |backward| find option.
753           embedder.test.assertEq(results.activeMatchOrdinal, 4);
754
755           // Test the |matchCase| find option.
756           webview.find("Dog", {matchCase: true}, function(results) {
757             embedder.test.assertEq(results.numberOfMatches, 40);
758
759             // Test canceling find requests.
760             webview.find("dog");
761             webview.stopFinding();
762             webview.find("dog");
763             webview.find("cat");
764
765             // Test find results when looking for something that isn't there.
766             webview.find("fish", {}, function(results) {
767               embedder.test.assertEq(results.numberOfMatches, 0);
768               embedder.test.assertEq(results.activeMatchOrdinal, 0);
769               embedder.test.assertEq(results.selectionRect.left, 0);
770               embedder.test.assertEq(results.selectionRect.top, 0);
771               embedder.test.assertEq(results.selectionRect.width, 0);
772               embedder.test.assertEq(results.selectionRect.height, 0);
773
774               // Test following a link with stopFinding().
775               webview.removeEventListener('loadstop', loadstopListener1);
776               webview.addEventListener('loadstop', loadstopListener2);
777               webview.find("click here!", {}, function() {
778                 webview.stopFinding("activate");
779               });
780             });
781           });
782         });
783       });
784     });
785   };
786
787   webview.addEventListener('loadstop', loadstopListener1);
788   document.body.appendChild(webview);
789 };
790
791 function testFindAPI_findupdate() {
792   var webview = new WebView();
793   webview.src = 'data:text/html,Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
794       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
795       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
796       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
797       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
798       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
799       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
800       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
801       'Dog dog dog Dog dog dogcatDog dogDogdog.<br>' +
802       'Dog dog dog Dog dog dogcatDog dogDogdog.<br><br>' +
803       '<a href="about:blank">Click here!</a>';
804   var canceledTest = false;
805   webview.addEventListener('loadstop', function(e) {
806     // Test the |findupdate| event.
807     webview.addEventListener('findupdate', function(e) {
808       if (e.activeMatchOrdinal > 0) {
809         // embedder.test.assertTrue(e.numberOfMatches >= e.activeMatchOrdinal)
810         // This currently fails because of http://crbug.com/342445 .
811         embedder.test.assertTrue(e.selectionRect.width > 0);
812         embedder.test.assertTrue(e.selectionRect.height > 0);
813       }
814
815       if (e.finalUpdate) {
816         if (e.canceled) {
817           canceledTest = true;
818         } else {
819           embedder.test.assertEq(e.searchText, "dog");
820           embedder.test.assertEq(e.numberOfMatches, 100);
821           embedder.test.assertEq(e.activeMatchOrdinal, 1);
822           embedder.test.assertTrue(canceledTest);
823           embedder.test.succeed();
824         }
825       }
826     });
827     wv.find("dog");
828     wv.find("cat");
829     wv.find("dog");
830   });
831
832   document.body.appendChild(webview);
833 };
834
835 // This test verifies that getProcessId is defined and returns a non-zero
836 // value corresponding to the processId of the guest process.
837 function testGetProcessId() {
838   var webview = document.createElement('webview');
839   webview.setAttribute('src', 'data:text/html,trigger navigation');
840   var firstLoad = function() {
841     webview.removeEventListener('loadstop', firstLoad);
842     embedder.test.assertTrue(webview.getProcessId() > 0);
843     embedder.test.succeed();
844   };
845   webview.addEventListener('loadstop', firstLoad);
846   document.body.appendChild(webview);
847 }
848
849 function testHiddenBeforeNavigation() {
850   var webview = document.createElement('webview');
851   webview.style.visibility = 'hidden';
852
853   var postMessageHandler = function(e) {
854     var data = JSON.parse(e.data);
855     window.removeEventListener('message', postMessageHandler);
856     if (data[0] == 'visibilityState-response') {
857       embedder.test.assertEq('hidden', data[1]);
858       embedder.test.succeed();
859     } else {
860       window.console.warn('Unexpected message: ' + data);
861       embedder.test.fail();
862     }
863   };
864
865   webview.addEventListener('loadstop', function(e) {
866     window.console.warn('webview.loadstop');
867     window.addEventListener('message', postMessageHandler);
868     webview.addEventListener('consolemessage', function(e) {
869       window.console.warn('g: ' + e.message);
870     });
871
872     webview.executeScript(
873       {file: 'inject_hidden_test.js'},
874       function(results) {
875         if (!results || !results.length) {
876           window.console.warn('Failed to inject script: inject_hidden_test.js');
877           embedder.test.fail();
878           return;
879         }
880
881         window.console.warn('script injection success');
882         webview.contentWindow.postMessage(
883             JSON.stringify(['visibilityState-request']), '*');
884       });
885   });
886
887   webview.setAttribute('src', 'data:text/html,<html><body></body></html>');
888   document.body.appendChild(webview);
889 }
890
891 // Makes sure inline scripts works inside guest that was loaded from
892 // accessible_resources.
893 function testInlineScriptFromAccessibleResources() {
894   var webview = document.createElement('webview');
895   // foobar is a privileged partition according to the manifest file.
896   webview.partition = 'foobar';
897   webview.addEventListener('loadabort', function(e) {
898     embedder.test.fail();
899   });
900   webview.addEventListener('consolemessage', function(e) {
901     window.console.log('consolemessage: ' + e.message);
902     if (e.message == 'guest_with_inline_script.html: Inline script ran') {
903       embedder.test.succeed();
904     }
905   });
906   webview.setAttribute('src', 'guest_with_inline_script.html');
907   document.body.appendChild(webview);
908 }
909
910 // This tests verifies that webview fires a loadabort event instead of crashing
911 // the browser if we attempt to navigate to a chrome-extension: URL with an
912 // extension ID that does not exist.
913 function testInvalidChromeExtensionURL() {
914   var invalidResource = 'chrome-extension://abc123/guest.html';
915   var webview = document.createElement('webview');
916   // foobar is a privileged partition according to the manifest file.
917   webview.partition = 'foobar';
918   webview.addEventListener('loadabort', function(e) {
919     embedder.test.succeed();
920   });
921   webview.setAttribute('src', invalidResource);
922   document.body.appendChild(webview);
923 }
924
925 // This test verifies that the loadabort event fires when loading a webview
926 // accessible resource from a partition that is not privileged.
927 function testLoadAbortChromeExtensionURLWrongPartition() {
928   var localResource = chrome.runtime.getURL('guest.html');
929   var webview = document.createElement('webview');
930   webview.addEventListener('loadabort', function(e) {
931     embedder.test.assertEq('ERR_ADDRESS_UNREACHABLE', e.reason);
932     embedder.test.succeed();
933   });
934   webview.addEventListener('loadstop', function(e) {
935     embedder.test.fail();
936   });
937   webview.setAttribute('src', localResource);
938   document.body.appendChild(webview);
939 }
940
941 // This test verifies that the loadabort event fires as expected and with the
942 // appropriate fields when an empty response is returned.
943 function testLoadAbortEmptyResponse() {
944   var webview = document.createElement('webview');
945   webview.addEventListener('loadabort', function(e) {
946     embedder.test.assertEq('ERR_EMPTY_RESPONSE', e.reason);
947     embedder.test.succeed();
948   });
949   webview.setAttribute('src', embedder.closeSocketURL);
950   document.body.appendChild(webview);
951 }
952
953 // This test verifies that the loadabort event fires as expected when an illegal
954 // chrome URL is provided.
955 function testLoadAbortIllegalChromeURL() {
956   var webview = document.createElement('webview');
957   var onFirstLoadStop = function(e) {
958     webview.removeEventListener('loadstop', onFirstLoadStop);
959     webview.setAttribute('src', 'chrome://newtab');
960   };
961   webview.addEventListener('loadstop', onFirstLoadStop);
962   webview.addEventListener('loadabort', function(e) {
963     embedder.test.assertEq('ERR_ABORTED', e.reason);
964     embedder.test.succeed();
965   });
966   webview.setAttribute('src', 'about:blank');
967   document.body.appendChild(webview);
968 }
969
970 function testLoadAbortIllegalFileURL() {
971   var webview = document.createElement('webview');
972   webview.addEventListener('loadabort', function(e) {
973     embedder.test.assertEq('ERR_ABORTED', e.reason);
974     embedder.test.succeed();
975   });
976   webview.setAttribute('src', 'file://foo');
977   document.body.appendChild(webview);
978 }
979
980 function testLoadAbortIllegalJavaScriptURL() {
981   var webview = document.createElement('webview');
982   webview.addEventListener('loadabort', function(e) {
983     embedder.test.assertEq('ERR_ABORTED', e.reason);
984     embedder.test.succeed();
985   });
986   webview.setAttribute('src', 'javascript:void(document.bgColor="#0000FF")');
987   document.body.appendChild(webview);
988 }
989
990 // Verifies that navigating to invalid URL (e.g. 'http:') doesn't cause a crash.
991 function testLoadAbortInvalidNavigation() {
992   var webview = document.createElement('webview');
993   var validSchemeWithEmptyURL = 'http:';
994   webview.addEventListener('loadabort', function(e) {
995     embedder.test.assertEq('ERR_ABORTED', e.reason);
996     embedder.test.assertEq('', e.url);
997     embedder.test.succeed();
998   });
999   webview.addEventListener('exit', function(e) {
1000     // We should not crash.
1001     embedder.test.fail();
1002   });
1003   webview.setAttribute('src', validSchemeWithEmptyURL);
1004   document.body.appendChild(webview);
1005 }
1006
1007 // Verifies that navigation to a URL that is valid but not web-safe or
1008 // pseudo-scheme fires loadabort and doesn't cause a crash.
1009 function testLoadAbortNonWebSafeScheme() {
1010   var webview = document.createElement('webview');
1011   var chromeGuestURL = 'chrome-guest://abc123';
1012   webview.addEventListener('loadabort', function(e) {
1013     embedder.test.assertEq('ERR_ABORTED', e.reason);
1014     embedder.test.assertEq('chrome-guest://abc123/', e.url);
1015     embedder.test.succeed();
1016   });
1017   webview.addEventListener('exit', function(e) {
1018     // We should not crash.
1019     embedder.test.fail();
1020   });
1021   webview.setAttribute('src', chromeGuestURL);
1022   document.body.appendChild(webview);
1023 };
1024
1025 // Tests that the 'loadprogress' event is triggered correctly.
1026 function testLoadProgressEvent() {
1027   var webview = document.createElement('webview');
1028   var progress = 0;
1029
1030   webview.addEventListener('loadstop', function(evt) {
1031     embedder.test.assertEq(1, progress);
1032     embedder.test.succeed();
1033   });
1034
1035   webview.addEventListener('loadprogress', function(evt) {
1036     progress = evt.progress;
1037   });
1038
1039   webview.setAttribute('src', 'data:text/html,trigger navigation');
1040   document.body.appendChild(webview);
1041 }
1042
1043 // This test verifies that the loadstart event fires at the beginning of a load
1044 // and the loadredirect event fires when a redirect occurs.
1045 function testLoadStartLoadRedirect() {
1046   var webview = document.createElement('webview');
1047   var loadstartCalled = false;
1048   webview.setAttribute('src', embedder.redirectGuestURL);
1049   webview.addEventListener('loadstart', function(e) {
1050     embedder.test.assertTrue(e.isTopLevel);
1051     embedder.test.assertEq(embedder.redirectGuestURL, e.url);
1052     loadstartCalled = true;
1053   });
1054   webview.addEventListener('loadredirect', function(e) {
1055     embedder.test.assertTrue(e.isTopLevel);
1056     embedder.test.assertEq(embedder.redirectGuestURL,
1057         e.oldUrl.replace('127.0.0.1', 'localhost'));
1058     embedder.test.assertEq(embedder.redirectGuestURLDest,
1059         e.newUrl.replace('127.0.0.1', 'localhost'));
1060     if (loadstartCalled) {
1061       embedder.test.succeed();
1062     } else {
1063       embedder.test.fail();
1064     }
1065   });
1066   document.body.appendChild(webview);
1067 }
1068
1069 function testNavigationToExternalProtocol() {
1070   var webview = document.createElement('webview');
1071   webview.addEventListener('loadstop', function(e) {
1072     webview.addEventListener('loadabort', function(e) {
1073       embedder.test.assertEq('ERR_UNKNOWN_URL_SCHEME', e.reason);
1074       embedder.test.succeed();
1075     });
1076     webview.executeScript({
1077       code: 'window.location.href = "tel:+12223334444";'
1078     }, function(results) {});
1079   });
1080   webview.setAttribute('src', 'data:text/html,navigate to external protocol');
1081   document.body.appendChild(webview);
1082 }
1083
1084 // This test ensures if the guest isn't there and we resize the guest (from JS),
1085 // it remembers the size correctly.
1086 function testNavigateAfterResize() {
1087   var webview = document.createElement('webview');
1088
1089   var postMessageHandler = function(e) {
1090     var data = JSON.parse(e.data);
1091     webview.removeEventListener('message', postMessageHandler);
1092     if (data[0] == 'dimension-response') {
1093       var actualWidth = data[1];
1094       var actualHeight = data[2];
1095       embedder.test.assertEq(100, actualWidth);
1096       embedder.test.assertEq(125, actualHeight);
1097       embedder.test.succeed();
1098     }
1099   };
1100   window.addEventListener('message', postMessageHandler);
1101
1102   webview.addEventListener('consolemessage', function(e) {
1103     window.console.warn('guest log: ' + e.message);
1104   });
1105
1106   webview.addEventListener('loadstop', function(e) {
1107     webview.executeScript(
1108       {file: 'navigate_after_resize.js'},
1109       function(results) {
1110         if (!results || !results.length) {
1111           window.console.warn('Failed to inject navigate_after_resize.js');
1112           embedder.test.fail();
1113           return;
1114         }
1115         var msg = ['dimension-request'];
1116         webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1117       });
1118   });
1119
1120   // First set size.
1121   webview.style.width = '100px';
1122   webview.style.height = '125px';
1123
1124   // Then navigate.
1125   webview.src = 'about:blank';
1126   document.body.appendChild(webview);
1127 }
1128
1129 // This test verifies that multiple consecutive changes to the <webview> src
1130 // attribute will cause a navigation.
1131 function testNavOnConsecutiveSrcAttributeChanges() {
1132   var testPage1 = 'data:text/html,test page 1';
1133   var testPage2 = 'data:text/html,test page 2';
1134   var testPage3 = 'data:text/html,test page 3';
1135   var webview = document.createElement('webview');
1136   webview.partition = arguments.callee.name;
1137   var loadCommitCount = 0;
1138   webview.addEventListener('loadcommit', function(e) {
1139     if (e.url == testPage3) {
1140       embedder.test.succeed();
1141     }
1142     loadCommitCount++;
1143     if (loadCommitCount > 3) {
1144       embedder.test.fail();
1145     }
1146   });
1147   document.body.appendChild(webview);
1148   webview.src = testPage1;
1149   webview.src = testPage2;
1150   webview.src = testPage3;
1151 }
1152
1153 // This test verifies that we can set the <webview> src multiple times and the
1154 // changes will cause a navigation.
1155 function testNavOnSrcAttributeChange() {
1156   var testPage1 = 'data:text/html,test page 1';
1157   var testPage2 = 'data:text/html,test page 2';
1158   var testPage3 = 'data:text/html,test page 3';
1159   var tests = [testPage1, testPage2, testPage3];
1160   var webview = document.createElement('webview');
1161   webview.partition = arguments.callee.name;
1162   var loadCommitCount = 0;
1163   webview.addEventListener('loadcommit', function(evt) {
1164     var success = tests.indexOf(evt.url) > -1;
1165     embedder.test.assertTrue(success);
1166     ++loadCommitCount;
1167     if (loadCommitCount == tests.length) {
1168       embedder.test.succeed();
1169     } else if (loadCommitCount > tests.length) {
1170       embedder.test.fail();
1171     } else {
1172       webview.src = tests[loadCommitCount];
1173     }
1174   });
1175   webview.src = tests[0];
1176   document.body.appendChild(webview);
1177 }
1178
1179 // This test verifies that new window attachment functions as expected.
1180 function testNewWindow() {
1181   var webview = document.createElement('webview');
1182   webview.addEventListener('newwindow', function(e) {
1183     e.preventDefault();
1184     var newwebview = document.createElement('webview');
1185     newwebview.addEventListener('loadstop', function(evt) {
1186       // If the new window finishes loading, the test is successful.
1187       embedder.test.succeed();
1188     });
1189     document.body.appendChild(newwebview);
1190     // Attach the new window to the new <webview>.
1191     e.window.attach(newwebview);
1192   });
1193   webview.setAttribute('src', embedder.windowOpenGuestURL);
1194   document.body.appendChild(webview);
1195 }
1196
1197 // This test verifies that the attach can be called inline without
1198 // preventing default.
1199 function testNewWindowNoPreventDefault() {
1200   var webview = document.createElement('webview');
1201   webview.addEventListener('newwindow', function(e) {
1202     var newwebview = document.createElement('webview');
1203     document.body.appendChild(newwebview);
1204     // Attach the new window to the new <webview>.
1205     try {
1206       e.window.attach(newwebview);
1207       embedder.test.succeed();
1208     } catch (err) {
1209       embedder.test.fail();
1210     }
1211   });
1212   webview.setAttribute('src', embedder.windowOpenGuestURL);
1213   document.body.appendChild(webview);
1214 }
1215
1216 function testNewWindowNoReferrerLink() {
1217   var webview = document.createElement('webview');
1218   webview.addEventListener('newwindow', function(e) {
1219     e.preventDefault();
1220     var newwebview = document.createElement('webview');
1221     newwebview.addEventListener('loadstop', function(evt) {
1222       // If the new window finishes loading, the test is successful.
1223       embedder.test.succeed();
1224     });
1225     document.body.appendChild(newwebview);
1226     // Attach the new window to the new <webview>.
1227     e.window.attach(newwebview);
1228   });
1229   webview.setAttribute('src', embedder.noReferrerGuestURL);
1230   document.body.appendChild(webview);
1231 }
1232
1233 // This test verifies "first-call-wins" semantics. That is, the first call
1234 // to perform an action on the new window takes the action and all
1235 // subsequent calls throw an exception.
1236 function testNewWindowTwoListeners() {
1237   var webview = document.createElement('webview');
1238   var error = false;
1239   webview.addEventListener('newwindow', function(e) {
1240     e.preventDefault();
1241     var newwebview = document.createElement('webview');
1242     document.body.appendChild(newwebview);
1243     try {
1244       e.window.attach(newwebview);
1245     } catch (err) {
1246       embedder.test.fail();
1247     }
1248   });
1249   webview.addEventListener('newwindow', function(e) {
1250     e.preventDefault();
1251     try {
1252       e.window.discard();
1253     } catch (err) {
1254       embedder.test.succeed();
1255     }
1256   });
1257   webview.setAttribute('src', embedder.windowOpenGuestURL);
1258   document.body.appendChild(webview);
1259 }
1260
1261 function testOnEventProperties() {
1262   var sequence = ['first', 'second', 'third', 'fourth'];
1263   var webview = document.createElement('webview');
1264   function createHandler(id) {
1265     return function(e) {
1266       embedder.test.assertEq(id, sequence.shift());
1267     };
1268   }
1269
1270   webview.addEventListener('loadstart', createHandler('first'));
1271   webview.addEventListener('loadstart', createHandler('second'));
1272   webview.onloadstart = createHandler('third');
1273   webview.addEventListener('loadstart', createHandler('fourth'));
1274   webview.addEventListener('loadstop', function(evt) {
1275     embedder.test.assertEq(0, sequence.length);
1276
1277     // Test that setting another 'onloadstart' handler replaces the previous
1278     // handler.
1279     sequence = ['first', 'second', 'fourth'];
1280     webview.onloadstart = function() {
1281       embedder.test.assertEq(0, sequence.length);
1282       embedder.test.succeed();
1283     };
1284
1285     webview.setAttribute('src', 'data:text/html,next navigation');
1286   });
1287
1288   webview.setAttribute('src', 'data:text/html,trigger navigation');
1289   document.body.appendChild(webview);
1290 }
1291
1292 // This test verifies that the partion attribute cannot be changed after the src
1293 // has been set.
1294 function testPartitionChangeAfterNavigation() {
1295   var webview = document.createElement('webview');
1296   var partitionAttribute = arguments.callee.name;
1297   webview.setAttribute('partition', partitionAttribute);
1298
1299   var loadstopHandler = function(e) {
1300     webview.partition = 'illegal';
1301     embedder.test.assertEq(partitionAttribute, webview.partition);
1302     embedder.test.succeed();
1303   };
1304   webview.addEventListener('loadstop', loadstopHandler);
1305
1306   webview.setAttribute('src', 'data:text/html,trigger navigation');
1307   document.body.appendChild(webview);
1308 }
1309
1310 // This test verifies that removing partition attribute after navigation does
1311 // not work, i.e. the partition remains the same.
1312 function testPartitionRemovalAfterNavigationFails() {
1313   var webview = document.createElement('webview');
1314
1315   var partition = 'testme';
1316   webview.setAttribute('partition', partition);
1317
1318   var loadstopHandler = function(e) {
1319     // Removing after navigation should not change the partition.
1320     webview.removeAttribute('partition');
1321     embedder.test.assertEq('testme', webview.partition);
1322     embedder.test.succeed();
1323   };
1324   webview.addEventListener('loadstop', loadstopHandler);
1325
1326   webview.setAttribute('src', 'data:text/html,<html><body>guest</body></html>');
1327   document.body.appendChild(webview);
1328 }
1329
1330 // This test verifies that <webview> reloads the page if the src attribute is
1331 // assigned the same value.
1332 function testReassignSrcAttribute() {
1333   var dataUrl = 'data:text/html,test page';
1334   var webview = document.createElement('webview');
1335   webview.partition = arguments.callee.name;
1336
1337   var loadStopCount = 0;
1338   webview.addEventListener('loadstop', function(evt) {
1339     embedder.test.assertEq(dataUrl, webview.getAttribute('src'));
1340     ++loadStopCount;
1341     console.log('[' + loadStopCount + '] loadstop called');
1342     if (loadStopCount == 3) {
1343       embedder.test.succeed();
1344     } else if (loadStopCount > 3) {
1345       embedder.test.fail();
1346     } else {
1347       webview.src = dataUrl;
1348     }
1349   });
1350   webview.src = dataUrl;
1351   document.body.appendChild(webview);
1352 }
1353
1354 // This test verifies that the reload method on webview functions as expected.
1355 function testReload() {
1356   var triggerNavUrl = 'data:text/html,trigger navigation';
1357   var webview = document.createElement('webview');
1358
1359   var loadCommitCount = 0;
1360   webview.addEventListener('loadstop', function(e) {
1361     if (loadCommitCount < 2) {
1362       webview.reload();
1363     } else if (loadCommitCount == 2) {
1364       embedder.test.succeed();
1365     } else {
1366       embedder.test.fail();
1367     }
1368   });
1369   webview.addEventListener('loadcommit', function(e) {
1370     embedder.test.assertEq(triggerNavUrl, e.url);
1371     embedder.test.assertTrue(e.isTopLevel);
1372     loadCommitCount++;
1373   });
1374
1375   webview.setAttribute('src', triggerNavUrl);
1376   document.body.appendChild(webview);
1377 }
1378
1379 // This test verifies that the reload method on webview functions as expected.
1380 function testReloadAfterTerminate() {
1381   var triggerNavUrl = 'data:text/html,trigger navigation';
1382   var webview = document.createElement('webview');
1383
1384   var step = 1;
1385   webview.addEventListener('loadstop', function(e) {
1386     switch (step) {
1387       case 1:
1388         webview.terminate();
1389         break;
1390       case 2:
1391         setTimeout(function() { embedder.test.succeed(); }, 0);
1392         break;
1393       default:
1394         window.console.log('Unexpected loadstop event, step = ' + step);
1395         embedder.test.fail();
1396         break;
1397     }
1398     ++step;
1399   });
1400
1401   webview.addEventListener('exit', function(e) {
1402     // Trigger a focus state change of the guest to test for
1403     // http://crbug.com/413874.
1404     webview.blur();
1405     webview.focus();
1406     setTimeout(function() { webview.reload(); }, 0);
1407   });
1408
1409   webview.src = triggerNavUrl;
1410   document.body.appendChild(webview);
1411 }
1412
1413 // This test verifies that <webview> restores the src attribute if it is
1414 // removed after navigation.
1415 function testRemoveSrcAttribute() {
1416   var dataUrl = 'data:text/html,test page';
1417   var webview = document.createElement('webview');
1418   webview.setAttribute('partition', arguments.callee.name);
1419   var terminated = false;
1420   webview.addEventListener('loadstop', function(evt) {
1421     webview.removeAttribute('src');
1422     setTimeout(function() {
1423       embedder.test.assertEq(dataUrl, webview.getAttribute('src'));
1424       embedder.test.succeed();
1425     }, 0);
1426   });
1427   webview.setAttribute('src', dataUrl);
1428   document.body.appendChild(webview);
1429 }
1430
1431 function testRemoveWebviewAfterNavigation() {
1432   var webview = document.createElement('webview');
1433   document.body.appendChild(webview);
1434   webview.src = 'data:text/html,trigger navigation';
1435   document.body.removeChild(webview);
1436   setTimeout(function() {
1437     embedder.test.succeed();
1438   }, 0);
1439 }
1440
1441 // This test verifies that a <webview> is torn down gracefully when removed from
1442 // the DOM on exit.
1443 window.removeWebviewOnExitDoCrash = null;
1444 function testRemoveWebviewOnExit() {
1445   var triggerNavUrl = 'data:text/html,trigger navigation';
1446   var webview = document.createElement('webview');
1447
1448   webview.addEventListener('loadstop', function(e) {
1449     chrome.test.sendMessage('guest-loaded');
1450   });
1451
1452   window.removeWebviewOnExitDoCrash = function() {
1453     webview.terminate();
1454   };
1455
1456   webview.addEventListener('exit', function(e) {
1457     // We expected to be killed.
1458     if (e.reason != 'killed') {
1459       return;
1460     }
1461     webview.parentNode.removeChild(webview);
1462   });
1463
1464   // Trigger a navigation to create a guest process.
1465   webview.setAttribute('src', embedder.emptyGuestURL);
1466   document.body.appendChild(webview);
1467 }
1468
1469 function testResizeWebviewResizesContent() {
1470   var webview = document.createElement('webview');
1471   webview.src = 'about:blank';
1472   webview.addEventListener('loadstop', function(e) {
1473     webview.executeScript(
1474       {file: 'inject_resize_test.js'},
1475       function(results) {
1476         window.console.log('The resize test has been injected into webview.');
1477       }
1478     );
1479     webview.executeScript(
1480       {file: 'inject_comm_channel.js'},
1481       function(results) {
1482         window.console.log('The guest script for a two-way comm channel has ' +
1483             'been injected into webview.');
1484         // Establish a communication channel with the guest.
1485         var msg = ['connect'];
1486         webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1487       }
1488     );
1489   });
1490   window.addEventListener('message', function(e) {
1491     var data = JSON.parse(e.data);
1492     if (data[0] == 'connected') {
1493       console.log('A communication channel has been established with webview.');
1494       console.log('Resizing <webview> width from 300px to 400px.');
1495       webview.style.width = '400px';
1496       return;
1497     }
1498     if (data[0] == 'resize') {
1499       var width = data[1];
1500       var height = data[2];
1501       embedder.test.assertEq(400, width);
1502       embedder.test.assertEq(300, height);
1503       embedder.test.succeed();
1504       return;
1505     }
1506     console.log('Unexpected message: \'' + data[0]  + '\'');
1507     embedder.test.fail();
1508   });
1509   document.body.appendChild(webview);
1510 }
1511
1512 // This test calls terminate() on guest after it has already been
1513 // terminated. This makes sure we ignore the call gracefully.
1514 function testTerminateAfterExit() {
1515   var webview = document.createElement('webview');
1516   webview.setAttribute('partition', arguments.callee.name);
1517   var loadstopSucceedsTest = false;
1518   webview.addEventListener('loadstop', function(evt) {
1519     embedder.test.assertEq('loadstop', evt.type);
1520     if (loadstopSucceedsTest) {
1521       embedder.test.succeed();
1522       return;
1523     }
1524
1525     webview.terminate();
1526   });
1527
1528   webview.addEventListener('exit', function(evt) {
1529     embedder.test.assertEq('exit', evt.type);
1530     // Call terminate again.
1531     webview.terminate();
1532     // Load another page. The test would pass when loadstop is called on
1533     // this second page. This would hopefully catch if call to
1534     // webview.terminate() caused a browser crash.
1535     setTimeout(function() {
1536       loadstopSucceedsTest = true;
1537       webview.setAttribute('src', 'data:text/html,test second page');
1538     }, 0);
1539   });
1540
1541   webview.setAttribute('src', 'data:text/html,test terminate() crash.');
1542   document.body.appendChild(webview);
1543 }
1544
1545 // This test verifies that the WebRequest API onBeforeRequest event fires on
1546 // webview.
1547 function testWebRequestAPI() {
1548   var webview = new WebView();
1549   webview.request.onBeforeRequest.addListener(function(e) {
1550     embedder.test.succeed();
1551   }, { urls: ['<all_urls>']}) ;
1552   webview.src = embedder.windowOpenGuestURL;
1553   document.body.appendChild(webview);
1554 }
1555
1556 // This test verifies that the WebRequest API onBeforeSendHeaders event fires on
1557 // webview and supports headers. This tests verifies that we can modify HTTP
1558 // headers via the WebRequest API and those modified headers will be sent to the
1559 // HTTP server.
1560 function testWebRequestAPIWithHeaders() {
1561   var webview = new WebView();
1562   var requestFilter = {
1563     urls: ['<all_urls>']
1564   };
1565   var extraInfoSpec = ['requestHeaders', 'blocking'];
1566   webview.request.onBeforeSendHeaders.addListener(function(details) {
1567     var headers = details.requestHeaders;
1568     for( var i = 0, l = headers.length; i < l; ++i ) {
1569       if (headers[i].name == 'User-Agent') {
1570         headers[i].value = 'foobar';
1571         break;
1572       }
1573     }
1574     var blockingResponse = {};
1575     blockingResponse.requestHeaders = headers;
1576     return blockingResponse;
1577   }, requestFilter, extraInfoSpec);
1578
1579   var loadstartCalled = false;
1580   webview.addEventListener('loadstart', function(e) {
1581     embedder.test.assertTrue(e.isTopLevel);
1582     embedder.test.assertEq(embedder.detectUserAgentURL, e.url);
1583     loadstartCalled = true;
1584   });
1585
1586   webview.addEventListener('loadredirect', function(e) {
1587     embedder.test.assertTrue(e.isTopLevel);
1588     embedder.test.assertEq(embedder.detectUserAgentURL,
1589         e.oldUrl.replace('127.0.0.1', 'localhost'));
1590     embedder.test.assertEq(embedder.redirectGuestURLDest,
1591         e.newUrl.replace('127.0.0.1', 'localhost'));
1592     if (loadstartCalled) {
1593       embedder.test.succeed();
1594     } else {
1595       embedder.test.fail();
1596     }
1597   });
1598   webview.src = embedder.detectUserAgentURL;
1599   document.body.appendChild(webview);
1600 }
1601
1602 function testWebRequestAPIExistence() {
1603   var apiPropertiesToCheck = [
1604     // Declarative WebRequest API.
1605     'onMessage',
1606     'onRequest',
1607     // WebRequest API.
1608     'onBeforeRequest',
1609     'onBeforeSendHeaders',
1610     'onSendHeaders',
1611     'onHeadersReceived',
1612     'onAuthRequired',
1613     'onBeforeRedirect',
1614     'onResponseStarted',
1615     'onCompleted',
1616     'onErrorOccurred'
1617   ];
1618   var webview = document.createElement('webview');
1619   webview.setAttribute('partition', arguments.callee.name);
1620   webview.addEventListener('loadstop', function(e) {
1621     for (var i = 0; i < apiPropertiesToCheck.length; ++i) {
1622       embedder.test.assertEq('object',
1623                              typeof webview.request[apiPropertiesToCheck[i]]);
1624       embedder.test.assertEq(
1625           'function',
1626           typeof webview.request[apiPropertiesToCheck[i]].addListener);
1627       embedder.test.assertEq(
1628           'function',
1629           typeof webview.request[apiPropertiesToCheck[i]].addRules);
1630       embedder.test.assertEq(
1631           'function',
1632           typeof webview.request[apiPropertiesToCheck[i]].getRules);
1633       embedder.test.assertEq(
1634           'function',
1635           typeof webview.request[apiPropertiesToCheck[i]].removeRules);
1636     }
1637
1638     // Try to overwrite webview.request, shall not succeed.
1639     webview.request = '123';
1640     embedder.test.assertTrue(typeof webview.request !== 'string');
1641
1642     embedder.test.succeed();
1643   });
1644   webview.setAttribute('src', 'data:text/html,webview check api');
1645   document.body.appendChild(webview);
1646 }
1647
1648 // This test verifies that the WebRequest API onBeforeRequest event fires on
1649 // clients*.google.com URLs.
1650 function testWebRequestAPIGoogleProperty() {
1651   var webview = new WebView();
1652   webview.request.onBeforeRequest.addListener(function(e) {
1653     embedder.test.succeed();
1654     return {cancel: true};
1655   }, { urls: ['<all_urls>']}, ['blocking']) ;
1656   webview.src = 'http://clients6.google.com';
1657   document.body.appendChild(webview);
1658 }
1659
1660 // Tests end.
1661
1662 embedder.test.testList = {
1663   'testAllowTransparencyAttribute': testAllowTransparencyAttribute,
1664   'testAPIMethodExistence': testAPIMethodExistence,
1665   'testAssignSrcAfterCrash': testAssignSrcAfterCrash,
1666   'testAutosizeAfterNavigation': testAutosizeAfterNavigation,
1667   'testAutosizeBeforeNavigation': testAutosizeBeforeNavigation,
1668   'testAutosizeHeight': testAutosizeHeight,
1669   'testAutosizeRemoveAttributes': testAutosizeRemoveAttributes,
1670   'testAutosizeWithPartialAttributes': testAutosizeWithPartialAttributes,
1671   'testCannotMutateEventName': testCannotMutateEventName,
1672   'testChromeExtensionRelativePath': testChromeExtensionRelativePath,
1673   'testChromeExtensionURL': testChromeExtensionURL,
1674   'testContentLoadEvent': testContentLoadEvent,
1675   'testDeclarativeWebRequestAPI': testDeclarativeWebRequestAPI,
1676   'testDeclarativeWebRequestAPISendMessage':
1677       testDeclarativeWebRequestAPISendMessage,
1678   'testDestroyOnEventListener': testDestroyOnEventListener,
1679   'testDisplayNoneWebviewLoad': testDisplayNoneWebviewLoad,
1680   'testDisplayNoneWebviewRemoveChild': testDisplayNoneWebviewRemoveChild,
1681   'testEventName': testEventName,
1682   'testExecuteScript': testExecuteScript,
1683   'testExecuteScriptFail': testExecuteScriptFail,
1684   'testExecuteScriptIsAbortedWhenWebViewSourceIsChanged':
1685       testExecuteScriptIsAbortedWhenWebViewSourceIsChanged,
1686   'testFindAPI': testFindAPI,
1687   'testFindAPI_findupdate': testFindAPI,
1688   'testGetProcessId': testGetProcessId,
1689   'testHiddenBeforeNavigation': testHiddenBeforeNavigation,
1690   'testInlineScriptFromAccessibleResources':
1691       testInlineScriptFromAccessibleResources,
1692   'testInvalidChromeExtensionURL': testInvalidChromeExtensionURL,
1693   'testLoadAbortChromeExtensionURLWrongPartition':
1694       testLoadAbortChromeExtensionURLWrongPartition,
1695   'testLoadAbortEmptyResponse': testLoadAbortEmptyResponse,
1696   'testLoadAbortIllegalChromeURL': testLoadAbortIllegalChromeURL,
1697   'testLoadAbortIllegalFileURL': testLoadAbortIllegalFileURL,
1698   'testLoadAbortIllegalJavaScriptURL': testLoadAbortIllegalJavaScriptURL,
1699   'testLoadAbortInvalidNavigation': testLoadAbortInvalidNavigation,
1700   'testLoadAbortNonWebSafeScheme': testLoadAbortNonWebSafeScheme,
1701   'testLoadProgressEvent': testLoadProgressEvent,
1702   'testLoadStartLoadRedirect': testLoadStartLoadRedirect,
1703   'testNavigateAfterResize': testNavigateAfterResize,
1704   'testNavigationToExternalProtocol': testNavigationToExternalProtocol,
1705   'testNavOnConsecutiveSrcAttributeChanges':
1706       testNavOnConsecutiveSrcAttributeChanges,
1707   'testNavOnSrcAttributeChange': testNavOnSrcAttributeChange,
1708   'testNewWindow': testNewWindow,
1709   'testNewWindowNoPreventDefault': testNewWindowNoPreventDefault,
1710   'testNewWindowNoReferrerLink': testNewWindowNoReferrerLink,
1711   'testNewWindowTwoListeners': testNewWindowTwoListeners,
1712   'testOnEventProperties': testOnEventProperties,
1713   'testPartitionChangeAfterNavigation': testPartitionChangeAfterNavigation,
1714   'testPartitionRemovalAfterNavigationFails':
1715       testPartitionRemovalAfterNavigationFails,
1716   'testReassignSrcAttribute': testReassignSrcAttribute,
1717   'testReload': testReload,
1718   'testReloadAfterTerminate': testReloadAfterTerminate,
1719   'testRemoveSrcAttribute': testRemoveSrcAttribute,
1720   'testRemoveWebviewAfterNavigation': testRemoveWebviewAfterNavigation,
1721   'testRemoveWebviewOnExit': testRemoveWebviewOnExit,
1722   'testResizeWebviewResizesContent': testResizeWebviewResizesContent,
1723   'testTerminateAfterExit': testTerminateAfterExit,
1724   'testWebRequestAPI': testWebRequestAPI,
1725   'testWebRequestAPIWithHeaders': testWebRequestAPIWithHeaders,
1726   'testWebRequestAPIExistence': testWebRequestAPIExistence,
1727   'testWebRequestAPIGoogleProperty': testWebRequestAPIGoogleProperty
1728 };
1729
1730 onload = function() {
1731   chrome.test.getConfig(function(config) {
1732     embedder.setUp_(config);
1733     chrome.test.sendMessage('LAUNCHED');
1734   });
1735 };