mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge fx-team to m-c. a=merge
CLOSED TREE
This commit is contained in:
commit
753509e66c
@ -1718,15 +1718,17 @@ pref("loop.debug.dispatcher", false);
|
|||||||
pref("loop.debug.websocket", false);
|
pref("loop.debug.websocket", false);
|
||||||
pref("loop.debug.sdk", false);
|
pref("loop.debug.sdk", false);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
pref("loop.CSP", "default-src 'self' about: file: chrome: http://localhost:*; img-src 'self' data: http://www.gravatar.com/ about: file: chrome:; font-src 'none'; connect-src wss://*.tokbox.com https://*.opentok.com https://*.tokbox.com wss://*.mozilla.com https://*.mozilla.org wss://*.mozaws.net http://localhost:* ws://localhost:*; media-src blob:");
|
pref("loop.CSP", "default-src 'self' about: file: chrome: http://localhost:*; img-src 'self' data: https://www.gravatar.com/ about: file: chrome:; font-src 'none'; connect-src wss://*.tokbox.com https://*.opentok.com https://*.tokbox.com wss://*.mozilla.com https://*.mozilla.org wss://*.mozaws.net http://localhost:* ws://localhost:*; media-src blob:");
|
||||||
#else
|
#else
|
||||||
pref("loop.CSP", "default-src 'self' about: file: chrome:; img-src 'self' data: http://www.gravatar.com/ about: file: chrome:; font-src 'none'; connect-src wss://*.tokbox.com https://*.opentok.com https://*.tokbox.com wss://*.mozilla.com https://*.mozilla.org wss://*.mozaws.net; media-src blob:");
|
pref("loop.CSP", "default-src 'self' about: file: chrome:; img-src 'self' data: https://www.gravatar.com/ about: file: chrome:; font-src 'none'; connect-src wss://*.tokbox.com https://*.opentok.com https://*.tokbox.com wss://*.mozilla.com https://*.mozilla.org wss://*.mozaws.net; media-src blob:");
|
||||||
#endif
|
#endif
|
||||||
pref("loop.oauth.google.redirect_uri", "urn:ietf:wg:oauth:2.0:oob:auto");
|
pref("loop.oauth.google.redirect_uri", "urn:ietf:wg:oauth:2.0:oob:auto");
|
||||||
pref("loop.oauth.google.scope", "https://www.google.com/m8/feeds");
|
pref("loop.oauth.google.scope", "https://www.google.com/m8/feeds");
|
||||||
pref("loop.fxa_oauth.tokendata", "");
|
pref("loop.fxa_oauth.tokendata", "");
|
||||||
pref("loop.fxa_oauth.profile", "");
|
pref("loop.fxa_oauth.profile", "");
|
||||||
pref("loop.support_url", "https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc");
|
pref("loop.support_url", "https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc");
|
||||||
|
pref("loop.contacts.gravatars.show", false);
|
||||||
|
pref("loop.contacts.gravatars.promo", true);
|
||||||
|
|
||||||
// serverURL to be assigned by services team
|
// serverURL to be assigned by services team
|
||||||
pref("services.push.serverURL", "wss://push.services.mozilla.com/");
|
pref("services.push.serverURL", "wss://push.services.mozilla.com/");
|
||||||
|
@ -446,7 +446,9 @@
|
|||||||
</menu>
|
</menu>
|
||||||
#ifndef XP_MACOSX
|
#ifndef XP_MACOSX
|
||||||
# Disabled on Mac because we can't fill native menupopups asynchronously
|
# Disabled on Mac because we can't fill native menupopups asynchronously
|
||||||
<menuseparator/>
|
<menuseparator id="menu_readingListSeparator">
|
||||||
|
<observes element="readingListSidebar" attribute="hidden"/>
|
||||||
|
</menuseparator>
|
||||||
<menu id="menu_readingList"
|
<menu id="menu_readingList"
|
||||||
class="menu-iconic bookmark-item"
|
class="menu-iconic bookmark-item"
|
||||||
label="&readingList.label;"
|
label="&readingList.label;"
|
||||||
|
@ -117,6 +117,15 @@ const cloneValueInto = function(value, targetWindow) {
|
|||||||
return clone;
|
return clone;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the two-digit hexadecimal code for a byte
|
||||||
|
*
|
||||||
|
* @param {byte} charCode
|
||||||
|
*/
|
||||||
|
const toHexString = function(charCode) {
|
||||||
|
return ("0" + charCode.toString(16)).slice(-2);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject any API containing _only_ function properties into the given window.
|
* Inject any API containing _only_ function properties into the given window.
|
||||||
*
|
*
|
||||||
@ -740,6 +749,43 @@ function injectLoopAPI(targetWindow) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose a URL pointing to the location of an avatar by email address.
|
||||||
|
* At the moment we use the Gravatar service to match email addresses with
|
||||||
|
* avatars. This might change in the future as avatars might come from another
|
||||||
|
* source.
|
||||||
|
*
|
||||||
|
* @param {String} emailAddress Users' email address
|
||||||
|
* @param {Number} size Size of the avatar image to return in pixels.
|
||||||
|
* Optional. Default value: 40.
|
||||||
|
* @return the URL pointing to an avatar matching the provided email address.
|
||||||
|
*/
|
||||||
|
getUserAvatar: {
|
||||||
|
enumerable: true,
|
||||||
|
writable: true,
|
||||||
|
value: function(emailAddress, size = 40) {
|
||||||
|
const kEmptyGif = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
||||||
|
if (!emailAddress || !MozLoopService.getLoopPref("contacts.gravatars.show")) {
|
||||||
|
return kEmptyGif;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the MD5 dance.
|
||||||
|
let hasher = Cc["@mozilla.org/security/hash;1"]
|
||||||
|
.createInstance(Ci.nsICryptoHash);
|
||||||
|
hasher.init(Ci.nsICryptoHash.MD5);
|
||||||
|
let stringStream = Cc["@mozilla.org/io/string-input-stream;1"]
|
||||||
|
.createInstance(Ci.nsIStringInputStream);
|
||||||
|
stringStream.data = emailAddress.trim().toLowerCase();
|
||||||
|
hasher.updateFromStream(stringStream, -1);
|
||||||
|
let hash = hasher.finish(false);
|
||||||
|
// Convert the binary hash data to a hex string.
|
||||||
|
let md5Email = [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
|
||||||
|
|
||||||
|
// Compose the Gravatar URL.
|
||||||
|
return "https://www.gravatar.com/avatar/" + md5Email + ".jpg?default=blank&s=" + size;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associates a session-id and a call-id with a window for debugging.
|
* Associates a session-id and a call-id with a window for debugging.
|
||||||
*
|
*
|
||||||
|
@ -229,3 +229,44 @@
|
|||||||
.contact-form > .button-group {
|
.contact-form > .button-group {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.contacts-gravatar-promo {
|
||||||
|
position: relative;
|
||||||
|
border: 1px dashed #c1c1c1;
|
||||||
|
border-radius: 2px;
|
||||||
|
background-color: #fbfbfb;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contacts-gravatar-promo > p {
|
||||||
|
margin-top: 2px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
margin-right: 4px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[dir=rtl] .contacts-gravatar-promo > p {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contacts-gravatar-promo > p > a {
|
||||||
|
color: #0295df;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contacts-gravatar-promo > p > a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contacts-gravatar-promo > .button-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[dir=rtl] .contacts-gravatar-promo > .button-close {
|
||||||
|
right: auto;
|
||||||
|
left: 8px;
|
||||||
|
}
|
||||||
|
@ -390,6 +390,23 @@ body {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-close {
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: url(../shared/img/icons-10x10.svg#close);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 8px 8px;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
height: 8px;
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-close:hover,
|
||||||
|
.button-close:hover:active {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Dropdown menu */
|
/* Dropdown menu */
|
||||||
|
|
||||||
.dropdown {
|
.dropdown {
|
||||||
|
@ -81,6 +81,59 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
contact[field][0].value = value;
|
contact[field][0].value = value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const GravatarPromo = React.createClass({displayName: "GravatarPromo",
|
||||||
|
propTypes: {
|
||||||
|
handleUse: React.PropTypes.func.isRequired
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
showMe: navigator.mozLoop.getLoopPref("contacts.gravatars.promo") &&
|
||||||
|
!navigator.mozLoop.getLoopPref("contacts.gravatars.show")
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
handleCloseButtonClick: function() {
|
||||||
|
navigator.mozLoop.setLoopPref("contacts.gravatars.promo", false);
|
||||||
|
this.setState({ showMe: false });
|
||||||
|
},
|
||||||
|
|
||||||
|
handleUseButtonClick: function() {
|
||||||
|
navigator.mozLoop.setLoopPref("contacts.gravatars.promo", false);
|
||||||
|
navigator.mozLoop.setLoopPref("contacts.gravatars.show", true);
|
||||||
|
this.setState({ showMe: false });
|
||||||
|
this.props.handleUse();
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
if (!this.state.showMe) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let privacyUrl = navigator.mozLoop.getLoopPref("legal.privacy_url");
|
||||||
|
let message = mozL10n.get("gravatars_promo_message", {
|
||||||
|
"learn_more": React.renderToStaticMarkup(
|
||||||
|
React.createElement("a", {href: privacyUrl, target: "_blank"},
|
||||||
|
mozL10n.get("gravatars_promo_message_learnmore")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
React.createElement("div", {className: "contacts-gravatar-promo"},
|
||||||
|
React.createElement(Button, {additionalClass: "button-close", onClick: this.handleCloseButtonClick}),
|
||||||
|
React.createElement("p", {dangerouslySetInnerHTML: {__html: message}}),
|
||||||
|
React.createElement(ButtonGroup, null,
|
||||||
|
React.createElement(Button, {caption: mozL10n.get("gravatars_promo_button_nothanks"),
|
||||||
|
onClick: this.handleCloseButtonClick}),
|
||||||
|
React.createElement(Button, {caption: mozL10n.get("gravatars_promo_button_use"),
|
||||||
|
additionalClass: "button-accept",
|
||||||
|
onClick: this.handleUseButtonClick})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const ContactDropdown = React.createClass({displayName: "ContactDropdown",
|
const ContactDropdown = React.createClass({displayName: "ContactDropdown",
|
||||||
propTypes: {
|
propTypes: {
|
||||||
handleAction: React.PropTypes.func.isRequired,
|
handleAction: React.PropTypes.func.isRequired,
|
||||||
@ -232,7 +285,9 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
React.createElement("li", {className: contactCSSClass, onMouseLeave: this.hideDropdownMenu},
|
React.createElement("li", {className: contactCSSClass, onMouseLeave: this.hideDropdownMenu},
|
||||||
React.createElement("div", {className: "avatar"}),
|
React.createElement("div", {className: "avatar"},
|
||||||
|
React.createElement("img", {src: navigator.mozLoop.getUserAvatar(email.value)})
|
||||||
|
),
|
||||||
React.createElement("div", {className: "details"},
|
React.createElement("div", {className: "details"},
|
||||||
React.createElement("div", {className: "username"}, React.createElement("strong", null, names.firstName), " ", names.lastName,
|
React.createElement("div", {className: "username"}, React.createElement("strong", null, names.firstName), " ", names.lastName,
|
||||||
React.createElement("i", {className: cx({"icon icon-google": this.props.contact.category[0] == "google"})}),
|
React.createElement("i", {className: cx({"icon icon-google": this.props.contact.category[0] == "google"})}),
|
||||||
@ -462,6 +517,12 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleUseGravatar: function() {
|
||||||
|
// We got permission to use Gravatar icons now, so we need to redraw the
|
||||||
|
// list entirely to show them.
|
||||||
|
this.refresh();
|
||||||
|
},
|
||||||
|
|
||||||
sortContacts: function(contact1, contact2) {
|
sortContacts: function(contact1, contact2) {
|
||||||
let comp = contact1.name[0].localeCompare(contact2.name[0]);
|
let comp = contact1.name[0].localeCompare(contact2.name[0]);
|
||||||
if (comp !== 0) {
|
if (comp !== 0) {
|
||||||
@ -522,7 +583,8 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
React.createElement("input", {className: "contact-filter",
|
React.createElement("input", {className: "contact-filter",
|
||||||
placeholder: mozL10n.get("contacts_search_placesholder"),
|
placeholder: mozL10n.get("contacts_search_placesholder"),
|
||||||
valueLink: this.linkState("filter")})
|
valueLink: this.linkState("filter")})
|
||||||
: null
|
: null,
|
||||||
|
React.createElement(GravatarPromo, {handleUse: this.handleUseGravatar})
|
||||||
),
|
),
|
||||||
React.createElement("ul", {className: "contact-list"},
|
React.createElement("ul", {className: "contact-list"},
|
||||||
shownContacts.available ?
|
shownContacts.available ?
|
||||||
|
@ -81,6 +81,59 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
contact[field][0].value = value;
|
contact[field][0].value = value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const GravatarPromo = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
handleUse: React.PropTypes.func.isRequired
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
showMe: navigator.mozLoop.getLoopPref("contacts.gravatars.promo") &&
|
||||||
|
!navigator.mozLoop.getLoopPref("contacts.gravatars.show")
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
handleCloseButtonClick: function() {
|
||||||
|
navigator.mozLoop.setLoopPref("contacts.gravatars.promo", false);
|
||||||
|
this.setState({ showMe: false });
|
||||||
|
},
|
||||||
|
|
||||||
|
handleUseButtonClick: function() {
|
||||||
|
navigator.mozLoop.setLoopPref("contacts.gravatars.promo", false);
|
||||||
|
navigator.mozLoop.setLoopPref("contacts.gravatars.show", true);
|
||||||
|
this.setState({ showMe: false });
|
||||||
|
this.props.handleUse();
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
if (!this.state.showMe) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let privacyUrl = navigator.mozLoop.getLoopPref("legal.privacy_url");
|
||||||
|
let message = mozL10n.get("gravatars_promo_message", {
|
||||||
|
"learn_more": React.renderToStaticMarkup(
|
||||||
|
<a href={privacyUrl} target="_blank">
|
||||||
|
{mozL10n.get("gravatars_promo_message_learnmore")}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div className="contacts-gravatar-promo">
|
||||||
|
<Button additionalClass="button-close" onClick={this.handleCloseButtonClick}/>
|
||||||
|
<p dangerouslySetInnerHTML={{__html: message}}></p>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button caption={mozL10n.get("gravatars_promo_button_nothanks")}
|
||||||
|
onClick={this.handleCloseButtonClick}/>
|
||||||
|
<Button caption={mozL10n.get("gravatars_promo_button_use")}
|
||||||
|
additionalClass="button-accept"
|
||||||
|
onClick={this.handleUseButtonClick}/>
|
||||||
|
</ButtonGroup>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const ContactDropdown = React.createClass({
|
const ContactDropdown = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
handleAction: React.PropTypes.func.isRequired,
|
handleAction: React.PropTypes.func.isRequired,
|
||||||
@ -232,7 +285,9 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<li className={contactCSSClass} onMouseLeave={this.hideDropdownMenu}>
|
<li className={contactCSSClass} onMouseLeave={this.hideDropdownMenu}>
|
||||||
<div className="avatar" />
|
<div className="avatar">
|
||||||
|
<img src={navigator.mozLoop.getUserAvatar(email.value)} />
|
||||||
|
</div>
|
||||||
<div className="details">
|
<div className="details">
|
||||||
<div className="username"><strong>{names.firstName}</strong> {names.lastName}
|
<div className="username"><strong>{names.firstName}</strong> {names.lastName}
|
||||||
<i className={cx({"icon icon-google": this.props.contact.category[0] == "google"})} />
|
<i className={cx({"icon icon-google": this.props.contact.category[0] == "google"})} />
|
||||||
@ -462,6 +517,12 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleUseGravatar: function() {
|
||||||
|
// We got permission to use Gravatar icons now, so we need to redraw the
|
||||||
|
// list entirely to show them.
|
||||||
|
this.refresh();
|
||||||
|
},
|
||||||
|
|
||||||
sortContacts: function(contact1, contact2) {
|
sortContacts: function(contact1, contact2) {
|
||||||
let comp = contact1.name[0].localeCompare(contact2.name[0]);
|
let comp = contact1.name[0].localeCompare(contact2.name[0]);
|
||||||
if (comp !== 0) {
|
if (comp !== 0) {
|
||||||
@ -523,6 +584,7 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
placeholder={mozL10n.get("contacts_search_placesholder")}
|
placeholder={mozL10n.get("contacts_search_placesholder")}
|
||||||
valueLink={this.linkState("filter")} />
|
valueLink={this.linkState("filter")} />
|
||||||
: null }
|
: null }
|
||||||
|
<GravatarPromo handleUse={this.handleUseGravatar}/>
|
||||||
</div>
|
</div>
|
||||||
<ul className="contact-list">
|
<ul className="contact-list">
|
||||||
{shownContacts.available ?
|
{shownContacts.available ?
|
||||||
|
@ -40,6 +40,18 @@ loop.panel = (function(_, mozL10n) {
|
|||||||
if (tabChange) {
|
if (tabChange) {
|
||||||
this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab);
|
this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tabChange && nextProps.buttonsHidden) {
|
||||||
|
if (nextProps.buttonsHidden.length !== this.props.buttonsHidden.length) {
|
||||||
|
tabChange = true;
|
||||||
|
} else {
|
||||||
|
for (var i = 0, l = nextProps.buttonsHidden.length; i < l && !tabChange; ++i) {
|
||||||
|
if (this.props.buttonsHidden.indexOf(nextProps.buttonsHidden[i]) === -1) {
|
||||||
|
tabChange = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return tabChange;
|
return tabChange;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -40,6 +40,18 @@ loop.panel = (function(_, mozL10n) {
|
|||||||
if (tabChange) {
|
if (tabChange) {
|
||||||
this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab);
|
this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tabChange && nextProps.buttonsHidden) {
|
||||||
|
if (nextProps.buttonsHidden.length !== this.props.buttonsHidden.length) {
|
||||||
|
tabChange = true;
|
||||||
|
} else {
|
||||||
|
for (var i = 0, l = nextProps.buttonsHidden.length; i < l && !tabChange; ++i) {
|
||||||
|
if (this.props.buttonsHidden.indexOf(nextProps.buttonsHidden[i]) === -1) {
|
||||||
|
tabChange = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return tabChange;
|
return tabChange;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -72,7 +72,11 @@ loop.Dispatcher = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registeredStores.forEach(function(store) {
|
registeredStores.forEach(function(store) {
|
||||||
|
try {
|
||||||
store[type](action);
|
store[type](action);
|
||||||
|
} catch (x) {
|
||||||
|
console.error("[Dispatcher] Dispatching action caused an exception: ", x);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this._active = false;
|
this._active = false;
|
||||||
|
@ -14,9 +14,71 @@ describe("loop.contacts", function() {
|
|||||||
var fakeAddContactButtonText = "Fake Add Contact";
|
var fakeAddContactButtonText = "Fake Add Contact";
|
||||||
var fakeEditContactButtonText = "Fake Edit Contact";
|
var fakeEditContactButtonText = "Fake Edit Contact";
|
||||||
var fakeDoneButtonText = "Fake Done";
|
var fakeDoneButtonText = "Fake Done";
|
||||||
|
// The fake contacts array is copied each time mozLoop.contacts.getAll() is called.
|
||||||
|
var fakeContacts = [{
|
||||||
|
id: 1,
|
||||||
|
_guid: 1,
|
||||||
|
name: ["Ally Avocado"],
|
||||||
|
email: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["work"],
|
||||||
|
"value": "ally@mail.com"
|
||||||
|
}],
|
||||||
|
tel: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["mobile"],
|
||||||
|
"value": "+31-6-12345678"
|
||||||
|
}],
|
||||||
|
category: ["google"],
|
||||||
|
published: 1406798311748,
|
||||||
|
updated: 1406798311748
|
||||||
|
},{
|
||||||
|
id: 2,
|
||||||
|
_guid: 2,
|
||||||
|
name: ["Bob Banana"],
|
||||||
|
email: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["work"],
|
||||||
|
"value": "bob@gmail.com"
|
||||||
|
}],
|
||||||
|
tel: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["mobile"],
|
||||||
|
"value": "+1-214-5551234"
|
||||||
|
}],
|
||||||
|
category: ["local"],
|
||||||
|
published: 1406798311748,
|
||||||
|
updated: 1406798311748
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
_guid: 3,
|
||||||
|
name: ["Caitlin Cantaloupe"],
|
||||||
|
email: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["work"],
|
||||||
|
"value": "caitlin.cant@hotmail.com"
|
||||||
|
}],
|
||||||
|
category: ["local"],
|
||||||
|
published: 1406798311748,
|
||||||
|
updated: 1406798311748
|
||||||
|
}, {
|
||||||
|
id: 4,
|
||||||
|
_guid: 4,
|
||||||
|
name: ["Dave Dragonfruit"],
|
||||||
|
email: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["work"],
|
||||||
|
"value": "dd@dragons.net"
|
||||||
|
}],
|
||||||
|
category: ["google"],
|
||||||
|
published: 1406798311748,
|
||||||
|
updated: 1406798311748
|
||||||
|
}];
|
||||||
var sandbox;
|
var sandbox;
|
||||||
var fakeWindow;
|
var fakeWindow;
|
||||||
var notifications;
|
var notifications;
|
||||||
|
var listView;
|
||||||
|
var oldMozLoop = navigator.mozLoop;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
sandbox = sinon.sandbox.create();
|
sandbox = sinon.sandbox.create();
|
||||||
@ -32,6 +94,27 @@ describe("loop.contacts", function() {
|
|||||||
}
|
}
|
||||||
return JSON.stringify({textContent: textContentValue});
|
return JSON.stringify({textContent: textContentValue});
|
||||||
},
|
},
|
||||||
|
getLoopPref: function(pref) {
|
||||||
|
if (pref == "contacts.gravatars.promo") {
|
||||||
|
return true;
|
||||||
|
} else if (pref == "contacts.gravatars.show") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
setLoopPref: sandbox.stub(),
|
||||||
|
getUserAvatar: function() {
|
||||||
|
if (navigator.mozLoop.getLoopPref("contacts.gravatars.show")) {
|
||||||
|
return "gravatarsEnabled";
|
||||||
|
}
|
||||||
|
return "gravatarsDisabled";
|
||||||
|
},
|
||||||
|
contacts: {
|
||||||
|
getAll: function(callback) {
|
||||||
|
callback(null, [].concat(fakeContacts));
|
||||||
|
},
|
||||||
|
on: sandbox.stub()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fakeWindow = {
|
fakeWindow = {
|
||||||
@ -39,18 +122,120 @@ describe("loop.contacts", function() {
|
|||||||
};
|
};
|
||||||
loop.shared.mixins.setRootObject(fakeWindow);
|
loop.shared.mixins.setRootObject(fakeWindow);
|
||||||
|
|
||||||
|
notifications = new loop.shared.models.NotificationCollection();
|
||||||
|
|
||||||
document.mozL10n.initialize(navigator.mozLoop);
|
document.mozL10n.initialize(navigator.mozLoop);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
|
listView = null;
|
||||||
loop.shared.mixins.setRootObject(window);
|
loop.shared.mixins.setRootObject(window);
|
||||||
|
navigator.mozLoop = oldMozLoop;
|
||||||
sandbox.restore();
|
sandbox.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("GravatarsPromo", function() {
|
||||||
|
function checkGravatarContacts(enabled) {
|
||||||
|
var node = listView.getDOMNode();
|
||||||
|
|
||||||
|
// When gravatars are enabled, contacts should be rendered with gravatars.
|
||||||
|
var gravatars = node.querySelectorAll(".contact img[src=gravatarsEnabled]");
|
||||||
|
expect(gravatars.length).to.equal(enabled ? fakeContacts.length : 0);
|
||||||
|
// Sanity check the reverse:
|
||||||
|
gravatars = node.querySelectorAll(".contact img[src=gravatarsDisabled]");
|
||||||
|
expect(gravatars.length).to.equal(enabled ? 0 : fakeContacts.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
it("should show the gravatars promo box", function() {
|
||||||
|
listView = TestUtils.renderIntoDocument(
|
||||||
|
React.createElement(loop.contacts.ContactsList, {
|
||||||
|
notifications: notifications
|
||||||
|
}));
|
||||||
|
|
||||||
|
var promo = listView.getDOMNode().querySelector(".contacts-gravatar-promo");
|
||||||
|
expect(promo).to.not.equal(null);
|
||||||
|
|
||||||
|
checkGravatarContacts(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not show the gravatars promo box when the 'contacts.gravatars.promo' pref is set", function() {
|
||||||
|
navigator.mozLoop.getLoopPref = function(pref) {
|
||||||
|
if (pref == "contacts.gravatars.promo") {
|
||||||
|
return false;
|
||||||
|
} else if (pref == "contacts.gravatars.show") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
listView = TestUtils.renderIntoDocument(
|
||||||
|
React.createElement(loop.contacts.ContactsList, {
|
||||||
|
notifications: notifications
|
||||||
|
}));
|
||||||
|
|
||||||
|
var promo = listView.getDOMNode().querySelector(".contacts-gravatar-promo");
|
||||||
|
expect(promo).to.equal(null);
|
||||||
|
|
||||||
|
checkGravatarContacts(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should hide the gravatars promo box when the 'use' button is clicked", function() {
|
||||||
|
listView = TestUtils.renderIntoDocument(
|
||||||
|
React.createElement(loop.contacts.ContactsList, {
|
||||||
|
notifications: notifications
|
||||||
|
}));
|
||||||
|
|
||||||
|
React.addons.TestUtils.Simulate.click(listView.getDOMNode().querySelector(
|
||||||
|
".contacts-gravatar-promo .button-accept"));
|
||||||
|
|
||||||
|
sinon.assert.calledTwice(navigator.mozLoop.setLoopPref);
|
||||||
|
|
||||||
|
var promo = listView.getDOMNode().querySelector(".contacts-gravatar-promo");
|
||||||
|
expect(promo).to.equal(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should should set the prefs correctly when the 'use' button is clicked", function() {
|
||||||
|
listView = TestUtils.renderIntoDocument(
|
||||||
|
React.createElement(loop.contacts.ContactsList, {
|
||||||
|
notifications: notifications
|
||||||
|
}));
|
||||||
|
|
||||||
|
React.addons.TestUtils.Simulate.click(listView.getDOMNode().querySelector(
|
||||||
|
".contacts-gravatar-promo .button-accept"));
|
||||||
|
|
||||||
|
sinon.assert.calledTwice(navigator.mozLoop.setLoopPref);
|
||||||
|
sinon.assert.calledWithExactly(navigator.mozLoop.setLoopPref, "contacts.gravatars.promo", false);
|
||||||
|
sinon.assert.calledWithExactly(navigator.mozLoop.setLoopPref, "contacts.gravatars.show", true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should hide the gravatars promo box when the 'close' button is clicked", function() {
|
||||||
|
listView = TestUtils.renderIntoDocument(
|
||||||
|
React.createElement(loop.contacts.ContactsList, {
|
||||||
|
notifications: notifications
|
||||||
|
}));
|
||||||
|
|
||||||
|
React.addons.TestUtils.Simulate.click(listView.getDOMNode().querySelector(
|
||||||
|
".contacts-gravatar-promo .button-close"));
|
||||||
|
|
||||||
|
var promo = listView.getDOMNode().querySelector(".contacts-gravatar-promo");
|
||||||
|
expect(promo).to.equal(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should set prefs correctly when the 'close' button is clicked", function() {
|
||||||
|
listView = TestUtils.renderIntoDocument(
|
||||||
|
React.createElement(loop.contacts.ContactsList, {
|
||||||
|
notifications: notifications
|
||||||
|
}));
|
||||||
|
|
||||||
|
React.addons.TestUtils.Simulate.click(listView.getDOMNode().querySelector(
|
||||||
|
".contacts-gravatar-promo .button-close"));
|
||||||
|
|
||||||
|
sinon.assert.calledOnce(navigator.mozLoop.setLoopPref);
|
||||||
|
sinon.assert.calledWithExactly(navigator.mozLoop.setLoopPref,
|
||||||
|
"contacts.gravatars.promo", false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("ContactsList", function () {
|
describe("ContactsList", function () {
|
||||||
var listView;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
navigator.mozLoop.calls = {
|
navigator.mozLoop.calls = {
|
||||||
startDirectCall: sandbox.stub(),
|
startDirectCall: sandbox.stub(),
|
||||||
@ -58,19 +243,12 @@ describe("loop.contacts", function() {
|
|||||||
};
|
};
|
||||||
navigator.mozLoop.contacts = {getAll: sandbox.stub()};
|
navigator.mozLoop.contacts = {getAll: sandbox.stub()};
|
||||||
|
|
||||||
notifications = new loop.shared.models.NotificationCollection();
|
|
||||||
listView = TestUtils.renderIntoDocument(
|
listView = TestUtils.renderIntoDocument(
|
||||||
React.createElement(loop.contacts.ContactsList, {
|
React.createElement(loop.contacts.ContactsList, {
|
||||||
notifications: notifications
|
notifications: notifications
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
|
||||||
listView = null;
|
|
||||||
delete navigator.mozLoop.calls;
|
|
||||||
delete navigator.mozLoop.contacts;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("#handleContactAction", function() {
|
describe("#handleContactAction", function() {
|
||||||
it("should call window.close when called with 'video-call' action",
|
it("should call window.close when called with 'video-call' action",
|
||||||
function() {
|
function() {
|
||||||
|
@ -38,6 +38,8 @@ add_task(function* test_LoopUI_getters() {
|
|||||||
yield loadLoopPanel();
|
yield loadLoopPanel();
|
||||||
Assert.ok(LoopUI.browser, "Browser element should be there");
|
Assert.ok(LoopUI.browser, "Browser element should be there");
|
||||||
Assert.strictEqual(LoopUI.selectedTab, "rooms", "Initially the rooms tab should be selected");
|
Assert.strictEqual(LoopUI.selectedTab, "rooms", "Initially the rooms tab should be selected");
|
||||||
|
let panelTabs = LoopUI.browser.contentDocument.querySelectorAll(".tab-view > li");
|
||||||
|
Assert.strictEqual(panelTabs.length, 1, "Only one tab, 'rooms', should be visible");
|
||||||
|
|
||||||
// Hide the panel.
|
// Hide the panel.
|
||||||
yield LoopUI.togglePanel();
|
yield LoopUI.togglePanel();
|
||||||
@ -48,6 +50,12 @@ add_task(function* test_LoopUI_getters() {
|
|||||||
MozLoopServiceInternal.fxAOAuthProfile = fxASampleProfile;
|
MozLoopServiceInternal.fxAOAuthProfile = fxASampleProfile;
|
||||||
yield MozLoopServiceInternal.notifyStatusChanged("login");
|
yield MozLoopServiceInternal.notifyStatusChanged("login");
|
||||||
|
|
||||||
|
yield LoopUI.togglePanel();
|
||||||
|
Assert.strictEqual(LoopUI.selectedTab, "rooms", "Rooms tab should still be selected");
|
||||||
|
panelTabs = LoopUI.browser.contentDocument.querySelectorAll(".tab-view > li");
|
||||||
|
Assert.strictEqual(panelTabs.length, 2, "Two tabs should be visible");
|
||||||
|
yield LoopUI.togglePanel();
|
||||||
|
|
||||||
// Programmatically select the contacts tab.
|
// Programmatically select the contacts tab.
|
||||||
yield LoopUI.togglePanel(null, "contacts");
|
yield LoopUI.togglePanel(null, "contacts");
|
||||||
Assert.strictEqual(LoopUI.selectedTab, "contacts", "Contacts tab should be selected now");
|
Assert.strictEqual(LoopUI.selectedTab, "contacts", "Contacts tab should be selected now");
|
||||||
|
@ -104,6 +104,31 @@ describe("loop.Dispatcher", function () {
|
|||||||
sinon.assert.calledOnce(getDataStore2.getWindowData);
|
sinon.assert.calledOnce(getDataStore2.getWindowData);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Error handling", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
sandbox.stub(console, "error");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should handle uncaught exceptions", function() {
|
||||||
|
getDataStore1.getWindowData.throws("Uncaught Error");
|
||||||
|
|
||||||
|
dispatcher.dispatch(getDataAction);
|
||||||
|
dispatcher.dispatch(cancelAction);
|
||||||
|
|
||||||
|
sinon.assert.calledOnce(getDataStore1.getWindowData);
|
||||||
|
sinon.assert.calledOnce(getDataStore2.getWindowData);
|
||||||
|
sinon.assert.calledOnce(cancelStore1.cancelCall);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should log uncaught exceptions", function() {
|
||||||
|
getDataStore1.getWindowData.throws("Uncaught Error");
|
||||||
|
|
||||||
|
dispatcher.dispatch(getDataAction);
|
||||||
|
|
||||||
|
sinon.assert.calledOnce(console.error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("Queued actions", function() {
|
describe("Queued actions", function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
// Restore the stub, so that we can easily add a function to be
|
// Restore the stub, so that we can easily add a function to be
|
||||||
|
@ -43,6 +43,66 @@ var fakeRooms = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var fakeContacts = [{
|
||||||
|
id: 1,
|
||||||
|
_guid: 1,
|
||||||
|
name: ["Ally Avocado"],
|
||||||
|
email: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["work"],
|
||||||
|
"value": "ally@mail.com"
|
||||||
|
}],
|
||||||
|
tel: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["mobile"],
|
||||||
|
"value": "+31-6-12345678"
|
||||||
|
}],
|
||||||
|
category: ["google"],
|
||||||
|
published: 1406798311748,
|
||||||
|
updated: 1406798311748
|
||||||
|
},{
|
||||||
|
id: 2,
|
||||||
|
_guid: 2,
|
||||||
|
name: ["Bob Banana"],
|
||||||
|
email: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["work"],
|
||||||
|
"value": "bob@gmail.com"
|
||||||
|
}],
|
||||||
|
tel: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["mobile"],
|
||||||
|
"value": "+1-214-5551234"
|
||||||
|
}],
|
||||||
|
category: ["local"],
|
||||||
|
published: 1406798311748,
|
||||||
|
updated: 1406798311748
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
_guid: 3,
|
||||||
|
name: ["Caitlin Cantaloupe"],
|
||||||
|
email: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["work"],
|
||||||
|
"value": "caitlin.cant@hotmail.com"
|
||||||
|
}],
|
||||||
|
category: ["local"],
|
||||||
|
published: 1406798311748,
|
||||||
|
updated: 1406798311748
|
||||||
|
}, {
|
||||||
|
id: 4,
|
||||||
|
_guid: 4,
|
||||||
|
name: ["Dave Dragonfruit"],
|
||||||
|
email: [{
|
||||||
|
"pref": true,
|
||||||
|
"type": ["work"],
|
||||||
|
"value": "dd@dragons.net"
|
||||||
|
}],
|
||||||
|
category: ["google"],
|
||||||
|
published: 1406798311748,
|
||||||
|
updated: 1406798311748
|
||||||
|
}];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Faking the mozLoop object which doesn't exist in regular web pages.
|
* Faking the mozLoop object which doesn't exist in regular web pages.
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
@ -54,21 +114,28 @@ navigator.mozLoop = {
|
|||||||
switch(pref) {
|
switch(pref) {
|
||||||
// Ensure we skip FTE completely.
|
// Ensure we skip FTE completely.
|
||||||
case "gettingStarted.seen":
|
case "gettingStarted.seen":
|
||||||
|
case "contacts.gravatars.promo":
|
||||||
return true;
|
return true;
|
||||||
|
case "contacts.gravatars.show":
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setLoopPref: function(){},
|
setLoopPref: function(){},
|
||||||
releaseCallData: function() {},
|
releaseCallData: function() {},
|
||||||
copyString: function() {},
|
copyString: function() {},
|
||||||
|
getUserAvatar: function(emailAddress) {
|
||||||
|
return "http://www.gravatar.com/avatar/" + (Math.ceil(Math.random() * 3) === 2 ?
|
||||||
|
"0a996f0fe2727ef1668bdb11897e4459" : "foo") + ".jpg?default=blank&s=40";
|
||||||
|
},
|
||||||
contacts: {
|
contacts: {
|
||||||
getAll: function(callback) {
|
getAll: function(callback) {
|
||||||
callback(null, []);
|
callback(null, [].concat(fakeContacts));
|
||||||
},
|
},
|
||||||
on: function() {}
|
on: function() {}
|
||||||
},
|
},
|
||||||
rooms: {
|
rooms: {
|
||||||
getAll: function(version, callback) {
|
getAll: function(version, callback) {
|
||||||
callback(null, fakeRooms);
|
callback(null, [].concat(fakeRooms));
|
||||||
},
|
},
|
||||||
on: function() {}
|
on: function() {}
|
||||||
},
|
},
|
||||||
|
@ -10,11 +10,22 @@ function checkRLState() {
|
|||||||
let sidebarBroadcaster = document.getElementById("readingListSidebar");
|
let sidebarBroadcaster = document.getElementById("readingListSidebar");
|
||||||
let sidebarMenuitem = document.getElementById("menu_readingListSidebar");
|
let sidebarMenuitem = document.getElementById("menu_readingListSidebar");
|
||||||
|
|
||||||
|
let bookmarksMenubarItem = document.getElementById("menu_readingList");
|
||||||
|
let bookmarksMenubarSeparator = document.getElementById("menu_readingListSeparator");
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
Assert.notEqual(sidebarBroadcaster.getAttribute("hidden"), "true",
|
Assert.notEqual(sidebarBroadcaster.getAttribute("hidden"), "true",
|
||||||
"Sidebar broadcaster should not be hidden");
|
"Sidebar broadcaster should not be hidden");
|
||||||
Assert.notEqual(sidebarMenuitem.getAttribute("hidden"), "true",
|
Assert.notEqual(sidebarMenuitem.getAttribute("hidden"), "true",
|
||||||
"Sidebar menuitem should be visible");
|
"Sidebar menuitem should be visible");
|
||||||
|
|
||||||
|
// Currently disabled on OSX.
|
||||||
|
if (bookmarksMenubarItem) {
|
||||||
|
Assert.notEqual(bookmarksMenubarItem.getAttribute("hidden"), "true",
|
||||||
|
"RL bookmarks submenu in menubar should not be hidden");
|
||||||
|
Assert.notEqual(sidebarMenuitem.getAttribute("hidden"), "true",
|
||||||
|
"RL bookmarks separator in menubar should be visible");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Assert.equal(sidebarBroadcaster.getAttribute("hidden"), "true",
|
Assert.equal(sidebarBroadcaster.getAttribute("hidden"), "true",
|
||||||
"Sidebar broadcaster should be hidden");
|
"Sidebar broadcaster should be hidden");
|
||||||
@ -22,6 +33,14 @@ function checkRLState() {
|
|||||||
"Sidebar menuitem should be hidden");
|
"Sidebar menuitem should be hidden");
|
||||||
Assert.equal(ReadingListUI.isSidebarOpen, false,
|
Assert.equal(ReadingListUI.isSidebarOpen, false,
|
||||||
"ReadingListUI should not think sidebar is open");
|
"ReadingListUI should not think sidebar is open");
|
||||||
|
|
||||||
|
// Currently disabled on OSX.
|
||||||
|
if (bookmarksMenubarItem) {
|
||||||
|
Assert.equal(bookmarksMenubarItem.getAttribute("hidden"), "true",
|
||||||
|
"RL bookmarks submenu in menubar should not be hidden");
|
||||||
|
Assert.equal(sidebarMenuitem.getAttribute("hidden"), "true",
|
||||||
|
"RL bookmarks separator in menubar should be visible");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
|
@ -266,7 +266,10 @@ function mousedown (win, button) {
|
|||||||
EventUtils.sendMouseEvent({ type: "mousedown" }, button, win);
|
EventUtils.sendMouseEvent({ type: "mousedown" }, button, win);
|
||||||
}
|
}
|
||||||
|
|
||||||
function* startRecording(panel, options={}) {
|
function* startRecording(panel, options = {
|
||||||
|
waitForOverview: true,
|
||||||
|
waitForStateChanged: true
|
||||||
|
}) {
|
||||||
let win = panel.panelWin;
|
let win = panel.panelWin;
|
||||||
let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_START_RECORDING);
|
let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_START_RECORDING);
|
||||||
let willStart = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_WILL_START);
|
let willStart = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_WILL_START);
|
||||||
@ -287,10 +290,14 @@ function* startRecording(panel, options={}) {
|
|||||||
"The record button should be locked.");
|
"The record button should be locked.");
|
||||||
|
|
||||||
yield willStart;
|
yield willStart;
|
||||||
let stateChanged = once(win.PerformanceView, win.EVENTS.UI_STATE_CHANGED);
|
let stateChanged = options.waitForStateChanged
|
||||||
|
? once(win.PerformanceView, win.EVENTS.UI_STATE_CHANGED)
|
||||||
|
: Promise.resolve();
|
||||||
|
|
||||||
yield hasStarted;
|
yield hasStarted;
|
||||||
let overviewRendered = options.waitForOverview ? once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED) : Promise.resolve();
|
let overviewRendered = options.waitForOverview
|
||||||
|
? once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED)
|
||||||
|
: Promise.resolve();
|
||||||
|
|
||||||
yield stateChanged;
|
yield stateChanged;
|
||||||
yield overviewRendered;
|
yield overviewRendered;
|
||||||
@ -304,7 +311,10 @@ function* startRecording(panel, options={}) {
|
|||||||
"The record button should not be locked.");
|
"The record button should not be locked.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function* stopRecording(panel, options={}) {
|
function* stopRecording(panel, options = {
|
||||||
|
waitForOverview: true,
|
||||||
|
waitForStateChanged: true
|
||||||
|
}) {
|
||||||
let win = panel.panelWin;
|
let win = panel.panelWin;
|
||||||
let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_STOP_RECORDING);
|
let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_STOP_RECORDING);
|
||||||
let willStop = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_WILL_STOP);
|
let willStop = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_WILL_STOP);
|
||||||
@ -325,10 +335,14 @@ function* stopRecording(panel, options={}) {
|
|||||||
"The record button should be locked.");
|
"The record button should be locked.");
|
||||||
|
|
||||||
yield willStop;
|
yield willStop;
|
||||||
let stateChanged = once(win.PerformanceView, win.EVENTS.UI_STATE_CHANGED);
|
let stateChanged = options.waitForStateChanged
|
||||||
|
? once(win.PerformanceView, win.EVENTS.UI_STATE_CHANGED)
|
||||||
|
: Promise.resolve();
|
||||||
|
|
||||||
yield hasStopped;
|
yield hasStopped;
|
||||||
let overviewRendered = options.waitForOverview ? once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED) : Promise.resolve();
|
let overviewRendered = options.waitForOverview
|
||||||
|
? once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED)
|
||||||
|
: Promise.resolve();
|
||||||
|
|
||||||
yield stateChanged;
|
yield stateChanged;
|
||||||
yield overviewRendered;
|
yield overviewRendered;
|
||||||
|
@ -34,11 +34,13 @@ let JsFlameGraphView = Heritage.extend(DetailsSubview, {
|
|||||||
/**
|
/**
|
||||||
* Unbinds events.
|
* Unbinds events.
|
||||||
*/
|
*/
|
||||||
destroy: function () {
|
destroy: Task.async(function* () {
|
||||||
DetailsSubview.destroy.call(this);
|
DetailsSubview.destroy.call(this);
|
||||||
|
|
||||||
this.graph.off("selecting", this._onRangeChangeInGraph);
|
this.graph.off("selecting", this._onRangeChangeInGraph);
|
||||||
},
|
|
||||||
|
yield this.graph.destroy();
|
||||||
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method for handling all the set up for rendering a new flamegraph.
|
* Method for handling all the set up for rendering a new flamegraph.
|
||||||
|
@ -33,11 +33,13 @@ let MemoryFlameGraphView = Heritage.extend(DetailsSubview, {
|
|||||||
/**
|
/**
|
||||||
* Unbinds events.
|
* Unbinds events.
|
||||||
*/
|
*/
|
||||||
destroy: function () {
|
destroy: Task.async(function* () {
|
||||||
DetailsSubview.destroy.call(this);
|
DetailsSubview.destroy.call(this);
|
||||||
|
|
||||||
this.graph.off("selecting", this._onRangeChangeInGraph);
|
this.graph.off("selecting", this._onRangeChangeInGraph);
|
||||||
},
|
|
||||||
|
yield this.graph.destroy();
|
||||||
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method for handling all the set up for rendering a new flamegraph.
|
* Method for handling all the set up for rendering a new flamegraph.
|
||||||
|
@ -54,15 +54,15 @@ let OverviewView = {
|
|||||||
/**
|
/**
|
||||||
* Unbinds events.
|
* Unbinds events.
|
||||||
*/
|
*/
|
||||||
destroy: function () {
|
destroy: Task.async(function*() {
|
||||||
if (this.markersOverview) {
|
if (this.markersOverview) {
|
||||||
this.markersOverview.destroy();
|
yield this.markersOverview.destroy();
|
||||||
}
|
}
|
||||||
if (this.memoryOverview) {
|
if (this.memoryOverview) {
|
||||||
this.memoryOverview.destroy();
|
yield this.memoryOverview.destroy();
|
||||||
}
|
}
|
||||||
if (this.framerateGraph) {
|
if (this.framerateGraph) {
|
||||||
this.framerateGraph.destroy();
|
yield this.framerateGraph.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceController.off(EVENTS.PREF_CHANGED, this._onPrefChanged);
|
PerformanceController.off(EVENTS.PREF_CHANGED, this._onPrefChanged);
|
||||||
@ -71,7 +71,7 @@ let OverviewView = {
|
|||||||
PerformanceController.off(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
|
PerformanceController.off(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
|
||||||
PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
|
PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
|
||||||
PerformanceController.off(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
|
PerformanceController.off(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
|
||||||
},
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disabled in the event we're using a Timeline mock, so we'll have no
|
* Disabled in the event we're using a Timeline mock, so we'll have no
|
||||||
|
@ -26,7 +26,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(host, graph);
|
testGraph(host, graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ function* performTest() {
|
|||||||
yield graph.ready();
|
yield graph.ready();
|
||||||
testGraph(host, graph);
|
testGraph(host, graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(graph);
|
testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(graph);
|
testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(graph);
|
testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(host, graph);
|
testGraph(host, graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ function* performTest() {
|
|||||||
testDataAndRegions(graph);
|
testDataAndRegions(graph);
|
||||||
testHighlights(graph);
|
testHighlights(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ function* performTest() {
|
|||||||
yield testSelection(graph);
|
yield testSelection(graph);
|
||||||
yield testCursor(graph);
|
yield testCursor(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(graph);
|
testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(graph);
|
testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(graph);
|
testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(graph);
|
testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(graph);
|
testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(graph);
|
testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ function* performTest() {
|
|||||||
|
|
||||||
yield testGraph(graph);
|
yield testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ function* performTest() {
|
|||||||
|
|
||||||
yield testGraph(graph);
|
yield testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ function* performTest() {
|
|||||||
|
|
||||||
yield testGraph(graph);
|
yield testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ function* performTest() {
|
|||||||
|
|
||||||
yield testGraph(graph);
|
yield testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ function* performTest() {
|
|||||||
|
|
||||||
yield testGraph(graph);
|
yield testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,5 +48,5 @@ function* testGraph (parent, options) {
|
|||||||
is(graph._avgGutterLine.hidden, options.avg === false,
|
is(graph._avgGutterLine.hidden, options.avg === false,
|
||||||
`The avg gutter should ${options.avg === false ? "not " : ""}be shown`);
|
`The avg gutter should ${options.avg === false ? "not " : ""}be shown`);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ function* performTest() {
|
|||||||
|
|
||||||
is(refreshCount, 2, "The graph should've been refreshed 2 times.");
|
is(refreshCount, 2, "The graph should've been refreshed 2 times.");
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ function* performTest() {
|
|||||||
is(refreshCount, 0, "The graph shouldn't have been refreshed at all.");
|
is(refreshCount, 0, "The graph shouldn't have been refreshed at all.");
|
||||||
is(refreshCancelledCount, 2, "The graph should've had 2 refresh attempts.");
|
is(refreshCancelledCount, 2, "The graph should've had 2 refresh attempts.");
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraph(graph);
|
testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ function* performTest() {
|
|||||||
yield graph.once("ready");
|
yield graph.once("ready");
|
||||||
yield testGraph(graph);
|
yield testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ function* performTest() {
|
|||||||
|
|
||||||
testGraphs(graph1, graph2);
|
testGraphs(graph1, graph2);
|
||||||
|
|
||||||
graph1.destroy();
|
yield graph1.destroy();
|
||||||
graph2.destroy();
|
yield graph2.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ function* performTest() {
|
|||||||
yield graph.ready();
|
yield graph.ready();
|
||||||
testGraph(host, graph);
|
testGraph(host, graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ function* performTest() {
|
|||||||
|
|
||||||
yield testGraph(graph);
|
yield testGraph(graph);
|
||||||
|
|
||||||
graph.destroy();
|
yield graph.destroy();
|
||||||
host.destroy();
|
host.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ const OVERVIEW_ROW_HEIGHT = 11; // px
|
|||||||
const OVERVIEW_SELECTION_LINE_COLOR = "#666";
|
const OVERVIEW_SELECTION_LINE_COLOR = "#666";
|
||||||
const OVERVIEW_CLIPHEAD_LINE_COLOR = "#555";
|
const OVERVIEW_CLIPHEAD_LINE_COLOR = "#555";
|
||||||
|
|
||||||
|
const FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS = 100;
|
||||||
const OVERVIEW_HEADER_TICKS_MULTIPLE = 100; // ms
|
const OVERVIEW_HEADER_TICKS_MULTIPLE = 100; // ms
|
||||||
const OVERVIEW_HEADER_TICKS_SPACING_MIN = 75; // px
|
const OVERVIEW_HEADER_TICKS_SPACING_MIN = 75; // px
|
||||||
const OVERVIEW_HEADER_TEXT_FONT_SIZE = 9; // px
|
const OVERVIEW_HEADER_TEXT_FONT_SIZE = 9; // px
|
||||||
@ -199,9 +200,18 @@ MarkersOverview.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||||||
_findOptimalTickInterval: function(dataScale) {
|
_findOptimalTickInterval: function(dataScale) {
|
||||||
let timingStep = OVERVIEW_HEADER_TICKS_MULTIPLE;
|
let timingStep = OVERVIEW_HEADER_TICKS_MULTIPLE;
|
||||||
let spacingMin = OVERVIEW_HEADER_TICKS_SPACING_MIN * this._pixelRatio;
|
let spacingMin = OVERVIEW_HEADER_TICKS_SPACING_MIN * this._pixelRatio;
|
||||||
|
let maxIters = FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS;
|
||||||
|
let numIters = 0;
|
||||||
|
|
||||||
|
if (dataScale > spacingMin) {
|
||||||
|
return dataScale;
|
||||||
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
let scaledStep = dataScale * timingStep;
|
let scaledStep = dataScale * timingStep;
|
||||||
|
if (++numIters > maxIters) {
|
||||||
|
return scaledStep;
|
||||||
|
}
|
||||||
if (scaledStep < spacingMin) {
|
if (scaledStep < spacingMin) {
|
||||||
timingStep <<= 1;
|
timingStep <<= 1;
|
||||||
continue;
|
continue;
|
||||||
|
@ -27,6 +27,7 @@ const WATERFALL_SIDEBAR_WIDTH = 150; // px
|
|||||||
const WATERFALL_IMMEDIATE_DRAW_MARKERS_COUNT = 30;
|
const WATERFALL_IMMEDIATE_DRAW_MARKERS_COUNT = 30;
|
||||||
const WATERFALL_FLUSH_OUTSTANDING_MARKERS_DELAY = 75; // ms
|
const WATERFALL_FLUSH_OUTSTANDING_MARKERS_DELAY = 75; // ms
|
||||||
|
|
||||||
|
const FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS = 100;
|
||||||
const WATERFALL_HEADER_TICKS_MULTIPLE = 5; // ms
|
const WATERFALL_HEADER_TICKS_MULTIPLE = 5; // ms
|
||||||
const WATERFALL_HEADER_TICKS_SPACING_MIN = 50; // px
|
const WATERFALL_HEADER_TICKS_SPACING_MIN = 50; // px
|
||||||
const WATERFALL_HEADER_TEXT_PADDING = 3; // px
|
const WATERFALL_HEADER_TEXT_PADDING = 3; // px
|
||||||
@ -575,9 +576,18 @@ Waterfall.prototype = {
|
|||||||
*/
|
*/
|
||||||
_findOptimalTickInterval: function({ ticksMultiple, ticksSpacingMin, dataScale }) {
|
_findOptimalTickInterval: function({ ticksMultiple, ticksSpacingMin, dataScale }) {
|
||||||
let timingStep = ticksMultiple;
|
let timingStep = ticksMultiple;
|
||||||
|
let maxIters = FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS;
|
||||||
|
let numIters = 0;
|
||||||
|
|
||||||
|
if (dataScale > ticksSpacingMin) {
|
||||||
|
return dataScale;
|
||||||
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
let scaledStep = dataScale * timingStep;
|
let scaledStep = dataScale * timingStep;
|
||||||
|
if (++numIters > maxIters) {
|
||||||
|
return scaledStep;
|
||||||
|
}
|
||||||
if (scaledStep < ticksSpacingMin) {
|
if (scaledStep < ticksSpacingMin) {
|
||||||
timingStep <<= 1;
|
timingStep <<= 1;
|
||||||
continue;
|
continue;
|
||||||
|
@ -26,6 +26,7 @@ const GRAPH_WHEEL_ZOOM_SENSITIVITY = 0.00035;
|
|||||||
const GRAPH_WHEEL_SCROLL_SENSITIVITY = 0.5;
|
const GRAPH_WHEEL_SCROLL_SENSITIVITY = 0.5;
|
||||||
const GRAPH_MIN_SELECTION_WIDTH = 0.001; // ms
|
const GRAPH_MIN_SELECTION_WIDTH = 0.001; // ms
|
||||||
|
|
||||||
|
const FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS = 100;
|
||||||
const TIMELINE_TICKS_MULTIPLE = 5; // ms
|
const TIMELINE_TICKS_MULTIPLE = 5; // ms
|
||||||
const TIMELINE_TICKS_SPACING_MIN = 75; // px
|
const TIMELINE_TICKS_SPACING_MIN = 75; // px
|
||||||
|
|
||||||
@ -180,7 +181,9 @@ FlameGraph.prototype = {
|
|||||||
/**
|
/**
|
||||||
* Destroys this graph.
|
* Destroys this graph.
|
||||||
*/
|
*/
|
||||||
destroy: function() {
|
destroy: Task.async(function*() {
|
||||||
|
yield this.ready();
|
||||||
|
|
||||||
this._window.removeEventListener("mousemove", this._onMouseMove);
|
this._window.removeEventListener("mousemove", this._onMouseMove);
|
||||||
this._window.removeEventListener("mousedown", this._onMouseDown);
|
this._window.removeEventListener("mousedown", this._onMouseDown);
|
||||||
this._window.removeEventListener("mouseup", this._onMouseUp);
|
this._window.removeEventListener("mouseup", this._onMouseUp);
|
||||||
@ -200,7 +203,7 @@ FlameGraph.prototype = {
|
|||||||
this._data = null;
|
this._data = null;
|
||||||
|
|
||||||
this.emit("destroyed");
|
this.emit("destroyed");
|
||||||
},
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rendering options. Subclasses should override these.
|
* Rendering options. Subclasses should override these.
|
||||||
@ -789,12 +792,17 @@ FlameGraph.prototype = {
|
|||||||
_findOptimalTickInterval: function(dataScale) {
|
_findOptimalTickInterval: function(dataScale) {
|
||||||
let timingStep = TIMELINE_TICKS_MULTIPLE;
|
let timingStep = TIMELINE_TICKS_MULTIPLE;
|
||||||
let spacingMin = TIMELINE_TICKS_SPACING_MIN * this._pixelRatio;
|
let spacingMin = TIMELINE_TICKS_SPACING_MIN * this._pixelRatio;
|
||||||
|
let maxIters = FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS;
|
||||||
|
let numIters = 0;
|
||||||
|
|
||||||
if (dataScale > spacingMin) {
|
if (dataScale > spacingMin) {
|
||||||
return dataScale;
|
return dataScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
if (++numIters > maxIters) {
|
||||||
|
return scaledStep;
|
||||||
|
}
|
||||||
let scaledStep = dataScale * timingStep;
|
let scaledStep = dataScale * timingStep;
|
||||||
if (scaledStep < spacingMin) {
|
if (scaledStep < spacingMin) {
|
||||||
timingStep <<= 1;
|
timingStep <<= 1;
|
||||||
|
@ -229,7 +229,9 @@ AbstractCanvasGraph.prototype = {
|
|||||||
/**
|
/**
|
||||||
* Destroys this graph.
|
* Destroys this graph.
|
||||||
*/
|
*/
|
||||||
destroy: function() {
|
destroy: Task.async(function *() {
|
||||||
|
yield this.ready();
|
||||||
|
|
||||||
this._window.removeEventListener("mousemove", this._onMouseMove);
|
this._window.removeEventListener("mousemove", this._onMouseMove);
|
||||||
this._window.removeEventListener("mousedown", this._onMouseDown);
|
this._window.removeEventListener("mousedown", this._onMouseDown);
|
||||||
this._window.removeEventListener("mouseup", this._onMouseUp);
|
this._window.removeEventListener("mouseup", this._onMouseUp);
|
||||||
@ -259,7 +261,7 @@ AbstractCanvasGraph.prototype = {
|
|||||||
gCachedStripePattern.clear();
|
gCachedStripePattern.clear();
|
||||||
|
|
||||||
this.emit("destroyed");
|
this.emit("destroyed");
|
||||||
},
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rendering options. Subclasses should override these.
|
* Rendering options. Subclasses should override these.
|
||||||
|
@ -387,9 +387,7 @@ PreviewController.prototype = {
|
|||||||
this.onTabPaint(r);
|
this.onTabPaint(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let preview = this.preview;
|
this.preview.invalidate();
|
||||||
if (preview.visible)
|
|
||||||
preview.invalidate();
|
|
||||||
break;
|
break;
|
||||||
case "TabAttrModified":
|
case "TabAttrModified":
|
||||||
this.updateTitleAndTooltip();
|
this.updateTitleAndTooltip();
|
||||||
|
@ -85,8 +85,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (min-resolution: 2dppx) {
|
@media (min-resolution: 2dppx) {
|
||||||
#element-picker::before,
|
#element-picker::before {
|
||||||
#toggle-all::before {
|
|
||||||
background-image: url("chrome://browser/skin/devtools/command-pick@2x.png");
|
background-image: url("chrome://browser/skin/devtools/command-pick@2x.png");
|
||||||
background-size: 64px;
|
background-size: 64px;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ public class CustomEditText extends ThemedEditText {
|
|||||||
super.setPrivateMode(isPrivate);
|
super.setPrivateMode(isPrivate);
|
||||||
|
|
||||||
mHighlightColor = getContext().getResources().getColor(isPrivate
|
mHighlightColor = getContext().getResources().getColor(isPrivate
|
||||||
? R.color.url_bar_text_highlight_pb : R.color.url_bar_text_highlight);
|
? R.color.url_bar_text_highlight_pb : R.color.fennec_ui_orange);
|
||||||
// android:textColorHighlight cannot support a ColorStateList.
|
// android:textColorHighlight cannot support a ColorStateList.
|
||||||
setHighlightColor(mHighlightColor);
|
setHighlightColor(mHighlightColor);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<item android:id="@android:id/progress">
|
<item android:id="@android:id/progress">
|
||||||
<clip>
|
<clip>
|
||||||
<shape>
|
<shape>
|
||||||
<solid android:color="@color/highlight_orange"/>
|
<solid android:color="@color/fennec_ui_orange"/>
|
||||||
</shape>
|
</shape>
|
||||||
</clip>
|
</clip>
|
||||||
</item>
|
</item>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<shape>
|
<shape>
|
||||||
<gradient android:angle="90"
|
<gradient android:angle="90"
|
||||||
android:startColor="#E66000"
|
android:startColor="#E66000"
|
||||||
android:endColor="#FF9500"
|
android:endColor="@color/fennec_ui_orange"
|
||||||
android:type="linear"/>
|
android:type="linear"/>
|
||||||
|
|
||||||
<corners android:radius="4dp"/>
|
<corners android:radius="4dp"/>
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
gecko:state_recording="false">
|
gecko:state_recording="false">
|
||||||
|
|
||||||
<shape android:shape="rectangle">
|
<shape android:shape="rectangle">
|
||||||
<solid android:color="#FFFF9500"/>
|
<solid android:color="@color/fennec_ui_orange"/>
|
||||||
<corners android:radius="3dp"/>
|
<corners android:radius="3dp"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
<View android:id="@+id/divider_doorhanger"
|
<View android:id="@+id/divider_doorhanger"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:background="#FFFF9500"
|
android:background="@color/fennec_ui_orange"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
</merge>
|
</merge>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
android:paddingLeft="@dimen/find_in_page_text_padding_left"
|
android:paddingLeft="@dimen/find_in_page_text_padding_left"
|
||||||
android:paddingRight="@dimen/find_in_page_text_padding_right"
|
android:paddingRight="@dimen/find_in_page_text_padding_right"
|
||||||
android:textColorHighlight="@color/url_bar_text_highlight"
|
android:textColorHighlight="@color/fennec_ui_orange"
|
||||||
android:imeOptions="actionSearch"
|
android:imeOptions="actionSearch"
|
||||||
android:selectAllOnFocus="true"
|
android:selectAllOnFocus="true"
|
||||||
android:gravity="center_vertical|left"/>
|
android:gravity="center_vertical|left"/>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
android:layout_gravity="top"
|
android:layout_gravity="top"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:background="@color/firstrun_tabstrip"
|
android:background="@color/firstrun_tabstrip"
|
||||||
gecko:tabIndicatorColor="@color/text_color_highlight"
|
gecko:tabIndicatorColor="@color/fennec_ui_orange"
|
||||||
android:textColor="@color/android:white"/>
|
android:textColor="@color/android:white"/>
|
||||||
</org.mozilla.gecko.firstrun.FirstrunPager>
|
</org.mozilla.gecko.firstrun.FirstrunPager>
|
||||||
</org.mozilla.gecko.firstrun.FirstrunPane>
|
</org.mozilla.gecko.firstrun.FirstrunPane>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
android:layout_gravity="top"
|
android:layout_gravity="top"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:background="@color/background_light"
|
android:background="@color/background_light"
|
||||||
gecko:tabIndicatorColor="@color/text_color_highlight"
|
gecko:tabIndicatorColor="@color/fennec_ui_orange"
|
||||||
android:textAppearance="@style/TextAppearance.Widget.HomePagerTabStrip"/>
|
android:textAppearance="@style/TextAppearance.Widget.HomePagerTabStrip"/>
|
||||||
|
|
||||||
</org.mozilla.gecko.home.HomePager>
|
</org.mozilla.gecko.home.HomePager>
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
android:background="@drawable/url_bar_entry"
|
android:background="@drawable/url_bar_entry"
|
||||||
android:textColor="@color/url_bar_title"
|
android:textColor="@color/url_bar_title"
|
||||||
android:textColorHint="@color/url_bar_title_hint"
|
android:textColorHint="@color/url_bar_title_hint"
|
||||||
android:textColorHighlight="@color/url_bar_text_highlight"
|
android:textColorHighlight="@color/fennec_ui_orange"
|
||||||
android:textSelectHandle="@drawable/handle_middle"
|
android:textSelectHandle="@drawable/handle_middle"
|
||||||
android:textSelectHandleLeft="@drawable/handle_start"
|
android:textSelectHandleLeft="@drawable/handle_start"
|
||||||
android:textSelectHandleRight="@drawable/handle_end"
|
android:textSelectHandleRight="@drawable/handle_end"
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
android:textSize="@dimen/query_text_size"
|
android:textSize="@dimen/query_text_size"
|
||||||
android:focusable="false"
|
android:focusable="false"
|
||||||
android:focusableInTouchMode="false"
|
android:focusableInTouchMode="false"
|
||||||
android:textColorHighlight="@color/highlight_orange"
|
android:textColorHighlight="@color/fennec_ui_orange"
|
||||||
android:textSelectHandle="@drawable/handle_middle"
|
android:textSelectHandle="@drawable/handle_middle"
|
||||||
android:textSelectHandleLeft="@drawable/handle_start"
|
android:textSelectHandleLeft="@drawable/handle_start"
|
||||||
android:textSelectHandleRight="@drawable/handle_end" />
|
android:textSelectHandleRight="@drawable/handle_end" />
|
||||||
|
@ -4,6 +4,28 @@
|
|||||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
<!-- Fennec color palette (bug 1127517) -->
|
||||||
|
<color name="fennec_ui_orange">#FF9500</color>
|
||||||
|
<color name="action_orange">#E66000</color>
|
||||||
|
<color name="action_orange_pressed">#DC5600</color>
|
||||||
|
<color name="link_blue">#0096DD</color>
|
||||||
|
<color name="private_browsing_purple">#CF68FF</color>
|
||||||
|
|
||||||
|
<color name="placeholder_active_grey">#222222</color>
|
||||||
|
<color name="placeholder_grey">#777777</color>
|
||||||
|
<color name="private_toolbar_grey">#292C29</color>
|
||||||
|
<color name="text_and_tabs_tray_grey">#363B40</color>
|
||||||
|
<color name="tabs_tray_grey_pressed">#45494E</color>
|
||||||
|
<color name="toolbar_icon_grey">#5F6368</color>
|
||||||
|
|
||||||
|
<color name="tabs_tray_icon_grey">#AFB1B3</color>
|
||||||
|
<color name="disabled_grey">#BFBFBF</color>
|
||||||
|
<color name="toolbar_grey_pressed">#D7D7DC</color>
|
||||||
|
<color name="toolbar_menu_dark_grey">#E1E1E6</color>
|
||||||
|
<color name="toolbar_grey">#EBEBF0</color>
|
||||||
|
<color name="about_page_header_grey">#F5F5F5</color>
|
||||||
|
|
||||||
|
<!-- Non-palette colors -->
|
||||||
<color name="primary">#363B40</color>
|
<color name="primary">#363B40</color>
|
||||||
|
|
||||||
<color name="background_light">#FFF5F5F5</color>
|
<color name="background_light">#FFF5F5F5</color>
|
||||||
@ -83,7 +105,6 @@
|
|||||||
<color name="text_color_hint_floating_focused">#33b5e5</color>
|
<color name="text_color_hint_floating_focused">#33b5e5</color>
|
||||||
|
|
||||||
<!-- Highlight colors -->
|
<!-- Highlight colors -->
|
||||||
<color name="text_color_highlight">#FF9500</color>
|
|
||||||
<color name="text_color_highlight_inverse">#D06BFF</color>
|
<color name="text_color_highlight_inverse">#D06BFF</color>
|
||||||
|
|
||||||
<!-- Link colors -->
|
<!-- Link colors -->
|
||||||
@ -103,7 +124,6 @@
|
|||||||
<color name="doorhanger_background_dark">#FFDDE4EA</color>
|
<color name="doorhanger_background_dark">#FFDDE4EA</color>
|
||||||
|
|
||||||
<color name="validation_message_text">#ffffff</color>
|
<color name="validation_message_text">#ffffff</color>
|
||||||
<color name="url_bar_text_highlight">#FFFF9500</color>
|
|
||||||
<color name="url_bar_text_highlight_pb">#FFD06BFF</color>
|
<color name="url_bar_text_highlight_pb">#FFD06BFF</color>
|
||||||
<color name="suggestion_primary">#dddddd</color>
|
<color name="suggestion_primary">#dddddd</color>
|
||||||
<color name="suggestion_pressed">#bbbbbb</color>
|
<color name="suggestion_pressed">#bbbbbb</color>
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
<color name="global_background_color">#EBEBF0</color>
|
<color name="global_background_color">#EBEBF0</color>
|
||||||
|
|
||||||
<color name="highlight_orange">#FF9500</color>
|
|
||||||
|
|
||||||
<color name="edit_text_default">#AFB1B3</color>
|
<color name="edit_text_default">#AFB1B3</color>
|
||||||
|
|
||||||
<!-- card colors -->
|
<!-- card colors -->
|
||||||
|
@ -143,7 +143,7 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Widget.ReadingListRow.ReadTime">
|
<style name="Widget.ReadingListRow.ReadTime">
|
||||||
<item name="android:textColor">@color/text_color_highlight</item>
|
<item name="android:textColor">@color/fennec_ui_orange</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLinePageRow.Title">
|
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLinePageRow.Title">
|
||||||
@ -292,7 +292,7 @@
|
|||||||
-->
|
-->
|
||||||
<style name="TextAppearance">
|
<style name="TextAppearance">
|
||||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
<item name="android:textColorHighlight">@color/text_color_highlight</item>
|
<item name="android:textColorHighlight">@color/fennec_ui_orange</item>
|
||||||
<item name="android:textColorHint">?android:attr/textColorHint</item>
|
<item name="android:textColorHint">?android:attr/textColorHint</item>
|
||||||
<item name="android:textColorLink">?android:attr/textColorLink</item>
|
<item name="android:textColorLink">?android:attr/textColorLink</item>
|
||||||
<item name="android:textSize">@dimen/menu_item_textsize</item>
|
<item name="android:textSize">@dimen/menu_item_textsize</item>
|
||||||
@ -457,7 +457,7 @@
|
|||||||
<item name="android:textAppearance">@style/TextAppearance.UrlBar.Title</item>
|
<item name="android:textAppearance">@style/TextAppearance.UrlBar.Title</item>
|
||||||
<item name="android:textColor">@color/url_bar_title</item>
|
<item name="android:textColor">@color/url_bar_title</item>
|
||||||
<item name="android:textColorHint">@color/url_bar_title_hint</item>
|
<item name="android:textColorHint">@color/url_bar_title_hint</item>
|
||||||
<item name="android:textColorHighlight">@color/url_bar_text_highlight</item>
|
<item name="android:textColorHighlight">@color/fennec_ui_orange</item>
|
||||||
<item name="android:textSelectHandle">@drawable/handle_middle</item>
|
<item name="android:textSelectHandle">@drawable/handle_middle</item>
|
||||||
<item name="android:textSelectHandleLeft">@drawable/handle_start</item>
|
<item name="android:textSelectHandleLeft">@drawable/handle_start</item>
|
||||||
<item name="android:textSelectHandleRight">@drawable/handle_end</item>
|
<item name="android:textSelectHandleRight">@drawable/handle_end</item>
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
<item name="android:textColorHintInverse">@color/text_color_hint_inverse</item>
|
<item name="android:textColorHintInverse">@color/text_color_hint_inverse</item>
|
||||||
|
|
||||||
<!-- Highlight colors -->
|
<!-- Highlight colors -->
|
||||||
<item name="android:textColorHighlight">@color/text_color_highlight</item>
|
<item name="android:textColorHighlight">@color/fennec_ui_orange</item>
|
||||||
<item name="android:textColorHighlightInverse">@color/text_color_highlight_inverse</item>
|
<item name="android:textColorHighlightInverse">@color/text_color_highlight_inverse</item>
|
||||||
|
|
||||||
<!-- Link colors -->
|
<!-- Link colors -->
|
||||||
|
@ -184,7 +184,7 @@ TaskbarPreview::GetActive(bool *active) {
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
TaskbarPreview::Invalidate() {
|
TaskbarPreview::Invalidate() {
|
||||||
if (!mVisible)
|
if (!mVisible)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_OK;
|
||||||
|
|
||||||
// DWM Composition is required for previews
|
// DWM Composition is required for previews
|
||||||
if (!nsUXThemeData::CheckForCompositor())
|
if (!nsUXThemeData::CheckForCompositor())
|
||||||
|
Loading…
Reference in New Issue
Block a user