Back out 8 changesets (bug 1223573) for Win7 PGO xperf unexpected access failures

CLOSED TREE

Backed out changeset 19876a153a00 (bug 1223573)
Backed out changeset 14251062e347 (bug 1223573)
Backed out changeset 081b0af71d6e (bug 1223573)
Backed out changeset 21ebe3534e58 (bug 1223573)
Backed out changeset d6754894897c (bug 1223573)
Backed out changeset 1b4d6308002e (bug 1223573)
Backed out changeset a13b3bba5529 (bug 1223573)
Backed out changeset f3ccccf5b6fe (bug 1223573)
This commit is contained in:
Phil Ringnalda 2015-11-27 21:39:23 -08:00
parent 490fc101a5
commit 7e101683a3
359 changed files with 1461 additions and 1781 deletions

View File

@ -80,15 +80,9 @@ GRTAGS
GSYMS
GPATH
# Various items for Loop
# Unit tests for Loop
^browser/components/loop/standalone/content/config\.js$
^browser/extensions/loop/.*/node_modules/
^browser/extensions/loop/.*\.module-cache
^browser/extensions/loop/test/coverage/desktop
^browser/extensions/loop/test/coverage/shared_standalone
^browser/extensions/loop/test/visual-regression/diff
^browser/extensions/loop/test/visual-regression/new
^browser/extensions/loop/test/visual-regression/refs
^browser/components/loop/standalone/node_modules/
# Git clone directory for updating web-platform-tests
^testing/web-platform/sync/

View File

@ -1376,6 +1376,42 @@ pref("shumway.disabled", true);
// (This is intentionally on the high side; see bug 746055.)
pref("image.mem.max_decoded_image_kb", 256000);
pref("loop.enabled", true);
pref("loop.textChat.enabled", true);
pref("loop.server", "https://loop.services.mozilla.com/v0");
pref("loop.linkClicker.url", "https://hello.firefox.com/");
pref("loop.gettingStarted.seen", false);
pref("loop.gettingStarted.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/hello/start/");
pref("loop.gettingStarted.resumeOnFirstJoin", false);
pref("loop.learnMoreUrl", "https://www.firefox.com/hello/");
pref("loop.legal.ToS_url", "https://www.mozilla.org/about/legal/terms/firefox-hello/");
pref("loop.legal.privacy_url", "https://www.mozilla.org/privacy/firefox-hello/");
pref("loop.do_not_disturb", false);
pref("loop.ringtone", "chrome://browser/content/loop/shared/sounds/ringtone.ogg");
pref("loop.retry_delay.start", 60000);
pref("loop.retry_delay.limit", 300000);
pref("loop.ping.interval", 1800000);
pref("loop.ping.timeout", 10000);
pref("loop.feedback.baseUrl", "https://input.mozilla.org/api/v1/feedback");
pref("loop.feedback.product", "Loop");
pref("loop.debug.loglevel", "Error");
pref("loop.debug.dispatcher", false);
pref("loop.debug.sdk", false);
pref("loop.debug.twoWayMediaTelemetry", false);
pref("loop.feedback.dateLastSeenSec", 0);
pref("loop.feedback.periodSec", 15770000); // 6 months.
pref("loop.feedback.formURL", "https://www.mozilla.org/firefox/hello/npssurvey/");
pref("loop.feedback.manualFormURL", "https://www.mozilla.org/firefox/hello/feedbacksurvey/");
#ifdef DEBUG
pref("loop.CSP", "default-src 'self' about: file: chrome: http://localhost:*; img-src * data:; 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
pref("loop.CSP", "default-src 'self' about: file: chrome:; img-src * data:; 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
pref("loop.fxa_oauth.tokendata", "");
pref("loop.fxa_oauth.profile", "");
pref("loop.support_url", "https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc");
pref("loop.browserSharing.showInfoBar", true);
pref("social.sidebar.unload_timeout_ms", 10000);
// Activation from inside of share panel is possible if activationPanelEnabled

View File

@ -0,0 +1,613 @@
// 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/.
// the "exported" symbols
var LoopUI;
(function() {
const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const kBrowserSharingNotificationId = "loop-sharing-notification";
const kPrefBrowserSharingInfoBar = "browserSharing.showInfoBar";
LoopUI = {
/**
* @var {XULWidgetSingleWrapper} toolbarButton Getter for the Loop toolbarbutton
* instance for this window.
*/
get toolbarButton() {
delete this.toolbarButton;
return this.toolbarButton = CustomizableUI.getWidget("loop-button").forWindow(window);
},
/**
* @var {XULElement} panel Getter for the Loop panel element.
*/
get panel() {
delete this.panel;
return this.panel = document.getElementById("loop-notification-panel");
},
/**
* @var {XULElement|null} browser Getter for the Loop panel browser element.
* Will be NULL if the panel hasn't loaded yet.
*/
get browser() {
let browser = document.querySelector("#loop-notification-panel > #loop-panel-iframe");
if (browser) {
delete this.browser;
this.browser = browser;
}
return browser;
},
/**
* @var {String|null} selectedTab Getter for the name of the currently selected
* tab inside the Loop panel. Will be NULL if
* the panel hasn't loaded yet.
*/
get selectedTab() {
if (!this.browser) {
return null;
}
let selectedTab = this.browser.contentDocument.querySelector(".tab-view > .selected");
return selectedTab && selectedTab.getAttribute("data-tab-name");
},
/**
* @return {Promise}
*/
promiseDocumentVisible(aDocument) {
if (!aDocument.hidden) {
return Promise.resolve(aDocument);
}
return new Promise((resolve) => {
aDocument.addEventListener("visibilitychange", function onVisibilityChanged() {
aDocument.removeEventListener("visibilitychange", onVisibilityChanged);
resolve(aDocument);
});
});
},
/**
* Toggle between opening or hiding the Loop panel.
*
* @param {DOMEvent} [event] Optional event that triggered the call to this
* function.
* @param {String} [tabId] Optional name of the tab to select after the panel
* has opened. Does nothing when the panel is hidden.
* @return {Promise}
*/
togglePanel: function(event, tabId = null) {
if (!this.panel) {
// We're on the hidden window! What fun!
let obs = win => {
Services.obs.removeObserver(obs, "browser-delayed-startup-finished");
win.LoopUI.togglePanel(event, tabId);
};
Services.obs.addObserver(obs, "browser-delayed-startup-finished", false);
return OpenBrowserWindow();
}
if (this.panel.state == "open") {
return new Promise(resolve => {
this.panel.hidePopup();
resolve();
});
}
return this.openCallPanel(event, tabId).then(doc => {
let fm = Services.focus;
fm.moveFocus(doc.defaultView, null, fm.MOVEFOCUS_FIRST, fm.FLAG_NOSCROLL);
}).catch(err => {
Cu.reportError(x);
});
},
/**
* Opens the panel for Loop and sizes it appropriately.
*
* @param {event} event The event opening the panel, used to anchor
* the panel to the button which triggers it.
* @param {String} [tabId] Identifier of the tab to select when the panel is
* opened. Example: 'rooms', 'contacts', etc.
* @return {Promise}
*/
openCallPanel: function(event, tabId = null) {
return new Promise((resolve) => {
let callback = iframe => {
// Helper function to show a specific tab view in the panel.
function showTab() {
if (!tabId) {
resolve(LoopUI.promiseDocumentVisible(iframe.contentDocument));
return;
}
let win = iframe.contentWindow;
let ev = new win.CustomEvent("UIAction", Cu.cloneInto({
detail: {
action: "selectTab",
tab: tabId
}
}, win));
win.dispatchEvent(ev);
resolve(LoopUI.promiseDocumentVisible(iframe.contentDocument));
}
// If the panel has been opened and initialized before, we can skip waiting
// for the content to load - because it's already there.
if (("contentWindow" in iframe) && iframe.contentWindow.document.readyState == "complete") {
showTab();
return;
}
let documentDOMLoaded = () => {
iframe.removeEventListener("DOMContentLoaded", documentDOMLoaded, true);
// Handle window.close correctly on the panel.
this.hookWindowCloseForPanelClose(iframe.contentWindow);
iframe.contentWindow.addEventListener("loopPanelInitialized", function loopPanelInitialized() {
iframe.contentWindow.removeEventListener("loopPanelInitialized",
loopPanelInitialized);
showTab();
});
};
iframe.addEventListener("DOMContentLoaded", documentDOMLoaded, true);
};
// Used to clear the temporary "login" state from the button.
Services.obs.notifyObservers(null, "loop-status-changed", null);
this.shouldResumeTour().then((resume) => {
if (resume) {
// Assume the conversation with the visitor wasn't open since we would
// have resumed the tour as soon as the visitor joined if it was (and
// the pref would have been set to false already.
this.MozLoopService.resumeTour("waiting");
resolve();
return;
}
this.LoopAPI.initialize();
let anchor = event ? event.target : this.toolbarButton.anchor;
let setHeight = 410;
if (gBrowser.selectedBrowser.getAttribute("remote") === "true") {
setHeight = 262;
}
this.PanelFrame.showPopup(window, anchor,
"loop", null, "about:looppanel",
// Loop wants a fixed size for the panel. This also stops it dynamically resizing.
{ width: 330, height: setHeight },
callback);
});
});
},
/**
* Method to know whether actions to open the panel should instead resume the tour.
*
* We need the panel to be opened via UITour so that it gets @noautohide.
*
* @return {Promise} resolving with a {Boolean} of whether the tour should be resumed instead of
* opening the panel.
*/
shouldResumeTour: Task.async(function* () {
// Resume the FTU tour if this is the first time a room was joined by
// someone else since the tour.
if (!Services.prefs.getBoolPref("loop.gettingStarted.resumeOnFirstJoin")) {
return false;
}
if (!this.LoopRooms.participantsCount) {
// Nobody is in the rooms
return false;
}
let roomsWithNonOwners = yield this.roomsWithNonOwners();
if (!roomsWithNonOwners.length) {
// We were the only one in a room but we want to know about someone else joining.
return false;
}
return true;
}),
/**
* @return {Promise} resolved with an array of Rooms with participants (excluding owners)
*/
roomsWithNonOwners: function() {
return new Promise(resolve => {
this.LoopRooms.getAll((error, rooms) => {
let roomsWithNonOwners = [];
for (let room of rooms) {
if (!("participants" in room)) {
continue;
}
let numNonOwners = room.participants.filter(participant => !participant.owner).length;
if (!numNonOwners) {
continue;
}
roomsWithNonOwners.push(room);
}
resolve(roomsWithNonOwners);
});
});
},
/**
* Triggers the initialization of the loop service. Called by
* delayedStartup.
*/
init: function() {
// Add observer notifications before the service is initialized
Services.obs.addObserver(this, "loop-status-changed", false);
// This is a promise for test purposes, but we don't want to be logging
// expected errors to the console, so we catch them here.
this.MozLoopService.initialize().catch(ex => {
if (!ex.message ||
(!ex.message.contains("not enabled") &&
!ex.message.contains("not needed"))) {
console.error(ex);
}
});
this.updateToolbarState();
},
uninit: function() {
Services.obs.removeObserver(this, "loop-status-changed");
},
// Implements nsIObserver
observe: function(subject, topic, data) {
if (topic != "loop-status-changed") {
return;
}
this.updateToolbarState(data);
},
/**
* Updates the toolbar/menu-button state to reflect Loop status.
*
* @param {string} [aReason] Some states are only shown if
* a related reason is provided.
*
* aReason="login": Used after a login is completed
* successfully. This is used so the state can be
* temporarily shown until the next state change.
*/
updateToolbarState: function(aReason = null) {
if (!this.toolbarButton.node) {
return;
}
let state = "";
let mozL10nId = "loop-call-button3";
let suffix = ".tooltiptext";
if (this.MozLoopService.errors.size) {
state = "error";
mozL10nId += "-error";
} else if (this.MozLoopService.screenShareActive) {
state = "action";
mozL10nId += "-screensharing";
} else if (aReason == "login" && this.MozLoopService.userProfile) {
state = "active";
mozL10nId += "-active";
suffix += "2";
} else if (this.MozLoopService.doNotDisturb) {
state = "disabled";
mozL10nId += "-donotdisturb";
} else if (this.MozLoopService.roomsParticipantsCount > 0) {
state = "active";
this.roomsWithNonOwners().then(roomsWithNonOwners => {
if (roomsWithNonOwners.length > 0) {
mozL10nId += "-participantswaiting";
} else {
mozL10nId += "-active";
}
suffix += "2";
this.updateTooltiptext(mozL10nId + suffix);
this.toolbarButton.node.setAttribute("state", state);
});
return;
} else {
suffix += "2";
}
this.toolbarButton.node.setAttribute("state", state);
this.updateTooltiptext(mozL10nId + suffix);
},
/**
* Updates the tootltiptext to reflect Loop status.
*
* @param {string} [mozL10nId] l10n ID that refelct the current
* Loop status.
*/
updateTooltiptext: function(mozL10nId) {
this.toolbarButton.node.setAttribute("tooltiptext", mozL10nId);
var tooltiptext = CustomizableUI.getLocalizedProperty(this.toolbarButton, "tooltiptext");
this.toolbarButton.node.setAttribute("tooltiptext", tooltiptext);
},
/**
* Show a desktop notification when 'do not disturb' isn't enabled.
*
* @param {Object} options Set of options that may tweak the appearance and
* behavior of the notification.
* Option params:
* - {String} title Notification title message
* - {String} [message] Notification body text
* - {String} [icon] Notification icon
* - {String} [sound] Sound to play
* - {String} [selectTab] Tab to select when the panel
* opens
* - {Function} [onclick] Callback to invoke when
* the notification is clicked.
* Opens the panel by default.
*/
showNotification: function(options) {
if (this.MozLoopService.doNotDisturb) {
return;
}
if (!options.title) {
throw new Error("Missing title, can not display notification");
}
let notificationOptions = {
body: options.message || ""
};
if (options.icon) {
notificationOptions.icon = options.icon;
}
if (options.sound) {
// This will not do anything, until bug bug 1105222 is resolved.
notificationOptions.mozbehavior = {
soundFile: ""
};
this.playSound(options.sound);
}
let notification = new window.Notification(options.title, notificationOptions);
notification.addEventListener("click", e => {
if (window.closed) {
return;
}
try {
window.focus();
} catch (ex) {}
// We need a setTimeout here, otherwise the panel won't show after the
// window received focus.
window.setTimeout(() => {
if (typeof options.onclick == "function") {
options.onclick();
} else {
// Open the Loop panel as a default action.
this.openCallPanel(null, options.selectTab || null);
}
}, 0);
});
},
/**
* Play a sound in this window IF there's no sound playing yet.
*
* @param {String} name Name of the sound, like 'ringtone' or 'room-joined'
*/
playSound: function(name) {
if (this.ActiveSound || this.MozLoopService.doNotDisturb) {
return;
}
this.activeSound = new window.Audio();
this.activeSound.src = `chrome://browser/content/loop/shared/sounds/${name}.ogg`;
this.activeSound.load();
this.activeSound.play();
this.activeSound.addEventListener("ended", () => this.activeSound = undefined, false);
},
/**
* Start listening to selected tab changes and notify any content page that's
* listening to 'BrowserSwitch' push messages.
*
* Push message parameters:
* - {Integer} windowId The new windowId for the browser.
*/
startBrowserSharing: function() {
if (!this._listeningToTabSelect) {
gBrowser.tabContainer.addEventListener("TabSelect", this);
this._listeningToTabSelect = true;
}
this._maybeShowBrowserSharingInfoBar();
// Get the first window Id for the listener.
this.LoopAPI.broadcastPushMessage("BrowserSwitch",
gBrowser.selectedBrowser.outerWindowID);
},
/**
* Stop listening to selected tab changes.
*/
stopBrowserSharing: function() {
if (!this._listeningToTabSelect) {
return;
}
this._hideBrowserSharingInfoBar();
gBrowser.tabContainer.removeEventListener("TabSelect", this);
this._listeningToTabSelect = false;
},
/**
* Helper function to fetch a localized string via the MozLoopService API.
* It's currently inconveniently wrapped inside a string of stringified JSON.
*
* @param {String} key The element id to get strings for.
* @return {String}
*/
_getString: function(key) {
let str = this.MozLoopService.getStrings(key);
if (str) {
str = JSON.parse(str).textContent;
}
return str;
},
/**
* Shows an infobar notification at the top of the browser window that warns
* the user that their browser tabs are being broadcasted through the current
* conversation.
*/
_maybeShowBrowserSharingInfoBar: function() {
this._hideBrowserSharingInfoBar();
// Don't show the infobar if it's been permanently disabled from the menu.
if (!this.MozLoopService.getLoopPref(kPrefBrowserSharingInfoBar)) {
return;
}
let box = gBrowser.getNotificationBox();
let paused = false;
let bar = box.appendNotification(
this._getString("infobar_screenshare_browser_message"),
kBrowserSharingNotificationId,
// Icon is defined in browser theme CSS.
null,
box.PRIORITY_WARNING_LOW,
[{
label: this._getString("infobar_button_pause_label"),
accessKey: this._getString("infobar_button_pause_accesskey"),
isDefault: false,
callback: (event, buttonInfo, buttonNode) => {
paused = !paused;
bar.label = paused ? this._getString("infobar_screenshare_paused_browser_message") :
this._getString("infobar_screenshare_browser_message");
bar.classList.toggle("paused", paused);
buttonNode.label = paused ? this._getString("infobar_button_resume_label") :
this._getString("infobar_button_pause_label");
buttonNode.accessKey = paused ? this._getString("infobar_button_resume_accesskey") :
this._getString("infobar_button_pause_accesskey");
return true;
}
},
{
label: this._getString("infobar_button_stop_label"),
accessKey: this._getString("infobar_button_stop_accesskey"),
isDefault: true,
callback: () => {
this._hideBrowserSharingInfoBar();
LoopUI.MozLoopService.hangupAllChatWindows();
}
}]
);
// Keep showing the notification bar until the user explicitly closes it.
bar.persistence = -1;
},
/**
* Hides the infobar, permanantly if requested.
*
* @param {Boolean} permanently Flag that determines if the infobar will never
* been shown again. Defaults to `false`.
* @return {Boolean} |true| if the infobar was hidden here.
*/
_hideBrowserSharingInfoBar: function(permanently = false, browser) {
browser = browser || gBrowser.selectedBrowser;
let box = gBrowser.getNotificationBox(browser);
let notification = box.getNotificationWithValue(kBrowserSharingNotificationId);
let removed = false;
if (notification) {
box.removeNotification(notification);
removed = true;
}
if (permanently) {
this.MozLoopService.setLoopPref(kPrefBrowserSharingInfoBar, false);
}
return removed;
},
/**
* Handles events from gBrowser.
*/
handleEvent: function(event) {
// We only should get "select" events.
if (event.type != "TabSelect") {
return;
}
let wasVisible = false;
// Hide the infobar from the previous tab.
if (event.detail.previousTab) {
wasVisible = this._hideBrowserSharingInfoBar(false,
event.detail.previousTab.linkedBrowser);
}
// We've changed the tab, so get the new window id.
this.LoopAPI.broadcastPushMessage("BrowserSwitch",
gBrowser.selectedBrowser.outerWindowID);
if (wasVisible) {
// If the infobar was visible before, we should show it again after the
// switch.
this._maybeShowBrowserSharingInfoBar();
}
},
/**
* Fetch the favicon of the currently selected tab in the format of a data-uri.
*
* @param {Function} callback Function to be invoked with an error object as
* its first argument when an error occurred or
* a string as second argument when the favicon
* has been fetched.
*/
getFavicon: function(callback) {
let pageURI = gBrowser.selectedTab.linkedBrowser.currentURI.spec;
// If the tab pages url starts with http(s), fetch icon.
if (!/^https?:/.test(pageURI)) {
callback();
return;
}
this.PlacesUtils.promiseFaviconLinkUrl(pageURI).then(uri => {
// We XHR the favicon to get a File object, which we can pass to the FileReader
// object. The FileReader turns the File object into a data-uri.
let xhr = new XMLHttpRequest();
xhr.open("get", uri.spec, true);
xhr.responseType = "blob";
xhr.overrideMimeType("image/x-icon");
xhr.onload = () => {
if (xhr.status != 200) {
callback(new Error("Invalid status code received for favicon XHR: " + xhr.status));
return;
}
let reader = new FileReader();
reader.onload = reader.onload = () => callback(null, reader.result);
reader.onerror = callback;
reader.readAsDataURL(xhr.response);
};
xhr.onerror = callback;
xhr.send();
}).catch(err => {
callback(err || new Error("No favicon found"));
});
}
};
})();
XPCOMUtils.defineLazyModuleGetter(LoopUI, "hookWindowCloseForPanelClose", "resource://gre/modules/MozSocialAPI.jsm");
XPCOMUtils.defineLazyModuleGetter(LoopUI, "LoopAPI", "resource:///modules/loop/MozLoopAPI.jsm");
XPCOMUtils.defineLazyModuleGetter(LoopUI, "LoopRooms", "resource:///modules/loop/LoopRooms.jsm");
XPCOMUtils.defineLazyModuleGetter(LoopUI, "MozLoopService", "resource:///modules/loop/MozLoopService.jsm");
XPCOMUtils.defineLazyModuleGetter(LoopUI, "PanelFrame", "resource:///modules/PanelFrame.jsm");
XPCOMUtils.defineLazyModuleGetter(LoopUI, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm");

View File

@ -902,6 +902,11 @@ notification[value="translation"] {
-moz-binding: url("chrome://browser/content/translation-infobar.xml#translationbar");
}
/* Loop/ Hello */
notification[value="loop-sharing-notification"] .close-icon {
display: none;
}
/* Social */
/* Note the chatbox 'width' values are duplicated in socialchat.xml */
chatbox {

View File

@ -274,6 +274,7 @@ var gInitialPages = [
#include browser-fullScreen.js
#include browser-fullZoom.js
#include browser-gestureSupport.js
#include browser-loop.js
#include browser-places.js
#include browser-plugins.js
#include browser-safebrowsing.js
@ -1356,6 +1357,8 @@ var gBrowserInit = {
gDataNotificationInfoBar.init();
#endif
LoopUI.init();
gBrowserThumbnails.init();
// Add Devtools menuitems and listeners
@ -1537,6 +1540,7 @@ var gBrowserInit = {
TabView.uninit();
SocialUI.uninit();
gBrowserThumbnails.uninit();
LoopUI.uninit();
FullZoom.destroy();
Services.obs.removeObserver(gSessionHistoryObserver, "browser:purge-session-history");

View File

@ -108,12 +108,12 @@ static RedirEntry kRedirMap[] = {
{
"debugging", "chrome://devtools/content/aboutdebugging/aboutdebugging.xhtml",
nsIAboutModule::ALLOW_SCRIPT },
{ "loopconversation", "chrome://loop/content/panels/conversation.html",
{ "loopconversation", "chrome://browser/content/loop/conversation.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT |
nsIAboutModule::ENABLE_INDEXED_DB },
{ "looppanel", "chrome://loop/content/panels/panel.html",
{ "looppanel", "chrome://browser/content/loop/panel.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT |

View File

@ -950,6 +950,42 @@ const CustomizableWidgets = [
let win = aEvent.view;
win.MailIntegration.sendLinkForBrowser(win.gBrowser.selectedBrowser)
}
}, {
id: "loop-button",
type: "custom",
label: "loop-call-button3.label",
tooltiptext: "loop-call-button3.tooltiptext2",
privateBrowsingTooltiptext: "loop-call-button3-pb.tooltiptext",
defaultArea: CustomizableUI.AREA_NAVBAR,
introducedInVersion: 4,
onBuild: function(aDocument) {
// If we're not supposed to see the button, return zip.
if (!Services.prefs.getBoolPref("loop.enabled")) {
return null;
}
let isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(aDocument.defaultView);
let node = aDocument.createElementNS(kNSXUL, "toolbarbutton");
node.setAttribute("id", this.id);
node.classList.add("toolbarbutton-1");
node.classList.add("chromeclass-toolbar-additional");
node.classList.add("badged-button");
node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label"));
if (isWindowPrivate)
node.setAttribute("disabled", "true");
let tooltiptext = isWindowPrivate ?
CustomizableUI.getLocalizedProperty(this, "privateBrowsingTooltiptext",
[CustomizableUI.getLocalizedProperty(this, "label")]) :
CustomizableUI.getLocalizedProperty(this, "tooltiptext");
node.setAttribute("tooltiptext", tooltiptext);
node.setAttribute("removable", "true");
node.addEventListener("command", function(event) {
aDocument.defaultView.LoopUI.togglePanel(event);
});
return node;
}
}, {
id: "web-apps-button",
label: "web-apps-button.label",

View File

@ -1,16 +1,12 @@
# This file currently uses a non-standard (and not on a standards track)
# if statement within catch.
content/modules/MozLoopWorker.js
modules/MozLoopWorker.js
# This file currently uses es7 features eslint issue:
# https://github.com/eslint/espree/issues/125
content/modules/MozLoopAPI.jsm
# Need to fix the configuration for this.
bootstrap.js
# Need to drop the preprocessing (bug 1212428)
content/preferences/prefs.js
modules/MozLoopAPI.jsm
# Libs we don't need to check
content/panels/vendor
content/shared/vendor
content/libs
content/shared/libs
standalone/content/libs
standalone/node_modules
# Libs we don't need to check
@ -19,11 +15,11 @@ test/shared/vendor
test/coverage
test/node_modules
# These are generated react files that we don't need to check
content/panels/js/conversation.js
content/panels/js/conversationViews.js
content/panels/js/panel.js
content/panels/js/roomViews.js
content/panels/js/feedbackViews.js
content/js/conversation.js
content/js/conversationViews.js
content/js/panel.js
content/js/roomViews.js
content/js/feedbackViews.js
content/shared/js/textChatView.js
content/shared/js/linkifiedTextView.js
content/shared/js/views.js

View File

@ -7,10 +7,9 @@
"blockBindings": true,
"destructuring": true,
"generators": true,
"objectLiteralShorthandMethods": true,
"restParams": true,
"spread": true,
"templateStrings": true,
"objectLiteralShorthandMethods": true,
},
"globals": {
// Gecko + Loop Globals.
@ -42,7 +41,6 @@
"MozLoopPushHandler": true,
"MozLoopService": true,
"OS": false,
"PrivateBrowsingUtils": false,
"roomsPushNotification": true,
"Services": false,
"Social": false,

View File

@ -22,9 +22,9 @@ using npm in order to compile the .jsx files into regular .js ones:
npm install -g react-tools@0.12.2
Once installed, run build-jsx with the --watch option from
browser/extensions/loop, eg.:
browser/components/loop, eg.:
cd browser/extensions/loop
cd browser/components/loop
./build-jsx --watch
build-jsx can also be do a one-time compile pass instead of watching if
@ -36,7 +36,7 @@ Hacking
=======
Please be sure to execute
browser/extensions/loop/run-all-loop-tests.sh
browser/components/loop/run-all-loop-tests.sh
from the top level before requesting review on a patch.
@ -52,7 +52,7 @@ If you install eslint and the react plugin globally:
npm install -g eslint
npm install -g eslint-plugin-react
You can also run it by hand in the browser/extensions/loop directory:
You can also run it by hand in the browser/components/loop directory:
eslint --ext .js --ext .jsx --ext .jsm .
@ -88,7 +88,7 @@ install that is properly configured. From the top-level gecko directory,
execute:
export LOOP_SERVER=/Users/larry/src/loop-server
./mach marionette-test browser/extensions/loop/test/functional/manifest.ini
./mach marionette-test browser/components/loop/test/functional/manifest.ini
Once the automation is complete, we'll include this in run-all-loop-tests.sh
as well.

View File

@ -74,7 +74,7 @@ def find_react_command():
return [node, jsx_path]
SHARED_LIBS_DIR=os.path.join(os.path.dirname(__file__), "content", "shared", "vendor")
SHARED_LIBS_DIR=os.path.join(os.path.dirname(__file__), "content", "shared", "libs")
REACT_VERSION=find_react_version(SHARED_LIBS_DIR)
src_files = [] # files to be compiled
@ -99,7 +99,7 @@ else:
# parse the CLI arguments
description = 'Loop build tool for JSX files. ' + \
'Will scan entire loop directory and compile them in place. ' + \
'Must be executed from browser/extensions/loop directory.'
'Must be executed from browser/components/loop directory.'
parser = argparse.ArgumentParser(description=description)
parser.add_argument('--watch', '-w', action='store_true', help='continuous' +

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<!-- 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/. -->
<html>
<head>
<meta charset="utf-8">
<!-- Title is set in conversation.js -->
<title></title>
<link rel="stylesheet" type="text/css" href="loop/shared/css/reset.css">
<link rel="stylesheet" type="text/css" href="loop/shared/css/common.css">
<link rel="stylesheet" type="text/css" href="loop/shared/css/conversation.css">
</head>
<body class="fx-embedded">
<div id="messages"></div>
<div id="main"></div>
<script type="text/javascript" src="loop/libs/l10n.js"></script>
<script type="text/javascript" src="loop/js/otconfig.js"></script>
<script type="text/javascript" src="loop/libs/sdk.js"></script>
<script type="text/javascript" src="loop/shared/libs/react-0.13.3.js"></script>
<script type="text/javascript" src="loop/shared/libs/lodash-3.9.3.js"></script>
<script type="text/javascript" src="loop/shared/libs/backbone-1.2.1.js"></script>
<script type="text/javascript" src="loop/shared/libs/classnames-2.2.0.js"></script>
<script type="text/javascript" src="loop/shared/js/loopapi-client.js"></script>
<script type="text/javascript" src="loop/shared/js/utils.js"></script>
<script type="text/javascript" src="loop/shared/js/mixins.js"></script>
<script type="text/javascript" src="loop/shared/js/actions.js"></script>
<script type="text/javascript" src="loop/shared/js/validate.js"></script>
<script type="text/javascript" src="loop/shared/js/dispatcher.js"></script>
<script type="text/javascript" src="loop/shared/js/otSdkDriver.js"></script>
<script type="text/javascript" src="loop/shared/js/store.js"></script>
<script type="text/javascript" src="loop/shared/js/activeRoomStore.js"></script>
<script type="text/javascript" src="loop/shared/js/views.js"></script>
<script type="text/javascript" src="loop/js/feedbackViews.js"></script>
<script type="text/javascript" src="loop/shared/js/textChatStore.js"></script>
<script type="text/javascript" src="loop/shared/js/textChatView.js"></script>
<script type="text/javascript" src="loop/shared/js/linkifiedTextView.js"></script>
<script type="text/javascript" src="loop/shared/js/urlRegExps.js"></script>
<script type="text/javascript" src="loop/js/conversationAppStore.js"></script>
<script type="text/javascript" src="loop/js/roomStore.js"></script>
<script type="text/javascript" src="loop/js/roomViews.js"></script>
<script type="text/javascript" src="loop/js/conversation.js"></script>
</body>
</html>

View File

@ -12,7 +12,7 @@ body {
/* Beta Ribbon */
.beta-ribbon {
background: url("../../shared/img/beta-ribbon.svg") no-repeat;
background: url("../shared/img/beta-ribbon.svg") no-repeat;
background-size: 30px;
width: 30px;
height: 30px;
@ -158,7 +158,7 @@ body {
transform: translateY(-50%);
padding-top: 11rem;
padding-bottom: 1rem;
background-image: url("../../shared/img/empty_conversations.svg");
background-image: url("../shared/img/empty_conversations.svg");
background-repeat: no-repeat;
background-position: top center;
}
@ -324,11 +324,11 @@ body {
}
.room-list > .room-entry:hover > h2 > .copy-link {
background-image: url(../../shared/img/icons-16x16.svg#copy);
background-image: url(../shared/img/icons-16x16.svg#copy);
}
.room-list > .room-entry:hover > h2 > .delete-link {
background-image: url(../../shared/img/icons-16x16.svg#trash);
background-image: url(../shared/img/icons-16x16.svg#trash);
}
/* scale this up to 1.1x and then back to the original size */
@ -338,7 +338,7 @@ body {
}
.room-list > .room-entry > h2 > .copy-link.checked {
background: transparent url(../../shared/img/icons-16x16.svg#checkmark);
background: transparent url(../shared/img/icons-16x16.svg#checkmark);
animation: pulse .150s;
animation-timing-function: ease-in-out;
top: 0;
@ -362,7 +362,7 @@ body {
/* Room entry edit button */
.room-entry-context-edit-btn {
background-image: url("../../shared/img/icons-10x10.svg#edit-darkgrey");
background-image: url("../shared/img/icons-10x10.svg#edit-darkgrey");
background-position: center;
background-repeat: no-repeat;
background-size: 12px;
@ -399,7 +399,7 @@ html[dir="rtl"] .room-entry-context-actions > .dropdown-menu {
.button-close {
background-color: transparent;
background-image: url(../../shared/img/icons-10x10.svg#close);
background-image: url(../shared/img/icons-10x10.svg#close);
background-repeat: no-repeat;
background-size: 8px 8px;
border: none;
@ -428,7 +428,7 @@ html[dir="rtl"] .room-entry-context-actions > .dropdown-menu {
}
.spinner.busy {
background-image: url(../../shared/img/spinner.png);
background-image: url(../shared/img/spinner.png);
animation-name: spinnerRotate;
animation-duration: 1s;
animation-timing-function: linear;
@ -437,7 +437,7 @@ html[dir="rtl"] .room-entry-context-actions > .dropdown-menu {
@media (min-resolution: 2dppx) {
.spinner.busy {
background-image: url(../../shared/img/spinner@2x.png);
background-image: url(../shared/img/spinner@2x.png);
}
}
@ -502,7 +502,7 @@ html[dir="rtl"] .generate-url-spinner {
margin-left: 10px;
margin-right: 10px;
vertical-align: middle;
background-image: url("../../shared/img/telefonica.png");
background-image: url("../shared/img/telefonica.png");
background-size: 72px 20px;
width: 72px;
height: 20px;
@ -510,21 +510,21 @@ html[dir="rtl"] .generate-url-spinner {
#powered-by-logo.en-GB,
#powered-by-logo.de {
background-image: url("../../shared/img/02.png");
background-image: url("../shared/img/02.png");
background-size: 21px 20px;
width: 21px;
height: 20px;
}
#powered-by-logo.pt-BR {
background-image: url("../../shared/img/vivo.png");
background-image: url("../shared/img/vivo.png");
background-size: 53px 26px;
width: 53px;
height: 26px;
}
#powered-by-logo[class^="es-"] {
background-image: url("../../shared/img/movistar.png");
background-image: url("../shared/img/movistar.png");
background-size: 92px 20px;
width: 92px;
height: 20px;
@ -532,20 +532,20 @@ html[dir="rtl"] .generate-url-spinner {
@media (min-resolution: 2dppx) {
#powered-by-logo {
background-image: url("../../shared/img/telefonica@2x.png");
background-image: url("../shared/img/telefonica@2x.png");
}
#powered-by-logo.en-GB,
#powered-by-logo.de {
background-image: url("../../shared/img/02@2x.png");
background-image: url("../shared/img/02@2x.png");
}
#powered-by-logo.pt-BR {
background-image: url("../../shared/img/vivo@2x.png");
background-image: url("../shared/img/vivo@2x.png");
}
#powered-by-logo[class^="es-"] {
background-image: url("../../shared/img/movistar@2x.png");
background-image: url("../shared/img/movistar@2x.png");
}
}
@ -594,7 +594,7 @@ html[dir="rtl"] .generate-url-spinner {
border: none;
cursor: pointer;
vertical-align: middle;
background: transparent url("../../shared/img/icons-10x10.svg#settings-cog");
background: transparent url("../shared/img/icons-10x10.svg#settings-cog");
background-position: center;
background-repeat: no-repeat;
background-size: cover;

View File

@ -29,7 +29,7 @@ loop.panel = (function(_, mozL10n) {
return (
React.createElement("div", {className: "fte-get-started-content"},
React.createElement("header", {className: "fte-title"},
React.createElement("img", {src: "shared/img/hello_logo.svg"}),
React.createElement("img", {src: "loop/shared/img/hello_logo.svg"}),
React.createElement("div", {className: "fte-subheader"},
mozL10n.get("first_time_experience_subheading")
)
@ -379,7 +379,7 @@ loop.panel = (function(_, mozL10n) {
_renderDefaultIcon: function() {
return (
React.createElement("div", {className: "room-entry-context-item"},
React.createElement("img", {src: "shared/img/icons-16x16.svg#globe"})
React.createElement("img", {src: "loop/shared/img/icons-16x16.svg#globe"})
)
);
},
@ -390,7 +390,7 @@ loop.panel = (function(_, mozL10n) {
React.createElement("a", {href: roomUrl.location,
onClick: this.handleClick,
title: roomUrl.description},
React.createElement("img", {src: roomUrl.thumbnail || "shared/img/icons-16x16.svg#globe"})
React.createElement("img", {src: roomUrl.thumbnail || "loop/shared/img/icons-16x16.svg#globe"})
)
)
);
@ -717,7 +717,7 @@ loop.panel = (function(_, mozL10n) {
React.createElement("div", {className: "room-list"},
this._renderNewRoomButton(),
React.createElement("div", {className: "room-list-loading"},
React.createElement("img", {src: "shared/img/animated-spinner.svg"})
React.createElement("img", {src: "loop/shared/img/animated-spinner.svg"})
)
)
);
@ -884,7 +884,7 @@ loop.panel = (function(_, mozL10n) {
return (
React.createElement("div", {className: "error-content"},
React.createElement("header", {className: "error-title"},
React.createElement("img", {src: "shared/img/sad_hello_icon_64x64.svg"}),
React.createElement("img", {src: "loop/shared/img/sad_hello_icon_64x64.svg"}),
React.createElement("p", {className: "error-subheader"},
mozL10n.get("e10s_not_supported_subheading", {
brandShortname: mozL10n.get("clientShortname2")

View File

@ -29,7 +29,7 @@ loop.panel = (function(_, mozL10n) {
return (
<div className="fte-get-started-content">
<header className="fte-title">
<img src="shared/img/hello_logo.svg" />
<img src="loop/shared/img/hello_logo.svg" />
<div className="fte-subheader">
{mozL10n.get("first_time_experience_subheading")}
</div>
@ -379,7 +379,7 @@ loop.panel = (function(_, mozL10n) {
_renderDefaultIcon: function() {
return (
<div className="room-entry-context-item">
<img src="shared/img/icons-16x16.svg#globe" />
<img src="loop/shared/img/icons-16x16.svg#globe" />
</div>
);
},
@ -390,7 +390,7 @@ loop.panel = (function(_, mozL10n) {
<a href={roomUrl.location}
onClick={this.handleClick}
title={roomUrl.description}>
<img src={roomUrl.thumbnail || "shared/img/icons-16x16.svg#globe"} />
<img src={roomUrl.thumbnail || "loop/shared/img/icons-16x16.svg#globe"} />
</a>
</div>
);
@ -717,7 +717,7 @@ loop.panel = (function(_, mozL10n) {
<div className="room-list">
{this._renderNewRoomButton()}
<div className="room-list-loading">
<img src="shared/img/animated-spinner.svg" />
<img src="loop/shared/img/animated-spinner.svg" />
</div>
</div>
);
@ -884,7 +884,7 @@ loop.panel = (function(_, mozL10n) {
return (
<div className="error-content">
<header className="error-title">
<img src="shared/img/sad_hello_icon_64x64.svg" />
<img src="loop/shared/img/sad_hello_icon_64x64.svg" />
<p className="error-subheader">
{mozL10n.get("e10s_not_supported_subheading", {
brandShortname: mozL10n.get("clientShortname2")

View File

@ -346,14 +346,14 @@ loop.roomViews = (function(mozL10n) {
"triggered": this.state.copiedUrl
}),
onClick: this.handleCopyButtonClick},
React.createElement("img", {src: "shared/img/glyph-link-16x16.svg"}),
React.createElement("img", {src: "loop/shared/img/svg/glyph-link-16x16.svg"}),
React.createElement("p", null, mozL10n.get(this.state.copiedUrl ?
"invite_copied_link_button" : "invite_copy_link_button"))
),
React.createElement("div", {className: "btn-email invite-button",
onClick: this.handleEmailButtonClick,
onMouseOver: this.resetTriggeredButtons},
React.createElement("img", {src: "shared/img/glyph-email-16x16.svg"}),
React.createElement("img", {src: "loop/shared/img/svg/glyph-email-16x16.svg"}),
React.createElement("p", null, mozL10n.get("invite_email_link_button"))
)
),
@ -536,7 +536,7 @@ loop.roomViews = (function(mozL10n) {
}
var url = this._getURL();
var thumbnail = url && url.thumbnail || "shared/img/icons-16x16.svg#globe";
var thumbnail = url && url.thumbnail || "loop/shared/img/icons-16x16.svg#globe";
var urlDescription = url && url.description || "";
var location = url && url.location || "";

View File

@ -346,14 +346,14 @@ loop.roomViews = (function(mozL10n) {
"triggered": this.state.copiedUrl
})}
onClick={this.handleCopyButtonClick}>
<img src="shared/img/glyph-link-16x16.svg" />
<img src="loop/shared/img/svg/glyph-link-16x16.svg" />
<p>{mozL10n.get(this.state.copiedUrl ?
"invite_copied_link_button" : "invite_copy_link_button")}</p>
</div>
<div className="btn-email invite-button"
onClick={this.handleEmailButtonClick}
onMouseOver={this.resetTriggeredButtons}>
<img src="shared/img/glyph-email-16x16.svg" />
<img src="loop/shared/img/svg/glyph-email-16x16.svg" />
<p>{mozL10n.get("invite_email_link_button")}</p>
</div>
</div>
@ -536,7 +536,7 @@ loop.roomViews = (function(mozL10n) {
}
var url = this._getURL();
var thumbnail = url && url.thumbnail || "shared/img/icons-16x16.svg#globe";
var thumbnail = url && url.thumbnail || "loop/shared/img/icons-16x16.svg#globe";
var urlDescription = url && url.description || "";
var location = url && url.location || "";

View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<!-- 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/. -->
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="loop/shared/css/reset.css">
<link rel="stylesheet" type="text/css" href="loop/shared/css/common.css">
<link rel="stylesheet" type="text/css" href="loop/css/panel.css">
</head>
<body class="panel">
<div id="main"></div>
<script type="text/javascript" src="loop/shared/libs/react-0.13.3.js"></script>
<script type="text/javascript" src="loop/libs/l10n.js"></script>
<script type="text/javascript" src="loop/shared/libs/lodash-3.9.3.js"></script>
<script type="text/javascript" src="loop/shared/libs/backbone-1.2.1.js"></script>
<script type="text/javascript" src="loop/shared/libs/classnames-2.2.0.js"></script>
<script type="text/javascript" src="loop/shared/js/loopapi-client.js"></script>
<script type="text/javascript" src="loop/shared/js/utils.js"></script>
<script type="text/javascript" src="loop/shared/js/models.js"></script>
<script type="text/javascript" src="loop/shared/js/mixins.js"></script>
<script type="text/javascript" src="loop/shared/js/views.js"></script>
<script type="text/javascript" src="loop/shared/js/validate.js"></script>
<script type="text/javascript" src="loop/shared/js/actions.js"></script>
<script type="text/javascript" src="loop/shared/js/dispatcher.js"></script>
<script type="text/javascript" src="loop/shared/js/store.js"></script>
<script type="text/javascript" src="loop/shared/js/activeRoomStore.js"></script>
<script type="text/javascript" src="loop/js/roomStore.js"></script>
<script type="text/javascript" src="loop/js/panel.js"></script>
</body>
</html>

View File

@ -65,7 +65,7 @@ html[dir="rtl"] .conversation-toolbar > li {
background-position: center;
background-repeat: no-repeat;
background-color: transparent;
background-image: url("../img/media-group.svg");
background-image: url("../img/svg/media-group.svg");
background-size: cover;
height: 28px;
width: 67px;
@ -73,25 +73,25 @@ html[dir="rtl"] .conversation-toolbar > li {
.conversation-toolbar-media-btn-group-box > button:last-child:active,
.conversation-toolbar-media-btn-group-box > button:last-child:hover {
background-image: url("../img/media-group-right-hover.svg");
background-image: url("../img/svg/media-group-right-hover.svg");
background-size: cover;
}
html[dir="rtl"] .conversation-toolbar-media-btn-group-box > button:last-child:active,
html[dir="rtl"] .conversation-toolbar-media-btn-group-box > button:last-child:hover {
background-image: url("../img/media-group-left-hover.svg");
background-image: url("../img/svg/media-group-left-hover.svg");
background-size: cover;
}
.conversation-toolbar-media-btn-group-box > button:first-child:active,
.conversation-toolbar-media-btn-group-box > button:first-child:hover {
background-image: url("../img/media-group-left-hover.svg");
background-image: url("../img/svg/media-group-left-hover.svg");
background-size: cover;
}
html[dir="rtl"] .conversation-toolbar-media-btn-group-box > button:first-child:active,
html[dir="rtl"] .conversation-toolbar-media-btn-group-box > button:first-child:hover {
background-image: url("../img/media-group-right-hover.svg");
background-image: url("../img/svg/media-group-right-hover.svg");
background-size: cover;
}
@ -106,76 +106,76 @@ html[dir="rtl"] .conversation-toolbar-btn-box.btn-edit-entry {
/* conversationViews.jsx */
.conversation-toolbar .btn-hangup {
background-image: url("../img/exit.svg");
background-image: url("../img/svg/exit.svg");
border: 0;
}
/* Audio mute button */
.btn-mute-audio:after {
content: url("../img/audio.svg");
content: url("../img/svg/audio.svg");
}
.btn-mute-audio.muted:after {
content: url("../img/audio-mute.svg");
content: url("../img/svg/audio-mute.svg");
}
.btn-mute-audio:hover:after,
.btn-mute-audio:active:after {
content: url("../img/audio-hover.svg");
content: url("../img/svg/audio-hover.svg");
}
.btn-mute-audio.muted:hover:after,
.btn-mute-audio.muted:active:after {
content: url("../img/audio-mute-hover.svg");
content: url("../img/svg/audio-mute-hover.svg");
}
/* Video mute button */
.btn-mute-video:after {
content: url("../img/video.svg");
content: url("../img/svg/video.svg");
}
.btn-mute-video:active:after,
.btn-mute-video:hover:after {
content: url("../img/video-hover.svg");
content: url("../img/svg/video-hover.svg");
}
.btn-mute-video.muted:after {
content: url("../img/video-mute.svg");
content: url("../img/svg/video-mute.svg");
}
.btn-mute-video.muted:hover:after,
.btn-mute-video.muted:active:after {
content: url("../img/video-mute-hover.svg");
content: url("../img/svg/video-mute-hover.svg");
}
.btn-settings {
width: 28px;
height: 28px;
background-size: 28px;
background-image: url("../img/settings.svg");
background-image: url("../img/svg/settings.svg");
background-color: transparent;
}
.btn-settings:hover,
.btn-settings:active {
background-image: url("../img/settings-hover.svg");
background-image: url("../img/svg/settings-hover.svg");
}
.btn-screen-share {
background-image: url("../img/sharing.svg");
background-image: url("../img/svg/sharing.svg");
}
.btn-screen-share:hover,
.btn-screen-share:active {
background-image: url("../img/sharing-hover.svg");
background-image: url("../img/svg/sharing-hover.svg");
}
.btn-screen-share.active {
background-image: url("../img/sharing-active.svg");
background-image: url("../img/svg/sharing-active.svg");
}
.btn-screen-share.disabled {
/* The screen share button is in its pending state when its disabled. */
background-image: url("../img/sharing-pending.svg");
background-image: url("../img/svg/sharing-pending.svg");
}
/* General Call (incoming or outgoing). */

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 700 B

After

Width:  |  Height:  |  Size: 700 B

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 225 B

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 218 B

After

Width:  |  Height:  |  Size: 218 B

View File

Before

Width:  |  Height:  |  Size: 373 B

After

Width:  |  Height:  |  Size: 373 B

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

Before

Width:  |  Height:  |  Size: 188 B

After

Width:  |  Height:  |  Size: 188 B

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 599 B

After

Width:  |  Height:  |  Size: 599 B

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 241 B

After

Width:  |  Height:  |  Size: 241 B

View File

Before

Width:  |  Height:  |  Size: 718 B

After

Width:  |  Height:  |  Size: 718 B

View File

Before

Width:  |  Height:  |  Size: 473 B

After

Width:  |  Height:  |  Size: 473 B

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 912 B

After

Width:  |  Height:  |  Size: 912 B

View File

Before

Width:  |  Height:  |  Size: 724 B

After

Width:  |  Height:  |  Size: 724 B

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 499 B

After

Width:  |  Height:  |  Size: 499 B

View File

Before

Width:  |  Height:  |  Size: 532 B

After

Width:  |  Height:  |  Size: 532 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 535 B

After

Width:  |  Height:  |  Size: 535 B

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 635 B

After

Width:  |  Height:  |  Size: 635 B

View File

Before

Width:  |  Height:  |  Size: 451 B

After

Width:  |  Height:  |  Size: 451 B

View File

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 832 B

View File

Before

Width:  |  Height:  |  Size: 556 B

After

Width:  |  Height:  |  Size: 556 B

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 670 B

After

Width:  |  Height:  |  Size: 670 B

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 673 B

After

Width:  |  Height:  |  Size: 673 B

View File

Before

Width:  |  Height:  |  Size: 669 B

After

Width:  |  Height:  |  Size: 669 B

View File

Before

Width:  |  Height:  |  Size: 561 B

After

Width:  |  Height:  |  Size: 561 B

View File

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 762 B

View File

Before

Width:  |  Height:  |  Size: 784 B

After

Width:  |  Height:  |  Size: 784 B

View File

Before

Width:  |  Height:  |  Size: 564 B

After

Width:  |  Height:  |  Size: 564 B

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

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