Merge fx-team to m-c. a=merge

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2015-02-12 18:02:35 -05:00
commit 52da79328b
171 changed files with 6593 additions and 1382 deletions

View File

@ -238,8 +238,6 @@ DEFAULT_TEST_PREFS = {
'media.eme.apiVisible': True,
# Don't forceably kill content processes after a timeout
'dom.ipc.tabs.shutdownTimeoutSecs': 0,
# Don't show the search first run UI by default
'browser.search.highlightCount': 0,
'general.useragent.locale': "en-US",
'intl.locale.matchOS': "en-US",
'dom.indexedDB.experimental': True

View File

@ -45,7 +45,6 @@
"media.eme.enabled": true,
"media.eme.apiVisible": true,
"dom.ipc.tabs.shutdownTimeoutSecs": 0,
"browser.search.highlightCount": 0,
"general.useragent.locale": "en-US",
"intl.locale.matchOS": "en-US",
"dom.indexedDB.experimental": true

View File

@ -408,9 +408,6 @@ pref("browser.search.showOneOffButtons", true);
// comma seperated list of of engines to hide in the search panel.
pref("browser.search.hiddenOneOffs", "");
// How many times to show the new search highlight
pref("browser.search.highlightCount", 5);
pref("browser.sessionhistory.max_entries", 50);
// handle links targeting new windows
@ -1670,7 +1667,6 @@ pref("shumway.swf.whitelist", "http://g-ecx.images-amazon.com/*/AiryBasicRendere
pref("image.mem.max_decoded_image_kb", 256000);
pref("loop.enabled", true);
pref("loop.screenshare.enabled", false);
pref("loop.server", "https://loop.services.mozilla.com/v0");
pref("loop.seenToS", "unseen");
pref("loop.showPartnerLogo", true);

View File

@ -19,8 +19,6 @@
#endif
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
%aboutHomeDTD;
<!ENTITY % searchBarDTD SYSTEM "chrome://browser/locale/searchbar.dtd">
%searchBarDTD;
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
%syncBrandDTD;
]>

View File

@ -1427,7 +1427,6 @@ var gBrowserInit = {
SocialUI.init();
TabView.init();
SearchHighlight.init();
// Telemetry for master-password - we do this after 5 seconds as it
// can cause IO if NSS/PSM has not already initialized.
@ -3636,138 +3635,6 @@ const BrowserSearch = {
}
};
const SearchHighlight = {
eventsReady: false,
// The pref that controls how many times to show the highlight.
countPref: "browser.search.highlightCount",
// The current highlight to show.
currentPos: 0,
// Tracks if the popup closed very recently.
hideTimer: null,
// The list of highlights and the items in the panel to anchor them to.
highlights: [{
id: "SearchHighlight1",
anchor: "search-panel-one-offs"
}, {
id: "SearchHighlight2",
anchor: "searchbar-engine",
}],
init: function() {
this.panel = document.getElementById("PopupSearchAutoComplete");
this.panel.addEventListener("popupshowing", this.searchPanelShown.bind(this), false);
},
initEvents: function() {
if (this.eventsReady) {
return;
}
this.panel.addEventListener("popuphidden", this.searchPanelHidden.bind(this), false);
for (let highlight of this.highlights) {
highlight.panel = document.getElementById(highlight.id);
highlight.panel.addEventListener("popupshowing", this.disablePanelHiding.bind(this), false);
highlight.panel.addEventListener("popuphiding", this.enablePanelHiding.bind(this), false);
highlight.panel.querySelector("button").addEventListener("command", this.highlightButtonClicked.bind(this), false);
}
this.eventsReady = true;
},
get highlightPanel() {
return this.highlights[this.currentPos].panel;
},
showHighlight: function() {
// Check that all the events are setup.
this.initEvents();
// If a highlight is already showing then do nothing.
if (this.highlightPanel.state != "closed") {
return;
}
// Show the first highlight.
this.currentPos = 0;
this.showCurrentHighlight();
},
showCurrentHighlight: function() {
let highlight = this.highlights[this.currentPos];
let anchor = document.getAnonymousElementByAttribute(this.panel, "anonid", highlight.anchor);
highlight.panel.hidden = false;
highlight.panel.openPopup(anchor, "leftcenter topright");
},
searchPanelShown: function() {
let placement = CustomizableUI.getPlacementOfWidget("search-container");
if (placement.area == CustomizableUI.AREA_PANEL) {
// Opening a panel anchored to a panel anchored to a panel anchored to the
// window doesn't work very well
return;
}
if (!BrowserSearch.searchBar.value) {
// Don't show the panels when there is no text in the search box
return;
}
// If the panel was only very recently closed re-show the last highlight.
if (this.hideTimer) {
clearTimeout(this.hideTimer);
this.hideTimer = null;
this.showCurrentHighlight();
return;
}
// If the highlight has already been show the appropriate number of times
// do nothing.
let count = Services.prefs.getIntPref(this.countPref);
if (count <= 0)
return;
this.showHighlight();
Services.prefs.setIntPref(this.countPref, count - 1);
},
searchPanelHidden: function() {
if (this.highlightPanel.state == "closed") {
return;
}
this.highlightPanel.hidePopup();
// Set a flag when the panel was closed in the last short time.
this.hideTimer = setTimeout(() => {
this.hideTimer = null;
}, 500);
},
highlightButtonClicked: function() {
// When the button is clicked close the current highlight and open the next
// one.
this.highlightPanel.hidePopup();
this.currentPos++;
if (this.currentPos < this.highlights.length) {
this.showCurrentHighlight();
} else {
Services.prefs.setIntPref(this.countPref, 0);
this.currentPos = 0;
}
},
disablePanelHiding: function() {
this.panel.setAttribute("noautohide", "true");
},
enablePanelHiding: function() {
this.panel.setAttribute("noautohide", "false");
},
};
function FillHistoryMenu(aParent) {
// Lazily add the hover listeners on first showing and never remove them
if (!aParent.hasStatusListener) {

View File

@ -245,41 +245,6 @@
mousethrough="always">
<box id="UITourHighlight"></box>
</panel>
<!-- Used to highlight the new search experience -->
<panel id="SearchHighlight1"
class="SearchHighlight"
type="arrow"
hidden="true"
noautofocus="true"
noautohide="true"
orient="vertical"
align="stretch">
<label class="SearchHighlightTitle">&SearchHighlight1.title;</label>
<description class="SearchHighlightText" flex="1">&SearchHighlight1.text;</description>
<hbox class="SearchHighlightFooter" align="center">
<spacer class="dot filled"/>
<spacer class="dot"/>
<spacer flex="1"/>
<button label="&SearchHighlightNext;"/>
</hbox>
</panel>
<panel id="SearchHighlight2"
class="SearchHighlight"
type="arrow"
hidden="true"
noautofocus="true"
noautohide="true"
orient="vertical"
align="stretch">
<label class="SearchHighlightTitle">&SearchHighlight2.title;</label>
<description class="SearchHighlightText" flex="1">&SearchHighlight2.text;</description>
<hbox class="SearchHighlightFooter" align="center">
<spacer class="dot"/>
<spacer class="dot filled"/>
<spacer flex="1"/>
<button label="&SearchHighlightClose;"/>
</hbox>
</panel>
<panel id="abouthome-search-panel" orient="vertical" type="arrow" hidden="true"
onclick="this.hidePopup()">

View File

@ -26,7 +26,7 @@
dlgbuttons="accept,cancel"
title="&sanitizeDialog2.title;"
noneverythingtitle="&sanitizeDialog2.title;"
style="width: &dialog.width2;;"
style="width: &sanitizeDialog2.width;;"
ondialogaccept="return gSanitizePromptDialog.sanitize();">
<prefpane id="SanitizeDialogPane" onpaneload="gSanitizePromptDialog.init();">

View File

@ -12,8 +12,14 @@
<xul:image class="chat-status-icon" xbl:inherits="src=image"/>
<xul:label class="chat-title" flex="1" xbl:inherits="value=label" crop="center"/>
</xul:hbox>
<xul:toolbarbutton anonid="webRTC-shareScreen-icon"
class="notification-anchor-icon chat-toolbarbutton"
oncommand="document.getBindingParent(this).showNotifications(this); event.stopPropagation();"/>
<xul:toolbarbutton anonid="webRTC-sharingScreen-icon"
class="notification-anchor-icon chat-toolbarbutton"
oncommand="document.getBindingParent(this).showNotifications(this); event.stopPropagation();"/>
<xul:toolbarbutton anonid="notification-icon" class="notification-anchor-icon chat-toolbarbutton"
oncommand="document.getBindingParent(this).showNotifications(); event.stopPropagation();"/>
oncommand="document.getBindingParent(this).showNotifications(this); event.stopPropagation();"/>
<xul:toolbarbutton anonid="minimize" class="chat-minimize-button chat-toolbarbutton"
oncommand="document.getBindingParent(this).toggle();"/>
<xul:toolbarbutton anonid="swap" class="chat-swap-button chat-toolbarbutton"
@ -30,8 +36,20 @@
<implementation implements="nsIDOMEventListener">
<constructor><![CDATA[
this.content.__defineGetter__("popupnotificationanchor",
() => document.getAnonymousElementByAttribute(this, "anonid", "notification-icon"));
const kAnchorMap = new Map([
["", "notification-"],
["webRTC-shareScreen-", ""],
["webRTC-sharingScreen-", ""]
]);
for (let [getterPrefix, idPrefix] of kAnchorMap) {
let getter = getterPrefix + "popupnotificationanchor";
let anonid = (idPrefix || getterPrefix) + "icon";
this.content.__defineGetter__(getter, () => {
delete this.content[getter];
return this.content[getter] = document.getAnonymousElementByAttribute(
this, "anonid", anonid);
});
}
if (!this.chatbar) {
document.getAnonymousElementByAttribute(this, "anonid", "minimize").hidden = true;
@ -136,8 +154,9 @@
</property>
<method name="showNotifications">
<parameter name="aAnchor"/>
<body><![CDATA[
PopupNotifications._reshowNotifications(this.content.popupnotificationanchor,
PopupNotifications._reshowNotifications(aAnchor,
this.content);
]]></body>
</method>

View File

@ -391,8 +391,6 @@ skip-if = buildapp == 'mulet' || e10s # e10s: Bug 933103 - mochitest's EventUtil
skip-if = buildapp == 'mulet' || e10s # Bug 1100698 - test uses synthesizeMouse and then does a load of other stuff that breaks in e10s
[browser_save_video_frame.js]
[browser_scope.js]
[browser_searchHighlight.js]
skip-if = true
[browser_searchSuggestionUI.js]
skip-if = e10s
support-files =

View File

@ -1,260 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
const PREF = "browser.search.highlightCount";
const searchBar = BrowserSearch.searchBar;
const popup = document.getElementById("PopupSearchAutoComplete");
const panel1 = document.getElementById("SearchHighlight1");
const panel2 = document.getElementById("SearchHighlight2");
let current = Services.prefs.getIntPref(PREF);
registerCleanupFunction(() => {
Services.prefs.setIntPref(PREF, current);
});
// The highlight panel should be displayed a set number of times
add_task(function* firstrun() {
yield promiseNewEngine(TEST_ENGINE_BASENAME);
ok(searchBar, "got search bar");
if (!searchBar.getAttribute("oneoffui"))
return; // This tests the one-off UI
searchBar.value = "foo";
searchBar.focus();
Services.prefs.setIntPref(PREF, 2);
let promise = promiseWaitForEvent(panel1, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise
ok(true, "Saw panel 1 show");
is(Services.prefs.getIntPref(PREF), 1, "Should have counted this show");
promise = promiseWaitForEvent(panel1, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw panel 1 hide");
clearTimer();
promise = promiseWaitForEvent(panel1, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise
ok(true, "Saw panel 1 show");
is(Services.prefs.getIntPref(PREF), 0, "Should have counted this show");
promise = promiseWaitForEvent(panel1, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw panel 1 hide");
clearTimer();
function listener() {
ok(false, "Should not have seen the pane show");
}
panel1.addEventListener("popupshowing", listener, false);
promise = promiseWaitForEvent(popup, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise;
ok(true, "Saw popup show");
promise = promiseWaitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw popup hide");
panel1.removeEventListener("popupshowing", listener, false);
clearTimer();
});
// Completing the tour should stop the popup from showing again
add_task(function* dismiss() {
ok(searchBar, "got search bar");
if (!searchBar.getAttribute("oneoffui"))
return; // This tests the one-off UI
searchBar.value = "foo";
searchBar.focus();
Services.prefs.setIntPref(PREF, 200);
let promise = promiseWaitForEvent(panel1, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise
ok(true, "Saw panel 1 show");
promise = promiseWaitForEvent(panel2, "popupshown");
EventUtils.synthesizeMouseAtCenter(panel1.querySelector("button"), {});
yield promise;
ok(true, "Saw panel 2 show");
promise = promiseWaitForEvent(panel2, "popuphidden");
EventUtils.synthesizeMouseAtCenter(panel2.querySelector("button"), {});
yield promise;
ok(true, "Saw panel 2 hide");
is(Services.prefs.getIntPref(PREF), 0, "Should have cleared the counter");
promise = promiseWaitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw popup hide");
clearTimer();
function listener() {
ok(false, "Should not have seen the pane show");
}
panel1.addEventListener("popupshowing", listener, false);
promise = promiseWaitForEvent(popup, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise;
ok(true, "Saw popup show");
promise = promiseWaitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw popup hide");
panel1.removeEventListener("popupshowing", listener, false);
clearTimer();
});
// The highlight panel should be re-displayed if the search popup closes and
// opens quickly
add_task(function* testRedisplay() {
ok(searchBar, "got search bar");
if (!searchBar.getAttribute("oneoffui"))
return; // This tests the one-off UI
searchBar.value = "foo";
searchBar.focus();
Services.prefs.setIntPref(PREF, 2);
let promise = promiseWaitForEvent(panel1, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise
ok(true, "Saw panel 1 show");
is(Services.prefs.getIntPref(PREF), 1, "Should have counted this show");
promise = promiseWaitForEvent(panel2, "popupshown");
EventUtils.synthesizeMouseAtCenter(panel1.querySelector("button"), {});
yield promise;
ok(true, "Saw panel 2 show");
promise = promiseWaitForEvent(panel2, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw panel 2 hide");
promise = promiseWaitForEvent(panel2, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise;
ok(true, "Saw panel 2 show");
is(Services.prefs.getIntPref(PREF), 1, "Should not have counted this show");
promise = promiseWaitForEvent(panel2, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw panel 2 hide");
clearTimer();
});
// The highlight panel shouldn't be displayed if there is no text in the search
// box
add_task(function* testNoText() {
ok(searchBar, "got search bar");
if (!searchBar.getAttribute("oneoffui"))
return; // This tests the one-off UI
searchBar.value = "";
searchBar.focus();
Services.prefs.setIntPref(PREF, 2);
function listener() {
ok(false, "Should not have seen the pane show");
}
panel1.addEventListener("popupshowing", listener, false);
let button = document.getAnonymousElementByAttribute(searchBar,
"anonid",
"searchbar-search-button");
let promise = promiseWaitForEvent(popup, "popupshown");
EventUtils.synthesizeMouseAtCenter(button, {});
yield promise;
ok(true, "Saw popup show");
promise = promiseWaitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw popup hide");
clearTimer();
promise = promiseWaitForEvent(popup, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise;
ok(true, "Saw popup show");
promise = promiseWaitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw popup hide");
panel1.removeEventListener("popupshowing", listener, false);
clearTimer();
});
function clearTimer() {
// Clear the timeout
clearTimeout(SearchHighlight.hideTimer);
SearchHighlight.hideTimer = null;
}
function promiseWaitForEvent(node, type, capturing) {
return new Promise((resolve) => {
node.addEventListener(type, function listener(event) {
node.removeEventListener(type, listener, capturing);
resolve(event);
}, capturing);
});
}
function promiseNewEngine(basename) {
return new Promise((resolve, reject) => {
info("Waiting for engine to be added: " + basename);
Services.search.init({
onInitComplete: function() {
let url = getRootDirectory(gTestPath) + basename;
let current = Services.search.currentEngine;
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
Services.search.currentEngine = engine;
registerCleanupFunction(() => {
Services.search.currentEngine = current;
Services.search.removeEngine(engine);
});
resolve(engine);
},
onError: function (errCode) {
ok(false, "addEngine failed with error code " + errCode);
reject();
},
});
}
});
});
}

View File

@ -42,8 +42,7 @@ loop.conversation = (function(mozL10n) {
conversationStore: React.PropTypes.instanceOf(loop.store.ConversationStore)
.isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
roomStore: React.PropTypes.instanceOf(loop.store.RoomStore),
mozLoop: React.PropTypes.object.isRequired,
roomStore: React.PropTypes.instanceOf(loop.store.RoomStore)
},
getInitialState: function() {
@ -79,7 +78,6 @@ loop.conversation = (function(mozL10n) {
case "room": {
return (React.createElement(DesktopRoomConversationView, {
dispatcher: this.props.dispatcher,
mozLoop: this.props.mozLoop,
roomStore: this.props.roomStore}
));
}
@ -190,8 +188,7 @@ loop.conversation = (function(mozL10n) {
client: client,
conversation: conversation,
dispatcher: dispatcher,
sdk: window.OT,
mozLoop: navigator.mozLoop}
sdk: window.OT}
), document.querySelector('#main'));
dispatcher.dispatch(new sharedActions.GetWindowData({

View File

@ -42,8 +42,7 @@ loop.conversation = (function(mozL10n) {
conversationStore: React.PropTypes.instanceOf(loop.store.ConversationStore)
.isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
roomStore: React.PropTypes.instanceOf(loop.store.RoomStore),
mozLoop: React.PropTypes.object.isRequired,
roomStore: React.PropTypes.instanceOf(loop.store.RoomStore)
},
getInitialState: function() {
@ -79,7 +78,6 @@ loop.conversation = (function(mozL10n) {
case "room": {
return (<DesktopRoomConversationView
dispatcher={this.props.dispatcher}
mozLoop={this.props.mozLoop}
roomStore={this.props.roomStore}
/>);
}
@ -191,7 +189,6 @@ loop.conversation = (function(mozL10n) {
conversation={conversation}
dispatcher={dispatcher}
sdk={window.OT}
mozLoop={navigator.mozLoop}
/>, document.querySelector('#main'));
dispatcher.dispatch(new sharedActions.GetWindowData({

View File

@ -170,8 +170,7 @@ loop.roomViews = (function(mozL10n) {
],
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
mozLoop: React.PropTypes.object.isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
},
_renderInvitationOverlay: function() {
@ -243,7 +242,7 @@ loop.roomViews = (function(mozL10n) {
var screenShareData = {
state: this.state.screenSharingState,
visible: this.props.mozLoop.getLoopPref("screenshare.enabled")
visible: true
};
switch(this.state.roomState) {

View File

@ -170,8 +170,7 @@ loop.roomViews = (function(mozL10n) {
],
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
mozLoop: React.PropTypes.object.isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
},
_renderInvitationOverlay: function() {
@ -243,7 +242,7 @@ loop.roomViews = (function(mozL10n) {
var screenShareData = {
state: this.state.screenSharingState,
visible: this.props.mozLoop.getLoopPref("screenshare.enabled")
visible: true
};
switch(this.state.roomState) {

View File

@ -295,15 +295,37 @@ loop.shared.mixins = (function() {
width: width,
height: node.offsetHeight
};
var ratio = this._videoDimensionsCache.remote[videoType].aspectRatio;
// Leading axis is the side that has the smallest ratio.
var leadingAxis = Math.min(ratio.width, ratio.height) === ratio.width ?
"width" : "height";
var slaveSize = remoteVideoDimensions[leadingAxis] +
(remoteVideoDimensions[leadingAxis] * (1 - ratio[leadingAxis]));
remoteVideoDimensions.streamWidth = leadingAxis === "width" ?
remoteVideoDimensions.width : slaveSize;
remoteVideoDimensions.streamHeight = leadingAxis === "height" ?
remoteVideoDimensions.height: slaveSize;
var slaveAxis = leadingAxis === "height" ? "width" : "height";
// We need to work out if the leading axis of the video is full, by
// calculating the expected length of the leading axis based on the
// length of the slave axis and aspect ratio.
var leadingAxisFull = remoteVideoDimensions[slaveAxis] * ratio[leadingAxis] >
remoteVideoDimensions[leadingAxis];
if (leadingAxisFull) {
// If the leading axis is "full" then we need to adjust the slave axis.
var slaveAxisSize = remoteVideoDimensions[leadingAxis] / ratio[leadingAxis];
remoteVideoDimensions.streamWidth = leadingAxis === "width" ?
remoteVideoDimensions.width : slaveAxisSize;
remoteVideoDimensions.streamHeight = leadingAxis === "height" ?
remoteVideoDimensions.height: slaveAxisSize;
} else {
// If the leading axis is not "full" then we need to adjust it, based
// on the length of the leading axis.
var leadingAxisSize = remoteVideoDimensions[slaveAxis] * ratio[leadingAxis];
remoteVideoDimensions.streamWidth = leadingAxis === "height" ?
remoteVideoDimensions.width : leadingAxisSize;
remoteVideoDimensions.streamHeight = leadingAxis === "width" ?
remoteVideoDimensions.height: leadingAxisSize;
}
}
}, this);

View File

@ -14,7 +14,6 @@ FIREFOX_PREFERENCES = {
"media.volume_scale": "0",
"loop.gettingStarted.seen": True,
"loop.seenToS": "seen",
"loop.screenshare.enabled": True,
# this dialog is fragile, and likely to introduce intermittent failures
"media.navigator.permission.disabled": True

View File

@ -195,6 +195,7 @@ describe("loop.shared.mixins", function() {
describe("loop.shared.mixins.MediaSetupMixin", function() {
var view, TestComp, rootObject;
var localElement, remoteElement, screenShareElement;
beforeEach(function() {
TestComp = React.createClass({
@ -225,6 +226,23 @@ describe("loop.shared.mixins", function() {
sharedMixins.setRootObject(rootObject);
view = TestUtils.renderIntoDocument(React.createElement(TestComp));
sandbox.stub(view, "getDOMNode").returns({
querySelector: function(classSelector) {
if (classSelector.contains("local")) {
return localElement;
} else if (classSelector.contains("screen")) {
return screenShareElement;
}
return remoteElement;
}
});
});
afterEach(function() {
localElement = null;
remoteElement = null;
screenShareElement = null;
});
describe("#getDefaultPublisherConfig", function() {
@ -235,22 +253,124 @@ describe("loop.shared.mixins", function() {
});
});
describe("Events", function() {
var localElement, remoteElement, screenShareElement;
describe("#getRemoteVideoDimensions", function() {
var localVideoDimensions, remoteVideoDimensions;
beforeEach(function() {
sandbox.stub(view, "getDOMNode").returns({
querySelector: function(classSelector) {
if (classSelector.contains("local")) {
return localElement;
} else if (classSelector.contains("screen")) {
return screenShareElement;
}
return remoteElement;
localVideoDimensions = {
camera: {
width: 640,
height: 480
}
});
};
});
it("should fetch the correct stream sizes for leading axis width and full",
function() {
remoteVideoDimensions = {
camera: {
width: 240,
height: 320
}
};
remoteElement = {
offsetWidth: 480,
offsetHeight: 700
};
view.updateVideoDimensions(localVideoDimensions, remoteVideoDimensions);
var result = view.getRemoteVideoDimensions();
expect(result.width).eql(remoteElement.offsetWidth);
expect(result.height).eql(remoteElement.offsetHeight);
expect(result.streamWidth).eql(remoteElement.offsetWidth);
// The real height of the stream accounting for the aspect ratio.
expect(result.streamHeight).eql(640);
expect(result.offsetX).eql(0);
// The remote element height (700) minus the stream height (640) split in 2.
expect(result.offsetY).eql(30);
});
it("should fetch the correct stream sizes for leading axis width and not full",
function() {
remoteVideoDimensions = {
camera: {
width: 240,
height: 320
}
};
remoteElement = {
offsetWidth: 640,
offsetHeight: 480
};
view.updateVideoDimensions(localVideoDimensions, remoteVideoDimensions);
var result = view.getRemoteVideoDimensions();
expect(result.width).eql(remoteElement.offsetWidth);
expect(result.height).eql(remoteElement.offsetHeight);
// Aspect ratio modified from the height.
expect(result.streamWidth).eql(360);
expect(result.streamHeight).eql(remoteElement.offsetHeight);
// The remote element width (640) minus the stream width (360) split in 2.
expect(result.offsetX).eql(140);
expect(result.offsetY).eql(0);
});
it("should fetch the correct stream sizes for leading axis height and full",
function() {
remoteVideoDimensions = {
camera: {
width: 320,
height: 240
}
};
remoteElement = {
offsetWidth: 700,
offsetHeight: 480
};
view.updateVideoDimensions(localVideoDimensions, remoteVideoDimensions);
var result = view.getRemoteVideoDimensions();
expect(result.width).eql(remoteElement.offsetWidth);
expect(result.height).eql(remoteElement.offsetHeight);
// The real width of the stream accounting for the aspect ratio.
expect(result.streamWidth).eql(640);
expect(result.streamHeight).eql(remoteElement.offsetHeight);
// The remote element width (700) minus the stream width (640) split in 2.
expect(result.offsetX).eql(30);
expect(result.offsetY).eql(0);
});
it("should fetch the correct stream sizes for leading axis height and not full",
function() {
remoteVideoDimensions = {
camera: {
width: 320,
height: 240
}
};
remoteElement = {
offsetWidth: 480,
offsetHeight: 640
};
view.updateVideoDimensions(localVideoDimensions, remoteVideoDimensions);
var result = view.getRemoteVideoDimensions();
expect(result.width).eql(remoteElement.offsetWidth);
expect(result.height).eql(remoteElement.offsetHeight);
expect(result.streamWidth).eql(remoteElement.offsetWidth);
// Aspect ratio modified from the width.
expect(result.streamHeight).eql(360);
expect(result.offsetX).eql(0);
// The remote element width (640) minus the stream width (360) split in 2.
expect(result.offsetY).eql(140);
});
});
describe("Events", function() {
describe("resize", function() {
it("should update the width on the local stream element", function() {
localElement = {
@ -367,21 +487,6 @@ describe("loop.shared.mixins", function() {
expect(view._videoDimensionsCache.remote.camera.aspectRatio.height)
.eql(0.32857142857142857);
});
it("should fetch remote video stream dimensions correctly", function() {
remoteElement = {
offsetWidth: 600,
offsetHeight: 320
};
var remoteVideoDimensions = view.getRemoteVideoDimensions();
expect(remoteVideoDimensions.width).eql(remoteElement.offsetWidth);
expect(remoteVideoDimensions.height).eql(remoteElement.offsetHeight);
expect(remoteVideoDimensions.streamWidth).eql(534.8571428571429);
expect(remoteVideoDimensions.streamHeight).eql(remoteElement.offsetHeight);
expect(remoteVideoDimensions.offsetX).eql(32.571428571428555);
expect(remoteVideoDimensions.offsetY).eql(0);
});
});
});
});

View File

@ -54,7 +54,6 @@ navigator.mozLoop = {
switch(pref) {
// Ensure we skip FTE completely.
case "gettingStarted.seen":
case "screenshare.enabled":
return true;
}
},

View File

@ -19,8 +19,8 @@
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
dlgbuttons="accept,cancel,help"
ondialoghelp="openPrefsHelp()"
dialogWidth="&dialog.width2;"
subdialogWidth="&inContentDialog.width;"
dialogWidth="&sanitizePrefs2.modal.width;"
subdialogWidth="&sanitizePrefs2.inContent.dialog.width;"
title="&sanitizePrefs2.title;"
onload="gSanitizeDialog.init();">
@ -49,8 +49,8 @@
<caption label="&historySection.label;"/>
<grid flex="1">
<columns>
<column dialogWidth="&column.width2;"
subdialogWidth="&inContentColumn.width;"/>
<column dialogWidth="&sanitizePrefs2.column.width;"
subdialogWidth="&sanitizePrefs2.inContent.column.width;"/>
<column flex="1"/>
</columns>
<rows>

View File

@ -209,9 +209,9 @@ add_task(function test_pushstate_replacestate() {
is(entries.length, 1, "there is one shistory entry");
is(entries[0].url, "http://example.com/1", "url is correct");
browser.messageManager.
sendAsyncMessage("ss-test:historyPushState", {url: 'test-entry/'});
yield promiseContentMessage(browser, "ss-test:historyPushState");
yield ContentTask.spawn(browser, {}, function* () {
content.window.history.pushState({}, "", 'test-entry/');
});
// Check that we have added the history entry.
TabState.flush(browser);
@ -219,9 +219,9 @@ add_task(function test_pushstate_replacestate() {
is(entries.length, 2, "there is another shistory entry");
is(entries[1].url, "http://example.com/test-entry/", "url is correct");
browser.messageManager.
sendAsyncMessage("ss-test:historyReplaceState", {url: 'test-entry2/'});
yield promiseContentMessage(browser, "ss-test:historyReplaceState");
yield ContentTask.spawn(browser, {}, function* () {
content.window.history.replaceState({}, "", "test-entry2/");
});
// Check that we have modified the history entry.
TabState.flush(browser);

View File

@ -239,20 +239,6 @@ addMessageListener("ss-test:click", function ({data}) {
sendAsyncMessage("ss-test:click");
});
addMessageListener("ss-test:historyPushState", function ({data}) {
content.window.history.
pushState(data.stateObj || {}, data.title || "", data.url);
sendAsyncMessage("ss-test:historyPushState");
});
addMessageListener("ss-test:historyReplaceState", function ({data}) {
content.window.history.
replaceState(data.stateObj || {}, data.title || "", data.url);
sendAsyncMessage("ss-test:historyReplaceState");
});
addMessageListener("ss-test:run", function({data, objects}) {
let f = eval('(' + data.code + ')');
let result = f(content, objects.arg);

View File

@ -40,10 +40,11 @@ let startup = Task.async(function*(inspector) {
throw new Error("AnimationsPanel was not loaded in the animationinspector window");
}
yield promise.all([
AnimationsController.initialize(),
AnimationsPanel.initialize()
]).then(null, Cu.reportError);
// Startup first initalizes the controller and then the panel, in sequence.
// If you want to know when everything's ready, do:
// AnimationsPanel.once(AnimationsPanel.PANEL_INITIALIZED)
yield AnimationsController.initialize();
yield AnimationsPanel.initialize();
});
/**
@ -51,23 +52,20 @@ let startup = Task.async(function*(inspector) {
* widget when loading/unloading the iframe into the tab.
*/
let shutdown = Task.async(function*() {
yield promise.all([
AnimationsController.destroy(),
// Don't assume that AnimationsPanel is defined here, it's in another file.
typeof AnimationsPanel !== "undefined"
? AnimationsPanel.destroy()
: promise.resolve()
]).then(() => {
gToolbox = gInspector = null;
}, Cu.reportError);
yield AnimationsController.destroy();
// Don't assume that AnimationsPanel is defined here, it's in another file.
if (typeof AnimationsPanel !== "undefined") {
yield AnimationsPanel.destroy()
}
gToolbox = gInspector = null;
});
// This is what makes the sidebar widget able to load/unload the panel.
function setPanel(panel) {
return startup(panel);
return startup(panel).catch(Cu.reportError);
}
function destroy() {
return shutdown();
return shutdown().catch(Cu.reportError);
}
/**
@ -101,6 +99,8 @@ let AnimationsController = {
let target = gToolbox.target;
this.animationsFront = new AnimationsFront(target.client, target.form);
// Not all server versions provide a way to pause all animations at once.
this.hasToggleAll = yield target.actorHasMethod("animations", "toggleAll");
this.onPanelVisibilityChange = this.onPanelVisibilityChange.bind(this);
this.onNewNodeFront = this.onNewNodeFront.bind(this);
@ -186,6 +186,17 @@ let AnimationsController = {
done();
}),
/**
* Toggle (pause/play) all animations in the current target.
*/
toggleAll: function() {
if (!this.hasToggleAll) {
return promis.resolve();
}
return this.animationsFront.toggleAll().catch(Cu.reportError);
},
// AnimationPlayerFront objects are managed by this controller. They are
// retrieved when refreshAnimationPlayers is called, stored in the
// animationPlayers array, and destroyed when refreshAnimationPlayers is

View File

@ -15,6 +15,10 @@
<script type="application/javascript;version=1.8" src="chrome://browser/content/devtools/theme-switching.js"/>
</head>
<body class="theme-sidebar devtools-monospace" role="application">
<div id="toolbar" class="theme-toolbar">
<span class="label">&allAnimations;</span>
<button id="toggle-all" standalone="true" class="devtools-button"></button>
</div>
<div id="players" class="theme-toolbar"></div>
<div id="error-message">
<p>&invalidElement;</p>

View File

@ -11,6 +11,7 @@
*/
let AnimationsPanel = {
UI_UPDATED_EVENT: "ui-updated",
PANEL_INITIALIZED: "panel-initialized",
initialize: Task.async(function*() {
if (this.initialized) {
@ -21,16 +22,27 @@ let AnimationsPanel = {
this.playersEl = document.querySelector("#players");
this.errorMessageEl = document.querySelector("#error-message");
this.pickerButtonEl = document.querySelector("#element-picker");
this.toggleAllButtonEl = document.querySelector("#toggle-all");
// If the server doesn't support toggling all animations at once, hide the
// whole bottom toolbar.
if (!AnimationsController.hasToggleAll) {
document.querySelector("#toolbar").style.display = "none";
}
let hUtils = gToolbox.highlighterUtils;
this.togglePicker = hUtils.togglePicker.bind(hUtils);
this.onPickerStarted = this.onPickerStarted.bind(this);
this.onPickerStopped = this.onPickerStopped.bind(this);
this.createPlayerWidgets = this.createPlayerWidgets.bind(this);
this.toggleAll = this.toggleAll.bind(this);
this.onTabNavigated = this.onTabNavigated.bind(this);
this.startListeners();
this.initialized.resolve();
this.emit(this.PANEL_INITIALIZED);
}),
destroy: Task.async(function*() {
@ -47,6 +59,7 @@ let AnimationsPanel = {
yield this.destroyPlayerWidgets();
this.playersEl = this.errorMessageEl = null;
this.toggleAllButtonEl = this.pickerButtonEl = null;
this.destroyed.resolve();
}),
@ -54,25 +67,35 @@ let AnimationsPanel = {
startListeners: function() {
AnimationsController.on(AnimationsController.PLAYERS_UPDATED_EVENT,
this.createPlayerWidgets);
this.pickerButtonEl.addEventListener("click", this.togglePicker, false);
gToolbox.on("picker-started", this.onPickerStarted);
gToolbox.on("picker-stopped", this.onPickerStopped);
this.toggleAllButtonEl.addEventListener("click", this.toggleAll, false);
gToolbox.target.on("navigate", this.onTabNavigated);
},
stopListeners: function() {
AnimationsController.off(AnimationsController.PLAYERS_UPDATED_EVENT,
this.createPlayerWidgets);
this.pickerButtonEl.removeEventListener("click", this.togglePicker, false);
gToolbox.off("picker-started", this.onPickerStarted);
gToolbox.off("picker-stopped", this.onPickerStopped);
this.toggleAllButtonEl.removeEventListener("click", this.toggleAll, false);
gToolbox.target.off("navigate", this.onTabNavigated);
},
displayErrorMessage: function() {
this.errorMessageEl.style.display = "block";
this.playersEl.style.display = "none";
},
hideErrorMessage: function() {
this.errorMessageEl.style.display = "none";
this.playersEl.style.display = "block";
},
onPickerStarted: function() {
@ -83,6 +106,29 @@ let AnimationsPanel = {
this.pickerButtonEl.removeAttribute("checked");
},
toggleAll: Task.async(function*() {
let btnClass = this.toggleAllButtonEl.classList;
// Toggling all animations is async and it may be some time before each of
// the current players get their states updated, so toggle locally too, to
// avoid the timelines from jumping back and forth.
if (this.playerWidgets) {
let currentWidgetStateChange = [];
for (let widget of this.playerWidgets) {
currentWidgetStateChange.push(btnClass.contains("paused")
? widget.play() : widget.pause());
}
yield promise.all(currentWidgetStateChange).catch(Cu.reportError);
}
btnClass.toggle("paused");
yield AnimationsController.toggleAll();
}),
onTabNavigated: function() {
this.toggleAllButtonEl.classList.remove("paused");
},
createPlayerWidgets: Task.async(function*() {
let done = gInspector.updating("animationspanel");
@ -307,12 +353,15 @@ PlayerWidget.prototype = {
* switched to the right state, and the timeline animation is stopped.
*/
pause: function() {
if (this.player.state.playState === "finished") {
return;
}
// Switch to the right className on the element right away to avoid waiting
// for the next state update to change the playPause icon.
this.updateWidgetState({playState: "paused"});
return this.player.pause().then(() => {
this.stopTimelineAnimation();
});
this.stopTimelineAnimation();
return this.player.pause();
},
/**
@ -321,6 +370,10 @@ PlayerWidget.prototype = {
* switched to the right state, and the timeline animation is started.
*/
play: function() {
if (this.player.state.playState === "finished") {
return;
}
// Switch to the right className on the element right away to avoid waiting
// for the next state update to change the playPause icon.
this.updateWidgetState({playState: "running"});

View File

@ -21,5 +21,9 @@ support-files =
[browser_animation_shows_player_on_valid_node.js]
[browser_animation_timeline_animates.js]
[browser_animation_timeline_waits_for_delay.js]
[browser_animation_toggle_button_resets_on_navigate.js]
[browser_animation_toggle_button_toggles_animations.js]
[browser_animation_toggle_button_updates_playerWidgets.js]
[browser_animation_toolbar_exists.js]
[browser_animation_ui_updates_when_animation_changes.js]
[browser_animation_ui_updates_when_animation_data_changes.js]

View File

@ -0,0 +1,29 @@
/* vim: set 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 that a page navigation resets the state of the global toggle button.
add_task(function*() {
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
let {inspector, panel} = yield openAnimationInspector();
ok(!panel.toggleAllButtonEl.classList.contains("paused"),
"The toggle button is in its running state by default");
info("Toggle all animations, so that they pause");
yield panel.toggleAll();
ok(panel.toggleAllButtonEl.classList.contains("paused"),
"The toggle button now is in its paused state");
info("Reloading the page");
let onNewRoot = inspector.once("new-root");
yield reloadTab();
yield onNewRoot;
yield inspector.once("inspector-updated");
ok(!panel.toggleAllButtonEl.classList.contains("paused"),
"The toggle button is back in its running state");
});

View File

@ -0,0 +1,30 @@
/* vim: set 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 that the main toggle button actually toggles animations.
// This test doesn't need to be extra careful about checking that *all*
// animations have been paused (including inside iframes) because there's an
// actor test in /toolkit/devtools/server/tests/browser/ that does this.
add_task(function*() {
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
let {inspector, panel} = yield openAnimationInspector();
info("Click the toggle button");
yield panel.toggleAll();
yield checkState("paused");
info("Click again the toggle button");
yield panel.toggleAll();
yield checkState("running");
});
function* checkState(state) {
for (let selector of [".animated", ".multi", ".long"]) {
let playState = yield getAnimationPlayerState(selector);
is(playState, state, "The animation on node " + selector + " is " + state);
}
}

View File

@ -0,0 +1,35 @@
/* vim: set 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 that pressing the main toggle button also updates the displayed
// player widgets.
add_task(function*() {
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
let {inspector, panel} = yield openAnimationInspector();
info("Select an animated node");
yield selectNode(".animated", inspector);
let widget = panel.playerWidgets[0];
info("Click the toggle button to pause all animations");
let onRefresh = widget.player.once(widget.player.AUTO_REFRESH_EVENT);
yield panel.toggleAll();
yield onRefresh;
info("Checking the selected node's animation player widget's state");
is(widget.player.state.playState, "paused", "The player front's state is paused");
ok(widget.el.classList.contains("paused"), "The widget's UI is in paused state");
info("Click the toggle button to play all animations");
onRefresh = widget.player.once(widget.player.AUTO_REFRESH_EVENT);
yield panel.toggleAll();
yield onRefresh;
info("Checking the selected node's animation player widget's state again");
is(widget.player.state.playState, "running", "The player front's state is running");
ok(widget.el.classList.contains("running"), "The widget's UI is in running state");
});

View File

@ -0,0 +1,26 @@
/* vim: set 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 that the animation panel has a top toolbar that contains the play/pause
// button and that is displayed at all times.
add_task(function*() {
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
let {inspector, panel, window} = yield openAnimationInspector();
let doc = window.document;
let toolbar = doc.querySelector("#toolbar");
ok(toolbar, "The panel contains the toolbar element");
ok(toolbar.querySelector("#toggle-all"), "The toolbar contains the toggle button");
ok(isNodeVisible(toolbar), "The toolbar is visible");
info("Select an animated node");
yield selectNode(".animated", inspector);
toolbar = doc.querySelector("#toolbar");
ok(toolbar, "The panel still contains the toolbar element");
ok(isNodeVisible(toolbar), "The toolbar is still visible");
});

View File

@ -44,3 +44,20 @@ addMessageListener("Test:SetNodeStyle", function(msg) {
sendAsyncMessage("Test:SetNodeStyle");
});
/**
* Get the current playState of an animation player on a given node.
* @param {Object} data
* - {Number} animationIndex The index of the node's animationPlayers to check
* @param {Object} objects
* - {DOMNode} node The node to check
*/
addMessageListener("Test:GetAnimationPlayerState", function(msg) {
let {animationIndex} = msg.data;
let {node} = msg.objects;
let player = node.getAnimationPlayers()[animationIndex];
player.ready.then(() => {
sendAsyncMessage("Test:GetAnimationPlayerState", player.playState);
});
});

View File

@ -18,6 +18,7 @@ waitForExplicitFinish();
const TEST_URL_ROOT = "http://example.com/browser/browser/devtools/animationinspector/test/";
const ROOT_TEST_DIR = getRootDirectory(gTestPath);
const FRAME_SCRIPT_URL = ROOT_TEST_DIR + "doc_frame_script.js";
const COMMON_FRAME_SCRIPT_URL = "chrome://browser/content/devtools/frame-script-utils.js";
// Auto clean-up when a test ends
registerCleanupFunction(function*() {
@ -63,6 +64,9 @@ function addTab(url) {
info("Loading the helper frame script " + FRAME_SCRIPT_URL);
browser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
info("Loading the helper frame script " + COMMON_FRAME_SCRIPT_URL);
browser.messageManager.loadFrameScript(COMMON_FRAME_SCRIPT_URL, false);
browser.addEventListener("load", function onload() {
browser.removeEventListener("load", onload, true);
info("URL '" + url + "' loading complete");
@ -73,6 +77,13 @@ function addTab(url) {
return def.promise;
}
/**
* Reload the current tab location.
*/
function reloadTab() {
return executeInContent("devtools:test:reload", {}, {}, false);
}
/**
* Simple DOM node accesor function that takes either a node or a string css
* selector as argument and returns the corresponding node
@ -148,10 +159,7 @@ let openAnimationInspector = Task.async(function*() {
let win = inspector.sidebar.getWindowForTab("animationinspector");
let {AnimationsController, AnimationsPanel} = win;
yield promise.all([
AnimationsController.initialized,
AnimationsPanel.initialized
]);
yield AnimationsPanel.once(AnimationsPanel.PANEL_INITIALIZED);
return {
toolbox: toolbox,
@ -283,6 +291,16 @@ let togglePlayPauseButton = Task.async(function*(widget) {
yield widget.player.once(widget.player.AUTO_REFRESH_EVENT);
});
/**
* Get the current playState of an animation player on a given node.
*/
let getAnimationPlayerState = Task.async(function*(selector, animationIndex=0) {
let playState = yield executeInContent("Test:GetAnimationPlayerState",
{animationIndex},
{node: getNode(selector)});
return playState;
});
/**
* Is the given node visible in the page (rendered in the frame tree).
* @param {DOMNode}

View File

@ -18,27 +18,27 @@ devtools.lazyRequireGetter(this, "DevToolsUtils",
"devtools/toolkit/DevToolsUtils");
devtools.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
"devtools/timeline/global", true);
"devtools/shared/timeline/global", true);
devtools.lazyRequireGetter(this, "L10N",
"devtools/profiler/global", true);
"devtools/shared/profiler/global", true);
devtools.lazyRequireGetter(this, "RecordingUtils",
"devtools/performance/recording-utils", true);
devtools.lazyRequireGetter(this, "RecordingModel",
"devtools/performance/recording-model", true);
devtools.lazyRequireGetter(this, "MarkersOverview",
"devtools/timeline/markers-overview", true);
"devtools/shared/timeline/markers-overview", true);
devtools.lazyRequireGetter(this, "MemoryOverview",
"devtools/timeline/memory-overview", true);
"devtools/shared/timeline/memory-overview", true);
devtools.lazyRequireGetter(this, "Waterfall",
"devtools/timeline/waterfall", true);
"devtools/shared/timeline/waterfall", true);
devtools.lazyRequireGetter(this, "MarkerDetails",
"devtools/timeline/marker-details", true);
"devtools/shared/timeline/marker-details", true);
devtools.lazyRequireGetter(this, "CallView",
"devtools/profiler/tree-view", true);
"devtools/shared/profiler/tree-view", true);
devtools.lazyRequireGetter(this, "ThreadNode",
"devtools/profiler/tree-model", true);
"devtools/shared/profiler/tree-model", true);
devtools.lazyRequireGetter(this, "FrameNode",
"devtools/profiler/tree-model", true);
"devtools/shared/profiler/tree-model", true);
devtools.lazyRequireGetter(this, "OptionsView",
"devtools/shared/options-view", true);

View File

@ -23,7 +23,7 @@ support-files =
[browser_perf-details-waterfall-render.js]
[browser_perf-details-01.js]
[browser_perf-details-02.js]
[browser_perf-details-03.js]
# [browser_perf-details-03.js] bug 1132206
[browser_perf-details-04.js]
[browser_perf-events-calltree.js]
[browser_perf-front-basic-profiler-01.js]
@ -62,6 +62,7 @@ support-files =
[browser_perf-shared-connection-02.js]
[browser_perf-shared-connection-03.js]
[browser_perf-states.js]
[browser_perf-refresh.js]
[browser_perf-ui-recording.js]
[browser_perf-recording-notices-01.js]
[browser_perf-recording-notices-02.js]
@ -74,3 +75,23 @@ support-files =
[browser_perf-recording-selected-02.js]
[browser_perf-recording-selected-03.js]
[browser_perf-recording-selected-04.js]
[browser_profiler_categories.js]
[browser_profiler_content-check.js]
[browser_profiler_tree-abstract-01.js]
[browser_profiler_tree-abstract-02.js]
[browser_profiler_tree-abstract-03.js]
[browser_profiler_tree-abstract-04.js]
[browser_profiler_tree-frame-node.js]
[browser_profiler_tree-model-01.js]
[browser_profiler_tree-model-02.js]
[browser_profiler_tree-model-03.js]
[browser_profiler_tree-model-04.js]
[browser_profiler_tree-model-05.js]
[browser_profiler_tree-view-01.js]
[browser_profiler_tree-view-02.js]
[browser_profiler_tree-view-03.js]
[browser_profiler_tree-view-04.js]
[browser_profiler_tree-view-05.js]
[browser_profiler_tree-view-06.js]
[browser_profiler_tree-view-07.js]
[browser_timeline_blueprint.js]

View File

@ -4,7 +4,7 @@
/**
* Tests that the call tree up/down events work for js calltree and memory calltree.
*/
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
function spawnTest () {
let focus = 0;
let focusEvent = () => focus++;

View File

@ -0,0 +1,42 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Rough test that the recording still continues after a refresh.
*/
function spawnTest () {
let { panel, target } = yield initPerformance(SIMPLE_URL);
let { EVENTS, PerformanceController } = panel.panelWin;
// Enable memory to test all the overview graphs.
Services.prefs.setBoolPref(MEMORY_PREF, true);
yield startRecording(panel);
yield reload(target)
let rec = PerformanceController.getCurrentRecording();
let { markers, memory, ticks } = rec.getAllData();
// Store current length of items
let markersLength = markers.length;
let memoryLength = memory.length;
let ticksLength = ticks.length;
ok(rec.isRecording(), "RecordingModel should still be recording after reload");
yield busyWait(100);
yield waitUntil(() => rec.getMarkers().length > markersLength);
yield waitUntil(() => rec.getMemory().length > memoryLength);
yield waitUntil(() => rec.getTicks().length > ticksLength);
ok("Markers, memory and ticks continue after reload");
yield stopRecording(panel);
let { allocations, profile, frames } = rec.getAllData();
ok(allocations, "allocations exist after refresh");
ok(profile, "profile exists after refresh");
ok(frames, "frames exist after refresh");
yield teardown(panel);
finish();
}

View File

@ -6,7 +6,7 @@
*/
function test() {
let global = devtools.require("devtools/profiler/global");
let global = devtools.require("devtools/shared/profiler/global");
let l10n = global.L10N;
let categories = global.CATEGORIES;
let mappings = global.CATEGORY_MAPPINGS;

View File

@ -7,7 +7,7 @@
*/
function test() {
let { FrameNode } = devtools.require("devtools/profiler/tree-model");
let { FrameNode } = devtools.require("devtools/shared/profiler/tree-model");
ok(FrameNode.isContent({ location: "http://foo" }),
"Verifying content/chrome frames is working properly.");

View File

@ -9,7 +9,7 @@
let { AbstractTreeItem } = Cu.import("resource:///modules/devtools/AbstractTreeItem.jsm", {});
let { Heritage } = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
let test = Task.async(function*() {
function spawnTest () {
let container = document.createElement("vbox");
gBrowser.selectedBrowser.parentNode.appendChild(container);
@ -135,7 +135,7 @@ let test = Task.async(function*() {
container.remove();
finish();
});
}
function MyCustomTreeItem(dataSrc, properties) {
AbstractTreeItem.call(this, properties);

View File

@ -9,7 +9,7 @@
let { AbstractTreeItem } = Cu.import("resource:///modules/devtools/AbstractTreeItem.jsm", {});
let { Heritage } = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
let test = Task.async(function*() {
function spawnTest () {
let container = document.createElement("vbox");
gBrowser.selectedBrowser.parentNode.appendChild(container);
@ -138,7 +138,7 @@ let test = Task.async(function*() {
container.remove();
finish();
});
}
function MyCustomTreeItem(dataSrc, properties) {
AbstractTreeItem.call(this, properties);

View File

@ -9,7 +9,7 @@
let { AbstractTreeItem } = Cu.import("resource:///modules/devtools/AbstractTreeItem.jsm", {});
let { Heritage } = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
let test = Task.async(function*() {
function spawnTest () {
let container = document.createElement("vbox");
gBrowser.selectedBrowser.parentNode.appendChild(container);
@ -146,7 +146,7 @@ let test = Task.async(function*() {
container.remove();
finish();
});
}
function MyCustomTreeItem(dataSrc, properties) {
AbstractTreeItem.call(this, properties);

View File

@ -8,7 +8,7 @@
let { AbstractTreeItem } = Cu.import("resource:///modules/devtools/AbstractTreeItem.jsm", {});
let { Heritage } = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
let test = Task.async(function*() {
function spawnTest () {
let container = document.createElement("vbox");
gBrowser.selectedBrowser.parentNode.appendChild(container);
@ -28,7 +28,7 @@ let test = Task.async(function*() {
container.remove();
finish();
});
}
function MyCustomTreeItem(dataSrc, properties) {
AbstractTreeItem.call(this, properties);

View File

@ -6,7 +6,7 @@
*/
function test() {
let { FrameNode } = devtools.require("devtools/profiler/tree-model");
let { FrameNode } = devtools.require("devtools/shared/profiler/tree-model");
let frame1 = new FrameNode({
location: "hello/<.world (http://foo/bar.js:123:987)",

View File

@ -6,7 +6,7 @@
*/
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
// Create a root node from a given samples array.

View File

@ -6,7 +6,7 @@
*/
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
// Create a root node from a given samples array.

View File

@ -7,7 +7,7 @@
*/
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
// Create a root node from a given samples array, filtering by time.

View File

@ -7,7 +7,7 @@
*/
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
// Create a root node from a given samples array, filtering by time.

View File

@ -43,7 +43,7 @@ let samples = [{
}];
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
let root = new ThreadNode(samples, { invertTree: true });

View File

@ -7,8 +7,8 @@
*/
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { CallView } = devtools.require("devtools/profiler/tree-view");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
let { CallView } = devtools.require("devtools/shared/profiler/tree-view");
let threadNode = new ThreadNode(gSamples);
let treeRoot = new CallView({ frame: threadNode });

View File

@ -7,8 +7,8 @@
*/
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { CallView } = devtools.require("devtools/profiler/tree-view");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
let { CallView } = devtools.require("devtools/shared/profiler/tree-view");
let threadNode = new ThreadNode(gSamples);
let treeRoot = new CallView({ frame: threadNode });

View File

@ -7,8 +7,8 @@
*/
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { CallView } = devtools.require("devtools/profiler/tree-view");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
let { CallView } = devtools.require("devtools/shared/profiler/tree-view");
let threadNode = new ThreadNode(gSamples);
let treeRoot = new CallView({ frame: threadNode });

View File

@ -7,8 +7,8 @@
*/
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { CallView } = devtools.require("devtools/profiler/tree-view");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
let { CallView } = devtools.require("devtools/shared/profiler/tree-view");
let threadNode = new ThreadNode(gSamples);
let treeRoot = new CallView({ frame: threadNode });

View File

@ -7,8 +7,8 @@
*/
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { CallView } = devtools.require("devtools/profiler/tree-view");
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
let { CallView } = devtools.require("devtools/shared/profiler/tree-view");
let threadNode = new ThreadNode(gSamples);
let treeRoot = new CallView({ frame: threadNode });

View File

@ -6,9 +6,9 @@
* correctly emits events when certain DOM nodes are clicked.
*/
let test = Task.async(function*() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { CallView } = devtools.require("devtools/profiler/tree-view");
function spawnTest () {
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
let { CallView } = devtools.require("devtools/shared/profiler/tree-view");
let threadNode = new ThreadNode(gSamples);
let treeRoot = new CallView({ frame: threadNode });
@ -31,9 +31,8 @@ let test = Task.async(function*() {
eventItem = yield receivedZoomEvent;
is(eventItem, D, "The 'zoom' event target is correct.");
finish();
});
}
let gSamples = [{
time: 5,

View File

@ -6,9 +6,9 @@
* has the correct 'root', 'parent', 'level' etc. accessors on child nodes.
*/
function test() {
let { ThreadNode } = devtools.require("devtools/profiler/tree-model");
let { CallView } = devtools.require("devtools/profiler/tree-view");
function spawnTest () {
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
let { CallView } = devtools.require("devtools/shared/profiler/tree-view");
let threadNode = new ThreadNode(gSamples);
let treeRoot = new CallView({ frame: threadNode });
@ -31,8 +31,6 @@ function test() {
"The .A.B.D node has the correct target node.");
is(D.container.id, "call-tree-container",
"The .A.B.D node has the correct container node.");
finish();
}
let gSamples = [{

View File

@ -5,8 +5,8 @@
* Tests if the timeline blueprint has a correct structure.
*/
add_task(function*() {
let { TIMELINE_BLUEPRINT } = devtools.require("devtools/timeline/global");
function spawnTest () {
let { TIMELINE_BLUEPRINT } = devtools.require("devtools/shared/timeline/global");
ok(TIMELINE_BLUEPRINT,
"A timeline blueprint should be available.");
@ -24,4 +24,4 @@ add_task(function*() {
ok("label" in value,
"Each entry in the timeline blueprint contains a `label` key.");
}
});
}

View File

@ -417,3 +417,8 @@ function getSourceActor(aSources, aURL) {
function fireKey (e) {
EventUtils.synthesizeKey(e, {});
}
function reload (aTarget, aEvent = "navigate") {
aTarget.activeTab.reload();
return once(aTarget, aEvent);
}

View File

@ -5,10 +5,7 @@
EXTRA_JS_MODULES.devtools.profiler += [
'panel.js',
'utils/global.js',
'utils/shared.js',
'utils/tree-model.js',
'utils/tree-view.js'
'utils/shared.js'
]
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

View File

@ -19,17 +19,17 @@ devtools.lazyRequireGetter(this, "FramerateFront",
"devtools/server/actors/framerate", true);
devtools.lazyRequireGetter(this, "L10N",
"devtools/profiler/global", true);
"devtools/shared/profiler/global", true);
devtools.lazyRequireGetter(this, "CATEGORIES",
"devtools/profiler/global", true);
"devtools/shared/profiler/global", true);
devtools.lazyRequireGetter(this, "CATEGORY_MAPPINGS",
"devtools/profiler/global", true);
"devtools/shared/profiler/global", true);
devtools.lazyRequireGetter(this, "CATEGORY_OTHER",
"devtools/profiler/global", true);
"devtools/shared/profiler/global", true);
devtools.lazyRequireGetter(this, "ThreadNode",
"devtools/profiler/tree-model", true);
"devtools/shared/profiler/tree-model", true);
devtools.lazyRequireGetter(this, "CallView",
"devtools/profiler/tree-view", true);
"devtools/shared/profiler/tree-view", true);
devtools.lazyImporter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");

View File

@ -5,7 +5,6 @@ support-files =
head.js
[browser_profiler_aaa_run_first_leaktest.js]
[browser_profiler_categories.js]
[browser_profiler_console-record-01.js]
skip-if = true # Bug 1047124
[browser_profiler_console-record-02.js]
@ -24,7 +23,6 @@ skip-if = true # Bug 1047124
skip-if = true # Bug 1047124
[browser_profiler_console-record-09.js]
skip-if = true # Bug 1047124
[browser_profiler_content-check.js]
[browser_profiler_data-massaging-01.js]
skip-if = true # Bug 1047124
[browser_profiler_data-massaging-02.js]
@ -92,20 +90,3 @@ skip-if = true # Bug 1047124
skip-if = true # Bug 1047124
[browser_profiler_tabbed-browser-add-remove-02.js]
skip-if = true # Bug 1047124
[browser_profiler_tree-abstract-01.js]
[browser_profiler_tree-abstract-02.js]
[browser_profiler_tree-abstract-03.js]
[browser_profiler_tree-abstract-04.js]
[browser_profiler_tree-frame-node.js]
[browser_profiler_tree-model-01.js]
[browser_profiler_tree-model-02.js]
[browser_profiler_tree-model-03.js]
[browser_profiler_tree-model-04.js]
[browser_profiler_tree-model-05.js]
[browser_profiler_tree-view-01.js]
[browser_profiler_tree-view-02.js]
[browser_profiler_tree-view-03.js]
[browser_profiler_tree-view-04.js]
[browser_profiler_tree-view-05.js]
[browser_profiler_tree-view-06.js]
[browser_profiler_tree-view-07.js]

View File

@ -204,10 +204,7 @@ SplitView.prototype = {
this._side.appendChild(aDetails);
if (binding.onCreate) {
// queue onCreate handler
this._root.ownerDocument.defaultView.setTimeout(function () {
binding.onCreate(aSummary, aDetails, binding.data);
}, 0);
binding.onCreate(aSummary, aDetails, binding.data);
}
},

View File

@ -31,6 +31,20 @@ EXTRA_JS_MODULES.devtools += [
'widgets/ViewHelpers.jsm',
]
EXTRA_JS_MODULES.devtools.shared.profiler += [
'profiler/global.js',
'profiler/tree-model.js',
'profiler/tree-view.js',
]
EXTRA_JS_MODULES.devtools.shared.timeline += [
'timeline/global.js',
'timeline/marker-details.js',
'timeline/markers-overview.js',
'timeline/memory-overview.js',
'timeline/waterfall.js',
]
EXTRA_JS_MODULES.devtools.shared += [
'autocomplete-popup.js',
'd3.js',

View File

@ -7,11 +7,11 @@ const {Cc, Ci, Cu, Cr} = require("chrome");
loader.lazyRequireGetter(this, "Services");
loader.lazyRequireGetter(this, "L10N",
"devtools/profiler/global", true);
"devtools/shared/profiler/global", true);
loader.lazyRequireGetter(this, "CATEGORY_MAPPINGS",
"devtools/profiler/global", true);
"devtools/shared/profiler/global", true);
loader.lazyRequireGetter(this, "CATEGORY_JIT",
"devtools/profiler/global", true);
"devtools/shared/profiler/global", true);
const CHROME_SCHEMES = ["chrome://", "resource://"];
const CONTENT_SCHEMES = ["http://", "https://", "file://"];

View File

@ -6,7 +6,7 @@
const {Cc, Ci, Cu, Cr} = require("chrome");
loader.lazyRequireGetter(this, "L10N",
"devtools/profiler/global", true);
"devtools/shared/profiler/global", true);
loader.lazyImporter(this, "Heritage",
"resource:///modules/devtools/ViewHelpers.jsm");

View File

@ -4,7 +4,7 @@
// Tests if platform frames are removed from the flame graph data.
let {FlameGraphUtils} = Cu.import("resource:///modules/devtools/FlameGraph.jsm", {});
let {FrameNode} = devtools.require("devtools/profiler/tree-model");
let {FrameNode} = devtools.require("devtools/shared/profiler/tree-model");
add_task(function*() {
yield promiseTab("about:blank");

View File

@ -4,7 +4,7 @@
// Tests if (idle) nodes are added when necessary in the flame graph data.
let {FlameGraphUtils} = Cu.import("resource:///modules/devtools/FlameGraph.jsm", {});
let {FrameNode} = devtools.require("devtools/profiler/tree-model");
let {FrameNode} = devtools.require("devtools/shared/profiler/tree-model");
add_task(function*() {
yield promiseTab("about:blank");

View File

@ -11,9 +11,9 @@ let WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils;
*/
loader.lazyRequireGetter(this, "L10N",
"devtools/timeline/global", true);
"devtools/shared/timeline/global", true);
loader.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
"devtools/timeline/global", true);
"devtools/shared/timeline/global", true);
loader.lazyRequireGetter(this, "EventEmitter",
"devtools/toolkit/event-emitter");

View File

@ -18,7 +18,7 @@ const { colorUtils: { setAlpha }} = require("devtools/css-color");
const { getColor } = require("devtools/shared/theme");
loader.lazyRequireGetter(this, "L10N",
"devtools/timeline/global", true);
"devtools/shared/timeline/global", true);
const OVERVIEW_HEADER_HEIGHT = 14; // px
const OVERVIEW_ROW_HEIGHT = 11; // px

View File

@ -17,7 +17,7 @@ const { colorUtils: { setAlpha }} = require("devtools/css-color");
const { getColor } = require("devtools/shared/theme");
loader.lazyRequireGetter(this, "L10N",
"devtools/timeline/global", true);
"devtools/shared/timeline/global", true);
const OVERVIEW_DAMPEN_VALUES = 0.95;

View File

@ -11,7 +11,7 @@
const {Ci, Cu} = require("chrome");
loader.lazyRequireGetter(this, "L10N",
"devtools/timeline/global", true);
"devtools/shared/timeline/global", true);
loader.lazyImporter(this, "setNamedTimeout",
"resource:///modules/devtools/ViewHelpers.jsm");

View File

@ -32,16 +32,19 @@ support-files =
sourcemap-css/sourcemaps.css.map
sourcemap-css/media-rules.css
sourcemap-css/media-rules.css.map
sourcemap-css/test-bootstrap-scss.css
sourcemap-css/test-stylus.css
sourcemap-sass/sourcemaps.scss
sourcemap-sass/media-rules.scss
sourcemap-styl/test-stylus.styl
sourcemaps.html
sourcemaps-large.html
sourcemaps-watching.html
test_private.css
test_private.html
doc_uncached.css
doc_uncached.html
doc_xulpage.xul
[browser_styleeditor_autocomplete.js]
[browser_styleeditor_bug_740541_iframes.js]
@ -70,6 +73,7 @@ skip-if = e10s # Bug 1055333 - style editor tests disabled with e10s
[browser_styleeditor_sv_resize.js]
[browser_styleeditor_selectstylesheet.js]
[browser_styleeditor_sourcemaps.js]
[browser_styleeditor_sourcemap_large.js]
[browser_styleeditor_sourcemap_watching.js]
skip-if = e10s # Bug 1055333 - style editor tests disabled with e10s
[browser_styleeditor_transition_rule.js]

View File

@ -0,0 +1,31 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Covers the case from Bug 1128747, where loading a sourcemapped
// file prevents the correct editor from being selected on load,
// and causes a second iframe to be appended when the user clicks
// editor in the list.
const TESTCASE_URI = TEST_BASE_HTTPS + "sourcemaps-large.html";
add_task(function*() {
let {UI} = yield addTabAndOpenStyleEditors(2, null, TESTCASE_URI);
yield openEditor(UI.editors[0]);
let iframes = UI.selectedEditor.details.querySelectorAll("iframe");
is (iframes.length, 1, "There is only one editor iframe");
ok (UI.selectedEditor.summary.classList.contains("splitview-active"),
"The editor is selected");
});
function openEditor(editor) {
getLinkFor(editor).click();
return editor.getSourceEditor();
}
function getLinkFor(editor) {
return editor.summary.querySelector(".stylesheet-name");
}

View File

@ -6,7 +6,7 @@
waitForExplicitFinish();
const TEST_URL = "about:config";
const TEST_URL = TEST_BASE + "doc_xulpage.xul";
add_task(function*() {
let tab = yield addTab(TEST_URL);

View File

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<?xml-stylesheet href="simple.css" type="text/css"?>
<!DOCTYPE window>
<window xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<label value="Simple XUL document" />
</window>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>testcase for a loading error with CSS source maps</title>
<link rel="stylesheet" type="text/css" href="sourcemap-css/test-bootstrap-scss.css"/>
</head>
<body>
<div>source maps <span>testcase</span> (see Bug 1128747)</div>
</body>
</html>

View File

@ -5,11 +5,6 @@
EXTRA_JS_MODULES.devtools.timeline += [
'panel.js',
'widgets/global.js',
'widgets/marker-details.js',
'widgets/markers-overview.js',
'widgets/memory-overview.js',
'widgets/waterfall.js'
]
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

View File

@ -5,7 +5,6 @@ support-files =
head.js
[browser_timeline_aaa_run_first_leaktest.js]
[browser_timeline_blueprint.js]
[browser_timeline_filters.js]
[browser_timeline_overview-initial-selection-01.js]
[browser_timeline_overview-initial-selection-02.js]

View File

@ -8,7 +8,7 @@
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { $, $$, EVENTS, TimelineController, TimelineView, TIMELINE_BLUEPRINT} = panel.panelWin;
let { L10N } = devtools.require("devtools/timeline/global");
let { L10N } = devtools.require("devtools/shared/timeline/global");
yield TimelineController.toggleRecording();
ok(true, "Recording has started.");

View File

@ -19,7 +19,7 @@ var gRGB_TO_HSL = {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { TIMELINE_BLUEPRINT } = devtools.require("devtools/timeline/global");
let { TIMELINE_BLUEPRINT } = devtools.require("devtools/shared/timeline/global");
let { $, $$, EVENTS, TimelineController } = panel.panelWin;
yield TimelineController.toggleRecording();

View File

@ -16,15 +16,15 @@ devtools.lazyRequireGetter(this, "EventEmitter",
"devtools/toolkit/event-emitter");
devtools.lazyRequireGetter(this, "MarkersOverview",
"devtools/timeline/markers-overview", true);
"devtools/shared/timeline/markers-overview", true);
devtools.lazyRequireGetter(this, "MemoryOverview",
"devtools/timeline/memory-overview", true);
"devtools/shared/timeline/memory-overview", true);
devtools.lazyRequireGetter(this, "Waterfall",
"devtools/timeline/waterfall", true);
"devtools/shared/timeline/waterfall", true);
devtools.lazyRequireGetter(this, "MarkerDetails",
"devtools/timeline/marker-details", true);
"devtools/shared/timeline/marker-details", true);
devtools.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
"devtools/timeline/global", true);
"devtools/shared/timeline/global", true);
devtools.lazyImporter(this, "CanvasGraphUtils",
"resource:///modules/devtools/Graphs.jsm");

View File

@ -12,6 +12,7 @@ support-files =
doc_iframe-context.html
doc_automation.html
doc_bug_1125817.html
doc_bug_1130901.html
440hz_sine.ogg
head.js
@ -29,21 +30,17 @@ skip-if = true # bug 1092571
[browser_audionode-actor-get-automation-data-01.js]
[browser_audionode-actor-get-automation-data-02.js]
[browser_audionode-actor-get-automation-data-03.js]
[browser_callwatcher-01.js]
[browser_webaudio-actor-simple.js]
[browser_webaudio-actor-destroy-node.js]
[browser_webaudio-actor-connect-param.js]
[browser_webaudio-actor-automation-event.js]
[browser_wa_destroy-node-01.js]
[browser_wa_first-run.js]
[browser_wa_reset-01.js]
[browser_wa_reset-02.js]
[browser_wa_reset-03.js]
[browser_wa_reset-04.js]
[browser_wa_navigate.js]
[browser_wa_automation-view-01.js]
[browser_wa_automation-view-02.js]
[browser_wa_controller-01.js]
[browser_wa_destroy-node-01.js]
[browser_wa_first-run.js]
[browser_wa_graph-click.js]
[browser_wa_graph-markers.js]
[browser_wa_graph-render-01.js]
@ -54,11 +51,10 @@ skip-if = true # bug 1092571
skip-if = true # bug 1092571
[browser_wa_graph-selected.js]
[browser_wa_graph-zoom.js]
[browser_wa_inspector.js]
[browser_wa_inspector-toggle.js]
[browser_wa_inspector-bypass-01.js]
[browser_wa_navigate.js]
[browser_wa_properties-view.js]
[browser_wa_properties-view-edit-01.js]
skip-if = true # bug 1010423
@ -67,6 +63,7 @@ skip-if = true # bug 1010423
[browser_wa_properties-view-media-nodes.js]
[browser_wa_properties-view-params.js]
[browser_wa_properties-view-params-objects.js]
[browser_wa_automation-view-01.js]
[browser_wa_automation-view-02.js]
[browser_wa_reset-01.js]
[browser_wa_reset-02.js]
[browser_wa_reset-03.js]
[browser_wa_reset-04.js]

View File

@ -0,0 +1,26 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 1130901
* Tests to ensure that calling call/apply on methods wrapped
* via CallWatcher do not throw a security permissions error:
* "Error: Permission denied to access property 'call'"
*/
const BUG_1130901_URL = EXAMPLE_URL + "doc_bug_1130901.html";
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(BUG_1130901_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, gAudioNodes } = panelWin;
reload(target);
yield waitForGraphRendered(panelWin, 3, 0);
ok(true, "Successfully created a node from AudioContext via `call`.");
ok(true, "Successfully created a node from AudioContext via `apply`.");
yield teardown(target);
});

View File

@ -0,0 +1,22 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Web Audio Editor test page</title>
</head>
<body>
<script type="text/javascript;version=1.8">
"use strict";
let ctx = new AudioContext();
ctx.createOscillator.call(ctx);
ctx.createGain.apply(ctx, []);
</script>
</body>
</html>

View File

@ -4,7 +4,6 @@
const Cu = Components.utils;
const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm");
const {AppManager} = require("devtools/webide/app-manager");
const {Connection} = require("devtools/client/connection-manager");
const ConfigView = require("devtools/webide/config-view");
@ -74,16 +73,8 @@ function BuildUI() {
configView.kind = "Pref";
configView.includeTypeName = true;
getAllPrefs = AppManager.preferenceFront.getAllPrefs();
getAllPrefs.then(json => {
let deviceItems = Object.keys(json);
deviceItems.sort();
configView.keys = deviceItems;
for (let i = 0; i < configView.keys.length; i++) {
let key = configView.keys[i];
configView.generateField(key, json[key].value, json[key].hasUserValue);
}
});
getAllPrefs = AppManager.preferenceFront.getAllPrefs()
.then(json => configView.generateDisplay(json));
} else {
CloseUI();
}

View File

@ -4,7 +4,6 @@
const Cu = Components.utils;
const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm");
const {AppManager} = require("devtools/webide/app-manager");
const {Connection} = require("devtools/client/connection-manager");
const ConfigView = require("devtools/webide/config-view");
@ -75,15 +74,7 @@ function BuildUI() {
configView.includeTypeName = false;
getAllSettings = AppManager.settingsFront.getAllSettings()
getAllSettings.then(json => {
let deviceItems = Object.keys(json);
deviceItems.sort();
configView.keys = deviceItems;
for (let i = 0; i < configView.keys.length; i++) {
let key = configView.keys[i];
configView.generateField(key, json[key].value, json[key].hasUserValue);
}
});
.then(json => configView.generateDisplay(json));
} else {
CloseUI();
}

View File

@ -30,6 +30,35 @@ function OnAppManagerUpdate(event, what) {
}
}
function generateFields(json) {
let table = document.querySelector("table");
let permissionsTable = json.rawPermissionsTable;
for (let name in permissionsTable) {
let tr = document.createElement("tr");
tr.className = "line";
let td = document.createElement("td");
td.textContent = name;
tr.appendChild(td);
for (let type of ["app","privileged","certified"]) {
let td = document.createElement("td");
if (permissionsTable[name][type] == json.ALLOW_ACTION) {
td.textContent = "✓";
td.className = "permallow";
}
if (permissionsTable[name][type] == json.PROMPT_ACTION) {
td.textContent = "!";
td.className = "permprompt";
}
if (permissionsTable[name][type] == json.DENY_ACTION) {
td.textContent = "✕";
td.className = "permdeny"
}
tr.appendChild(td);
}
table.appendChild(tr);
}
}
let getRawPermissionsTablePromise; // Used by tests
function BuildUI() {
let table = document.querySelector("table");
@ -41,34 +70,8 @@ function BuildUI() {
if (AppManager.connection &&
AppManager.connection.status == Connection.Status.CONNECTED &&
AppManager.deviceFront) {
getRawPermissionsTablePromise = AppManager.deviceFront.getRawPermissionsTable();
getRawPermissionsTablePromise.then(json => {
let permissionsTable = json.rawPermissionsTable;
for (let name in permissionsTable) {
let tr = document.createElement("tr");
tr.className = "line";
let td = document.createElement("td");
td.textContent = name;
tr.appendChild(td);
for (let type of ["app","privileged","certified"]) {
let td = document.createElement("td");
if (permissionsTable[name][type] == json.ALLOW_ACTION) {
td.textContent = "✓";
td.className = "permallow";
}
if (permissionsTable[name][type] == json.PROMPT_ACTION) {
td.textContent = "!";
td.className = "permprompt";
}
if (permissionsTable[name][type] == json.DENY_ACTION) {
td.textContent = "✕";
td.className = "permdeny"
}
tr.appendChild(td);
}
table.appendChild(tr);
}
});
getRawPermissionsTablePromise = AppManager.deviceFront.getRawPermissionsTable()
.then(json => generateFields(json));
} else {
CloseUI();
}

View File

@ -41,6 +41,20 @@ function OnAppManagerUpdate(event, what) {
}
}
function generateFields(json) {
let table = document.querySelector("table");
for (let name in json) {
let tr = document.createElement("tr");
let td = document.createElement("td");
td.textContent = name;
tr.appendChild(td);
td = document.createElement("td");
td.textContent = json[name];
tr.appendChild(td);
table.appendChild(tr);
};
}
let getDescriptionPromise; // Used by tests
function BuildUI() {
let table = document.querySelector("table");
@ -48,19 +62,8 @@ function BuildUI() {
if (AppManager.connection &&
AppManager.connection.status == Connection.Status.CONNECTED &&
AppManager.deviceFront) {
getDescriptionPromise = AppManager.deviceFront.getDescription();
getDescriptionPromise.then(json => {
for (let name in json) {
let tr = document.createElement("tr");
let td = document.createElement("td");
td.textContent = name;
tr.appendChild(td);
td = document.createElement("td");
td.textContent = json[name];
tr.appendChild(td);
table.appendChild(tr);
}
});
getDescriptionPromise = AppManager.deviceFront.getDescription()
.then(json => generateFields(json));
} else {
CloseUI();
}

View File

@ -196,11 +196,11 @@
<iframe id="deck-panel-projecteditor" flex="1"/>
<iframe id="deck-panel-addons" flex="1" src="addons.xhtml"/>
<iframe id="deck-panel-prefs" flex="1" src="prefs.xhtml"/>
<iframe id="deck-panel-permissionstable" flex="1" src="permissionstable.xhtml"/>
<iframe id="deck-panel-runtimedetails" flex="1" src="runtimedetails.xhtml"/>
<iframe id="deck-panel-permissionstable" flex="1" lazysrc="permissionstable.xhtml"/>
<iframe id="deck-panel-runtimedetails" flex="1" lazysrc="runtimedetails.xhtml"/>
<iframe id="deck-panel-monitor" flex="1" lazysrc="monitor.xhtml"/>
<iframe id="deck-panel-devicepreferences" flex="1" src="devicepreferences.xhtml"/>
<iframe id="deck-panel-devicesettings" flex="1" src="devicesettings.xhtml"/>
<iframe id="deck-panel-devicepreferences" flex="1" lazysrc="devicepreferences.xhtml"/>
<iframe id="deck-panel-devicesettings" flex="1" lazysrc="devicesettings.xhtml"/>
</deck>
<splitter hidden="true" class="devtools-horizontal-splitter" orient="vertical"/>
<!-- toolbox iframe will be inserted here -->

View File

@ -85,6 +85,16 @@ ConfigView.prototype = {
}
},
generateDisplay: function(json) {
let deviceItems = Object.keys(json);
deviceItems.sort();
this.keys = deviceItems;
for (let i = 0; i < this.keys.length; i++) {
let key = this.keys[i];
this.generateField(key, json[key].value, json[key].hasUserValue);
}
},
generateField: function(name, value, hasUserValue, customType, newRow) {
let table = this._doc.querySelector("table");
let sResetDefault = Strings.GetStringFromName("device_reset_default");
@ -115,6 +125,10 @@ ConfigView.prototype = {
input.value = value;
}
if (!(this._includeTypeName || isNaN(parseInt(value, 10)))) {
input.type = "number";
}
td.appendChild(input);
tr.appendChild(td);
td = this._doc.createElement("td");

View File

@ -44,7 +44,8 @@ support-files =
[test_runtime.html]
[test_manifestUpdate.html]
[test_addons.html]
[test_deviceinfo.html]
[test_device_runtime.html]
[test_device_permissions.html]
[test_autoconnect_runtime.html]
[test_telemetry.html]
[test_device_preferences.html]

View File

@ -133,7 +133,7 @@ let editFieldInteger = Task.async(function*() {
let resetExistingField = Task.async(function*(id) {
let existing = doc.getElementById(id);
existing.click();
is(existing.checked, false, "Existing boolean value is correct");
is(existing.checked, true, "Existing boolean value is correct");
resetBtn = doc.getElementById("btn-" + id);
resetBtn.click();

View File

@ -137,6 +137,15 @@ function documentIsLoaded(doc) {
return deferred.promise;
}
function lazyIframeIsLoaded(iframe) {
let deferred = promise.defer();
iframe.addEventListener("load", function onLoad() {
iframe.removeEventListener("load", onLoad, true);
deferred.resolve();
}, true);
return deferred.promise;
}
function addTab(aUrl, aWindow) {
info("Adding tab: " + aUrl);

View File

@ -29,53 +29,26 @@
let win = yield openWebIDE();
let permIframe = win.document.querySelector("#deck-panel-permissionstable");
let infoIframe = win.document.querySelector("#deck-panel-runtimedetails");
yield documentIsLoaded(permIframe.contentWindow.document);
yield documentIsLoaded(infoIframe.contentWindow.document);
yield connectToLocalRuntime(win);
yield nextTick();
let perm = win.document.querySelector("#cmd_showPermissionsTable");
let info = win.document.querySelector("#cmd_showRuntimeDetails");
ok(!perm.hasAttribute("disabled"), "perm cmd enabled");
ok(!info.hasAttribute("disabled"), "info cmd enabled");
let deck = win.document.querySelector("#deck");
win.Cmds.showRuntimeDetails();
is(deck.selectedPanel, infoIframe, "info iframe selected");
yield infoIframe.contentWindow.getDescriptionPromise;
yield nextTick();
// device info and permissions content is checked in other tests
// We just test one value to make sure we get something
let doc = infoIframe.contentWindow.document;
let trs = doc.querySelectorAll("tr");
let found = false;
for (let tr of trs) {
let [name,val] = tr.querySelectorAll("td");
if (name.textContent == "appid") {
found = true;
is(val.textContent, Services.appinfo.ID, "appid has the right value");
}
}
ok(found, "Found appid line");
win.Cmds.showPermissionsTable();
is(deck.selectedPanel, permIframe, "permission iframe selected");
yield permIframe.contentWindow.getRawPermissionsTablePromise;
yield nextTick();
yield lazyIframeIsLoaded(permIframe);
yield nextTick();
yield permIframe.contentWindow.getRawPermissionsTablePromise;
doc = permIframe.contentWindow.document;
trs = doc.querySelectorAll(".line");
found = false;
@ -86,6 +59,7 @@
is(v1.className, "permprompt", "geolocation perm is valid");
is(v2.className, "permprompt", "geolocation perm is valid");
is(v3.className, "permprompt", "geolocation perm is valid");
break;
}
}
ok(found, "Found geolocation line");
@ -99,15 +73,11 @@
yield closeWebIDE(win);
SimpleTest.finish();
}).then(null, e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View File

@ -30,14 +30,10 @@
let prefIframe = win.document.querySelector("#deck-panel-devicepreferences");
yield documentIsLoaded(prefIframe.contentWindow.document);
win.AppManager.update("runtimelist");
yield connectToLocalRuntime(win);
yield nextTick();
let prefs = win.document.querySelector("#cmd_showDevicePrefs");
ok(!prefs.hasAttribute("disabled"), "device prefs cmd enabled");
@ -47,18 +43,24 @@
win.Cmds.showDevicePrefs();
is(deck.selectedPanel, prefIframe, "device preferences iframe selected");
yield prefIframe.contentWindow.getAllPrefs;
yield nextTick();
yield lazyIframeIsLoaded(prefIframe);
yield nextTick();
yield prefIframe.contentWindow.getAllPrefs;
setDocument(prefIframe);
let fields = doc.querySelectorAll(".editable");
let preference = "accessibility.blockautorefresh";
fieldChange(fields, preference);
addNewField();
let preference = "accessibility.accesskeycausesactivation";
fieldChange(fields, preference);
addNewFieldWithEnter();
editExistingField();

View File

@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript;version=1.8" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript;version=1.8">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
Task.spawn(function* () {
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
let win = yield openWebIDE();
let detailsIframe = win.document.querySelector("#deck-panel-runtimedetails");
yield connectToLocalRuntime(win);
let details = win.document.querySelector("#cmd_showRuntimeDetails");
ok(!details.hasAttribute("disabled"), "info cmd enabled");
let deck = win.document.querySelector("#deck");
win.Cmds.showRuntimeDetails();
is(deck.selectedPanel, detailsIframe, "info iframe selected");
yield nextTick();
yield lazyIframeIsLoaded(detailsIframe);
yield nextTick();
yield detailsIframe.contentWindow.getDescriptionPromise;
// device info and permissions content is checked in other tests
// We just test one value to make sure we get something
let doc = detailsIframe.contentWindow.document;
let trs = doc.querySelectorAll("tr");
let found = false;
for (let tr of trs) {
let [name,val] = tr.querySelectorAll("td");
if (name.textContent == "appid") {
found = true;
is(val.textContent, Services.appinfo.ID, "appid has the right value");
break;
}
}
ok(found, "Found appid line");
doc.querySelector("#close").click();
ok(!deck.selectedPanel, "No panel selected");
DebuggerServer.destroy();
yield closeWebIDE(win);
SimpleTest.finish();
}).then(null, e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View File

@ -34,14 +34,10 @@
let settingIframe = win.document.querySelector("#deck-panel-devicesettings");
yield documentIsLoaded(settingIframe.contentWindow.document);
win.AppManager.update("runtimelist");
yield connectToLocalRuntime(win);
yield nextTick();
let settings = win.document.querySelector("#cmd_showSettings");
ok(!settings.hasAttribute("disabled"), "device settings cmd enabled");
@ -51,9 +47,14 @@
win.Cmds.showSettings();
is(deck.selectedPanel, settingIframe, "device settings iframe selected");
yield settingIframe.contentWindow.getAllSettings;
yield nextTick();
yield lazyIframeIsLoaded(settingIframe);
yield nextTick();
yield settingIframe.contentWindow.getAllSettings;
setDocument(settingIframe);
let fields = doc.querySelectorAll(".editable");

View File

@ -427,6 +427,9 @@ These should match what Safari and other Apple applications use on OS X Lion. --
searchFor.label and searchWith.label. This string will be used instead of
them when the user has not typed any keyword. -->
<!ENTITY searchWithHeader.label "Search with:">
<!-- LOCALIZATION NOTE (changeSearchSettings.button):
This string won't wrap, so if the translated string is longer,
consider translating it as if it said only "Search Settings". -->
<!ENTITY changeSearchSettings.button "Change Search Settings">
<!ENTITY tabView.commandkey "e">

View File

@ -1,24 +1,29 @@
<!-- 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/. -->
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/. -->
<!-- LOCALIZATION NOTE : FILE This file contains the Animations panel strings.
- The Animations panel is part of the Inspector sidebar -->
The Animations panel is part of the Inspector sidebar -->
<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
- keep it in English, or another language commonly spoken among web developers.
- You want to make that choice consistent across the developer tools.
- A good criteria is the language in which you'd find the best
- documentation on web development on the web. -->
keep it in English, or another language commonly spoken among web
developers. You want to make that choice consistent across the developer
tools. A good criteria is the language in which you'd find the best
documentation on web development on the web. -->
<!-- LOCALIZATION NOTE (title): This is the label shown in the sidebar tab -->
<!ENTITY title "Animations">
<!ENTITY title "Animations">
<!-- LOCALIZATION NOTE (invalidElement): This is the label shown in the panel
- when an invalid node is currently selected in the inspector. -->
<!ENTITY invalidElement "No animations were found for the current element.">
when an invalid node is currently selected in the inspector. -->
<!ENTITY invalidElement "No animations were found for the current element.">
<!-- LOCALIZATION NOTE (selectElement): This is the label shown in the panel
- when an invalid node is currently selected in the inspector, to invite the
- user to select a new node by clicking on the element-picker icon. -->
<!ENTITY selectElement "Pick another element from the page.">
when an invalid node is currently selected in the inspector, to invite the
user to select a new node by clicking on the element-picker icon. -->
<!ENTITY selectElement "Pick another element from the page.">
<!-- LOCALIZATION NOTE (allAnimations): This is the label shown at the bottom of
the panel, in a toolbar, to let the user know the toolbar applies to all
animations, not just the ones applying to the current element. -->
<!ENTITY allAnimations "All animations">

Some files were not shown because too many files have changed in this diff Show More