Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / test / data / webui / webview_content_script_test.js
blobb5a2daf421a57c10ffffbad1e387d35ad6aa0bb5
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 var REQUEST_TO_COMM_CHANNEL_1 = 'connect';
6 var REQUEST_TO_COMM_CHANNEL_2 = 'connect_request';
7 var RESPONSE_FROM_COMM_CHANNEL_1 = 'connected';
8 var RESPONSE_FROM_COMM_CHANNEL_2 = 'connected_response';
10 function createWebview() {
11   var webview = document.createElement('webview');
12   document.body.appendChild(webview);
13   return webview;
16 function onGetBackgroundExecuted(results) {
17   chrome.send('testResult', [results.length == 1 && results[0] == 'red']);
20 function testExecuteScriptCode(url) {
21   var webview = createWebview();
23   var onSetBackgroundExecuted = function() {
24     webview.executeScript({
25       code: 'document.body.style.backgroundColor;'
26     }, onGetBackgroundExecuted);
27   };
29   var onLoadStop = function() {
30     webview.executeScript({
31       code: 'document.body.style.backgroundColor = \'red\';'
32     }, onSetBackgroundExecuted);
33   };
35   webview.addEventListener('loadstop', onLoadStop);
36   webview.src = url;
39 function testExecuteScriptCodeFromFile(url) {
40   var webview = createWebview();
42   var onSetBackgroundExecuted = function() {
43     webview.executeScript({
44       code: 'document.body.style.backgroundColor;'
45     }, onGetBackgroundExecuted);
46   };
48   var onLoadStop = function() {
49     webview.executeScript({
50       file: 'test/webview_execute_script.js'
51     }, onSetBackgroundExecuted);
52   };
54   webview.addEventListener('loadstop', onLoadStop);
55   webview.src = url;
58 // This test verifies that a content script will be injected to the webview when
59 // the webview is navigated to a page that matches the URL pattern defined in
60 // the content sript.
61 function testAddContentScript(url) {
62   var webview = document.createElement('webview');
64   console.log('Step 1: call <webview>.addContentScripts.');
65   webview.addContentScripts(
66       [{name: 'myrule',
67         matches: ['http://*/empty*'],
68         js: {
69           files: ['test/inject_comm_channel.js',
70                   'test/inject_comm_channel_2.js']
71         },
72         run_at: 'document_start'}]);
74   webview.addEventListener('loadstop', function() {
75     console.log('Step 2: postMessage to build connection.');
76     var msg = [REQUEST_TO_COMM_CHANNEL_1];
77     webview.contentWindow.postMessage(JSON.stringify(msg), '*');
78   });
80   window.addEventListener('message', function(e) {
81     if (e.source != webview.contentWindow)
82       return;
83     var data = JSON.parse(e.data);
84     if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
85       console.log(
86           'Step 3: A communication channel has been established with webview.');
87       chrome.send('testResult', [true]);
88       return;
89     }
90     console.log('Unexpected message: \'' + data[0]  + '\'');
91     chrome.send('testResult', [false]);
92   });
94   webview.src = url;
95   document.body.appendChild(webview);
98 // Adds two content scripts with the same URL pattern to <webview> at the same
99 // time. This test verifies that both scripts are injected when the <webview>
100 // navigates to a URL that matches the URL pattern.
101 function testAddMultiContentScripts(url) {
102   var webview = document.createElement('webview');
104   console.log('Step 1: call <webview>.addContentScripts(myrule1 & myrule2)');
105   webview.addContentScripts(
106       [{name: 'myrule1',
107         matches: ['http://*/empty*'],
108         js: {
109           files: ['test/inject_comm_channel.js']
110         },
111         run_at: 'document_start'},
112        {name: 'myrule2',
113         matches: ['http://*/empty*'],
114         js: {
115           files: ['test/inject_comm_channel_2.js']
116         },
117         run_at: 'document_start'}]);
119   webview.addEventListener('loadstop', function() {
120     console.log('Step 2: postMessage to build connection.');
121     var msg1 = [REQUEST_TO_COMM_CHANNEL_1];
122     webview.contentWindow.postMessage(JSON.stringify(msg1), '*');
123     console.log('Step 3: postMessage to build connection to the other script.');
124     var msg2 = [REQUEST_TO_COMM_CHANNEL_2];
125     webview.contentWindow.postMessage(JSON.stringify(msg2), '*');
126   });
128   var response_1 = false;
129   var response_2 = false;
130   window.addEventListener('message', function(e) {
131     if (e.source != webview.contentWindow)
132       return;
133     var data = JSON.parse(e.data);
134     if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
135       console.log(
136           'Step 4: A communication channel has been established with webview.');
137       response_1 = true;
138       if (response_1 && response_2)
139         chrome.send('testResult', [true]);
140       return;
141     } else if (data == RESPONSE_FROM_COMM_CHANNEL_2) {
142       console.log(
143           'Step 5: A communication channel has been established with webview.');
144       response_2 = true;
145       if (response_1 && response_2)
146         chrome.send('testResult', [true]);
147       return;
148     }
149     console.log('Unexpected message: \'' + data[0]  + '\'');
150     chrome.send('testResult', [false]);
151   });
153   webview.src = url;
154   document.body.appendChild(webview);
157 // Adds a content script to <webview> and navigates. After seeing the script is
158 // injected, we add another content script with the same name to the <webview>.
159 // This test verifies that the second script will replace the first one and be
160 // injected after navigating the <webview>. Meanwhile, the <webview> shouldn't
161 // get any message from the first script anymore.
162 function testAddContentScriptWithSameNameShouldOverwriteTheExistingOne(url) {
163   var webview = document.createElement('webview');
165   console.log('Step 1: call <webview>.addContentScripts(myrule1)');
166   webview.addContentScripts(
167       [{name: 'myrule1',
168         matches: ['http://*/empty*'],
169         js: {
170           files: ['test/inject_comm_channel.js']
171         },
172         run_at: 'document_start'}]);
173   var connect_script_1 = true;
174   var connect_script_2 = false;
176   webview.addEventListener('loadstop', function() {
177     if (connect_script_1) {
178       var msg1 = [REQUEST_TO_COMM_CHANNEL_1];
179       webview.contentWindow.postMessage(JSON.stringify(msg1), '*');
180       connect_script_1 = false;
181     }
182     if (connect_script_2) {
183       var msg2 = [REQUEST_TO_COMM_CHANNEL_2];
184       webview.contentWindow.postMessage(JSON.stringify(msg2), '*');
185       connect_script_2 = false;
186     }
187   });
189   var should_get_response_from_script_1 = true;
190   window.addEventListener('message', function(e) {
191     if (e.source != webview.contentWindow)
192       return;
193     var data = JSON.parse(e.data);
194     if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
195       if (should_get_response_from_script_1) {
196         console.log(
197             'Step 2: A communication channel has been established with webview.'
198             );
199         console.log('Step 3: <webview>.addContentScripts() with a updated' +
200             ' \'myrule1\'');
201         webview.addContentScripts(
202             [{name: 'myrule1',
203               matches: ['http://*/empty*'],
204               js: {
205                 files: ['test/inject_comm_channel_2.js']
206               },
207               run_at: 'document_start'}]);
208         connect_script_2 = true;
209         should_get_response_from_script_1 = false;
210         webview.src = url;
211       } else {
212         chrome.send('testResult', [false]);
213       }
214       return;
215     } else if (data == RESPONSE_FROM_COMM_CHANNEL_2) {
216       console.log(
217           'Step 4: Another communication channel has been established ' +
218           'with webview.');
219       setTimeout(function() {
220         chrome.send('testResult', [true]);
221       }, 0);
222       return;
223     }
224     console.log('Unexpected message: \'' + data[0]  + '\'');
225     chrome.send('testResult', [false]);
226   });
228   webview.src = url;
229   document.body.appendChild(webview);
232 // There are two <webview>s are added to the DOM, and we add a content script
233 // to one of them. This test verifies that the script won't be injected in
234 // the other <webview>.
235 function testAddContentScriptToOneWebViewShouldNotInjectToTheOtherWebView(url) {
236   var webview1 = document.createElement('webview');
237   var webview2 = document.createElement('webview');
239   console.log('Step 1: call <webview1>.addContentScripts.');
240   webview1.addContentScripts(
241       [{name: 'myrule',
242         matches: ['http://*/empty*'],
243         js: {
244           files: ['test/inject_comm_channel.js']
245         },
246         run_at: 'document_start'}]);
248   webview2.addEventListener('loadstop', function() {
249     console.log('Step 2: webview2 requests to build communication channel.');
250     var msg = [REQUEST_TO_COMM_CHANNEL_1];
251     webview2.contentWindow.postMessage(JSON.stringify(msg), '*');
252     setTimeout(function() {
253       chrome.send('testResult', [true]);
254     }, 0);
255   });
257   window.addEventListener('message', function(e) {
258     if (e.source != webview2.contentWindow)
259       return;
260     var data = JSON.parse(e.data);
261     if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
262       chrome.send('testResult', [false]);
263       return;
264     }
265     console.log('Unexpected message: \'' + data[0]  + '\'');
266     chrome.send('testResult', [false]);
267   });
269   webview1.src = url;
270   webview2.src = url;
271   document.body.appendChild(webview1);
272   document.body.appendChild(webview2);
275 // Adds a content script to <webview> and navigates to a URL that matches the
276 // URL pattern defined in the script. After the first navigation, we remove this
277 // script from the <webview> and navigates to the same URL. This test verifies
278 // taht the script is injected during the first navigation, but isn't injected
279 // after removing it.
280 function testAddAndRemoveContentScripts(url) {
281   var webview = document.createElement('webview');
283   console.log('Step 1: call <webview>.addContentScripts.');
284   webview.addContentScripts(
285       [{name: 'myrule',
286         matches: ['http://*/empty*'],
287         js: {
288           files: ['test/inject_comm_channel.js']
289         },
290         run_at: 'document_start'}]);
292   var should_get_response_from_script_1 = true;
294   var count = 0;
295   webview.addEventListener('loadstop', function() {
296     if (count == 0) {
297       console.log('Step 2: post message to build connect.');
298       var msg = [REQUEST_TO_COMM_CHANNEL_1];
299       webview.contentWindow.postMessage(JSON.stringify(msg), '*');
300       ++count;
301     } else if (count == 1) {
302       console.log('Step 5: post message to build connect again.');
303       var msg = [REQUEST_TO_COMM_CHANNEL_1];
304       webview.contentWindow.postMessage(JSON.stringify(msg), '*');
305       setTimeout(function() {
306         chrome.send('testResult', [true]);
307       }, 0);
308     }
309   });
311   window.addEventListener('message', function(e) {
312     if (e.source != webview.contentWindow)
313       return;
314     var data = JSON.parse(e.data);
315     if (data[0] == RESPONSE_FROM_COMM_CHANNEL_1 &&
316         should_get_response_from_script_1) {
317         console.log('Step 3: A communication channel has been established ' +
318             'with webview.');
319         should_get_response_from_script_1 = false;
320       console.log(
321           'Step 4: call <webview>.removeContentScripts and navigate.');
322       webview.removeContentScripts();
323       webview.src = url;
324       return;
325     }
326     console.log('Unexpected message: \'' + data[0]  + '\'');
327     chrome.send('testResult', [false]);
328   });
330   webview.src = url;
331   document.body.appendChild(webview);
334 // This test verifies that the addContentScripts API works with the new window
335 // API.
336 function testAddContentScriptsWithNewWindowAPI(url) {
337   var webview = document.createElement('webview');
339   var newwebview;
340   webview.addEventListener('newwindow', function(e) {
341     e.preventDefault();
342     newwebview = document.createElement('webview');
344     console.log('Step 2: call newwebview.addContentScripts.');
345     newwebview.addContentScripts(
346         [{name: 'myrule',
347           matches: ['http://*/guest_from_opener*'],
348           js: {
349             files: ['test/inject_comm_channel.js']
350           },
351           run_at: 'document_start'}]);
353     newwebview.addEventListener('loadstop', function(evt) {
354       var msg = [REQUEST_TO_COMM_CHANNEL_1];
355       console.log('Step 4: new webview postmessage to build communication ' +
356           'channel.');
357       newwebview.contentWindow.postMessage(JSON.stringify(msg), '*');
358     });
360     document.body.appendChild(newwebview);
361     // attach the new window to the new <webview>.
362     console.log('Step 3: attaches the new webview.');
363     e.window.attach(newwebview);
364   });
366   window.addEventListener('message', function(e) {
367     if (!newwebview || e.source != newwebview.contentWindow)
368       return;
369     var data = JSON.parse(e.data);
370     if (data == RESPONSE_FROM_COMM_CHANNEL_1 &&
371         e.source == newwebview.contentWindow) {
372       console.log('Step 5: a communication channel has been established ' +
373           'with the new webview.');
374       chrome.send('testResult', [true]);
375       return;
376     } else {
377       chrome.send('testResult', [false]);
378       return;
379     }
380     console.log('Unexpected message: \'' + data[0]  + '\'');
381     chrome.send('testResult', [false]);
382   });
384   console.log('Step 1: navigates the webview to window open guest URL.');
385   webview.setAttribute('src', url);
386   document.body.appendChild(webview);
389 // Adds a content script to <webview>. This test verifies that the script is
390 // injected after terminate and reload <webview>.
391 function testContentScriptIsInjectedAfterTerminateAndReloadWebView(url) {
392   var webview = document.createElement('webview');
394   console.log('Step 1: call <webview>.addContentScripts.');
395   webview.addContentScripts(
396       [{name: 'myrule',
397         matches: ['http://*/empty*'],
398         js: {
399           files: ['test/webview_execute_script.js']
400         },
401         run_at: 'document_end'}]);
403   var count = 0;
404   webview.addEventListener('loadstop', function() {
405     if (count == 0) {
406       console.log('Step 2: call webview.terminate().');
407       webview.terminate();
408       ++count;
409       return;
410     } else if (count == 1) {
411       console.log('Step 4: call <webview>.executeScript to check result.');
412       webview.executeScript({
413         code: 'document.body.style.backgroundColor;'
414       }, onGetBackgroundExecuted);
415     }
416   });
418   webview.addEventListener('exit', function() {
419     console.log('Step 3: call webview.reload().');
420     webview.reload();
421   });
423   webview.src = url;
424   document.body.appendChild(webview);
427 // This test verifies the content script won't be removed when the guest is
428 // destroyed, i.e., removed <webview> from the DOM.
429 function testContentScriptExistsAsLongAsWebViewTagExists(url) {
430   var webview = document.createElement('webview');
432   console.log('Step 1: call <webview>.addContentScripts.');
433   webview.addContentScripts(
434       [{name: 'myrule',
435         matches: ['http://*/empty*'],
436         js: {
437           files: ['test/webview_execute_script.js']
438         },
439         run_at: 'document_end'}]);
441   var count = 0;
442   webview.addEventListener('loadstop', function() {
443     if (count == 0) {
444       console.log('Step 2: check the result of content script injected.');
445       webview.executeScript({
446         code: 'document.body.style.backgroundColor;'
447       }, function(results) {
448         assertEquals(1, results.length);
449         assertEquals('red', results[0]);
451         console.log('Step 3: remove webview from the DOM.');
452         document.body.removeChild(webview);
453         console.log('Step 4: add webview back to the DOM.');
454         document.body.appendChild(webview);
455         ++count;
456       });
457     } else if (count == 1) {
458       console.log('Step 5: check the result of content script injected again.');
459       webview.executeScript({
460         code: 'document.body.style.backgroundColor;'
461       }, onGetBackgroundExecuted);
462     }
463   });
465   webview.src = url;
466   document.body.appendChild(webview);
469 function testAddContentScriptWithCode(url) {
470   var webview = document.createElement('webview');
472   console.log('Step 1: call <webview>.addContentScripts.');
473   webview.addContentScripts(
474       [{name: 'myrule',
475         matches: ['http://*/empty*'],
476         js: {
477           code: 'document.body.style.backgroundColor = \'red\';'
478         },
479         run_at: 'document_end'}]);
481   webview.addEventListener('loadstop', function() {
482     console.log('Step 2: call webview.executeScript() to check result.')
483     webview.executeScript({
484       code: 'document.body.style.backgroundColor;'
485     }, onGetBackgroundExecuted);
486   });
488   webview.src = url;
489   document.body.appendChild(webview);