зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1050773 - Timeline actor pulls profiletimeline markers from all docShells; r=paul
This commit is contained in:
Родитель
67eed48f5b
Коммит
331201c0d8
|
@ -7,8 +7,7 @@
|
|||
/**
|
||||
* Many Gecko operations (painting, reflows, restyle, ...) can be tracked
|
||||
* in real time. A marker is a representation of one operation. A marker
|
||||
* has a name, and start and end timestamps. Markers are stored within
|
||||
* a docshell.
|
||||
* has a name, and start and end timestamps. Markers are stored in docShells.
|
||||
*
|
||||
* This actor exposes this tracking mechanism to the devtools protocol.
|
||||
*
|
||||
|
@ -28,21 +27,24 @@ const {method, Arg, RetVal} = protocol;
|
|||
const events = require("sdk/event/core");
|
||||
const {setTimeout, clearTimeout} = require("sdk/timers");
|
||||
|
||||
// How often do we pull markers from the docShells, and therefore, how often do
|
||||
// we send events to the front (knowing that when there are no markers in the
|
||||
// docShell, no event is sent).
|
||||
const DEFAULT_TIMELINE_DATA_PULL_TIMEOUT = 200; // ms
|
||||
|
||||
/**
|
||||
* The timeline actor pops and forwards timeline markers registered in
|
||||
* a docshell.
|
||||
* The timeline actor pops and forwards timeline markers registered in docshells.
|
||||
*/
|
||||
let TimelineActor = exports.TimelineActor = protocol.ActorClass({
|
||||
typeName: "timeline",
|
||||
|
||||
events: {
|
||||
/**
|
||||
* "markers" events are emitted at regular intervals when profile markers
|
||||
* are found. A marker has the following properties:
|
||||
* - start {Number}
|
||||
* - end {Number}
|
||||
* "markers" events are emitted every DEFAULT_TIMELINE_DATA_PULL_TIMEOUT ms
|
||||
* at most, when profile markers are found. A marker has the following
|
||||
* properties:
|
||||
* - start {Number} ms
|
||||
* - end {Number} ms
|
||||
* - name {String}
|
||||
*/
|
||||
"markers" : {
|
||||
|
@ -53,7 +55,13 @@ let TimelineActor = exports.TimelineActor = protocol.ActorClass({
|
|||
|
||||
initialize: function(conn, tabActor) {
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
this.docshell = tabActor.docShell;
|
||||
this.tabActor = tabActor;
|
||||
|
||||
this._isRecording = false;
|
||||
|
||||
// Make sure to get markers from new windows as they become available
|
||||
this._onWindowReady = this._onWindowReady.bind(this);
|
||||
events.on(this.tabActor, "window-ready", this._onWindowReady);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -67,29 +75,57 @@ let TimelineActor = exports.TimelineActor = protocol.ActorClass({
|
|||
|
||||
destroy: function() {
|
||||
this.stop();
|
||||
this.docshell = null;
|
||||
|
||||
events.off(this.tabActor, "window-ready", this._onWindowReady);
|
||||
this.tabActor = null;
|
||||
|
||||
protocol.Actor.prototype.destroy.call(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert a window to a docShell.
|
||||
* @param {nsIDOMWindow}
|
||||
* @return {nsIDocShell}
|
||||
*/
|
||||
toDocShell: win => win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell),
|
||||
|
||||
/**
|
||||
* Get the list of docShells in the currently attached tabActor.
|
||||
* @return {Array}
|
||||
*/
|
||||
get docShells() {
|
||||
return this.tabActor.windows.map(this.toDocShell);
|
||||
},
|
||||
|
||||
/**
|
||||
* At regular intervals, pop the markers from the docshell, and forward
|
||||
* markers if any.
|
||||
*/
|
||||
_pullTimelineData: function() {
|
||||
let markers = this.docshell.popProfileTimelineMarkers();
|
||||
if (!this._isRecording) {
|
||||
return;
|
||||
}
|
||||
|
||||
let markers = [];
|
||||
for (let docShell of this.docShells) {
|
||||
markers = [...markers, ...docShell.popProfileTimelineMarkers()];
|
||||
}
|
||||
if (markers.length > 0) {
|
||||
events.emit(this, "markers", markers);
|
||||
}
|
||||
|
||||
this._dataPullTimeout = setTimeout(() => {
|
||||
this._pullTimelineData();
|
||||
}, DEFAULT_TIMELINE_DATA_PULL_TIMEOUT);
|
||||
},
|
||||
|
||||
/**
|
||||
* Are we recording profile markers for the current docshell (window)?
|
||||
* Are we recording profile markers currently?
|
||||
*/
|
||||
isRecording: method(function() {
|
||||
return this.docshell.recordProfileTimelineMarkers;
|
||||
return this._isRecording;
|
||||
}, {
|
||||
request: {},
|
||||
response: {
|
||||
|
@ -98,21 +134,46 @@ let TimelineActor = exports.TimelineActor = protocol.ActorClass({
|
|||
}),
|
||||
|
||||
/**
|
||||
* Start/stop recording profile markers.
|
||||
* Start recording profile markers.
|
||||
*/
|
||||
start: method(function() {
|
||||
if (!this.docshell.recordProfileTimelineMarkers) {
|
||||
this.docshell.recordProfileTimelineMarkers = true;
|
||||
this._pullTimelineData();
|
||||
if (this._isRecording) {
|
||||
return;
|
||||
}
|
||||
this._isRecording = true;
|
||||
|
||||
for (let docShell of this.docShells) {
|
||||
docShell.recordProfileTimelineMarkers = true;
|
||||
}
|
||||
|
||||
this._pullTimelineData();
|
||||
}, {}),
|
||||
|
||||
/**
|
||||
* Stop recording profile markers.
|
||||
*/
|
||||
stop: method(function() {
|
||||
if (this.docshell.recordProfileTimelineMarkers) {
|
||||
this.docshell.recordProfileTimelineMarkers = false;
|
||||
clearTimeout(this._dataPullTimeout);
|
||||
if (!this._isRecording) {
|
||||
return;
|
||||
}
|
||||
this._isRecording = false;
|
||||
|
||||
for (let docShell of this.docShells) {
|
||||
docShell.recordProfileTimelineMarkers = false;
|
||||
}
|
||||
|
||||
clearTimeout(this._dataPullTimeout);
|
||||
}, {}),
|
||||
|
||||
/**
|
||||
* When a new window becomes available in the tabActor, start recording its
|
||||
* markers if we were recording.
|
||||
*/
|
||||
_onWindowReady: function({window}) {
|
||||
if (this._isRecording) {
|
||||
this.toDocShell(window).recordProfileTimelineMarkers = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
exports.TimelineFront = protocol.FrontClass(TimelineActor, {
|
||||
|
|
|
@ -3,17 +3,21 @@ skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
|
|||
subsuite = devtools
|
||||
support-files =
|
||||
head.js
|
||||
navigate-first.html
|
||||
navigate-second.html
|
||||
storage-dynamic-windows.html
|
||||
storage-listings.html
|
||||
storage-unsecured-iframe.html
|
||||
storage-updates.html
|
||||
storage-secured-iframe.html
|
||||
navigate-first.html
|
||||
navigate-second.html
|
||||
timeline-iframe-child.html
|
||||
timeline-iframe-parent.html
|
||||
|
||||
[browser_navigateEvents.js]
|
||||
[browser_storage_dynamic_windows.js]
|
||||
[browser_storage_listings.js]
|
||||
[browser_storage_updates.js]
|
||||
[browser_navigateEvents.js]
|
||||
[browser_timeline.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[browser_timeline_iframes.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let Cu = Components.utils;
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
"use strict";
|
||||
|
||||
const URL1 = MAIN_DOMAIN + "navigate-first.html";
|
||||
const URL2 = MAIN_DOMAIN + "navigate-second.html";
|
||||
|
||||
let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
|
||||
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||
|
||||
let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
let events = devtools.require("sdk/event/core");
|
||||
|
||||
let events = require("sdk/event/core");
|
||||
let client;
|
||||
|
||||
// State machine to check events order
|
||||
|
@ -97,24 +93,18 @@ function onLoad() {
|
|||
|
||||
function getServerTabActor(callback) {
|
||||
// Ensure having a minimal server
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init(function () { return true; });
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
initDebuggerServer();
|
||||
|
||||
// Connect to this tab
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
client = new DebuggerClient(transport);
|
||||
client.connect(function onConnect() {
|
||||
client.listTabs(function onListTabs(aResponse) {
|
||||
// Fetch the BrowserTabActor for this tab
|
||||
let actorID = aResponse.tabs[aResponse.selected].actor;
|
||||
client.attachTab(actorID, function(aResponse, aTabClient) {
|
||||
// !Hack! Retrieve a server side object, the BrowserTabActor instance
|
||||
let conn = transport._serverConnection;
|
||||
let tabActor = conn.getActor(actorID);
|
||||
callback(tabActor);
|
||||
});
|
||||
connectDebuggerClient(client).then(form => {
|
||||
let actorID = form.actor;
|
||||
client.attachTab(actorID, function(aResponse, aTabClient) {
|
||||
// !Hack! Retrieve a server side object, the BrowserTabActor instance
|
||||
let conn = transport._serverConnection;
|
||||
let tabActor = conn.getActor(actorID);
|
||||
callback(tabActor);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/Promise.jsm", tempScope);
|
||||
let {DebuggerServer, DebuggerClient, Promise} = tempScope;
|
||||
tempScope = null;
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {StorageFront} = require("devtools/server/actors/storage");
|
||||
let gFront, gWindow;
|
||||
|
@ -60,7 +57,7 @@ function finishTests(client) {
|
|||
forceCollections();
|
||||
DebuggerServer.destroy();
|
||||
forceCollections();
|
||||
gFront = gWindow = DebuggerClient = DebuggerServer = null;
|
||||
gFront = gWindow = null;
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -306,23 +303,13 @@ function testRemoveIframe() {
|
|||
|
||||
function test() {
|
||||
addTab(MAIN_DOMAIN + "storage-dynamic-windows.html").then(function(doc) {
|
||||
try {
|
||||
// Sometimes debugger server does not get destroyed correctly by previous
|
||||
// tests.
|
||||
DebuggerServer.destroy();
|
||||
} catch (ex) { }
|
||||
DebuggerServer.init(function () { return true; });
|
||||
DebuggerServer.addBrowserActors();
|
||||
initDebuggerServer();
|
||||
|
||||
let createConnection = () => {
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
client.connect(function onConnect() {
|
||||
client.listTabs(function onListTabs(aResponse) {
|
||||
let form = aResponse.tabs[aResponse.selected];
|
||||
gFront = StorageFront(client, form);
|
||||
|
||||
gFront.listStores().then(data => testStores(data, client));
|
||||
});
|
||||
connectDebuggerClient(client).then(form => {
|
||||
gFront = StorageFront(client, form);
|
||||
gFront.listStores().then(data => testStores(data, client));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
|
||||
let {DebuggerServer, DebuggerClient} = tempScope;
|
||||
tempScope = null;
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {StorageFront} = require("devtools/server/actors/storage");
|
||||
let {Task} = require("resource://gre/modules/Task.jsm");
|
||||
let gWindow = null;
|
||||
|
||||
const storeMap = {
|
||||
|
@ -348,7 +345,7 @@ function finishTests(client) {
|
|||
forceCollections();
|
||||
DebuggerServer.destroy();
|
||||
forceCollections();
|
||||
gWindow = DebuggerClient = DebuggerServer = null;
|
||||
gWindow = null;
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -640,24 +637,14 @@ let testIDBEntries = Task.async(function*(index, hosts, indexedDBActor) {
|
|||
|
||||
function test() {
|
||||
addTab(MAIN_DOMAIN + "storage-listings.html").then(function(doc) {
|
||||
try {
|
||||
// Sometimes debugger server does not get destroyed correctly by previous
|
||||
// tests.
|
||||
DebuggerServer.destroy();
|
||||
} catch (ex) { }
|
||||
DebuggerServer.init(function () { return true; });
|
||||
DebuggerServer.addBrowserActors();
|
||||
initDebuggerServer();
|
||||
|
||||
let createConnection = () => {
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
client.connect(function onConnect() {
|
||||
client.listTabs(function onListTabs(aResponse) {
|
||||
let form = aResponse.tabs[aResponse.selected];
|
||||
let front = StorageFront(client, form);
|
||||
|
||||
front.listStores().then(data => testStores(data))
|
||||
.then(() => finishTests(client));
|
||||
});
|
||||
connectDebuggerClient(client).then(form => {
|
||||
let front = StorageFront(client, form);
|
||||
front.listStores().then(data => testStores(data))
|
||||
.then(() => finishTests(client));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/Promise.jsm", tempScope);
|
||||
let {DebuggerServer, DebuggerClient, Promise} = tempScope;
|
||||
tempScope = null;
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {StorageFront} = require("devtools/server/actors/storage");
|
||||
let gTests;
|
||||
|
@ -25,7 +22,7 @@ function finishTests(client) {
|
|||
forceCollections();
|
||||
DebuggerServer.destroy();
|
||||
forceCollections();
|
||||
DebuggerClient = DebuggerServer = gTests = null;
|
||||
gTests = null;
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -232,24 +229,15 @@ function* UpdateTests(front, win, client) {
|
|||
|
||||
function test() {
|
||||
addTab(MAIN_DOMAIN + "storage-updates.html").then(function(doc) {
|
||||
try {
|
||||
// Sometimes debugger server does not get destroyed correctly by previous
|
||||
// tests.
|
||||
DebuggerServer.destroy();
|
||||
} catch (ex) { }
|
||||
DebuggerServer.init(function () { return true; });
|
||||
DebuggerServer.addBrowserActors();
|
||||
initDebuggerServer();
|
||||
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
client.connect(function onConnect() {
|
||||
client.listTabs(function onListTabs(aResponse) {
|
||||
let form = aResponse.tabs[aResponse.selected];
|
||||
let front = StorageFront(client, form);
|
||||
gTests = UpdateTests(front, doc.defaultView.wrappedJSObject,
|
||||
client);
|
||||
// Make an initial call to initialize the actor
|
||||
front.listStores().then(() => gTests.next());
|
||||
});
|
||||
connectDebuggerClient(client).then(form => {
|
||||
let front = StorageFront(client, form);
|
||||
gTests = UpdateTests(front, doc.defaultView.wrappedJSObject,
|
||||
client);
|
||||
// Make an initial call to initialize the actor
|
||||
front.listStores().then(() => gTests.next());
|
||||
});
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,29 +1,21 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
const {TimelineFront} = require("devtools/server/actors/timeline");
|
||||
const Cu = Components.utils;
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
|
||||
let {DebuggerServer, DebuggerClient} = tempScope;
|
||||
// Test that the timeline front's start/stop/isRecording methods work in a
|
||||
// simple use case, and that markers events are sent when operations occur.
|
||||
|
||||
const {TimelineFront} = require("devtools/server/actors/timeline");
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
let doc = yield addTab("data:text/html;charset=utf-8,mop");
|
||||
|
||||
DebuggerServer.init(function () { return true; });
|
||||
DebuggerServer.addBrowserActors();
|
||||
initDebuggerServer();
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
let onListTabs = promise.defer();
|
||||
client.connect(() => {
|
||||
client.listTabs(onListTabs.resolve);
|
||||
});
|
||||
|
||||
let listTabs = yield onListTabs.promise;
|
||||
|
||||
let form = listTabs.tabs[listTabs.selected];
|
||||
let form = yield connectDebuggerClient(client);
|
||||
let front = TimelineFront(client, form);
|
||||
|
||||
let isActive = yield front.isRecording();
|
||||
|
@ -59,9 +51,6 @@ let test = asyncTest(function*() {
|
|||
isActive = yield front.isRecording();
|
||||
ok(!isActive, "Not recording after stop()");
|
||||
|
||||
let onClose = promise.defer();
|
||||
client.close(onClose.resolve);
|
||||
yield onClose;
|
||||
|
||||
yield closeDebuggerClient(client);
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test the timeline front receives markers events for operations that occur in
|
||||
// iframes.
|
||||
|
||||
const {TimelineFront} = require("devtools/server/actors/timeline");
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
let doc = yield addTab(MAIN_DOMAIN + "timeline-iframe-parent.html");
|
||||
|
||||
initDebuggerServer();
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
let form = yield connectDebuggerClient(client);
|
||||
let front = TimelineFront(client, form);
|
||||
|
||||
info("Start timeline marker recording");
|
||||
yield front.start();
|
||||
|
||||
// Check that we get markers for a few iterations of the timer that runs in
|
||||
// the child frame.
|
||||
for (let i = 0; i < 3; i ++) {
|
||||
yield wait(300); // That's the time the child frame waits before changing styles.
|
||||
let markers = yield once(front, "markers");
|
||||
ok(markers.length, "Markers were received for operations in the child frame");
|
||||
}
|
||||
|
||||
info("Stop timeline marker recording");
|
||||
yield front.stop();
|
||||
yield closeDebuggerClient(client);
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
function wait(ms) {
|
||||
let def = promise.defer();
|
||||
setTimeout(def.resolve, ms);
|
||||
return def.promise;
|
||||
}
|
|
@ -1,23 +1,28 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/Console.jsm", tempScope);
|
||||
const require = tempScope.devtools.require;
|
||||
const console = tempScope.console;
|
||||
tempScope = null;
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
const {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
|
||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
const {devtools: {require}} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const {DebuggerClient} = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
|
||||
const {DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||
|
||||
const PATH = "browser/toolkit/devtools/server/tests/browser/";
|
||||
const MAIN_DOMAIN = "http://test1.example.org/" + PATH;
|
||||
const ALT_DOMAIN = "http://sectest1.example.org/" + PATH;
|
||||
const ALT_DOMAIN_SECURED = "https://sectest1.example.org:443/" + PATH;
|
||||
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
|
||||
// All test are asynchronous
|
||||
// All tests are asynchronous.
|
||||
waitForExplicitFinish();
|
||||
|
||||
/**
|
||||
* Define an async test based on a generator function
|
||||
* Define an async test based on a generator function.
|
||||
*/
|
||||
function asyncTest(generator) {
|
||||
return () => Task.spawn(generator).then(null, ok.bind(null, false)).then(finish);
|
||||
|
@ -47,6 +52,43 @@ let addTab = Task.async(function* (url) {
|
|||
return tab.linkedBrowser.contentWindow.document;
|
||||
});
|
||||
|
||||
function initDebuggerServer() {
|
||||
try {
|
||||
// Sometimes debugger server does not get destroyed correctly by previous
|
||||
// tests.
|
||||
DebuggerServer.destroy();
|
||||
} catch (ex) { }
|
||||
DebuggerServer.init(() => true);
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect a debugger client.
|
||||
* @param {DebuggerClient}
|
||||
* @return {Promise} Resolves to the selected tabActor form when the client is
|
||||
* connected.
|
||||
*/
|
||||
function connectDebuggerClient(client) {
|
||||
let def = promise.defer();
|
||||
client.connect(() => {
|
||||
client.listTabs(tabs => {
|
||||
def.resolve(tabs.tabs[tabs.selected]);
|
||||
});
|
||||
});
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a debugger client's connection.
|
||||
* @param {DebuggerClient}
|
||||
* @return {Promise} Resolves when the connection is closed.
|
||||
*/
|
||||
function closeDebuggerClient(client) {
|
||||
let def = promise.defer();
|
||||
client.close(def.resolve);
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for eventName on target.
|
||||
* @param {Object} target An observable object that either supports on/off or
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Timeline iframe test - child frame</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Child frame</h1>
|
||||
<script>
|
||||
var h1 = document.querySelector("h1");
|
||||
setInterval(function() {
|
||||
h1.style.backgroundColor = "rgb(" + ((Math.random()*255)|0) + "," +
|
||||
((Math.random()*255)|0) + "," +
|
||||
((Math.random()*255)|0) +")";
|
||||
h1.style.width = ((Math.random()*500)|0) + "px";
|
||||
}, 300);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Timeline iframe test - parent frame</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Parent frame</h1>
|
||||
<iframe src="timeline-iframe-child.html"></iframe>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче