blob: 61df885bac634feec4067cd0effc810c48192109 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var REQUEST_TO_COMM_CHANNEL_1 = 'connect';
var REQUEST_TO_COMM_CHANNEL_2 = 'connect_request';
var RESPONSE_FROM_COMM_CHANNEL_1 = 'connected';
var RESPONSE_FROM_COMM_CHANNEL_2 = 'connected_response';
function createWebview() {
var webview = document.createElement('webview');
document.body.appendChild(webview);
return webview;
}
function onGetBackgroundExecuted(results) {
chrome.send('testResult', [results.length == 1 && results[0] == 'red']);
};
function testExecuteScriptCode(url) {
var webview = createWebview();
var onSetBackgroundExecuted = function() {
webview.executeScript({
code: 'document.body.style.backgroundColor;'
}, onGetBackgroundExecuted);
};
var onLoadStop = function() {
webview.executeScript({
code: 'document.body.style.backgroundColor = \'red\';'
}, onSetBackgroundExecuted);
};
webview.addEventListener('loadstop', onLoadStop);
webview.src = url;
}
function testExecuteScriptCodeFromFile(url) {
var webview = createWebview();
var onSetBackgroundExecuted = function() {
webview.executeScript({
code: 'document.body.style.backgroundColor;'
}, onGetBackgroundExecuted);
};
var onLoadStop = function() {
webview.executeScript({
file: 'test/webview_execute_script.js'
}, onSetBackgroundExecuted);
};
webview.addEventListener('loadstop', onLoadStop);
webview.src = url;
}
// This test verifies that a content script will be injected to the webview when
// the webview is navigated to a page that matches the URL pattern defined in
// the content sript.
function testAddContentScript(url) {
var webview = document.createElement('webview');
console.log('Step 1: call <webview>.addContentScripts.');
webview.addContentScripts(
[{name: 'myrule',
matches: ['http://*/empty*'],
js: {
files: ['test/inject_comm_channel.js',
'test/inject_comm_channel_2.js']
},
run_at: 'document_start'}]);
webview.addEventListener('loadstop', function() {
console.log('Step 2: postMessage to build connection.');
var msg = [REQUEST_TO_COMM_CHANNEL_1];
webview.contentWindow.postMessage(JSON.stringify(msg), '*');
});
window.addEventListener('message', function(e) {
if (e.source != webview.contentWindow)
return;
var data = JSON.parse(e.data);
if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
console.log(
'Step 3: A communication channel has been established with webview.');
chrome.send('testResult', [true]);
return;
}
console.log('Unexpected message: \'' + data[0] + '\'');
chrome.send('testResult', [false]);
});
webview.src = url;
document.body.appendChild(webview);
}
// Adds two content scripts with the same URL pattern to <webview> at the same
// time. This test verifies that both scripts are injected when the <webview>
// navigates to a URL that matches the URL pattern.
function testAddMultiContentScripts(url) {
var webview = document.createElement('webview');
console.log('Step 1: call <webview>.addContentScripts(myrule1 & myrule2)');
webview.addContentScripts(
[{name: 'myrule1',
matches: ['http://*/empty*'],
js: {
files: ['test/inject_comm_channel.js']
},
run_at: 'document_start'},
{name: 'myrule2',
matches: ['http://*/empty*'],
js: {
files: ['test/inject_comm_channel_2.js']
},
run_at: 'document_start'}]);
webview.addEventListener('loadstop', function() {
console.log('Step 2: postMessage to build connection.');
var msg1 = [REQUEST_TO_COMM_CHANNEL_1];
webview.contentWindow.postMessage(JSON.stringify(msg1), '*');
console.log('Step 3: postMessage to build connection to the other script.');
var msg2 = [REQUEST_TO_COMM_CHANNEL_2];
webview.contentWindow.postMessage(JSON.stringify(msg2), '*');
});
var response_1 = false;
var response_2 = false;
window.addEventListener('message', function(e) {
if (e.source != webview.contentWindow)
return;
var data = JSON.parse(e.data);
if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
console.log(
'Step 4: A communication channel has been established with webview.');
response_1 = true;
if (response_1 && response_2)
chrome.send('testResult', [true]);
return;
} else if (data == RESPONSE_FROM_COMM_CHANNEL_2) {
console.log(
'Step 5: A communication channel has been established with webview.');
response_2 = true;
if (response_1 && response_2)
chrome.send('testResult', [true]);
return;
}
console.log('Unexpected message: \'' + data[0] + '\'');
chrome.send('testResult', [false]);
});
webview.src = url;
document.body.appendChild(webview);
}
// Adds a content script to <webview> and navigates. After seeing the script is
// injected, we add another content script with the same name to the <webview>.
// This test verifies that the second script will replace the first one and be
// injected after navigating the <webview>. Meanwhile, the <webview> shouldn't
// get any message from the first script anymore.
function testAddContentScriptWithSameNameShouldOverwriteTheExistingOne(url) {
var webview = document.createElement('webview');
console.log('Step 1: call <webview>.addContentScripts(myrule1)');
webview.addContentScripts(
[{name: 'myrule1',
matches: ['http://*/empty*'],
js: {
files: ['test/inject_comm_channel.js']
},
run_at: 'document_start'}]);
var connect_script_1 = true;
var connect_script_2 = false;
webview.addEventListener('loadstop', function() {
if (connect_script_1) {
var msg1 = [REQUEST_TO_COMM_CHANNEL_1];
webview.contentWindow.postMessage(JSON.stringify(msg1), '*');
connect_script_1 = false;
}
if (connect_script_2) {
var msg2 = [REQUEST_TO_COMM_CHANNEL_2];
webview.contentWindow.postMessage(JSON.stringify(msg2), '*');
connect_script_2 = false;
}
});
var should_get_response_from_script_1 = true;
window.addEventListener('message', function(e) {
if (e.source != webview.contentWindow)
return;
var data = JSON.parse(e.data);
if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
if (should_get_response_from_script_1) {
console.log(
'Step 2: A communication channel has been established with webview.'
);
console.log('Step 3: <webview>.addContentScripts() with a updated' +
' \'myrule1\'');
webview.addContentScripts(
[{name: 'myrule1',
matches: ['http://*/empty*'],
js: {
files: ['test/inject_comm_channel_2.js']
},
run_at: 'document_start'}]);
connect_script_2 = true;
should_get_response_from_script_1 = false;
webview.src = url;
} else {
chrome.send('testResult', [false]);
}
return;
} else if (data == RESPONSE_FROM_COMM_CHANNEL_2) {
console.log(
'Step 4: Another communication channel has been established ' +
'with webview.');
setTimeout(function() {
chrome.send('testResult', [true]);
}, 0);
return;
}
console.log('Unexpected message: \'' + data[0] + '\'');
chrome.send('testResult', [false]);
});
webview.src = url;
document.body.appendChild(webview);
}
// There are two <webview>s are added to the DOM, and we add a content script
// to one of them. This test verifies that the script won't be injected in
// the other <webview>.
function testAddContentScriptToOneWebViewShouldNotInjectToTheOtherWebView(url) {
var webview1 = document.createElement('webview');
var webview2 = document.createElement('webview');
console.log('Step 1: call <webview1>.addContentScripts.');
webview1.addContentScripts(
[{name: 'myrule',
matches: ['http://*/empty*'],
js: {
files: ['test/inject_comm_channel.js']
},
run_at: 'document_start'}]);
webview2.addEventListener('loadstop', function() {
console.log('Step 2: webview2 requests to build communication channel.');
var msg = [REQUEST_TO_COMM_CHANNEL_1];
webview2.contentWindow.postMessage(JSON.stringify(msg), '*');
setTimeout(function() {
chrome.send('testResult', [true]);
}, 0);
});
window.addEventListener('message', function(e) {
if (e.source != webview2.contentWindow)
return;
var data = JSON.parse(e.data);
if (data == RESPONSE_FROM_COMM_CHANNEL_1) {
chrome.send('testResult', [false]);
return;
}
console.log('Unexpected message: \'' + data[0] + '\'');
chrome.send('testResult', [false]);
});
webview1.src = url;
webview2.src = url;
document.body.appendChild(webview1);
document.body.appendChild(webview2);
}
// Adds a content script to <webview> and navigates to a URL that matches the
// URL pattern defined in the script. After the first navigation, we remove this
// script from the <webview> and navigates to the same URL. This test verifies
// taht the script is injected during the first navigation, but isn't injected
// after removing it.
function testAddAndRemoveContentScripts(url) {
var webview = document.createElement('webview');
console.log('Step 1: call <webview>.addContentScripts.');
webview.addContentScripts(
[{name: 'myrule',
matches: ['http://*/empty*'],
js: {
files: ['test/inject_comm_channel.js']
},
run_at: 'document_start'}]);
var should_get_response_from_script_1 = true;
var count = 0;
webview.addEventListener('loadstop', function() {
if (count == 0) {
console.log('Step 2: post message to build connect.');
var msg = [REQUEST_TO_COMM_CHANNEL_1];
webview.contentWindow.postMessage(JSON.stringify(msg), '*');
++count;
} else if (count == 1) {
console.log('Step 5: post message to build connect again.');
var msg = [REQUEST_TO_COMM_CHANNEL_1];
webview.contentWindow.postMessage(JSON.stringify(msg), '*');
setTimeout(function() {
chrome.send('testResult', [true]);
}, 0);
}
});
window.addEventListener('message', function(e) {
if (e.source != webview.contentWindow)
return;
var data = JSON.parse(e.data);
if (data[0] == RESPONSE_FROM_COMM_CHANNEL_1 &&
should_get_response_from_script_1) {
console.log('Step 3: A communication channel has been established ' +
'with webview.');
should_get_response_from_script_1 = false;
console.log(
'Step 4: call <webview>.removeContentScripts and navigate.');
webview.removeContentScripts();
webview.src = url;
return;
}
console.log('Unexpected message: \'' + data[0] + '\'');
chrome.send('testResult', [false]);
});
webview.src = url;
document.body.appendChild(webview);
}
// This test verifies that the addContentScripts API works with the new window
// API.
function testAddContentScriptsWithNewWindowAPI(url) {
var webview = document.createElement('webview');
var newwebview;
webview.addEventListener('newwindow', function(e) {
e.preventDefault();
newwebview = document.createElement('webview');
console.log('Step 2: call newwebview.addContentScripts.');
newwebview.addContentScripts(
[{name: 'myrule',
matches: ['http://*/guest_from_opener*'],
js: {
files: ['test/inject_comm_channel.js']
},
run_at: 'document_start'}]);
newwebview.addEventListener('loadstop', function(evt) {
var msg = [REQUEST_TO_COMM_CHANNEL_1];
console.log('Step 4: new webview postmessage to build communication ' +
'channel.');
newwebview.contentWindow.postMessage(JSON.stringify(msg), '*');
});
document.body.appendChild(newwebview);
// attach the new window to the new <webview>.
console.log('Step 3: attaches the new webview.');
e.window.attach(newwebview);
});
window.addEventListener('message', function(e) {
if (!newwebview || e.source != newwebview.contentWindow)
return;
var data = JSON.parse(e.data);
if (data == RESPONSE_FROM_COMM_CHANNEL_1 &&
e.source == newwebview.contentWindow) {
console.log('Step 5: a communication channel has been established ' +
'with the new webview.');
chrome.send('testResult', [true]);
return;
} else {
chrome.send('testResult', [false]);
return;
}
console.log('Unexpected message: \'' + data[0] + '\'');
chrome.send('testResult', [false]);
});
console.log('Step 1: navigates the webview to window open guest URL.');
webview.setAttribute('src', url);
document.body.appendChild(webview);
}
// Adds a content script to <webview>. This test verifies that the script is
// injected after terminate and reload <webview>.
function testContentScriptIsInjectedAfterTerminateAndReloadWebView(url) {
var webview = document.createElement('webview');
console.log('Step 1: call <webview>.addContentScripts.');
webview.addContentScripts(
[{name: 'myrule',
matches: ['http://*/empty*'],
js: {
files: ['test/webview_execute_script.js']
},
run_at: 'document_end'}]);
var count = 0;
webview.addEventListener('loadstop', function() {
if (count == 0) {
console.log('Step 2: call webview.terminate().');
webview.terminate();
++count;
return;
} else if (count == 1) {
console.log('Step 4: call <webview>.executeScript to check result.');
webview.executeScript({
code: 'document.body.style.backgroundColor;'
}, onGetBackgroundExecuted);
}
});
webview.addEventListener('exit', function() {
console.log('Step 3: call webview.reload().');
webview.reload();
});
webview.src = url;
document.body.appendChild(webview);
}
// This test verifies the content script won't be removed when the guest is
// destroyed, i.e., removed <webview> from the DOM.
function testContentScriptExistsAsLongAsWebViewTagExists(url) {
var webview = document.createElement('webview');
console.log('Step 1: call <webview>.addContentScripts.');
webview.addContentScripts(
[{name: 'myrule',
matches: ['http://*/empty*'],
js: {
files: ['test/webview_execute_script.js']
},
run_at: 'document_end'}]);
var count = 0;
webview.addEventListener('loadstop', function() {
if (count == 0) {
console.log('Step 2: check the result of content script injected.');
webview.executeScript({
code: 'document.body.style.backgroundColor;'
}, function(results) {
assertEquals(1, results.length);
assertEquals('red', results[0]);
console.log('Step 3: remove webview from the DOM.');
document.body.removeChild(webview);
console.log('Step 4: add webview back to the DOM.');
document.body.appendChild(webview);
++count;
});
} else if (count == 1) {
console.log('Step 5: check the result of content script injected again.');
webview.executeScript({
code: 'document.body.style.backgroundColor;'
}, onGetBackgroundExecuted);
}
});
webview.src = url;
document.body.appendChild(webview);
}
function testAddContentScriptWithCode(url) {
var webview = document.createElement('webview');
console.log('Step 1: call <webview>.addContentScripts.');
webview.addContentScripts(
[{name: 'myrule',
matches: ['http://*/empty*'],
js: {
code: 'document.body.style.backgroundColor = \'red\';'
},
run_at: 'document_end'}]);
webview.addEventListener('loadstop', function() {
console.log('Step 2: call webview.executeScript() to check result.')
webview.executeScript({
code: 'document.body.style.backgroundColor;'
}, onGetBackgroundExecuted);
});
webview.src = url;
document.body.appendChild(webview);
}
function testDragAndDropToInput() {
var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = "html, body { height: 400px }";
document.body.appendChild(css);
var contents = document.getElementById("contents");
while (contents.childElementCount) {
contents.removeChild(contents.firstChild);
}
var webview = document.createElement('webview');
webview.id = 'webview';
webview.style = "width:640px; height:480px";
window.addEventListener('message', function (e) {
var data = JSON.parse(e.data)[0];
console.log("get message: " + data);
if (data === "connected") {
chrome.send('testResult', [true]);
return;
}
chrome.send(data);
});
webview.addEventListener('loadstop', function (e) {
if (webview.src != 'about:blank')
return;
console.log("load stop of src = :" + webview.src);
webview.executeScript({ file: 'test/draganddroptoinput.js' },
function (results) {
console.log("finish guest load");
webview.contentWindow.postMessage(
JSON.stringify(['create-channel']), '*');
});
});
// For debug messages from guests.
webview.addEventListener('consolemessage', function (e) {
console.log('[Guest]: ' + e.message);
});
webview.src = 'about:blank';
contents.appendChild(webview);
}