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);
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);
29 var onLoadStop = function() {
30 webview.executeScript({
31 code: 'document.body.style.backgroundColor = \'red\';'
32 }, onSetBackgroundExecuted);
35 webview.addEventListener('loadstop', onLoadStop);
39 function testExecuteScriptCodeFromFile(url) {
40 var webview = createWebview();
42 var onSetBackgroundExecuted = function() {
43 webview.executeScript({
44 code: 'document.body.style.backgroundColor;'
45 }, onGetBackgroundExecuted);
48 var onLoadStop = function() {
49 webview.executeScript({
50 file: 'test/webview_execute_script.js'
51 }, onSetBackgroundExecuted);
54 webview.addEventListener('loadstop', onLoadStop);
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
61 function testAddContentScript(url) {
62 var webview = document.createElement('webview');
64 console.log('Step 1: call <webview>.addContentScripts.');
65 webview.addContentScripts(
67 matches: ['http://*/empty*'],
69 files: ['test/inject_comm_channel.js',
70 'test/inject_comm_channel_2.js']
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), '*');
80 window.addEventListener('message', function(e) {
81 if (e.source != webview.contentWindow)
83 var data = JSON.parse(e.data);
84 if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
86 'Step 3: A communication channel has been established with webview.');
87 chrome.send('testResult', [true]);
90 console.log('Unexpected message: \'' + data[0] + '\'');
91 chrome.send('testResult', [false]);
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(
107 matches: ['http://*/empty*'],
109 files: ['test/inject_comm_channel.js']
111 run_at: 'document_start'},
113 matches: ['http://*/empty*'],
115 files: ['test/inject_comm_channel_2.js']
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), '*');
128 var response_1 = false;
129 var response_2 = false;
130 window.addEventListener('message', function(e) {
131 if (e.source != webview.contentWindow)
133 var data = JSON.parse(e.data);
134 if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
136 'Step 4: A communication channel has been established with webview.');
138 if (response_1 && response_2)
139 chrome.send('testResult', [true]);
141 } else if (data == RESPONSE_FROM_COMM_CHANNEL_2) {
143 'Step 5: A communication channel has been established with webview.');
145 if (response_1 && response_2)
146 chrome.send('testResult', [true]);
149 console.log('Unexpected message: \'' + data[0] + '\'');
150 chrome.send('testResult', [false]);
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(
168 matches: ['http://*/empty*'],
170 files: ['test/inject_comm_channel.js']
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;
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;
189 var should_get_response_from_script_1 = true;
190 window.addEventListener('message', function(e) {
191 if (e.source != webview.contentWindow)
193 var data = JSON.parse(e.data);
194 if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
195 if (should_get_response_from_script_1) {
197 'Step 2: A communication channel has been established with webview.'
199 console.log('Step 3: <webview>.addContentScripts() with a updated' +
201 webview.addContentScripts(
203 matches: ['http://*/empty*'],
205 files: ['test/inject_comm_channel_2.js']
207 run_at: 'document_start'}]);
208 connect_script_2 = true;
209 should_get_response_from_script_1 = false;
212 chrome.send('testResult', [false]);
215 } else if (data == RESPONSE_FROM_COMM_CHANNEL_2) {
217 'Step 4: Another communication channel has been established ' +
219 setTimeout(function() {
220 chrome.send('testResult', [true]);
224 console.log('Unexpected message: \'' + data[0] + '\'');
225 chrome.send('testResult', [false]);
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(
242 matches: ['http://*/empty*'],
244 files: ['test/inject_comm_channel.js']
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]);
257 window.addEventListener('message', function(e) {
258 if (e.source != webview2.contentWindow)
260 var data = JSON.parse(e.data);
261 if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
262 chrome.send('testResult', [false]);
265 console.log('Unexpected message: \'' + data[0] + '\'');
266 chrome.send('testResult', [false]);
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(
286 matches: ['http://*/empty*'],
288 files: ['test/inject_comm_channel.js']
290 run_at: 'document_start'}]);
292 var should_get_response_from_script_1 = true;
295 webview.addEventListener('loadstop', function() {
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), '*');
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]);
311 window.addEventListener('message', function(e) {
312 if (e.source != webview.contentWindow)
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 ' +
319 should_get_response_from_script_1 = false;
321 'Step 4: call <webview>.removeContentScripts and navigate.');
322 webview.removeContentScripts();
326 console.log('Unexpected message: \'' + data[0] + '\'');
327 chrome.send('testResult', [false]);
331 document.body.appendChild(webview);
334 // This test verifies that the addContentScripts API works with the new window
336 function testAddContentScriptsWithNewWindowAPI(url) {
337 var webview = document.createElement('webview');
340 webview.addEventListener('newwindow', function(e) {
342 newwebview = document.createElement('webview');
344 console.log('Step 2: call newwebview.addContentScripts.');
345 newwebview.addContentScripts(
347 matches: ['http://*/guest_from_opener*'],
349 files: ['test/inject_comm_channel.js']
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 ' +
357 newwebview.contentWindow.postMessage(JSON.stringify(msg), '*');
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);
366 window.addEventListener('message', function(e) {
367 if (!newwebview || e.source != newwebview.contentWindow)
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]);
377 chrome.send('testResult', [false]);
380 console.log('Unexpected message: \'' + data[0] + '\'');
381 chrome.send('testResult', [false]);
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(
397 matches: ['http://*/empty*'],
399 files: ['test/webview_execute_script.js']
401 run_at: 'document_end'}]);
404 webview.addEventListener('loadstop', function() {
406 console.log('Step 2: call webview.terminate().');
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);
418 webview.addEventListener('exit', function() {
419 console.log('Step 3: call webview.reload().');
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(
435 matches: ['http://*/empty*'],
437 files: ['test/webview_execute_script.js']
439 run_at: 'document_end'}]);
442 webview.addEventListener('loadstop', function() {
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);
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);
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(
475 matches: ['http://*/empty*'],
477 code: 'document.body.style.backgroundColor = \'red\';'
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);
489 document.body.appendChild(webview);