123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- // Copyright 2012 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- goog.provide('goog.net.xpc.IframePollingTransportTest');
- goog.setTestOnly('goog.net.xpc.IframePollingTransportTest');
- goog.require('goog.Timer');
- goog.require('goog.dom');
- goog.require('goog.dom.TagName');
- goog.require('goog.functions');
- goog.require('goog.net.xpc.CfgFields');
- goog.require('goog.net.xpc.CrossPageChannel');
- goog.require('goog.net.xpc.CrossPageChannelRole');
- goog.require('goog.net.xpc.TransportTypes');
- goog.require('goog.object');
- goog.require('goog.testing.MockClock');
- goog.require('goog.testing.jsunit');
- goog.require('goog.testing.recordFunction');
- /** @type {?goog.testing.MockClock} */
- var mockClock = null;
- /** @type {?goog.net.xpc.CrossPageChannel} */
- var outerChannel = null;
- /** @type {?goog.net.xpc.CrossPageChannel} */
- var innerChannel = null;
- function setUp() {
- mockClock = new goog.testing.MockClock(true /* opt_autoInstall */);
- // Create the peer windows.
- var outerPeerHostName = 'https://www.youtube.com';
- var outerPeerWindow = createMockPeerWindow(outerPeerHostName);
- var innerPeerHostName = 'https://www.google.com';
- var innerPeerWindow = createMockPeerWindow(innerPeerHostName);
- // Create the channels.
- outerChannel = createChannel(
- goog.net.xpc.CrossPageChannelRole.OUTER, 'test', outerPeerHostName,
- outerPeerWindow, innerPeerHostName, innerPeerWindow);
- innerChannel = createChannel(
- goog.net.xpc.CrossPageChannelRole.INNER, 'test', innerPeerHostName,
- innerPeerWindow, outerPeerHostName, outerPeerWindow);
- }
- function tearDown() {
- outerChannel.dispose();
- innerChannel.dispose();
- mockClock.uninstall();
- }
- /** Tests that connection happens normally and callbacks are invoked. */
- function testConnect() {
- var outerConnectCallback = goog.testing.recordFunction();
- var innerConnectCallback = goog.testing.recordFunction();
- // Connect the two channels.
- outerChannel.connect(outerConnectCallback);
- innerChannel.connect(innerConnectCallback);
- mockClock.tick(1000);
- // Check that channels were connected and callbacks invoked.
- assertEquals(1, outerConnectCallback.getCallCount());
- assertEquals(1, innerConnectCallback.getCallCount());
- assertTrue(outerChannel.isConnected());
- assertTrue(innerChannel.isConnected());
- }
- /** Tests that messages are successfully delivered to the inner peer. */
- function testSend_outerToInner() {
- var serviceCallback = goog.testing.recordFunction();
- // Register a service handler in the inner channel.
- innerChannel.registerService('svc', function(payload) {
- assertEquals('hello', payload);
- serviceCallback();
- });
- // Connect the two channels.
- outerChannel.connect();
- innerChannel.connect();
- mockClock.tick(1000);
- // Send a message.
- outerChannel.send('svc', 'hello');
- mockClock.tick(1000);
- // Check that the message was handled.
- assertEquals(1, serviceCallback.getCallCount());
- }
- /** Tests that messages are successfully delivered to the outer peer. */
- function testSend_innerToOuter() {
- var serviceCallback = goog.testing.recordFunction();
- // Register a service handler in the inner channel.
- outerChannel.registerService('svc', function(payload) {
- assertEquals('hello', payload);
- serviceCallback();
- });
- // Connect the two channels.
- outerChannel.connect();
- innerChannel.connect();
- mockClock.tick(1000);
- // Send a message.
- innerChannel.send('svc', 'hello');
- mockClock.tick(1000);
- // Check that the message was handled.
- assertEquals(1, serviceCallback.getCallCount());
- }
- /** Tests that closing the outer peer does not cause an error. */
- function testSend_outerPeerClosed() {
- // Connect the inner channel.
- innerChannel.connect();
- mockClock.tick(1000);
- // Close the outer peer before it has a chance to connect.
- closeWindow(innerChannel.getPeerWindowObject());
- // Allow timers to execute (and fail).
- mockClock.tick(1000);
- }
- /** Tests that closing the inner peer does not cause an error. */
- function testSend_innerPeerClosed() {
- // Connect the outer channel.
- outerChannel.connect();
- mockClock.tick(1000);
- // Close the inner peer before it has a chance to connect.
- closeWindow(outerChannel.getPeerWindowObject());
- // Allow timers to execute (and fail).
- mockClock.tick(1000);
- }
- /** Tests that partially closing the outer peer does not cause an error. */
- function testSend_outerPeerClosing() {
- // Connect the inner channel.
- innerChannel.connect();
- mockClock.tick(1000);
- // Close the outer peer before it has a chance to connect, but
- // leave closed set to false to simulate a partially closed window.
- closeWindow(innerChannel.getPeerWindowObject());
- innerChannel.getPeerWindowObject().closed = false;
- // Allow timers to execute (and fail).
- mockClock.tick(1000);
- }
- /** Tests that partially closing the inner peer does not cause an error. */
- function testSend_innerPeerClosing() {
- // Connect the outer channel.
- outerChannel.connect();
- mockClock.tick(1000);
- // Close the inner peer before it has a chance to connect, but
- // leave closed set to false to simulate a partially closed window.
- closeWindow(outerChannel.getPeerWindowObject());
- outerChannel.getPeerWindowObject().closed = false;
- // Allow timers to execute (and fail).
- mockClock.tick(1000);
- }
- /**
- * Creates a channel with the specified configuration, using frame polling.
- * @param {!goog.net.xpc.CrossPageChannelRole} role The channel role.
- * @param {string} channelName The channel name.
- * @param {string} fromHostName The host name of the window hosting the channel.
- * @param {!Object} fromWindow The window hosting the channel.
- * @param {string} toHostName The host name of the peer window.
- * @param {!Object} toWindow The peer window.
- * @return {!goog.net.xpc.CrossPageChannel}
- */
- function createChannel(
- role, channelName, fromHostName, fromWindow, toHostName, toWindow) {
- // Build a channel config using frame polling.
- var channelConfig = goog.object.create(
- goog.net.xpc.CfgFields.ROLE, role, goog.net.xpc.CfgFields.PEER_HOSTNAME,
- toHostName, goog.net.xpc.CfgFields.CHANNEL_NAME, channelName,
- goog.net.xpc.CfgFields.LOCAL_POLL_URI, fromHostName + '/robots.txt',
- goog.net.xpc.CfgFields.PEER_POLL_URI, toHostName + '/robots.txt',
- goog.net.xpc.CfgFields.TRANSPORT,
- goog.net.xpc.TransportTypes.IFRAME_POLLING);
- // Build the channel.
- var channel = new goog.net.xpc.CrossPageChannel(channelConfig);
- channel.setPeerWindowObject(toWindow);
- // Update the transport's getWindow, to return the correct host window.
- channel.createTransport_();
- channel.transport_.getWindow = goog.functions.constant(fromWindow);
- return channel;
- }
- /**
- * Creates a mock window to use as a peer. The peer window will host the frame
- * elements.
- * @param {string} url The peer window's initial URL.
- */
- function createMockPeerWindow(url) {
- var mockPeer = createMockWindow(url);
- // Update the appendChild method to use a mock frame window.
- mockPeer.document.body.appendChild = function(el) {
- assertEquals(String(goog.dom.TagName.IFRAME), el.tagName);
- mockPeer.frames[el.name] = createMockWindow(el.src);
- mockPeer.document.body.element.appendChild(el);
- };
- return mockPeer;
- }
- /**
- * Creates a mock window.
- * @param {string} url The window's initial URL.
- */
- function createMockWindow(url) {
- // Create the mock window, document and body.
- var mockWindow = {};
- var mockDocument = {};
- var mockBody = {};
- var mockLocation = {};
- // Configure the mock window's document body.
- mockBody.element = goog.dom.createDom(goog.dom.TagName.BODY);
- // Configure the mock window's document.
- mockDocument.body = mockBody;
- // Configure the mock window's location.
- mockLocation.href = url;
- mockLocation.replace = function(value) { mockLocation.href = value; };
- // Configure the mock window.
- mockWindow.document = mockDocument;
- mockWindow.frames = {};
- mockWindow.location = mockLocation;
- mockWindow.setTimeout = goog.Timer.callOnce;
- return mockWindow;
- }
- /**
- * Emulates closing the specified window by clearing frames, document and
- * location.
- */
- function closeWindow(targetWindow) {
- // Close any child frame windows.
- for (var frameName in targetWindow.frames) {
- closeWindow(targetWindow.frames[frameName]);
- }
- // Clear the target window, set closed to true.
- targetWindow.closed = true;
- targetWindow.frames = null;
- targetWindow.document = null;
- targetWindow.location = null;
- }
|