928d440f5b4a8bf1f8da0fa749799972af7f0017
[platform/framework/web/crosswalk.git] / src / chrome / test / data / extensions / platform_apps / web_view / shim / main.js
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 var util = {};
6 var embedder = {};
7 embedder.baseGuestURL = '';
8 embedder.emptyGuestURL = '';
9 embedder.windowOpenGuestURL = '';
10 embedder.noReferrerGuestURL = '';
11 embedder.redirectGuestURL = '';
12 embedder.redirectGuestURLDest = '';
13 embedder.closeSocketURL = '';
14 embedder.tests = {};
15
16 embedder.setUp_ = function(config) {
17   if (!config || !config.testServer) {
18     return;
19   }
20   embedder.baseGuestURL = 'http://localhost:' + config.testServer.port;
21   embedder.emptyGuestURL = embedder.baseGuestURL +
22       '/extensions/platform_apps/web_view/shim/empty_guest.html';
23   embedder.windowOpenGuestURL = embedder.baseGuestURL +
24       '/extensions/platform_apps/web_view/shim/guest.html';
25   embedder.noReferrerGuestURL = embedder.baseGuestURL +
26       '/extensions/platform_apps/web_view/shim/guest_noreferrer.html';
27   embedder.redirectGuestURL = embedder.baseGuestURL + '/server-redirect';
28   embedder.redirectGuestURLDest = embedder.baseGuestURL +
29       '/extensions/platform_apps/web_view/shim/guest_redirect.html';
30   embedder.closeSocketURL = embedder.baseGuestURL + '/close-socket';
31 };
32
33 window.runTest = function(testName) {
34   if (!embedder.test.testList[testName]) {
35     console.log('Incorrect testName: ' + testName);
36     embedder.test.fail();
37     return;
38   }
39
40   // Run the test.
41   embedder.test.testList[testName]();
42 };
43
44 // Creates a <webview> tag in document.body and returns the reference to it.
45 // It also sets a dummy src. The dummy src is significant because this makes
46 // sure that the <object> shim is created (asynchronously at this point) for the
47 // <webview> tag. This makes the <webview> tag ready for add/removeEventListener
48 // calls.
49 util.createWebViewTagInDOM = function(partitionName) {
50   var webview = document.createElement('webview');
51   webview.style.width = '300px';
52   webview.style.height = '200px';
53   var urlDummy = 'data:text/html,<body>Initial dummy guest</body>';
54   webview.setAttribute('src', urlDummy);
55   webview.setAttribute('partition', partitionName);
56   document.body.appendChild(webview);
57   return webview;
58 };
59
60 embedder.test = {};
61 embedder.test.succeed = function() {
62   chrome.test.sendMessage('TEST_PASSED');
63 };
64
65 embedder.test.fail = function() {
66   chrome.test.sendMessage('TEST_FAILED');
67 };
68
69 embedder.test.assertEq = function(a, b) {
70   if (a != b) {
71     console.log('assertion failed: ' + a + ' != ' + b);
72     embedder.test.fail();
73   }
74 };
75
76 embedder.test.assertTrue = function(condition) {
77   if (!condition) {
78     console.log('assertion failed: true != ' + condition);
79     embedder.test.fail();
80   }
81 };
82
83 embedder.test.assertFalse = function(condition) {
84   if (condition) {
85     console.log('assertion failed: false != ' + condition);
86     embedder.test.fail();
87   }
88 };
89
90 // Tests begin.
91
92 // This test verifies that if a browser plugin is in autosize mode before
93 // navigation then the guest starts auto-sized.
94 function testAutosizeBeforeNavigation() {
95   var webview = document.createElement('webview');
96
97   webview.setAttribute('autosize', 'true');
98   webview.setAttribute('minwidth', 200);
99   webview.setAttribute('maxwidth', 210);
100   webview.setAttribute('minheight', 100);
101   webview.setAttribute('maxheight', 110);
102
103   webview.addEventListener('sizechanged', function(e) {
104     embedder.test.assertEq(0, e.oldWidth);
105     embedder.test.assertEq(0, e.oldHeight);
106     embedder.test.assertTrue(e.newWidth >= 200 && e.newWidth <= 210);
107     embedder.test.assertTrue(e.newHeight >= 100 && e.newHeight <= 110);
108     embedder.test.succeed();
109   });
110
111   webview.setAttribute('src', 'data:text/html,webview test sizechanged event');
112   document.body.appendChild(webview);
113 }
114
115 // Makes sure 'sizechanged' event is fired only if autosize attribute is
116 // specified.
117 // After loading <webview> without autosize attribute and a size, say size1,
118 // we set autosize attribute and new min size with size2. We would get (only
119 // one) sizechanged event with size1 as old size and size2 as new size.
120 function testAutosizeAfterNavigation() {
121   var webview = document.createElement('webview');
122
123   var step = 1;
124   var sizeChangeHandler = function(e) {
125     switch (step) {
126       case 1:
127         // This would be triggered after we set autosize attribute.
128         embedder.test.assertEq(50, e.oldWidth);
129         embedder.test.assertEq(100, e.oldHeight);
130         embedder.test.assertTrue(e.newWidth >= 60 && e.newWidth <= 70);
131         embedder.test.assertTrue(e.newHeight >= 110 && e.newHeight <= 120);
132
133         // Remove autosize attribute and expect webview to return to its
134         // original size.
135         webview.removeAttribute('autosize');
136         break;
137       case 2:
138         // Expect 50x100.
139         embedder.test.assertEq(50, e.newWidth);
140         embedder.test.assertEq(100, e.newHeight);
141
142         embedder.test.succeed();
143         break;
144       default:
145         window.console.log('Unexpected sizechanged event, step = ' + step);
146         embedder.test.fail();
147         break;
148     }
149
150     ++step;
151   };
152
153   webview.addEventListener('sizechanged', sizeChangeHandler);
154
155   webview.addEventListener('loadstop', function(e) {
156     webview.setAttribute('autosize', true);
157     webview.setAttribute('minwidth', 60);
158     webview.setAttribute('maxwidth', 70);
159     webview.setAttribute('minheight', 110);
160     webview.setAttribute('maxheight', 120);
161   });
162
163   webview.style.width = '50px';
164   webview.style.height = '100px';
165   webview.setAttribute('src', 'data:text/html,webview test sizechanged event');
166   document.body.appendChild(webview);
167 }
168
169 // This test verifies that autosize works when some of the parameters are unset.
170 function testAutosizeWithPartialAttributes() {
171   window.console.log('testAutosizeWithPartialAttributes');
172   var webview = document.createElement('webview');
173
174   var step = 1;
175   var sizeChangeHandler = function(e) {
176     window.console.log('sizeChangeHandler, new: ' +
177                        e.newWidth + ' X ' + e.newHeight);
178     switch (step) {
179       case 1:
180         // Expect 300x200.
181         embedder.test.assertEq(300, e.newWidth);
182         embedder.test.assertEq(200, e.newHeight);
183
184         // Change the min size to cause a relayout.
185         webview.minwidth = 500;
186         break;
187       case 2:
188         embedder.test.assertTrue(e.newWidth >= webview.minwidth);
189         embedder.test.assertTrue(e.newWidth <= webview.maxwidth);
190
191         // Tests when minwidth > maxwidth, minwidth = maxwidth.
192         // i.e. minwidth is essentially 700.
193         webview.minwidth = 800;
194         break;
195       case 3:
196         // Expect 700X?
197         embedder.test.assertEq(700, e.newWidth);
198         embedder.test.assertTrue(e.newHeight >= 200);
199         embedder.test.assertTrue(e.newHeight <= 600);
200
201         embedder.test.succeed();
202         break;
203       default:
204         window.console.log('Unexpected sizechanged event, step = ' + step);
205         embedder.test.fail();
206         break;
207     }
208
209     ++step;
210   };
211
212   webview.addEventListener('sizechanged', sizeChangeHandler);
213
214   webview.addEventListener('loadstop', function(e) {
215     webview.minwidth = 300;
216     webview.maxwidth = 700;
217     webview.minheight = 200;
218     webview.maxheight = 600;
219     webview.autosize = true;
220   });
221
222   webview.style.width = '640px';
223   webview.style.height = '480px';
224   webview.setAttribute('src', 'data:text/html,webview check autosize');
225   document.body.appendChild(webview);
226 }
227
228 // This test verifies that all autosize attributes can be removed
229 // without crashing the plugin, or throwing errors.
230 function testAutosizeRemoveAttributes() {
231   var webview = document.createElement('webview');
232
233   var step = 1;
234   var sizeChangeHandler = function(e) {
235     switch (step) {
236       case 1:
237         // This is the sizechanged event for autosize.
238
239         // Remove attributes.
240         webview.removeAttribute('minwidth');
241         webview.removeAttribute('maxwidth');
242         webview.removeAttribute('minheight');
243         webview.removeAttribute('maxheight');
244         webview.removeAttribute('autosize');
245
246         // We'd get one more sizechanged event after we turn off
247         // autosize.
248         webview.style.width = '500px';
249         webview.style.height = '500px';
250         break;
251       case 2:
252         embedder.test.succeed();
253         break;
254     }
255
256     ++step;
257   };
258
259   webview.addEventListener('loadstop', function(e) {
260     webview.minwidth = 300;
261     webview.maxwidth = 700;
262     webview.minheight = 600;
263     webview.maxheight = 400;
264     webview.autosize = true;
265   });
266
267   webview.addEventListener('sizechanged', sizeChangeHandler);
268
269   webview.style.width = '640px';
270   webview.style.height = '480px';
271   webview.setAttribute('src', 'data:text/html,webview check autosize');
272   document.body.appendChild(webview);
273 }
274
275 function testAPIMethodExistence() {
276   var apiMethodsToCheck = [
277     'back',
278     'canGoBack',
279     'canGoForward',
280     'forward',
281     'getProcessId',
282     'go',
283     'reload',
284     'stop',
285     'terminate'
286   ];
287   var webview = document.createElement('webview');
288   webview.setAttribute('partition', arguments.callee.name);
289   webview.addEventListener('loadstop', function(e) {
290     for (var i = 0; i < apiMethodsToCheck.length; ++i) {
291       embedder.test.assertEq('function',
292                            typeof webview[apiMethodsToCheck[i]]);
293     }
294
295     // Check contentWindow.
296     embedder.test.assertEq('object', typeof webview.contentWindow);
297     embedder.test.assertEq('function',
298                          typeof webview.contentWindow.postMessage);
299     embedder.test.succeed();
300   });
301   webview.setAttribute('src', 'data:text/html,webview check api');
302   document.body.appendChild(webview);
303 }
304
305 // This test verifies that the loadstop event fires when loading a webview
306 // accessible resource from a partition that is privileged.
307 function testChromeExtensionURL() {
308   var localResource = chrome.runtime.getURL('guest.html');
309   var webview = document.createElement('webview');
310   // foobar is a privileged partition according to the manifest file.
311   webview.partition = 'foobar';
312   webview.addEventListener('loadabort', function(e) {
313     embedder.test.fail();
314   });
315   webview.addEventListener('loadstop', function(e) {
316     embedder.test.succeed();
317   });
318   webview.setAttribute('src', localResource);
319   document.body.appendChild(webview);
320 }
321
322 // This test verifies that the loadstop event fires when loading a webview
323 // accessible resource from a partition that is privileged if the src URL
324 // is not fully qualified.
325 function testChromeExtensionRelativePath() {
326   var webview = document.createElement('webview');
327   // foobar is a privileged partition according to the manifest file.
328   webview.partition = 'foobar';
329   webview.addEventListener('loadabort', function(e) {
330     embedder.test.fail();
331   });
332   webview.addEventListener('loadstop', function(e) {
333     embedder.test.succeed();
334   });
335   webview.setAttribute('src', 'guest.html');
336   document.body.appendChild(webview);
337 }
338
339 // This tests verifies that webview fires a loadabort event instead of crashing
340 // the browser if we attempt to navigate to a chrome-extension: URL with an
341 // extension ID that does not exist.
342 function testInvalidChromeExtensionURL() {
343   var invalidResource = 'chrome-extension://abc123/guest.html';
344   var webview = document.createElement('webview');
345   // foobar is a privileged partition according to the manifest file.
346   webview.partition = 'foobar';
347   webview.addEventListener('loadabort', function(e) {
348     embedder.test.succeed();
349   });
350   webview.setAttribute('src', invalidResource);
351   document.body.appendChild(webview);
352 }
353
354 function testWebRequestAPIExistence() {
355   var apiPropertiesToCheck = [
356     // Declarative WebRequest API.
357     'onMessage',
358     'onRequest',
359     // WebRequest API.
360     'onBeforeRequest',
361     'onBeforeSendHeaders',
362     'onSendHeaders',
363     'onHeadersReceived',
364     'onAuthRequired',
365     'onBeforeRedirect',
366     'onResponseStarted',
367     'onCompleted',
368     'onErrorOccurred'
369   ];
370   var webview = document.createElement('webview');
371   webview.setAttribute('partition', arguments.callee.name);
372   webview.addEventListener('loadstop', function(e) {
373     for (var i = 0; i < apiPropertiesToCheck.length; ++i) {
374       embedder.test.assertEq('object',
375                              typeof webview.request[apiPropertiesToCheck[i]]);
376       embedder.test.assertEq(
377           'function',
378           typeof webview.request[apiPropertiesToCheck[i]].addListener);
379       embedder.test.assertEq(
380           'function',
381           typeof webview.request[apiPropertiesToCheck[i]].addRules);
382       embedder.test.assertEq(
383           'function',
384           typeof webview.request[apiPropertiesToCheck[i]].getRules);
385       embedder.test.assertEq(
386           'function',
387           typeof webview.request[apiPropertiesToCheck[i]].removeRules);
388     }
389     embedder.test.succeed();
390   });
391   webview.setAttribute('src', 'data:text/html,webview check api');
392   document.body.appendChild(webview);
393 }
394
395 // This test verifies that the loadstart, loadstop, and exit events fire as
396 // expected.
397 function testEventName() {
398   var webview = document.createElement('webview');
399   webview.setAttribute('partition', arguments.callee.name);
400
401   webview.addEventListener('loadstart', function(evt) {
402     embedder.test.assertEq('loadstart', evt.type);
403   });
404
405   webview.addEventListener('loadstop', function(evt) {
406     embedder.test.assertEq('loadstop', evt.type);
407     webview.terminate();
408   });
409
410   webview.addEventListener('exit', function(evt) {
411     embedder.test.assertEq('exit', evt.type);
412     embedder.test.succeed();
413   });
414
415   webview.setAttribute('src', 'data:text/html,trigger navigation');
416   document.body.appendChild(webview);
417 }
418
419 function testOnEventProperties() {
420   var sequence = ['first', 'second', 'third', 'fourth'];
421   var webview = document.createElement('webview');
422   function createHandler(id) {
423     return function(e) {
424       embedder.test.assertEq(id, sequence.shift());
425     };
426   }
427
428   webview.addEventListener('loadstart', createHandler('first'));
429   webview.addEventListener('loadstart', createHandler('second'));
430   webview.onloadstart = createHandler('third');
431   webview.addEventListener('loadstart', createHandler('fourth'));
432   webview.addEventListener('loadstop', function(evt) {
433     embedder.test.assertEq(0, sequence.length);
434
435     // Test that setting another 'onloadstart' handler replaces the previous
436     // handler.
437     sequence = ['first', 'second', 'fourth'];
438     webview.onloadstart = function() {
439       embedder.test.assertEq(0, sequence.length);
440       embedder.test.succeed();
441     };
442
443     webview.setAttribute('src', 'data:text/html,next navigation');
444   });
445
446   webview.setAttribute('src', 'data:text/html,trigger navigation');
447   document.body.appendChild(webview);
448 }
449
450 // Tests that the 'loadprogress' event is triggered correctly.
451 function testLoadProgressEvent() {
452   var webview = document.createElement('webview');
453   var progress = 0;
454
455   webview.addEventListener('loadstop', function(evt) {
456     embedder.test.assertEq(1, progress);
457     embedder.test.succeed();
458   });
459
460   webview.addEventListener('loadprogress', function(evt) {
461     progress = evt.progress;
462   });
463
464   webview.setAttribute('src', 'data:text/html,trigger navigation');
465   document.body.appendChild(webview);
466 }
467
468 // This test registers two listeners on an event (loadcommit) and removes
469 // the <webview> tag when the first listener fires.
470 // Current expected behavior is that the second event listener will still
471 // fire without crashing.
472 function testDestroyOnEventListener() {
473   var webview = util.createWebViewTagInDOM(arguments.callee.name);
474   var url = 'data:text/html,<body>Destroy test</body>';
475
476   var loadCommitCount = 0;
477   function loadCommitCommon(e) {
478     embedder.test.assertEq('loadcommit', e.type);
479     if (url != e.url)
480       return;
481     ++loadCommitCount;
482     if (loadCommitCount == 1) {
483       setTimeout(function() {
484         embedder.test.succeed();
485       }, 0);
486     } else if (loadCommitCount > 2) {
487       embedder.test.fail();
488     }
489   };
490
491   // The test starts from here, by setting the src to |url|.
492   webview.addEventListener('loadcommit', function(e) {
493     webview.parentNode.removeChild(webview);
494     loadCommitCommon(e);
495   });
496   webview.addEventListener('loadcommit', function(e) {
497     loadCommitCommon(e);
498   });
499   webview.setAttribute('src', url);
500 }
501
502 // This test registers two event listeners on a same event (loadcommit).
503 // Each of the listener tries to change some properties on the event param,
504 // which should not be possible.
505 function testCannotMutateEventName() {
506   var webview = util.createWebViewTagInDOM(arguments.callee.name);
507   var url = 'data:text/html,<body>Two</body>';
508
509   var loadCommitACalled = false;
510   var loadCommitBCalled = false;
511
512   var maybeFinishTest = function(e) {
513     if (loadCommitACalled && loadCommitBCalled) {
514       embedder.test.assertEq('loadcommit', e.type);
515       embedder.test.succeed();
516     }
517   };
518
519   var onLoadCommitA = function(e) {
520     if (e.url == url) {
521       embedder.test.assertEq('loadcommit', e.type);
522       embedder.test.assertTrue(e.isTopLevel);
523       embedder.test.assertFalse(loadCommitACalled);
524       loadCommitACalled = true;
525       // Try mucking with properities inside |e|.
526       e.type = 'modified';
527       maybeFinishTest(e);
528     }
529   };
530   var onLoadCommitB = function(e) {
531     if (e.url == url) {
532       embedder.test.assertEq('loadcommit', e.type);
533       embedder.test.assertTrue(e.isTopLevel);
534       embedder.test.assertFalse(loadCommitBCalled);
535       loadCommitBCalled = true;
536       // Try mucking with properities inside |e|.
537       e.type = 'modified';
538       maybeFinishTest(e);
539     }
540   };
541
542   // The test starts from here, by setting the src to |url|. Event
543   // listener registration works because we already have a (dummy) src set
544   // on the <webview> tag.
545   webview.addEventListener('loadcommit', onLoadCommitA);
546   webview.addEventListener('loadcommit', onLoadCommitB);
547   webview.setAttribute('src', url);
548 }
549
550 // This test verifies that setting the partition attribute after the src has
551 // been set raises an exception.
552 function testPartitionRaisesException() {
553   var webview = document.createElement('webview');
554   webview.setAttribute('partition', arguments.callee.name);
555   webview.setAttribute('src', 'data:text/html,trigger navigation');
556   document.body.appendChild(webview);
557   setTimeout(function() {
558     try {
559       webview.partition = 'illegal';
560       embedder.test.fail();
561     } catch (e) {
562       embedder.test.succeed();
563     }
564   }, 0);
565 }
566
567 function testExecuteScriptFail() {
568   var webview = document.createElement('webview');
569   document.body.appendChild(webview);
570   setTimeout(function() {
571     try {
572     webview.executeScript(
573       {code:'document.body.style.backgroundColor = "red";'},
574       function(results) {
575         embedder.test.fail();
576       });
577     } catch (e) {
578       embedder.test.succeed();
579     }
580   }, 0);
581 }
582
583 function testExecuteScript() {
584   var webview = document.createElement('webview');
585   webview.setAttribute('partition', arguments.callee.name);
586   webview.addEventListener('loadstop', function() {
587     webview.executeScript(
588       {code:'document.body.style.backgroundColor = "red";'},
589       function(results) {
590         embedder.test.assertEq(1, results.length);
591         embedder.test.assertEq('red', results[0]);
592         embedder.test.succeed();
593       });
594   });
595   webview.setAttribute('src', 'data:text/html,trigger navigation');
596   document.body.appendChild(webview);
597 }
598
599 // This test calls terminate() on guest after it has already been
600 // terminated. This makes sure we ignore the call gracefully.
601 function testTerminateAfterExit() {
602   var webview = document.createElement('webview');
603   webview.setAttribute('partition', arguments.callee.name);
604   var loadstopSucceedsTest = false;
605   webview.addEventListener('loadstop', function(evt) {
606     embedder.test.assertEq('loadstop', evt.type);
607     if (loadstopSucceedsTest) {
608       embedder.test.succeed();
609       return;
610     }
611
612     webview.terminate();
613   });
614
615   webview.addEventListener('exit', function(evt) {
616     embedder.test.assertEq('exit', evt.type);
617     // Call terminate again.
618     webview.terminate();
619     // Load another page. The test would pass when loadstop is called on
620     // this second page. This would hopefully catch if call to
621     // webview.terminate() caused a browser crash.
622     setTimeout(function() {
623       loadstopSucceedsTest = true;
624       webview.setAttribute('src', 'data:text/html,test second page');
625     }, 0);
626   });
627
628   webview.setAttribute('src', 'data:text/html,test terminate() crash.');
629   document.body.appendChild(webview);
630 }
631
632 // This test verifies that multiple consecutive changes to the <webview> src
633 // attribute will cause a navigation.
634 function testNavOnConsecutiveSrcAttributeChanges() {
635   var testPage1 = 'data:text/html,test page 1';
636   var testPage2 = 'data:text/html,test page 2';
637   var testPage3 = 'data:text/html,test page 3';
638   var webview = new WebView();
639   webview.partition = arguments.callee.name;
640   var loadCommitCount = 0;
641   webview.addEventListener('loadcommit', function(e) {
642     if (e.url == testPage3) {
643       embedder.test.succeed();
644     }
645     loadCommitCount++;
646     if (loadCommitCount > 3) {
647       embedder.test.fail();
648     }
649   });
650   document.body.appendChild(webview);
651   webview.src = testPage1;
652   webview.src = testPage2;
653   webview.src = testPage3;
654 }
655
656 // This test verifies that we can set the <webview> src multiple times and the
657 // changes will cause a navigation.
658 function testNavOnSrcAttributeChange() {
659   var testPage1 = 'data:text/html,test page 1';
660   var testPage2 = 'data:text/html,test page 2';
661   var testPage3 = 'data:text/html,test page 3';
662   var tests = [testPage1, testPage2, testPage3];
663   var webview = new WebView();
664   webview.partition = arguments.callee.name;
665   var loadCommitCount = 0;
666   webview.addEventListener('loadcommit', function(evt) {
667     var success = tests.indexOf(evt.url) > -1;
668     embedder.test.assertTrue(success);
669     ++loadCommitCount;
670     if (loadCommitCount == tests.length) {
671       embedder.test.succeed();
672     } else if (loadCommitCount > tests.length) {
673       embedder.test.fail();
674     } else {
675       webview.src = tests[loadCommitCount];
676     }
677   });
678   webview.src = tests[0];
679   document.body.appendChild(webview);
680 }
681
682 // This test verifies that assigning the src attribute the same value it had
683 // prior to a crash spawns off a new guest process.
684 function testAssignSrcAfterCrash() {
685   var webview = document.createElement('webview');
686   webview.setAttribute('partition', arguments.callee.name);
687   var terminated = false;
688   webview.addEventListener('loadstop', function(evt) {
689     if (!terminated) {
690       webview.terminate();
691       return;
692     }
693     // The guest has recovered after being terminated.
694     embedder.test.succeed();
695   });
696   webview.addEventListener('exit', function(evt) {
697     terminated = true;
698     webview.setAttribute('src', 'data:text/html,test page');
699   });
700   webview.setAttribute('src', 'data:text/html,test page');
701   document.body.appendChild(webview);
702 }
703
704 // This test verifies that <webview> reloads the page if the src attribute is
705 // assigned the same value.
706 function testReassignSrcAttribute() {
707   var dataUrl = 'data:text/html,test page';
708   var webview = new WebView();
709   webview.partition = arguments.callee.name;
710
711   var loadStopCount = 0;
712   webview.addEventListener('loadstop', function(evt) {
713     embedder.test.assertEq(dataUrl, webview.getAttribute('src'));
714     ++loadStopCount;
715     console.log('[' + loadStopCount + '] loadstop called');
716     if (loadStopCount == 3) {
717       embedder.test.succeed();
718     } else if (loadStopCount > 3) {
719       embedder.test.fail();
720     } else {
721       webview.src = dataUrl;
722     }
723   });
724   webview.src = dataUrl;
725   document.body.appendChild(webview);
726 }
727
728 // This test verifies that <webview> restores the src attribute if it is
729 // removed after navigation.
730 function testRemoveSrcAttribute() {
731   var dataUrl = 'data:text/html,test page';
732   var webview = document.createElement('webview');
733   webview.setAttribute('partition', arguments.callee.name);
734   var terminated = false;
735   webview.addEventListener('loadstop', function(evt) {
736     webview.removeAttribute('src');
737     setTimeout(function() {
738       embedder.test.assertEq(dataUrl, webview.getAttribute('src'));
739       embedder.test.succeed();
740     }, 0);
741   });
742   webview.setAttribute('src', dataUrl);
743   document.body.appendChild(webview);
744 }
745
746 // This test verifies that it is not possible to instantiate a browser plugin
747 // directly within an app.
748 function testBrowserPluginNotAllowed() {
749   var container = document.getElementById('object-container');
750   if (!container) {
751     embedder.test.fail('Container for object not found.');
752     return;
753   }
754   container.innerHTML = '<object type="application/browser-plugin"' +
755       ' id="object-plugin"' +
756       ' src="data:text/html,<body>You should not see this</body>">' +
757       '</object>';
758   var objectElement = document.getElementById('object-plugin');
759   // Check that bindings are not registered.
760   embedder.test.assertTrue(
761       objectElement['-internal-attach'] === undefined);
762   embedder.test.succeed();
763 }
764
765 function testPluginLoadPermission() {
766   var pluginIdentifier = 'unknown platform';
767   if (navigator.platform.match(/linux/i))
768     pluginIdentifier = 'libppapi_tests.so';
769   else if (navigator.platform.match(/win32/i))
770     pluginIdentifier = 'ppapi_tests.dll';
771   else if (navigator.platform.match(/mac/i))
772     pluginIdentifier = 'ppapi_tests.plugin';
773
774   var webview = document.createElement('webview');
775   webview.addEventListener('permissionrequest', function(e) {
776     e.preventDefault();
777     embedder.test.assertEq('loadplugin', e.permission);
778     embedder.test.assertEq(pluginIdentifier, e.name);
779     embedder.test.assertEq(pluginIdentifier, e.identifier);
780     embedder.test.assertEq('function', typeof e.request.allow);
781     embedder.test.assertEq('function', typeof e.request.deny);
782     embedder.test.succeed();
783   });
784   webview.setAttribute('src', 'data:text/html,<body>' +
785                               '<embed type="application/x-ppapi-tests">' +
786                               '</embed></body>');
787   document.body.appendChild(webview);
788 }
789
790 // This test verifies that new window attachment functions as expected.
791 function testNewWindow() {
792   var webview = document.createElement('webview');
793   webview.addEventListener('newwindow', function(e) {
794     e.preventDefault();
795     var newwebview = document.createElement('webview');
796     newwebview.addEventListener('loadstop', function(evt) {
797       // If the new window finishes loading, the test is successful.
798       embedder.test.succeed();
799     });
800     document.body.appendChild(newwebview);
801     // Attach the new window to the new <webview>.
802     e.window.attach(newwebview);
803   });
804   webview.setAttribute('src', embedder.windowOpenGuestURL);
805   document.body.appendChild(webview);
806 }
807
808 // This test verifies "first-call-wins" semantics. That is, the first call
809 // to perform an action on the new window takes the action and all
810 // subsequent calls throw an exception.
811 function testNewWindowTwoListeners() {
812   var webview = document.createElement('webview');
813   var error = false;
814   webview.addEventListener('newwindow', function(e) {
815     e.preventDefault();
816     var newwebview = document.createElement('webview');
817     document.body.appendChild(newwebview);
818     try {
819       e.window.attach(newwebview);
820     } catch (err) {
821       embedder.test.fail();
822     }
823   });
824   webview.addEventListener('newwindow', function(e) {
825     e.preventDefault();
826     try {
827       e.window.discard();
828     } catch (err) {
829       embedder.test.succeed();
830     }
831   });
832   webview.setAttribute('src', embedder.windowOpenGuestURL);
833   document.body.appendChild(webview);
834 }
835
836 // This test verifies that the attach can be called inline without
837 // preventing default.
838 function testNewWindowNoPreventDefault() {
839   var webview = document.createElement('webview');
840   webview.addEventListener('newwindow', function(e) {
841     var newwebview = document.createElement('webview');
842     document.body.appendChild(newwebview);
843     // Attach the new window to the new <webview>.
844     try {
845       e.window.attach(newwebview);
846       embedder.test.succeed();
847     } catch (err) {
848       embedder.test.fail();
849     }
850   });
851   webview.setAttribute('src', embedder.windowOpenGuestURL);
852   document.body.appendChild(webview);
853 }
854
855 function testNewWindowNoReferrerLink() {
856   var webview = document.createElement('webview');
857   webview.addEventListener('newwindow', function(e) {
858     e.preventDefault();
859     var newwebview = document.createElement('webview');
860     newwebview.addEventListener('loadstop', function(evt) {
861       // If the new window finishes loading, the test is successful.
862       embedder.test.succeed();
863     });
864     document.body.appendChild(newwebview);
865     // Attach the new window to the new <webview>.
866     e.window.attach(newwebview);
867   });
868   webview.setAttribute('src', embedder.noReferrerGuestURL);
869   document.body.appendChild(webview);
870 }
871
872 // This test verifies that the load event fires when the a new page is
873 // loaded.
874 // TODO(fsamuel): Add a test to verify that subframe loads within a guest
875 // do not fire the 'contentload' event.
876 function testContentLoadEvent() {
877   var webview = document.createElement('webview');
878   webview.addEventListener('contentload', function(e) {
879     embedder.test.succeed();
880   });
881   webview.setAttribute('src', 'data:text/html,trigger navigation');
882   document.body.appendChild(webview);
883 }
884
885 // This test verifies that the WebRequest API onBeforeRequest event fires on
886 // webview.
887 function testWebRequestAPI() {
888   var webview = new WebView();
889   webview.request.onBeforeRequest.addListener(function(e) {
890     embedder.test.succeed();
891   }, { urls: ['<all_urls>']}) ;
892   webview.src = embedder.windowOpenGuestURL;
893   document.body.appendChild(webview);
894 }
895
896 // This test verifies that the basic use cases of the declarative WebRequest API
897 // work as expected. This test demonstrates that rules can be added prior to
898 // navigation and attachment.
899 // 1. It adds a rule to block URLs that contain guest.
900 // 2. It attempts to navigate to a guest.html page.
901 // 3. It detects the appropriate loadabort message.
902 // 4. It removes the rule blocking the page and reloads.
903 // 5. The page loads successfully.
904 function testDeclarativeWebRequestAPI() {
905   var step = 1;
906   var webview = new WebView();
907   var rule = {
908     conditions: [
909       new chrome.webViewRequest.RequestMatcher(
910         {
911           url: { urlContains: 'guest' }
912         }
913       )
914     ],
915     actions: [
916       new chrome.webViewRequest.CancelRequest()
917     ]
918   };
919   webview.request.onRequest.addRules([rule]);
920   webview.addEventListener('loadabort', function(e) {
921     embedder.test.assertEq(1, step);
922     embedder.test.assertEq('ERR_BLOCKED_BY_CLIENT', e.reason);
923     step = 2;
924     webview.request.onRequest.removeRules();
925     webview.reload();
926   });
927   webview.addEventListener('loadcommit', function(e) {
928     embedder.test.assertEq(2, step);
929     embedder.test.succeed();
930   });
931   webview.src = embedder.emptyGuestURL;
932   document.body.appendChild(webview);
933 }
934
935 // This test verifies that the WebRequest API onBeforeRequest event fires on
936 // clients*.google.com URLs.
937 function testWebRequestAPIGoogleProperty() {
938   var webview = new WebView();
939   webview.request.onBeforeRequest.addListener(function(e) {
940     embedder.test.succeed();
941     return {cancel: true};
942   }, { urls: ['<all_urls>']}, ['blocking']) ;
943   webview.src = 'http://clients6.google.com';
944   document.body.appendChild(webview);
945 }
946
947 // This test verifies that the WebRequest event listener for onBeforeRequest
948 // survives reparenting of the <webview>.
949 function testWebRequestListenerSurvivesReparenting() {
950   var webview = new WebView();
951   var count = 0;
952   webview.request.onBeforeRequest.addListener(function(e) {
953     if (++count == 2) {
954       embedder.test.succeed();
955     }
956   }, { urls: ['<all_urls>']});
957   var onLoadStop =  function(e) {
958     webview.removeEventListener('loadstop', onLoadStop);
959     webview.parentNode.removeChild(webview);
960     var container = document.getElementById('object-container');
961     if (!container) {
962       embedder.test.fail('Container for object not found.');
963       return;
964     }
965     container.appendChild(webview);
966   };
967   webview.addEventListener('loadstop', onLoadStop);
968   webview.src = embedder.emptyGuestURL;
969   document.body.appendChild(webview);
970 }
971
972 // This test verifies that getProcessId is defined and returns a non-zero
973 // value corresponding to the processId of the guest process.
974 function testGetProcessId() {
975   var webview = document.createElement('webview');
976   webview.setAttribute('src', 'data:text/html,trigger navigation');
977   var firstLoad = function() {
978     webview.removeEventListener('loadstop', firstLoad);
979     embedder.test.assertTrue(webview.getProcessId() > 0);
980     embedder.test.succeed();
981   };
982   webview.addEventListener('loadstop', firstLoad);
983   document.body.appendChild(webview);
984 }
985
986 // This test verifies that the loadstart event fires at the beginning of a load
987 // and the loadredirect event fires when a redirect occurs.
988 function testLoadStartLoadRedirect() {
989   var webview = document.createElement('webview');
990   var loadstartCalled = false;
991   webview.setAttribute('src', embedder.redirectGuestURL);
992   webview.addEventListener('loadstart', function(e) {
993     embedder.test.assertTrue(e.isTopLevel);
994     embedder.test.assertEq(embedder.redirectGuestURL, e.url);
995     loadstartCalled = true;
996   });
997   webview.addEventListener('loadredirect', function(e) {
998     embedder.test.assertTrue(e.isTopLevel);
999     embedder.test.assertEq(embedder.redirectGuestURL,
1000         e.oldUrl.replace('127.0.0.1', 'localhost'));
1001     embedder.test.assertEq(embedder.redirectGuestURLDest,
1002         e.newUrl.replace('127.0.0.1', 'localhost'));
1003     if (loadstartCalled) {
1004       embedder.test.succeed();
1005     } else {
1006       embedder.test.fail();
1007     }
1008   });
1009   document.body.appendChild(webview);
1010 }
1011
1012 // This test verifies that the loadabort event fires when loading a webview
1013 // accessible resource from a partition that is not privileged.
1014 function testLoadAbortChromeExtensionURLWrongPartition() {
1015   var localResource = chrome.runtime.getURL('guest.html');
1016   var webview = document.createElement('webview');
1017   webview.addEventListener('loadabort', function(e) {
1018     embedder.test.assertEq('ERR_ADDRESS_UNREACHABLE', e.reason);
1019     embedder.test.succeed();
1020   });
1021   webview.addEventListener('loadstop', function(e) {
1022     embedder.test.fail();
1023   });
1024   webview.setAttribute('src', localResource);
1025   document.body.appendChild(webview);
1026 }
1027
1028 // This test verifies that the loadabort event fires as expected and with the
1029 // appropriate fields when an empty response is returned.
1030 function testLoadAbortEmptyResponse() {
1031   var webview = document.createElement('webview');
1032   webview.addEventListener('loadabort', function(e) {
1033     embedder.test.assertEq('ERR_EMPTY_RESPONSE', e.reason);
1034     embedder.test.succeed();
1035   });
1036   webview.setAttribute('src', embedder.closeSocketURL);
1037   document.body.appendChild(webview);
1038 }
1039
1040 // This test verifies that the loadabort event fires as expected when an illegal
1041 // chrome URL is provided.
1042 function testLoadAbortIllegalChromeURL() {
1043   var webview = document.createElement('webview');
1044   var onFirstLoadStop = function(e) {
1045     webview.removeEventListener('loadstop', onFirstLoadStop);
1046     webview.setAttribute('src', 'chrome://newtab');
1047   };
1048   webview.addEventListener('loadstop', onFirstLoadStop);
1049   webview.addEventListener('loadabort', function(e) {
1050     embedder.test.assertEq('ERR_ABORTED', e.reason);
1051     embedder.test.succeed();
1052   });
1053   webview.setAttribute('src', 'about:blank');
1054   document.body.appendChild(webview);
1055 }
1056
1057 function testLoadAbortIllegalFileURL() {
1058   var webview = document.createElement('webview');
1059   webview.addEventListener('loadabort', function(e) {
1060     embedder.test.assertEq('ERR_ABORTED', e.reason);
1061     embedder.test.succeed();
1062   });
1063   webview.setAttribute('src', 'file://foo');
1064   document.body.appendChild(webview);
1065 }
1066
1067 function testLoadAbortIllegalJavaScriptURL() {
1068   var webview = document.createElement('webview');
1069   webview.addEventListener('loadabort', function(e) {
1070     embedder.test.assertEq('ERR_ABORTED', e.reason);
1071     embedder.test.succeed();
1072   });
1073   webview.setAttribute('src', 'javascript:void(document.bgColor="#0000FF")');
1074   document.body.appendChild(webview);
1075 }
1076
1077 // This test verifies that the reload method on webview functions as expected.
1078 function testReload() {
1079   var triggerNavUrl = 'data:text/html,trigger navigation';
1080   var webview = document.createElement('webview');
1081
1082   var loadCommitCount = 0;
1083   webview.addEventListener('loadstop', function(e) {
1084     if (loadCommitCount < 2) {
1085       webview.reload();
1086     } else if (loadCommitCount == 2) {
1087       embedder.test.succeed();
1088     } else {
1089       embedder.test.fail();
1090     }
1091   });
1092   webview.addEventListener('loadcommit', function(e) {
1093     embedder.test.assertEq(triggerNavUrl, e.url);
1094     embedder.test.assertTrue(e.isTopLevel);
1095     loadCommitCount++;
1096   });
1097
1098   webview.setAttribute('src', triggerNavUrl);
1099   document.body.appendChild(webview);
1100 }
1101
1102 // This test verifies that a <webview> is torn down gracefully when removed from
1103 // the DOM on exit.
1104
1105 window.removeWebviewOnExitDoCrash = null;
1106
1107 function testRemoveWebviewOnExit() {
1108   var triggerNavUrl = 'data:text/html,trigger navigation';
1109   var webview = document.createElement('webview');
1110
1111   webview.addEventListener('loadstop', function(e) {
1112     chrome.test.sendMessage('guest-loaded');
1113   });
1114
1115   window.removeWebviewOnExitDoCrash = function() {
1116     webview.terminate();
1117   };
1118
1119   webview.addEventListener('exit', function(e) {
1120     // We expected to be killed.
1121     if (e.reason != 'killed') {
1122       console.log('EXPECTED TO BE KILLED!');
1123       return;
1124     }
1125     webview.parentNode.removeChild(webview);
1126   });
1127
1128   // Trigger a navigation to create a guest process.
1129   webview.setAttribute('src', embedder.emptyGuestURL);
1130   document.body.appendChild(webview);
1131 }
1132
1133 function testRemoveWebviewAfterNavigation() {
1134   var webview = new WebView();
1135   document.body.appendChild(webview);
1136   webview.src = 'data:text/html,trigger navigation';
1137   document.body.removeChild(webview);
1138   setTimeout(function() {
1139     embedder.test.succeed();
1140   }, 0);
1141 }
1142
1143 function testNavigationToExternalProtocol() {
1144   var webview = document.createElement('webview');
1145   webview.addEventListener('loadstop', function(e) {
1146     webview.addEventListener('loadabort', function(e) {
1147       embedder.test.assertEq('ERR_UNKNOWN_URL_SCHEME', e.reason);
1148       embedder.test.succeed();
1149     });
1150     webview.executeScript({
1151       code: 'window.location.href = "tel:+12223334444";'
1152     }, function(results) {});
1153   });
1154   webview.setAttribute('src', 'data:text/html,navigate to external protocol');
1155   document.body.appendChild(webview);
1156 }
1157
1158 function testResizeWebviewResizesContent() {
1159   var webview = new WebView();
1160   webview.src = 'about:blank';
1161   webview.addEventListener('loadstop', function(e) {
1162     webview.executeScript(
1163       {file: 'inject_resize_test.js'},
1164       function(results) {
1165         window.console.log('The resize test has been injected into webview.');
1166       }
1167     );
1168     webview.executeScript(
1169       {file: 'inject_comm_channel.js'},
1170       function(results) {
1171         window.console.log('The guest script for a two-way comm channel has ' +
1172             'been injected into webview.');
1173         // Establish a communication channel with the guest.
1174         var msg = ['connect'];
1175         webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1176       }
1177     );
1178   });
1179   window.addEventListener('message', function(e) {
1180     var data = JSON.parse(e.data);
1181     if (data[0] == 'connected') {
1182       console.log('A communication channel has been established with webview.');
1183       console.log('Resizing <webview> width from 300px to 400px.');
1184       webview.style.width = '400px';
1185       return;
1186     }
1187     if (data[0] == 'resize') {
1188       var width = data[1];
1189       var height = data[2];
1190       embedder.test.assertEq(400, width);
1191       embedder.test.assertEq(300, height);
1192       embedder.test.succeed();
1193       return;
1194     }
1195     console.log('Unexpected message: \'' + data[0]  + '\'');
1196     embedder.test.fail();
1197   });
1198   document.body.appendChild(webview);
1199 }
1200
1201 function testPostMessageCommChannel() {
1202   var webview = new WebView();
1203   webview.src = 'about:blank';
1204   webview.addEventListener('loadstop', function(e) {
1205     webview.executeScript(
1206       {file: 'inject_comm_channel.js'},
1207       function(results) {
1208         window.console.log('The guest script for a two-way comm channel has ' +
1209             'been injected into webview.');
1210         // Establish a communication channel with the guest.
1211         var msg = ['connect'];
1212         webview.contentWindow.postMessage(JSON.stringify(msg), '*');
1213       }
1214     );
1215   });
1216   window.addEventListener('message', function(e) {
1217     var data = JSON.parse(e.data);
1218     if (data[0] == 'connected') {
1219       console.log('A communication channel has been established with webview.');
1220       embedder.test.succeed();
1221       return;
1222     }
1223     console.log('Unexpected message: \'' + data[0]  + '\'');
1224     embedder.test.fail();
1225   });
1226   document.body.appendChild(webview);
1227 }
1228
1229 function testScreenshotCapture() {
1230   var webview = document.createElement('webview');
1231
1232   webview.addEventListener('loadstop', function(e) {
1233     webview.captureVisibleRegion(null, function(dataUrl) {
1234       // 100x100 red box.
1235       var expectedUrl = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/' +
1236           '2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLE' +
1237           'BYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFB' +
1238           'QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCABkAGQ' +
1239           'DASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAA' +
1240           'AgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM' +
1241           '2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3' +
1242           'R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8j' +
1243           'JytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAA' +
1244           'AAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBU' +
1245           'QdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERU' +
1246           'ZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqO' +
1247           'kpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3' +
1248           '+Pn6/9oADAMBAAIRAxEAPwD50ooor8MP9UwooooAKKKKACiiigAooooAKKKKACiii' +
1249           'gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiig' +
1250           'AooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigA' +
1251           'ooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAo' +
1252           'oooAKKKKACiiigAooooAKKKKACiiigD/2Q==';
1253       embedder.test.assertEq(expectedUrl, dataUrl);
1254       embedder.test.succeed();
1255     });
1256   });
1257
1258   webview.style.width = '100px';
1259   webview.style.height = '100px';
1260   webview.setAttribute('src',
1261       'data:text/html,<body style="background-color: red"></body>');
1262   document.body.appendChild(webview);
1263 }
1264
1265 embedder.test.testList = {
1266   'testAutosizeAfterNavigation': testAutosizeAfterNavigation,
1267   'testAutosizeBeforeNavigation': testAutosizeBeforeNavigation,
1268   'testAutosizeRemoveAttributes': testAutosizeRemoveAttributes,
1269   'testAutosizeWithPartialAttributes': testAutosizeWithPartialAttributes,
1270   'testAPIMethodExistence': testAPIMethodExistence,
1271   'testChromeExtensionURL': testChromeExtensionURL,
1272   'testChromeExtensionRelativePath': testChromeExtensionRelativePath,
1273   'testInvalidChromeExtensionURL': testInvalidChromeExtensionURL,
1274   'testWebRequestAPIExistence': testWebRequestAPIExistence,
1275   'testEventName': testEventName,
1276   'testOnEventProperties': testOnEventProperties,
1277   'testLoadProgressEvent': testLoadProgressEvent,
1278   'testDestroyOnEventListener': testDestroyOnEventListener,
1279   'testCannotMutateEventName': testCannotMutateEventName,
1280   'testPartitionRaisesException': testPartitionRaisesException,
1281   'testExecuteScriptFail': testExecuteScriptFail,
1282   'testExecuteScript': testExecuteScript,
1283   'testTerminateAfterExit': testTerminateAfterExit,
1284   'testAssignSrcAfterCrash': testAssignSrcAfterCrash,
1285   'testNavOnConsecutiveSrcAttributeChanges':
1286       testNavOnConsecutiveSrcAttributeChanges,
1287   'testNavOnSrcAttributeChange': testNavOnSrcAttributeChange,
1288   'testReassignSrcAttribute': testReassignSrcAttribute,
1289   'testRemoveSrcAttribute': testRemoveSrcAttribute,
1290   'testBrowserPluginNotAllowed': testBrowserPluginNotAllowed,
1291   'testPluginLoadPermission': testPluginLoadPermission,
1292   'testNewWindow': testNewWindow,
1293   'testNewWindowTwoListeners': testNewWindowTwoListeners,
1294   'testNewWindowNoPreventDefault': testNewWindowNoPreventDefault,
1295   'testNewWindowNoReferrerLink': testNewWindowNoReferrerLink,
1296   'testContentLoadEvent': testContentLoadEvent,
1297   'testDeclarativeWebRequestAPI': testDeclarativeWebRequestAPI,
1298   'testWebRequestAPI': testWebRequestAPI,
1299   'testWebRequestAPIGoogleProperty': testWebRequestAPIGoogleProperty,
1300   'testWebRequestListenerSurvivesReparenting':
1301       testWebRequestListenerSurvivesReparenting,
1302   'testGetProcessId': testGetProcessId,
1303   'testLoadStartLoadRedirect': testLoadStartLoadRedirect,
1304   'testLoadAbortChromeExtensionURLWrongPartition':
1305       testLoadAbortChromeExtensionURLWrongPartition,
1306   'testLoadAbortEmptyResponse': testLoadAbortEmptyResponse,
1307   'testLoadAbortIllegalChromeURL': testLoadAbortIllegalChromeURL,
1308   'testLoadAbortIllegalFileURL': testLoadAbortIllegalFileURL,
1309   'testLoadAbortIllegalJavaScriptURL': testLoadAbortIllegalJavaScriptURL,
1310   'testNavigationToExternalProtocol': testNavigationToExternalProtocol,
1311   'testReload': testReload,
1312   'testRemoveWebviewOnExit': testRemoveWebviewOnExit,
1313   'testRemoveWebviewAfterNavigation': testRemoveWebviewAfterNavigation,
1314   'testResizeWebviewResizesContent': testResizeWebviewResizesContent,
1315   'testPostMessageCommChannel': testPostMessageCommChannel,
1316   'testScreenshotCapture' : testScreenshotCapture
1317 };
1318
1319 onload = function() {
1320   chrome.test.getConfig(function(config) {
1321     embedder.setUp_(config);
1322     chrome.test.sendMessage("Launched");
1323   });
1324 };