This commit is contained in:
Ryan VanderMeulen 2016-08-24 09:04:42 -04:00
Родитель 51b6dcc500 f35f0c69e0
Коммит 44f6964ba9
138 изменённых файлов: 2104 добавлений и 7468 удалений

Просмотреть файл

@ -392,7 +392,7 @@
// The order of these links in the description is fixed in
// TransportSecurityInfo.cpp:formatOverridableCertErrorMessage.
var firstResult = domainResult;
if(!domainResult)
if (!domainResult)
firstResult = codeResult;
if (!firstResult)
return;
@ -655,7 +655,9 @@
- an onload handler. This is because error pages are loaded as
- LOAD_BACKGROUND, which means that onload handlers will not be executed.
-->
<script type="application/javascript">initPage();</script>
<script type="application/javascript">
initPage();
</script>
</body>
</html>

Просмотреть файл

@ -189,6 +189,8 @@
- an onload handler. This is because error pages are loaded as
- LOAD_BACKGROUND, which means that onload handlers will not be executed.
-->
<script type="application/javascript">initPage();</script>
<script type="application/javascript">
initPage();
</script>
</body>
</html>

Просмотреть файл

@ -93,10 +93,6 @@
label="&saveLinkCmd.label;"
accesskey="&saveLinkCmd.accesskey;"
oncommand="gContextMenu.saveLink();"/>
<menu id="context-marklinkMenu" label="&social.marklinkMenu.label;"
accesskey="&social.marklinkMenu.accesskey;">
<menupopup/>
</menu>
<menuitem id="context-copyemail"
label="&copyEmailCmd.label;"
accesskey="&copyEmailCmd.accesskey;"
@ -291,10 +287,6 @@
<menupopup id="context-sendpagetodevice-popup"
onpopupshowing="(() => { let browser = gBrowser || getPanelBrowser(); gFxAccounts.populateSendTabToDevicesMenu(event.target, browser.currentURI.spec, browser.contentTitle); })()"/>
</menu>
<menu id="context-markpageMenu" label="&social.markpageMenu.label;"
accesskey="&social.markpageMenu.accesskey;">
<menupopup/>
</menu>
<menuseparator id="context-sep-viewbgimage"/>
<menuitem id="context-viewbgimage"
label="&viewBGImageCmd.label;"

Просмотреть файл

@ -220,9 +220,6 @@
<menuitem id="menu_tabsSidebar"
observes="viewTabsSidebar"
label="&syncedTabs.sidebar.label;"/>
<!-- Service providers with sidebars are inserted between these two menuseperators -->
<menuseparator hidden="true"/>
<menuseparator class="social-provider-menu" hidden="true"/>
</menupopup>
</menu>
<menuseparator/>

Просмотреть файл

@ -108,10 +108,7 @@
<command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
<command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
<command id="Social:SharePage" oncommand="SocialShare.sharePage();"/>
<command id="Social:ToggleSidebar" oncommand="SocialSidebar.toggleSidebar();" hidden="true"/>
<command id="Social:ToggleNotifications" oncommand="Social.toggleNotifications();" hidden="true"/>
<command id="Social:Addons" oncommand="BrowserOpenAddonsMgr('addons://list/service');"/>
<command id="Chat:Focus" oncommand="Cu.import('resource:///modules/Chat.jsm', {}).Chat.focus(window);"/>
</commandset>
<commandset id="placesCommands">
@ -122,7 +119,7 @@
</commandset>
<broadcasterset id="mainBroadcasterSet">
<broadcaster id="Social:PageShareOrMark" disabled="true"/>
<broadcaster id="Social:PageShareable" disabled="true"/>
<broadcaster id="viewBookmarksSidebar" autoCheck="false" label="&bookmarksButton.label;"
type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/bookmarks/bookmarksPanel.xul"
oncommand="SidebarUI.toggle('viewBookmarksSidebar');"/>
@ -182,7 +179,6 @@
sidebarurl="chrome://browser/content/syncedtabs/sidebar.xhtml"
oncommand="SidebarUI.toggle('viewTabsSidebar');"/>
<broadcaster id="workOfflineMenuitemState"/>
<broadcaster id="socialSidebarBroadcaster" hidden="true"/>
<broadcaster id="devtoolsMenuBroadcaster_PageSource"
label="&pageSourceCmd.label;"
@ -317,17 +313,6 @@
<key id="viewBookmarksSidebarWinKb" key="&bookmarksWinCmd.commandkey;" command="viewBookmarksSidebar" modifiers="accel"/>
#endif
<!--<key id="markPage" key="&markPageCmd.commandkey;" command="Social:TogglePageMark" modifiers="accel,shift"/>-->
<key id="focusChatBar" key="&social.chatBar.commandkey;" command="Chat:Focus"
#ifdef XP_MACOSX
# Sadly the devtools uses shift-accel-c on non-mac and alt-accel-c everywhere else
# So we just use the other
modifiers="accel,shift"
#else
modifiers="accel,alt"
#endif
/>
<key id="key_stop" keycode="VK_ESCAPE" command="Browser:Stop"/>
#ifdef XP_MACOSX

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -19,30 +19,6 @@
%endif
}
/* These values are chosen to keep the Loop detached chat window from
* getting too small. When it's too small, three bad things happen:
*
* - It looks terrible
* - It's not really usable
* - It's possible for the user to be transmitting video that's cropped by the
* the edge of the window, so that they're not aware of it, which is a
* privacy problem
*
* Note that if the chat window grows more users than Loop who want this
* ability, we'll need to generalize. A partial patch for this is in
* bug 1112264.
*/
#chat-window {
/*
* In some ideal world, we'd have a simple way to express "block resizing
* along any dimension beyond the point at which an overflow event would
* occur". But none of -moz-{fit,max,min}-content do what we want here. So..
*/
min-width: 260px;
min-height: 315px;
}
#main-window[customize-entered] {
min-width: -moz-fit-content;
}
@ -923,10 +899,6 @@ html|*#gcli-output-frame,
transition: none;
}
toolbarbutton[type="socialmark"] {
-moz-binding: url("chrome://browser/content/socialmarks.xml#toolbarbutton-marks");
}
panelview > .social-panel-frame {
width: auto;
height: auto;
@ -937,77 +909,6 @@ notification[value="translation"] {
-moz-binding: url("chrome://browser/content/translation-infobar.xml#translationbar");
}
/* Social */
/* Note the chatbox 'width' values are duplicated in socialchat.xml */
chatbox {
-moz-binding: url("chrome://browser/content/socialchat.xml#chatbox");
transition: height 150ms ease-out, width 150ms ease-out;
height: 290px;
width: 300px; /* CHAT_WIDTH_OPEN in socialchat.xml */
}
chatbox[customSize] {
width: 350px; /* CHAT_WIDTH_OPEN_ALT in socialchat.xml */
}
#chat-window[customSize] {
min-width: 350px;
}
chatbox[customSize="loopChatEnabled"] {
/* 430px as defined per UX */
height: 430px;
}
#chat-window[customSize="loopChatEnabled"] {
/* 325px + 30px top bar height. */
min-height: calc(325px + 30px);
}
chatbox[customSize="loopChatMessageAppended"] {
/* 430px as defined per UX */
height: 430px;
}
chatbox[customSize="loopChatDisabledMessageAppended"] {
/* 388px as defined per UX */
height: 388px;
}
#chat-window[customSize="loopChatMessageAppended"] {
/* 445px + 30px top bar height. */
min-height: calc(400px + 30px);
}
chatbox[minimized="true"] {
width: 160px;
height: 20px; /* CHAT_WIDTH_MINIMIZED in socialchat.xml */
}
chatbar {
-moz-binding: url("chrome://browser/content/socialchat.xml#chatbar");
height: 0;
max-height: 0;
}
.chatbar-innerbox {
margin: -285px 0 0;
}
chatbar[customSize] > .chatbar-innerbox {
/* 450px to make room for the maximum custom-size chatbox; currently 'loopChatMessageAppended'. */
margin-top: -450px;
}
/* Apply crisp rendering for favicons at exactly 2dppx resolution */
@media (resolution: 2dppx) {
#social-sidebar-favico,
.social-status-button,
.chat-status-icon {
image-rendering: -moz-crisp-edges;
}
}
/** See bug 872317 for why the following rule is necessary. */
#downloads-button {
@ -1039,18 +940,6 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > #downloads-
visibility: hidden;
}
/* hide chat chrome when chat is fullscreen */
#chat-window[sizemode="fullscreen"] chatbox > .chat-titlebar {
display: none;
}
/* hide chatbar and sidebar if browser tab is fullscreen */
#main-window[inFullscreen][inDOMFullscreen] chatbar,
#main-window[inFullscreen][inDOMFullscreen] #social-sidebar-box,
#main-window[inFullscreen][inDOMFullscreen] #social-sidebar-splitter {
display: none;
}
/* Combobox dropdown renderer */
#ContentSelectDropdown > menupopup {
/* The menupopup itself should always be rendered LTR to ensure the scrollbar aligns with

Просмотреть файл

@ -2282,9 +2282,6 @@ function BrowserViewSourceOfDocument(aArgsOrDocument) {
!E10SUtils.canLoadURIInProcess(args.URL, contentProcess)
}
// In the case of sidebars and chat windows, gBrowser is defined but null,
// because no #content element exists. For these cases, we need to find
// the most recent browser window.
// In the case of popups, we need to find a non-popup browser window.
if (!tabBrowser || !window.toolbar.visible) {
// This returns only non-popup browser windows by default.

Просмотреть файл

@ -272,23 +272,6 @@
<hbox id="share-container" flex="1"/>
</panel>
<panel id="social-notification-panel"
class="social-panel"
type="arrow"
hidden="true"
noautofocus="true"/>
<panel id="social-flyout-panel"
class="social-panel"
onpopupshown="SocialFlyout.onShown()"
onpopuphidden="SocialFlyout.onHidden()"
side="right"
type="arrow"
hidden="true"
flip="slide"
rolluponmousewheel="true"
noautofocus="true"
position="topcenter topright"/>
<menupopup id="toolbar-context-menu"
onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator'));">
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
@ -1081,56 +1064,6 @@
contentcontextmenu="contentAreaContextMenu"
autocompletepopup="PopupAutoComplete"
selectmenulist="ContentSelectDropdown"/>
<chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/>
</vbox>
<splitter id="social-sidebar-splitter"
class="chromeclass-extrachrome sidebar-splitter"
observes="socialSidebarBroadcaster"/>
<vbox id="social-sidebar-box"
class="chromeclass-extrachrome"
observes="socialSidebarBroadcaster"
persist="width">
<sidebarheader id="social-sidebar-header" class="sidebar-header" align="center">
<image id="social-sidebar-favico"/>
<label id="social-sidebar-title" class="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/>
<toolbarbutton id="social-sidebar-button"
class="toolbarbutton-1"
type="menu">
<menupopup id="social-statusarea-popup" position="after_end">
<menuitem class="social-toggle-sidebar-menuitem"
type="checkbox"
autocheck="false"
command="Social:ToggleSidebar"
label="&social.toggleSidebar.label;"
accesskey="&social.toggleSidebar.accesskey;"/>
<menuitem class="social-toggle-notifications-menuitem"
type="checkbox"
autocheck="false"
command="Social:ToggleNotifications"
label="&social.toggleNotifications.label;"
accesskey="&social.toggleNotifications.accesskey;"/>
<menuseparator/>
<menuseparator class="social-provider-menu" hidden="true"/>
<menuitem class="social-addons-menuitem" command="Social:Addons"
label="&social.addons.label;"/>
<menuitem label="&social.learnMore.label;"
accesskey="&social.learnMore.accesskey;"
oncommand="SocialUI.showLearnMore();"/>
</menupopup>
</toolbarbutton>
</sidebarheader>
<browser id="social-sidebar-browser"
type="content"
context="contentAreaContextMenu"
message="true"
messagemanagergroup="social"
disableglobalhistory="true"
tooltip="aHTMLTooltip"
popupnotificationanchor="social-sidebar-favico"
flex="1"
style="min-width: 14em; width: 18em; max-width: 36em;"/>
</vbox>
<vbox id="browser-border-end" hidden="true" layer="true"/>
</hbox>

Просмотреть файл

@ -1,170 +0,0 @@
#filter substitution
<?xml version="1.0"?>
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
# 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/.
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
<?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?>
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
#include browser-doctype.inc
<window id="chat-window"
windowtype="Social:Chat"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&mainWindow.title;"
onload="gChatWindow.onLoad();"
onunload="gChatWindow.onUnload();"
macanimationtype="document"
fullscreenbutton="true"
# width and height are also used in socialchat.xml: chatbar dragend handler
width="400px"
height="420px"
persist="screenX screenY width height sizemode">
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
<script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/>
#include global-scripts.inc
<script type="application/javascript">
var gChatWindow = {
// cargo-culted from browser.js for nonBrowserStartup, but we're slightly
// different what what we need to leave enabled
onLoad: function() {
// Disable inappropriate commands / submenus
var disabledItems = ['Browser:SavePage', 'Browser:OpenFile',
'Browser:SendLink', 'cmd_pageSetup', 'cmd_print',
'cmd_find', 'cmd_findAgain', 'cmd_findPrevious',
'cmd_fullZoomReduce', 'cmd_fullZoomEnlarge', 'cmd_fullZoomReset',
#ifdef XP_MACOSX
'viewToolbarsMenu', 'viewSidebarMenuMenu',
'viewFullZoomMenu', 'pageStyleMenu', 'charsetMenu',
#else
'Browser:OpenLocation', 'Tools:Search',
#endif
'Tools:Sanitize', 'Tools:DevToolbox',
'key_selectTab1', 'key_selectTab2', 'key_selectTab3',
'key_selectTab4', 'key_selectTab5', 'key_selectTab6',
'key_selectTab7', 'key_selectTab8', 'key_selectLastTab',
'viewHistorySidebar', 'viewBookmarksSidebar',
'Browser:AddBookmarkAs', 'Browser:BookmarkAllTabs'];
for (let disabledItem of disabledItems) {
document.getElementById(disabledItem).setAttribute("disabled", "true");
}
window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow =
new chatBrowserAccess();
// initialise the offline listener
BrowserOffline.init();
},
onUnload: function() {
BrowserOffline.uninit();
}
}
// define a popupnotifications handler for this window. we don't use
// an iconbox here, and only support the browser frame for chat.
XPCOMUtils.defineLazyGetter(this, "PopupNotifications", function () {
let tmp = {};
Cu.import("resource://gre/modules/PopupNotifications.jsm", tmp);
try {
return new tmp.PopupNotifications(document.getElementById("chatter").content,
document.getElementById("notification-popup"),
null);
} catch (ex) {
console.error(ex);
return null;
}
});
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
function chatBrowserAccess() { }
chatBrowserAccess.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow, Ci.nsISupports]),
_openURIInNewTab: function(aURI, aWhere) {
if (aWhere != Ci.nsIBrowserDOMWindow.OPEN_NEWTAB)
return null;
let win = RecentWindow.getMostRecentBrowserWindow();
if (!win) {
// We couldn't find a suitable window, a new one needs to be opened.
return null;
}
let loadInBackground =
Services.prefs.getBoolPref("browser.tabs.loadDivertedInBackground");
let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank",
{inBackground: loadInBackground});
let browser = win.gBrowser.getBrowserForTab(tab);
win.focus();
return browser;
},
openURI: function (aURI, aOpener, aWhere, aContext) {
let browser = this._openURIInNewTab(aURI, aWhere);
return browser ? browser.contentWindow : null;
},
openURIInFrame: function browser_openURIInFrame(aURI, aParams, aWhere, aContext) {
let browser = this._openURIInNewTab(aURI, aWhere);
return browser ? browser.QueryInterface(Ci.nsIFrameLoaderOwner) : null;
},
isTabContentWindow: function (aWindow) {
return this.contentWindow == aWindow;
},
canClose() {
let {BrowserUtils} = Cu.import("resource://gre/modules/BrowserUtils.jsm", {});
return BrowserUtils.canCloseWindow(window);
},
};
</script>
#include browser-sets.inc
#ifdef XP_MACOSX
#include browser-menubar.inc
#endif
<popupset id="mainPopupSet">
<tooltip id="aHTMLTooltip" page="true"/>
<menupopup id="contentAreaContextMenu" pagemenu="start"
onpopupshowing="if (event.target != this)
return true;
gContextMenu = new nsContextMenu(this, event.shiftKey);
if (gContextMenu.shouldDisplay)
document.popupNode = this.triggerNode;
return gContextMenu.shouldDisplay;"
onpopuphiding="if (event.target != this)
return;
gContextMenu.hiding();
gContextMenu = null;">
#include browser-context.inc
</menupopup>
#include popup-notifications.inc
</popupset>
<commandset id="editMenuCommands"/>
<chatbox id="chatter" flex="1"/>
</window>

Просмотреть файл

@ -714,10 +714,6 @@ PageMetadataMessenger.init();
addEventListener("ActivateSocialFeature", function (aEvent) {
let document = content.document;
if (PrivateBrowsingUtils.isContentWindowPrivate(content)) {
Cu.reportError("cannot use social providers in private windows");
return;
}
let dwu = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
if (!dwu.isHandlingUserInput) {

Просмотреть файл

@ -350,28 +350,6 @@ nsContextMenu.prototype = {
this.showItem("context-bidi-page-direction-toggle",
!this.onTextInput && top.gBidiUI);
// SocialMarks. Marks does not work with text selections, only links. If
// there is more than MENU_LIMIT providers, we show a submenu for them,
// otherwise we have a menuitem per provider (added in SocialMarks class).
let markProviders = SocialMarks.getProviders();
let enablePageMarks = markProviders.length > 0 && !(this.onLink || this.onImage
|| this.onVideo || this.onAudio);
this.showItem("context-markpageMenu", enablePageMarks && markProviders.length > SocialMarks.MENU_LIMIT);
let enablePageMarkItems = enablePageMarks && markProviders.length <= SocialMarks.MENU_LIMIT;
let linkmenus = document.getElementsByClassName("context-markpage");
for (let m of linkmenus) {
m.hidden = !enablePageMarkItems;
}
let enableLinkMarks = markProviders.length > 0 &&
((this.onLink && !this.onMailtoLink) || this.onPlainTextLink);
this.showItem("context-marklinkMenu", enableLinkMarks && markProviders.length > SocialMarks.MENU_LIMIT);
let enableLinkMarkItems = enableLinkMarks && markProviders.length <= SocialMarks.MENU_LIMIT;
linkmenus = document.getElementsByClassName("context-marklink");
for (let m of linkmenus) {
m.hidden = !enableLinkMarkItems;
}
// SocialShare
let shareButton = SocialShare.shareButton;
let shareEnabled = shareButton && !shareButton.disabled && !this.onSocial;
@ -1073,12 +1051,7 @@ nsContextMenu.prototype = {
},
reload: function(event) {
if (this.onSocial) {
// full reload of social provider
Social._getProviderFromOrigin(this.browser.getAttribute("origin")).reload();
} else {
BrowserReloadOrDuplicate(event);
}
BrowserReloadOrDuplicate(event);
},
// View Partial Source
@ -1086,9 +1059,6 @@ nsContextMenu.prototype = {
let inWindow = !Services.prefs.getBoolPref("view_source.tab");
let openSelectionFn = inWindow ? null : function() {
let tabBrowser = gBrowser;
// In the case of sidebars and chat windows, gBrowser is defined but null,
// because no #content element exists. For these cases, we need to find
// the most recent browser window.
// In the case of popups, we need to find a non-popup browser window.
if (!tabBrowser || !window.toolbar.visible) {
// This returns only non-popup browser windows by default.
@ -1737,10 +1707,6 @@ nsContextMenu.prototype = {
mm.sendAsyncMessage("ContextMenu:BookmarkFrame", null, { target: this.target });
},
markLink: function CM_markLink(origin) {
// send link to social, if it is the page url linkURI will be null
SocialMarks.markLink(origin, this.linkURI ? this.linkURI.spec : null, this.target);
},
shareLink: function CM_shareLink() {
SocialShare.sharePage(null, { url: this.linkURI.spec }, this.target);
},

Просмотреть файл

@ -44,15 +44,6 @@ addEventListener("DOMTitleChanged", function(e) {
gDOMTitleChangedByUs = false;
});
addEventListener("Social:Notification", function(event) {
let frame = docShell.chromeEventHandler;
let origin = frame.getAttribute("origin");
sendAsyncMessage("Social:Notification", {
"origin": origin,
"detail": JSON.parse(event.detail)
});
});
addMessageListener("Social:OpenGraphData", (message) => {
let ev = new content.CustomEvent("OpenGraphData", { detail: JSON.stringify(message.data) });
content.dispatchEvent(ev);

Просмотреть файл

@ -1,913 +0,0 @@
<?xml version="1.0"?>
<bindings id="socialChatBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="chatbox">
<content orient="vertical" mousethrough="never">
<xul:hbox class="chat-titlebar" xbl:inherits="minimized,selected,activity" align="baseline">
<xul:hbox flex="1" onclick="document.getBindingParent(this).onTitlebarClick(event);">
<xul:image class="chat-status-icon" xbl:inherits="src=image"/>
<xul:label class="chat-title" flex="1" xbl:inherits="crop=titlecrop,value=label" crop="end"/>
</xul:hbox>
<xul:toolbarbutton anonid="webRTC-shareScreen-icon"
class="notification-anchor-icon chat-toolbarbutton screen-icon"
oncommand="document.getBindingParent(this).showNotifications(this); event.stopPropagation();"/>
<xul:toolbarbutton anonid="webRTC-sharingScreen-icon"
class="notification-anchor-icon chat-toolbarbutton screen-icon in-use"
oncommand="document.getBindingParent(this).showNotifications(this); event.stopPropagation();"/>
<xul:toolbarbutton anonid="notification-icon" class="notification-anchor-icon chat-toolbarbutton"
oncommand="document.getBindingParent(this).showNotifications(this); event.stopPropagation();"/>
<xul:toolbarbutton anonid="minimize" class="chat-minimize-button chat-toolbarbutton"
oncommand="document.getBindingParent(this).toggle();"/>
<xul:toolbarbutton anonid="swap" class="chat-swap-button chat-toolbarbutton"
oncommand="document.getBindingParent(this).swapWindows();"/>
<xul:toolbarbutton anonid="close" class="chat-close-button chat-toolbarbutton"
oncommand="document.getBindingParent(this).close();"/>
</xul:hbox>
<xul:browser anonid="remote-content" class="chat-frame" flex="1"
context="contentAreaContextMenu"
disableglobalhistory="true"
frameType="social"
message="true"
messagemanagergroup="social"
tooltip="aHTMLTooltip"
remote="true"
xbl:inherits="src,origin"
type="content"/>
<xul:browser anonid="content" class="chat-frame" flex="1"
context="contentAreaContextMenu"
disableglobalhistory="true"
message="true"
messagemanagergroup="social"
tooltip="aHTMLTooltip"
xbl:inherits="src,origin"
type="content"/>
</content>
<implementation implements="nsIDOMEventListener, nsIMessageListener">
<constructor><![CDATA[
const kAnchorMap = new Map([
["", "notification-"],
["webRTC-shareScreen-", ""],
["webRTC-sharingScreen-", ""]
]);
const kBrowsers = [
document.getAnonymousElementByAttribute(this, "anonid", "content"),
document.getAnonymousElementByAttribute(this, "anonid", "remote-content")
];
for (let content of kBrowsers) {
for (let [getterPrefix, idPrefix] of kAnchorMap) {
let getter = getterPrefix + "popupnotificationanchor";
let anonid = (idPrefix || getterPrefix) + "icon";
content.__defineGetter__(getter, () => {
delete content[getter];
return content[getter] = document.getAnonymousElementByAttribute(
this, "anonid", anonid);
});
}
}
let mm = this.content.messageManager;
// process this._callbacks, then set to null so the chatbox creator
// knows to make new callbacks immediately.
if (this._callbacks) {
for (let callback of this._callbacks) {
callback(this);
}
this._callbacks = null;
}
mm.addMessageListener("Social:DOMTitleChanged", this);
mm.sendAsyncMessage("WaitForDOMContentLoaded");
mm.addMessageListener("DOMContentLoaded", function DOMContentLoaded(event) {
mm.removeMessageListener("DOMContentLoaded", DOMContentLoaded);
this.isActive = !this.minimized;
this._chat.loadButtonSet(this, this.getAttribute("buttonSet"));
this._deferredChatLoaded.resolve(this);
}.bind(this));
this.setActiveBrowser();
]]></constructor>
<field name="_deferredChatLoaded" readonly="true">
Promise.defer();
</field>
<property name="promiseChatLoaded">
<getter>
return this._deferredChatLoaded.promise;
</getter>
</property>
<property name="content">
<getter>
return document.getAnonymousElementByAttribute(this, "anonid",
(this.remote ? "remote-" : "") + "content");
</getter>
</property>
<field name="_chat" readonly="true">
Cu.import("resource:///modules/Chat.jsm", {}).Chat;
</field>
<property name="minimized">
<getter>
return this.getAttribute("minimized") == "true";
</getter>
<setter><![CDATA[
// Note that this.isActive is set via our transitionend handler so
// the content doesn't see intermediate values.
let parent = this.chatbar;
if (val) {
this.setAttribute("minimized", "true");
// If this chat is the selected one a new one needs to be selected.
if (parent && parent.selectedChat == this)
parent._selectAnotherChat();
} else {
this.removeAttribute("minimized");
// this chat gets selected.
if (parent)
parent.selectedChat = this;
}
]]></setter>
</property>
<property name="chatbar">
<getter>
if (this.parentNode.nodeName == "chatbar")
return this.parentNode;
return null;
</getter>
</property>
<property name="isActive">
<getter>
return this.content.docShellIsActive;
</getter>
<setter>
this.content.docShellIsActive = !!val;
// Bug 1256431 to remove socialFrameShow/Hide from hello, keep this
// until that is complete.
// let the chat frame know if it is being shown or hidden
this.content.messageManager.sendAsyncMessage("Social:CustomEvent", {
name: val ? "socialFrameShow" : "socialFrameHide"
});
</setter>
</property>
<field name="_remote">false</field>
<property name="remote" onget="return this._remote;">
<setter><![CDATA[
this._remote = !!val;
this.setActiveBrowser();
]]></setter>
</property>
<method name="setActiveBrowser">
<body><![CDATA[
// Make sure we only show one browser element at a time.
let content = document.getAnonymousElementByAttribute(this, "anonid", "content");
let remoteContent = document.getAnonymousElementByAttribute(this, "anonid", "remote-content");
remoteContent.setAttribute("hidden", !this.remote);
content.setAttribute("hidden", this.remote);
remoteContent.removeAttribute("src");
content.removeAttribute("src");
if (this.src) {
this.setAttribute("src", this.src);
// Stop loading of the document - that is set before this method was
// called - in the now hidden browser.
(this.remote ? content : remoteContent).setAttribute("src", "about:blank");
}
]]></body>
</method>
<method name="showNotifications">
<parameter name="aAnchor"/>
<body><![CDATA[
PopupNotifications._reshowNotifications(aAnchor,
this.content);
]]></body>
</method>
<method name="swapDocShells">
<parameter name="aTarget"/>
<body><![CDATA[
aTarget.setAttribute("label", this.content.contentTitle);
aTarget.remote = this.remote;
aTarget.src = this.src;
let content = aTarget.content;
content.setAttribute("origin", this.content.getAttribute("origin"));
content.popupnotificationanchor.className = this.content.popupnotificationanchor.className;
content.swapDocShells(this.content);
// When a chat window is attached or detached, the docShell hosting
// the chat document is swapped to the newly created chat window.
// (Be it inside a popup or back inside a chatbox element attached to
// the chatbar.)
// Since a swapDocShells call does not swap the messageManager instances
// attached to a browser, we'll need to add the message listeners to
// the new messageManager. This is not a bug in swapDocShells, merely
// a design decision.
content.messageManager.addMessageListener("Social:DOMTitleChanged", content);
]]></body>
</method>
<method name="setDecorationAttributes">
<parameter name="aTarget"/>
<body><![CDATA[
if (this.hasAttribute("customSize"))
aTarget.setAttribute("customSize", this.getAttribute("customSize"));
this._chat.loadButtonSet(aTarget, this.getAttribute("buttonSet"));
]]></body>
</method>
<method name="onTitlebarClick">
<parameter name="aEvent"/>
<body><![CDATA[
if (!this.chatbar)
return;
if (aEvent.button == 0) { // left-click: toggle minimized.
this.toggle();
// if we restored it, we want to focus it.
if (!this.minimized)
this.chatbar.focus();
} else if (aEvent.button == 1) // middle-click: close chat
this.close();
]]></body>
</method>
<method name="close">
<body><![CDATA[
if (this.chatbar)
this.chatbar.remove(this);
else
window.close();
if (!this.swappingWindows)
this.dispatchEvent(new CustomEvent("ChatboxClosed"));
]]></body>
</method>
<method name="swapWindows">
<body><![CDATA[
let deferred = Promise.defer();
let title = this.getAttribute("label");
if (this.chatbar) {
this.chatbar.detachChatbox(this, { "centerscreen": "yes" }).then(
chatbox => {
chatbox.content.messageManager.sendAsyncMessage("Social:SetDocumentTitle", {
title: title
});
deferred.resolve(chatbox);
}
);
} else {
// attach this chatbox to the topmost browser window
let Chat = Cu.import("resource:///modules/Chat.jsm").Chat;
let win = Chat.findChromeWindowForChats();
let chatbar = win.document.getElementById("pinnedchats");
let origin = this.content.getAttribute("origin");
let cb = chatbar.openChat({
origin: origin,
title: title,
url: "about:blank"
});
cb.promiseChatLoaded.then(
() => {
this.setDecorationAttributes(cb);
this.swapDocShells(cb);
chatbar.focus();
this.swappingWindows = true;
this.close();
// chatboxForURL is a map of URL -> chatbox used to avoid opening
// duplicate chat windows. Ensure reattached chat windows aren't
// registered with about:blank as their URL, otherwise reattaching
// more than one chat window isn't possible.
chatbar.chatboxForURL.delete("about:blank");
chatbar.chatboxForURL.set(this.src, Cu.getWeakReference(cb));
cb.content.messageManager.sendAsyncMessage("Social:CustomEvent", {
name: "socialFrameAttached"
});
deferred.resolve(cb);
}
);
}
return deferred.promise;
]]></body>
</method>
<method name="toggle">
<body><![CDATA[
this.minimized = !this.minimized;
]]></body>
</method>
<method name="setTitle">
<body><![CDATA[
try {
this.setAttribute("label", this.content.contentTitle);
} catch (ex) {}
if (this.chatbar)
this.chatbar.updateTitlebar(this);
]]></body>
</method>
<method name="receiveMessage">
<parameter name="aMessage" />
<body><![CDATA[
switch (aMessage.name) {
case "Social:DOMTitleChanged":
this.setTitle();
break;
}
]]></body>
</method>
</implementation>
<handlers>
<handler event="focus" phase="capturing">
if (this.chatbar)
this.chatbar.selectedChat = this;
</handler>
<handler event="DOMTitleChanged">
this.setTitle();
</handler>
<handler event="DOMLinkAdded"><![CDATA[
// Much of this logic is from DOMLinkHandler in browser.js.
// This sets the presence icon for a chat user, we simply use favicon
// style updating.
let link = event.originalTarget;
let rel = link.rel && link.rel.toLowerCase();
if (!link || !link.ownerDocument || !rel || !link.href)
return;
if (link.rel.indexOf("icon") < 0)
return;
let ContentLinkHandler = Cu.import("resource:///modules/ContentLinkHandler.jsm", {})
.ContentLinkHandler;
let uri = ContentLinkHandler.getLinkIconURI(link);
if (!uri)
return;
// We made it this far, use it.
this.setAttribute("image", uri.spec);
if (this.chatbar)
this.chatbar.updateTitlebar(this);
]]></handler>
<handler event="transitionend">
if (this.isActive == this.minimized)
this.isActive = !this.minimized;
</handler>
</handlers>
</binding>
<binding id="chatbar">
<content>
<xul:hbox align="end" pack="end" anonid="innerbox" class="chatbar-innerbox" mousethrough="always" flex="1">
<xul:spacer flex="1" anonid="spacer" class="chatbar-overflow-spacer"/>
<xul:toolbarbutton anonid="nub" class="chatbar-button" type="menu" collapsed="true" mousethrough="never">
<xul:menupopup anonid="nubMenu" oncommand="document.getBindingParent(this).showChat(event.target.chat)"/>
</xul:toolbarbutton>
<children/>
</xul:hbox>
</content>
<implementation implements="nsIDOMEventListener">
<constructor>
// to avoid reflows we cache the width of the nub.
this.cachedWidthNub = 0;
this._selectedChat = null;
</constructor>
<field name="innerbox" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "innerbox");
</field>
<field name="menupopup" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "nubMenu");
</field>
<field name="nub" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "nub");
</field>
<method name="focus">
<body><![CDATA[
if (!this.selectedChat)
return;
this.selectedChat.content.messageManager.sendAsyncMessage("Social:EnsureFocus");
]]></body>
</method>
<method name="_isChatFocused">
<parameter name="aChatbox"/>
<body><![CDATA[
// If there are no XBL bindings for the chat it can't be focused.
if (!aChatbox.content)
return false;
let fw = Services.focus.focusedWindow;
if (!fw)
return false;
// We want to see if the focused window is in the subtree below our browser...
let containingBrowser = fw.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
return containingBrowser == aChatbox.content;
]]></body>
</method>
<property name="selectedChat">
<getter><![CDATA[
return this._selectedChat;
]]></getter>
<setter><![CDATA[
// this is pretty horrible, but we:
// * want to avoid doing touching 'selected' attribute when the
// specified chat is already selected.
// * remove 'activity' attribute on newly selected tab *even if*
// newly selected is already selected.
// * need to handle either current or new being null.
if (this._selectedChat != val) {
if (this._selectedChat) {
this._selectedChat.removeAttribute("selected");
}
this._selectedChat = val;
if (val) {
this._selectedChat.setAttribute("selected", "true");
}
}
if (val) {
this._selectedChat.removeAttribute("activity");
}
]]></setter>
</property>
<field name="menuitemMap">new WeakMap()</field>
<field name="chatboxForURL">new Map();</field>
<property name="hasCollapsedChildren">
<getter><![CDATA[
return !!this.querySelector("[collapsed]");
]]></getter>
</property>
<property name="collapsedChildren">
<getter><![CDATA[
// A generator yielding all collapsed chatboxes, in the order in
// which they should be restored.
return function*() {
let child = this.lastElementChild;
while (child) {
if (child.collapsed)
yield child;
child = child.previousElementSibling;
}
}
]]></getter>
</property>
<property name="visibleChildren">
<getter><![CDATA[
// A generator yielding all non-collapsed chatboxes.
return function*() {
let child = this.firstElementChild;
while (child) {
if (!child.collapsed)
yield child;
child = child.nextElementSibling;
}
}
]]></getter>
</property>
<property name="collapsibleChildren">
<getter><![CDATA[
// A generator yielding all children which are able to be collapsed
// in the order in which they should be collapsed.
// (currently this is all visible ones other than the selected one.)
return function*() {
for (let child of this.visibleChildren())
if (child != this.selectedChat)
yield child;
}
]]></getter>
</property>
<method name="_selectAnotherChat">
<body><![CDATA[
// Select a different chat (as the currently selected one is no
// longer suitable as the selection - maybe it is being minimized or
// closed.) We only select non-minimized and non-collapsed chats,
// and if none are found, set the selectedChat to null.
// It's possible in the future we will track most-recently-selected
// chats or similar to find the "best" candidate - for now though
// the choice is somewhat arbitrary.
let moveFocus = this.selectedChat && this._isChatFocused(this.selectedChat);
for (let other of this.children) {
if (other != this.selectedChat && !other.minimized && !other.collapsed) {
this.selectedChat = other;
if (moveFocus)
this.focus();
return;
}
}
// can't find another - so set no chat as selected.
this.selectedChat = null;
]]></body>
</method>
<method name="updateTitlebar">
<parameter name="aChatbox"/>
<body><![CDATA[
if (aChatbox.collapsed) {
let menuitem = this.menuitemMap.get(aChatbox);
if (aChatbox.getAttribute("activity")) {
menuitem.setAttribute("activity", true);
this.nub.setAttribute("activity", true);
}
menuitem.setAttribute("label", aChatbox.getAttribute("label"));
menuitem.setAttribute("image", aChatbox.getAttribute("image"));
}
]]></body>
</method>
<method name="calcTotalWidthOf">
<parameter name="aElement"/>
<body><![CDATA[
let cs = document.defaultView.getComputedStyle(aElement);
let margins = parseInt(cs.marginLeft) + parseInt(cs.marginRight);
return aElement.getBoundingClientRect().width + margins;
]]></body>
</method>
<method name="getTotalChildWidth">
<parameter name="aChatbox"/>
<body><![CDATA[
// These are from the CSS for the chatbox and must be kept in sync.
// We can't use calcTotalWidthOf due to the transitions...
const CHAT_WIDTH_OPEN = 300;
const CHAT_WIDTH_OPEN_ALT = 350;
const CHAT_WIDTH_MINIMIZED = 160;
let openWidth = aChatbox.hasAttribute("customSize") ?
CHAT_WIDTH_OPEN_ALT : CHAT_WIDTH_OPEN;
return aChatbox.minimized ? CHAT_WIDTH_MINIMIZED : openWidth;
]]></body>
</method>
<method name="collapseChat">
<parameter name="aChatbox"/>
<body><![CDATA[
// we ensure that the cached width for a child of this type is
// up-to-date so we can use it when resizing.
this.getTotalChildWidth(aChatbox);
aChatbox.collapsed = true;
aChatbox.isActive = false;
let menu = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem");
menu.setAttribute("class", "menuitem-iconic");
menu.setAttribute("label", aChatbox.content.contentTitle);
menu.setAttribute("image", aChatbox.getAttribute("image"));
menu.chat = aChatbox;
this.menuitemMap.set(aChatbox, menu);
this.menupopup.appendChild(menu);
this.nub.collapsed = false;
]]></body>
</method>
<method name="showChat">
<parameter name="aChatbox"/>
<parameter name="aMode"/>
<body><![CDATA[
if ((aMode != "minimized") && aChatbox.minimized)
aChatbox.minimized = false;
if (this.selectedChat != aChatbox)
this.selectedChat = aChatbox;
if (!aChatbox.collapsed)
return; // already showing - no more to do.
this._showChat(aChatbox);
// showing a collapsed chat might mean another needs to be collapsed
// to make room...
this.resize();
]]></body>
</method>
<method name="_showChat">
<parameter name="aChatbox"/>
<body><![CDATA[
// the actual implementation - doesn't check for overflow, assumes
// collapsed, etc.
let menuitem = this.menuitemMap.get(aChatbox);
this.menuitemMap.delete(aChatbox);
this.menupopup.removeChild(menuitem);
aChatbox.collapsed = false;
aChatbox.isActive = !aChatbox.minimized;
]]></body>
</method>
<method name="remove">
<parameter name="aChatbox"/>
<body><![CDATA[
this._remove(aChatbox);
// The removal of a chat may mean a collapsed one can spring up,
// or that the popup should be hidden. We also defer the selection
// of another chat until after a resize, as a new candidate may
// become uncollapsed after the resize.
this.resize();
if (this.selectedChat == aChatbox) {
this._selectAnotherChat();
}
]]></body>
</method>
<method name="_remove">
<parameter name="aChatbox"/>
<body><![CDATA[
this.removeChild(aChatbox);
// child might have been collapsed.
let menuitem = this.menuitemMap.get(aChatbox);
if (menuitem) {
this.menuitemMap.delete(aChatbox);
this.menupopup.removeChild(menuitem);
}
this.chatboxForURL.delete(aChatbox.src);
]]></body>
</method>
<method name="openChat">
<parameter name="aOptions"/>
<parameter name="aCallback"/>
<body><![CDATA[
let {origin, title, url, mode} = aOptions;
let cb = this.chatboxForURL.get(url);
if (cb && (cb = cb.get())) {
// A chatbox is still alive to us when it's parented and still has
// content.
if (cb.parentNode) {
this.showChat(cb, mode);
if (aCallback) {
if (cb._callbacks == null) {
// Chatbox has already been created, so callback now.
aCallback(cb);
} else {
// Chatbox is yet to have bindings created...
cb._callbacks.push(aCallback);
}
}
return cb;
}
this.chatboxForURL.delete(url);
}
cb = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "chatbox");
cb._callbacks = [];
if (aCallback) {
// _callbacks is a javascript property instead of a <field> as it
// must exist before the (possibly delayed) bindings are created.
cb._callbacks.push(aCallback);
}
cb.remote = !!aOptions.remote;
// src also a javascript property; the src attribute is set in the ctor.
cb.src = url;
if (mode == "minimized")
cb.setAttribute("minimized", "true");
cb.setAttribute("origin", origin);
cb.setAttribute("label", title);
this.insertBefore(cb, this.firstChild);
this.selectedChat = cb;
this.chatboxForURL.set(url, Cu.getWeakReference(cb));
this.resize();
return cb;
]]></body>
</method>
<method name="resize">
<body><![CDATA[
// Checks the current size against the collapsed state of children
// and collapses or expands as necessary such that as many as possible
// are shown.
// So 2 basic strategies:
// * Collapse/Expand one at a time until we can't collapse/expand any
// more - but this is one reflow per change.
// * Calculate the dimensions ourself and choose how many to collapse
// or expand based on this, then do them all in one go. This is one
// reflow regardless of how many we change.
// So we go the more complicated but more efficient second option...
let availWidth = this.getBoundingClientRect().width;
let currentWidth = 0;
if (!this.nub.collapsed) { // the nub is visible.
if (!this.cachedWidthNub)
this.cachedWidthNub = this.calcTotalWidthOf(this.nub);
currentWidth += this.cachedWidthNub;
}
for (let child of this.visibleChildren()) {
currentWidth += this.getTotalChildWidth(child);
}
if (currentWidth > availWidth) {
// we need to collapse some.
let toCollapse = [];
for (let child of this.collapsibleChildren()) {
if (currentWidth <= availWidth)
break;
toCollapse.push(child);
currentWidth -= this.getTotalChildWidth(child);
}
if (toCollapse.length) {
for (let child of toCollapse)
this.collapseChat(child);
}
} else if (currentWidth < availWidth) {
// we *might* be able to expand some - see how many.
// XXX - if this was clever, it could know when removing the nub
// leaves enough space to show all collapsed
let toShow = [];
for (let child of this.collapsedChildren()) {
currentWidth += this.getTotalChildWidth(child);
if (currentWidth > availWidth)
break;
toShow.push(child);
}
for (let child of toShow)
this._showChat(child);
// If none remain collapsed remove the nub.
if (!this.hasCollapsedChildren) {
this.nub.collapsed = true;
}
}
// else: achievement unlocked - we are pixel-perfect!
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.type == "resize") {
this.resize();
}
]]></body>
</method>
<method name="_getDragTarget">
<parameter name="event"/>
<body><![CDATA[
return event.target.localName == "chatbox" ? event.target : null;
]]></body>
</method>
<!-- Moves a chatbox to a new window. Returns a promise that is resolved
once the move to the other window is complete.
-->
<method name="detachChatbox">
<parameter name="aChatbox"/>
<parameter name="aOptions"/>
<body><![CDATA[
let deferred = Promise.defer();
let chatbar = this;
let options = "";
for (let name in aOptions)
options += "," + name + "=" + aOptions[name];
let otherWin = window.openDialog("chrome://browser/content/chatWindow.xul",
"_blank", "chrome,all,dialog=no" + options);
otherWin.addEventListener("load", function _chatLoad(event) {
if (event.target != otherWin.document)
return;
if (aChatbox.hasAttribute("customSize")) {
otherWin.document.getElementById("chat-window").
setAttribute("customSize", aChatbox.getAttribute("customSize"));
}
otherWin.removeEventListener("load", _chatLoad, true);
let otherChatbox = otherWin.document.getElementById("chatter");
aChatbox.setDecorationAttributes(otherChatbox);
aChatbox.swapDocShells(otherChatbox);
aChatbox.swappingWindows = true;
aChatbox.close();
let url = aChatbox.src;
chatbar.chatboxForURL.set(url, Cu.getWeakReference(otherChatbox));
// All processing is done, now we can fire the event.
otherChatbox.content.messageManager.sendAsyncMessage("Social:CustomEvent", {
name: "socialFrameDetached"
});
Services.obs.addObserver(function onDOMWindowClosed(subject) {
if (subject !== otherWin)
return;
Services.obs.removeObserver(onDOMWindowClosed, "domwindowclosed");
chatbar.chatboxForURL.delete(url);
if (!otherChatbox.swappingWindows)
otherChatbox.dispatchEvent(new CustomEvent("ChatboxClosed"));
}, "domwindowclosed", false);
deferred.resolve(otherChatbox);
}, true);
return deferred.promise;
]]></body>
</method>
</implementation>
<handlers>
<handler event="popupshown"><![CDATA[
this.nub.removeAttribute("activity");
]]></handler>
<handler event="load"><![CDATA[
window.addEventListener("resize", this, true);
]]></handler>
<handler event="unload"><![CDATA[
window.removeEventListener("resize", this, true);
]]></handler>
<handler event="dragstart"><![CDATA[
// chat window dragging is essentially duplicated from tabbrowser.xml
// to acheive the same visual experience
let chatbox = this._getDragTarget(event);
if (!chatbox) {
return;
}
let dt = event.dataTransfer;
// we do not set a url in the drag data to prevent moving to tabbrowser
// or otherwise having unexpected drop handlers do something with our
// chatbox
dt.mozSetDataAt("application/x-moz-chatbox", chatbox, 0);
// Set the cursor to an arrow during tab drags.
dt.mozCursor = "default";
// Create a canvas to which we capture the current tab.
// Until canvas is HiDPI-aware (bug 780362), we need to scale the desired
// canvas size (in CSS pixels) to the window's backing resolution in order
// to get a full-resolution drag image for use on HiDPI displays.
let windowUtils = window.getInterface(Ci.nsIDOMWindowUtils);
let scale = windowUtils.screenPixelsPerCSSPixel / windowUtils.fullZoom;
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.mozOpaque = true;
canvas.width = 160 * scale;
canvas.height = 90 * scale;
PageThumbs.captureToCanvas(chatbox, canvas);
dt.setDragImage(canvas, -16 * scale, -16 * scale);
event.stopPropagation();
]]></handler>
<handler event="dragend"><![CDATA[
let dt = event.dataTransfer;
let draggedChat = dt.mozGetDataAt("application/x-moz-chatbox", 0);
if (dt.mozUserCancelled || dt.dropEffect != "none") {
return;
}
let eX = event.screenX;
let eY = event.screenY;
// screen.availLeft et. al. only check the screen that this window is on,
// but we want to look at the screen the tab is being dropped onto.
let sX = {}, sY = {}, sWidth = {}, sHeight = {};
Cc["@mozilla.org/gfx/screenmanager;1"]
.getService(Ci.nsIScreenManager)
.screenForRect(eX, eY, 1, 1)
.GetAvailRect(sX, sY, sWidth, sHeight);
// default size for the chat window as used in chatWindow.xul, use them
// here to attempt to keep the window fully within the screen when
// opening at the drop point. If the user has resized the window to
// something larger (which gets persisted), at least a good portion of
// the window should still be within the screen.
let winWidth = 400;
let winHeight = 420;
// ensure new window entirely within screen
let left = Math.min(Math.max(eX, sX.value),
sX.value + sWidth.value - winWidth);
let top = Math.min(Math.max(eY, sY.value),
sY.value + sHeight.value - winHeight);
this.detachChatbox(draggedChat, { screenX: left, screenY: top });
event.stopPropagation();
]]></handler>
</handlers>
</binding>
</bindings>

Просмотреть файл

@ -1,366 +0,0 @@
<?xml version="1.0"?>
<bindings id="socialMarkBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="toolbarbutton-marks" display="xul:button"
extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton">
<content>
<xul:panel anonid="panel" hidden="true" type="arrow" class="social-panel"/>
<xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label"/>
<xul:label class="toolbarbutton-text" crop="right" flex="1"
xbl:inherits="value=label,accesskey,crop,wrap"/>
<xul:label class="toolbarbutton-multiline-text" flex="1"
xbl:inherits="xbl:text=label,accesskey,wrap"/>
</content>
<implementation implements="nsIDOMEventListener, nsIObserver">
<constructor>
// if we overflow, we have to reset the button. unfortunately we cannot
// use a widget listener because we need to do this *after* the node is
// moved, and the event happens before the node is moved.
this.update();
</constructor>
<property name="_anchor">
<getter>
let widgetGroup = CustomizableUI.getWidget(this.getAttribute("id"));
return widgetGroup.forWindow(window).anchor;
</getter>
</property>
<property name="_useDynamicResizer">
<getter>
let provider = Social._getProviderFromOrigin(this.getAttribute("origin"));
return !provider.getPageSize("marks");
</getter>
</property>
<property name="panel">
<getter>
return document.getAnonymousElementByAttribute(this, "anonid", "panel");
</getter>
</property>
<property name="content">
<getter><![CDATA[
if (this._frame)
return this._frame;
let provider = Social._getProviderFromOrigin(this.getAttribute("origin"));
let size = provider.getPageSize("marks");
let {width, height} = size ? size : {width: 330, height: 100};
let iframe = this._frame = document.createElement("iframe");
iframe.setAttribute("type", "content");
iframe.setAttribute("class", "social-panel-frame");
iframe.setAttribute("flex", "1");
iframe.setAttribute("message", "true");
iframe.setAttribute("messagemanagergroup", "social");
iframe.setAttribute("tooltip", "aHTMLTooltip");
iframe.setAttribute("context", "contentAreaContextMenu");
iframe.setAttribute("origin", provider.origin);
iframe.setAttribute("style", "width: " + width + "px; height: " + height + "px;");
this.panel.appendChild(iframe);
this._frame.addEventListener("DOMLinkAdded", this);
return this._frame;
]]></getter>
</property>
<property name="messageManager">
<getter>
return this.content.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.messageManager;
</getter>
</property>
<property name="contentWindow">
<getter>
return this.content.contentWindow;
</getter>
</property>
<property name="contentDocument">
<getter>
return this.content.contentDocument;
</getter>
</property>
<property name="provider">
<getter>
return Social._getProviderFromOrigin(this.getAttribute("origin"));
</getter>
</property>
<property name="isMarked">
<setter><![CDATA[
this._isMarked = val;
let provider = this.provider;
// we cannot size the image when we apply it via listStyleImage, so
// use the toolbar image
let widgetGroup = CustomizableUI.getWidget(this.getAttribute("id"));
val = val && !!widgetGroup.areaType;
let icon = val ? provider.markedIcon : provider.unmarkedIcon;
let iconURL = icon || provider.icon32URL || provider.iconURL;
this.setAttribute("image", iconURL);
]]></setter>
<getter>
return this._isMarked;
</getter>
</property>
<method name="update">
<body><![CDATA[
// update the button for use with the current tab
let provider = this.provider;
if (this._dynamicResizer) {
this._dynamicResizer.stop();
this._dynamicResizer = null;
}
this.content.setAttribute("src", "about:blank");
// called during onhidden, make sure the docshell is updated
if (this._frame.docShell)
this._frame.docShell.createAboutBlankContentViewer(null);
// disabled attr is set by Social:PageShareOrMark command
if (this.hasAttribute("disabled")) {
this.isMarked = false;
} else {
Social.isURIMarked(provider.origin, gBrowser.currentURI, (isMarked) => {
this.isMarked = isMarked;
});
}
this.content.setAttribute("origin", provider.origin);
let panel = this.panel;
// if customization is currently happening, we may not have a panel
// that we can hide
if (panel.hidePopup) {
panel.hidePopup();
}
this.pageData = null;
]]></body>
</method>
<method name="receiveMessage">
<parameter name="message"/>
<body><![CDATA[
if (message.name != "Social:ErrorPageNotify" || message.target != this.content)
return;
this.openPanel();
]]></body>
</method>
<method name="loadPanel">
<parameter name="pageData"/>
<parameter name="target"/>
<body><![CDATA[
let provider = this.provider;
let panel = this.panel;
panel.hidden = false;
// reparent the iframe if we've been customized to a new location
if (this.content.parentNode != panel)
panel.appendChild(this.content);
let URLTemplate = provider.markURL;
let _dataFn;
if (!pageData) {
messageManager.addMessageListener("PageMetadata:PageDataResult", _dataFn = (msg) => {
messageManager.removeMessageListener("PageMetadata:PageDataResult", _dataFn);
this.loadPanel(msg.json, target);
});
gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetPageData", null, { target });
return;
}
// if this is a share of a selected item, get any microformats
if (!pageData.microformats && target) {
messageManager.addMessageListener("PageMetadata:MicroformatsResult", _dataFn = (msg) => {
messageManager.removeMessageListener("PageMetadata:MicroformatsResult", _dataFn);
pageData.microformats = msg.data;
this.loadPanel(pageData, target);
});
gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetMicroformats", null, { target });
return;
}
this.pageData = pageData;
let endpoint = OpenGraphBuilder.generateEndpointURL(URLTemplate, this.pageData);
// setup listeners
let DOMContentLoaded = (event) => {
this._loading = false;
this.messageManager.removeMessageListener("DOMContentLoaded", DOMContentLoaded);
// add our resizer after the dom is ready
if (this._useDynamicResizer) {
let DynamicResizeWatcher = Cu.import("resource:///modules/Social.jsm", {}).DynamicResizeWatcher;
this._dynamicResizer = new DynamicResizeWatcher();
this._dynamicResizer.start(this.panel, this.content);
} else if (this._dynamicResizer) {
this._dynamicResizer.stop();
this._dynamicResizer = null;
}
let contentWindow = this.contentWindow;
let markUpdate = function(event) {
// update the annotation based on this event, then update the
// icon as well
this.isMarked = JSON.parse(event.detail).marked;
if (this.isMarked) {
Social.markURI(provider.origin, gBrowser.currentURI);
} else {
Social.unmarkURI(provider.origin, gBrowser.currentURI, () => {
this.update();
});
}
}.bind(this);
let unload = () => {
contentWindow.removeEventListener("unload", unload);
contentWindow.removeEventListener("socialMarkUpdate", markUpdate);
}
contentWindow.addEventListener("socialMarkUpdate", markUpdate);
contentWindow.addEventListener("unload", unload);
// send the opengraph data
this.messageManager.sendAsyncMessage("Social:OpenGraphData", pageData);
}
this.messageManager.addMessageListener("DOMContentLoaded", DOMContentLoaded);
this._loading = true;
this.content.setAttribute("src", endpoint);
]]></body>
</method>
<method name="openPanel">
<parameter name="aResetOnClose"/>
<body><![CDATA[
let panel = this.panel;
let anchor = document.getAnonymousElementByAttribute(this._anchor, "class", "toolbarbutton-icon");
// Bug 849216 - open the popup in a setTimeout so we avoid the auto-rollup
// handling from preventing it being opened in some cases.
setTimeout(() => {
panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
}, 0);
Services.telemetry.getHistogramById("SOCIAL_TOOLBAR_BUTTONS").add(2);
]]></body>
</method>
<method name="markCurrentPage">
<parameter name="aOpenPanel"/>
<body><![CDATA[
// we always set the src on click if it has not been set for this tab,
// but we only want to open the panel if it was previously annotated.
let openPanel = this.isMarked || aOpenPanel;
let src = this.content.getAttribute("src");
if (!src || src == "about:blank") {
this.loadPanel();
}
if (openPanel)
this.openPanel();
]]></body>
</method>
<method name="markLink">
<parameter name="aUrl"/>
<parameter name="aTarget"/>
<body><![CDATA[
if (!aUrl) {
this.markCurrentPage(true);
return;
}
// initiated form an external source, such as gContextMenu, where
// pageData is passed into us. In this case, we always load the iframe
// and show it since the url may not be the browser tab, but an image,
// link, etc. inside the page. We also "update" the iframe to the
// previous url when it is closed.
this.content.setAttribute("src", "about:blank");
this.loadPanel({ url: aUrl }, aTarget);
this.openPanel(true);
]]></body>
</method>
<method name="dispatchPanelEvent">
<parameter name="name"/>
<body><![CDATA[
let evt = this.contentDocument.createEvent("CustomEvent");
evt.initCustomEvent(name, true, true, {});
this.contentDocument.documentElement.dispatchEvent(evt);
]]></body>
</method>
<method name="onShown">
<body><![CDATA[
// because the panel may be preloaded, we need to size the panel when
// showing as well as after load
if (!this._useDynamicResizer) {
return;
}
let sizeSocialPanelToContent = Cu.import("resource:///modules/Social.jsm", {}).sizeSocialPanelToContent;
if (!this._loading && this.contentDocument &&
this.contentDocument.readyState == "complete") {
sizeSocialPanelToContent(this.panel, this.content);
} else {
let panelBrowserOnload = (message) => {
if (message.target != this.content)
return;
this.messageManager.removeMessageListener("PageVisibility:Show", panelBrowserOnload, true);
sizeSocialPanelToContent(this.panel, this.content);
};
this.messageManager.addMessageListener("PageVisibility:Show", panelBrowserOnload);
}
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.eventPhase != aEvent.BUBBLING_PHASE)
return;
switch (aEvent.type) {
case "DOMLinkAdded": {
// much of this logic is from DOMLinkHandler in browser.js, this sets
// the presence icon for a chat user, we simply use favicon style
// updating
let link = aEvent.originalTarget;
let rel = link.rel && link.rel.toLowerCase();
if (!link || !link.ownerDocument || !rel || !link.href)
return;
if (link.rel.indexOf("icon") < 0)
return;
let ContentLinkHandler = Cu.import("resource:///modules/ContentLinkHandler.jsm", {}).ContentLinkHandler;
let uri = ContentLinkHandler.getLinkIconURI(link);
if (!uri)
return;
// we cannot size the image when we apply it via listStyleImage, so
// use the toolbar image
this.setAttribute("image", uri.spec);
}
break;
case "click":
Services.telemetry.getHistogramById("SOCIAL_PANEL_CLICKS").add(2);
break;
}
]]></body>
</method>
</implementation>
<handlers>
<handler event="popupshowing"><![CDATA[
this._anchor.setAttribute("open", "true");
this.content.addEventListener("click", this);
]]></handler>
<handler event="popupshown"><![CDATA[
this.onShown();
]]></handler>
<handler event="popuphidden"><![CDATA[
this._anchor.removeAttribute("open");
this.update();
this.content.removeEventListener("click", this);
]]></handler>
<handler event="command"><![CDATA[
this.markCurrentPage();
]]></handler>
</handlers>
</binding>
</bindings>

Просмотреть файл

@ -1,5 +0,0 @@
{
"extends": [
"../../../../../testing/mochitest/browser.eslintrc"
]
}

Просмотреть файл

@ -1,9 +0,0 @@
[DEFAULT]
skip-if = buildapp == 'mulet'
support-files =
head.js
chat.html
[browser_chatwindow.js]
[browser_focus.js]
[browser_tearoff.js]

Просмотреть файл

@ -1,197 +0,0 @@
/* 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/. */
requestLongerTimeout(2);
var chatbar = document.getElementById("pinnedchats");
add_chat_task(function* testOpenCloseChat() {
let chatbox = yield promiseOpenChat("http://example.com");
Assert.strictEqual(chatbox, chatbar.selectedChat);
// we requested a "normal" chat, so shouldn't be minimized
Assert.ok(!chatbox.minimized, "chat is not minimized");
Assert.equal(chatbar.childNodes.length, 1, "should be 1 chat open");
// now request the same URL again - we should get the same chat.
let chatbox2 = yield promiseOpenChat("http://example.com");
Assert.strictEqual(chatbox2, chatbox, "got the same chat");
Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
chatbox.toggle();
is(chatbox.minimized, true, "chat is now minimized");
// was no other chat to select, so selected becomes null.
is(chatbar.selectedChat, null);
// We check the content gets an unload event as we close it.
chatbox.close();
});
// In this case we open a chat minimized, then request the same chat again
// without specifying minimized. On that second call the chat should open,
// selected, and no longer minimized.
add_chat_task(function* testMinimized() {
let chatbox = yield promiseOpenChat("http://example.com", "minimized");
Assert.strictEqual(chatbox, chatbar.selectedChat);
Assert.ok(chatbox.minimized, "chat is minimized");
Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
yield promiseOpenChat("http://example.com");
Assert.ok(!chatbox.minimized, false, "chat is no longer minimized");
});
// open enough chats to overflow the window, then check
// if the menupopup is visible
add_chat_task(function* testManyChats() {
Assert.ok(chatbar.menupopup.parentNode.collapsed, "popup nub collapsed at start");
// we should *never* find a test box that needs more than this to cause
// an overflow!
let maxToOpen = 20;
let numOpened = 0;
for (let i = 0; i < maxToOpen; i++) {
yield promiseOpenChat("http://example.com#" + i);
if (!chatbar.menupopup.parentNode.collapsed) {
info("the menu popup appeared");
return;
}
}
Assert.ok(false, "We didn't find a collapsed chat after " + maxToOpen + "chats!");
});
// Check that closeAll works as expected.
add_chat_task(function* testOpenTwiceCallbacks() {
yield promiseOpenChat("http://example.com#1");
yield promiseOpenChat("http://example.com#2");
yield promiseOpenChat("http://test2.example.com");
Assert.equal(numChatsInWindow(window), 3, "should be 3 chats open");
Chat.closeAll("http://example.com");
Assert.equal(numChatsInWindow(window), 1, "should have closed 2 chats");
Chat.closeAll("http://test2.example.com");
Assert.equal(numChatsInWindow(window), 0, "should have closed last chat");
});
// Check that when we open the same chat twice, the callbacks are called back
// twice.
add_chat_task(function* testOpenTwiceCallbacks() {
yield promiseOpenChatCallback("http://example.com");
yield promiseOpenChatCallback("http://example.com");
});
// Bug 817782 - check chats work in new top-level windows.
add_chat_task(function* testSecondTopLevelWindow() {
const chatUrl = "http://example.com";
let winPromise = BrowserTestUtils.waitForNewWindow();
OpenBrowserWindow();
let secondWindow = yield winPromise;
yield promiseOpenChat(chatUrl);
// the chat was created - let's make sure it was created in the second window.
Assert.equal(numChatsInWindow(window), 0, "main window has no chats");
Assert.equal(numChatsInWindow(secondWindow), 1, "second window has 1 chat");
secondWindow.close();
});
// Test that findChromeWindowForChats() returns the expected window.
add_chat_task(function* testChatWindowChooser() {
let chat = yield promiseOpenChat("http://example.com");
Assert.equal(numChatsInWindow(window), 1, "first window has the chat");
// create a second window - this will be the "most recent" and will
// therefore be the window that hosts the new chat (see bug 835111)
let secondWindow = OpenBrowserWindow();
yield promiseOneEvent(secondWindow, "load");
Assert.equal(secondWindow, Chat.findChromeWindowForChats(null), "Second window is the preferred chat window");
// focus the first window, and check it will be selected for future chats.
// Bug 1090633 - there are lots of issues around focus, especially when the
// browser itself doesn't have focus. We can end up with
// Services.wm.getMostRecentWindow("navigator:browser") returning a different
// window than, say, Services.focus.activeWindow. But the focus manager isn't
// the point of this test.
// So we simply keep focusing the first window until it is reported as the
// most recent.
do {
dump("trying to force window to become the most recent.\n");
secondWindow.focus();
window.focus();
yield promiseWaitForFocus();
} while (Services.wm.getMostRecentWindow("navigator:browser") != window)
Assert.equal(window, Chat.findChromeWindowForChats(null), "First window now the preferred chat window");
let privateWindow = OpenBrowserWindow({private: true});
yield promiseOneEvent(privateWindow, "load")
// The focused window can't accept chats (it's a private window), so the
// chat should open in the window that was selected before. This will be
// either window or secondWindow (linux may choose a different one) but the
// point is that the window is *not* the private one.
Assert.ok(Chat.findChromeWindowForChats(null) == window ||
Chat.findChromeWindowForChats(null) == secondWindow,
"Private window isn't selected for new chats.");
privateWindow.close();
secondWindow.close();
});
add_chat_task(function* testButtonSet() {
let chatbox = yield promiseOpenChat("http://example.com#1");
let document = chatbox.ownerDocument;
// Expect all default buttons to be visible.
for (let buttonId of kDefaultButtonSet) {
let button = document.getAnonymousElementByAttribute(chatbox, "anonid", buttonId);
Assert.ok(!button.hidden, "Button '" + buttonId + "' should be visible");
}
let visible = new Set(["minimize", "close"]);
chatbox = yield promiseOpenChat("http://example.com#2", null, null, [...visible].join(","));
for (let buttonId of kDefaultButtonSet) {
let button = document.getAnonymousElementByAttribute(chatbox, "anonid", buttonId);
if (visible.has(buttonId)) {
Assert.ok(!button.hidden, "Button '" + buttonId + "' should be visible");
} else {
Assert.ok(button.hidden, "Button '" + buttonId + "' should NOT be visible");
}
}
});
add_chat_task(function* testCustomButton() {
let commanded = 0;
let customButton = {
id: "custom",
onCommand: function() {
++commanded;
}
};
Chat.registerButton(customButton);
let chatbox = yield promiseOpenChat("http://example.com#1");
let document = chatbox.ownerDocument;
let titlebarNode = document.getAnonymousElementByAttribute(chatbox, "class",
"chat-titlebar");
Assert.equal(titlebarNode.getElementsByClassName("chat-custom")[0], null,
"Custom chat button should not be in the toolbar yet.");
let visible = new Set(["minimize", "close", "custom"]);
Chat.loadButtonSet(chatbox, [...visible].join(","));
for (let buttonId of kDefaultButtonSet) {
let button = document.getAnonymousElementByAttribute(chatbox, "anonid", buttonId);
if (visible.has(buttonId)) {
Assert.ok(!button.hidden, "Button '" + buttonId + "' should be visible");
} else {
Assert.ok(button.hidden, "Button '" + buttonId + "' should NOT be visible");
}
}
let customButtonNode = titlebarNode.getElementsByClassName("chat-custom")[0];
Assert.ok(!customButtonNode.hidden, "Custom button should be visible");
let ev = document.createEvent("XULCommandEvent");
ev.initCommandEvent("command", true, true, document.defaultView, 0, false,
false, false, false, null);
customButtonNode.dispatchEvent(ev);
Assert.equal(commanded, 1, "Button should have been commanded once");
});

Просмотреть файл

@ -1,262 +0,0 @@
/* 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/. */
// Tests the focus functionality.
Cu.import("resource://testing-common/ContentTask.jsm", this);
const CHAT_URL = "https://example.com/browser/browser/base/content/test/chat/chat.html";
requestLongerTimeout(2);
// Is the currently opened tab focused?
function isTabFocused() {
let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
// focus sucks in tests - our window may have lost focus.
let elt = Services.focus.getFocusedElementForWindow(window, false, {});
return elt == tabb;
}
// Is the specified chat focused?
function isChatFocused(chat) {
// focus sucks in tests - our window may have lost focus.
let elt = Services.focus.getFocusedElementForWindow(window, false, {});
return elt == chat.content;
}
var chatbar = document.getElementById("pinnedchats");
function* setUp() {
// Note that (probably) due to bug 604289, if a tab is focused but the
// focused element is null, our chat windows can "steal" focus. This is
// avoided if we explicitly focus an element in the tab.
// So we load a page with an <input> field and focus that before testing.
let html = '<input id="theinput"><button id="chat-opener"></button>';
let url = "data:text/html;charset=utf-8," + encodeURI(html);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url);
let browser = tab.linkedBrowser;
yield ContentTask.spawn(browser, null, function* () {
content.document.getElementById("theinput").focus();
});
registerCleanupFunction(function() {
gBrowser.removeTab(tab);
});
}
// Test default focus - not user input.
add_chat_task(function* testDefaultFocus() {
yield setUp();
let chat = yield promiseOpenChat("http://example.com");
// we used the default focus behaviour, which means that because this was
// not the direct result of user action the chat should not be focused.
Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
Assert.ok(isTabFocused(), "the tab should remain focused.");
Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
});
// Test default focus via user input.
add_chat_task(function* testDefaultFocusUserInput() {
todo(false, "BrowserTestUtils.synthesizeMouseAtCenter doesn't move the user " +
"focus to the chat window, even though we're recording a click correctly.");
return;
yield setUp();
let browser = gBrowser.selectedTab.linkedBrowser;
let mm = browser.messageManager;
let promise = new Promise(resolve => {
mm.addMessageListener("ChatOpenerClicked", function handler() {
mm.removeMessageListener("ChatOpenerClicked", handler);
promiseOpenChat("http://example.com").then(resolve);
});
});
yield ContentTask.spawn(browser, null, function* () {
let button = content.document.getElementById("chat-opener");
button.addEventListener("click", function onclick() {
button.removeEventListener("click", onclick);
sendAsyncMessage("ChatOpenerClicked");
});
});
// Note we must use synthesizeMouseAtCenter() rather than calling
// .click() directly as this causes nsIDOMWindowUtils.isHandlingUserInput
// to be true.
yield BrowserTestUtils.synthesizeMouseAtCenter("#chat-opener", {}, browser);
let chat = yield promise;
// we use the default focus behaviour but the chat was opened via user input,
// so the chat should be focused.
Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
yield promiseWaitForCondition(() => !isTabFocused());
Assert.ok(!isTabFocused(), "the tab should have lost focus.");
Assert.ok(isChatFocused(chat), "the chat should have got focus.");
});
// We explicitly ask for the chat to be focused.
add_chat_task(function* testExplicitFocus() {
yield setUp();
let chat = yield promiseOpenChat("http://example.com", undefined, true);
// we use the default focus behaviour, which means that because this was
// not the direct result of user action the chat should not be focused.
Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
yield promiseWaitForCondition(() => !isTabFocused());
Assert.ok(!isTabFocused(), "the tab should have lost focus.");
Assert.ok(isChatFocused(chat), "the chat should have got focus.");
});
// Open a minimized chat via default focus behaviour - it will open and not
// have focus. Then open the same chat without 'minimized' - it will be
// restored but should still not have grabbed focus.
add_chat_task(function* testNoFocusOnAutoRestore() {
yield setUp();
let chat = yield promiseOpenChat("http://example.com", "minimized");
Assert.ok(chat.minimized, "chat is minimized");
Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
Assert.ok(isTabFocused(), "the tab should remain focused.");
Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
yield promiseOpenChat("http://example.com");
Assert.ok(!chat.minimized, "chat should be restored");
Assert.ok(isTabFocused(), "the tab should remain focused.");
Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
});
// Here we open a chat, which will not be focused. Then we minimize it and
// restore it via a titlebar clock - it should get focus at that point.
add_chat_task(function* testFocusOnExplicitRestore() {
yield setUp();
let chat = yield promiseOpenChat("http://example.com");
Assert.ok(!chat.minimized, "chat should have been opened restored");
Assert.ok(isTabFocused(), "the tab should remain focused.");
Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
chat.minimized = true;
Assert.ok(isTabFocused(), "tab should still be focused");
Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
let promise = promiseOneMessage(chat.content, "Social:FocusEnsured");
// pretend we clicked on the titlebar
chat.onTitlebarClick({button: 0});
yield promise; // wait for focus event.
Assert.ok(!chat.minimized, "chat should have been restored");
Assert.ok(isChatFocused(chat), "chat should be focused");
Assert.strictEqual(chat, chatbar.selectedChat, "chat is marked selected");
});
// Open 2 chats and give 1 focus. Minimize the focused one - the second
// should get focus.
add_chat_task(function* testMinimizeFocused() {
yield setUp();
let chat1 = yield promiseOpenChat("http://example.com#1");
let chat2 = yield promiseOpenChat("http://example.com#2");
Assert.equal(numChatsInWindow(window), 2, "2 chats open");
Assert.strictEqual(chatbar.selectedChat, chat2, "chat2 is selected");
let promise = promiseOneMessage(chat1.content, "Social:FocusEnsured");
chatbar.selectedChat = chat1;
chatbar.focus();
yield promise; // wait for chat1 to get focus.
Assert.strictEqual(chat1, chatbar.selectedChat, "chat1 is marked selected");
Assert.notStrictEqual(chat2, chatbar.selectedChat, "chat2 is not marked selected");
todo(false, "Bug 1245803 should re-enable the test below to have a chat window " +
"re-gain focus when another chat window is minimized.");
return;
promise = promiseOneMessage(chat2.content, "Social:FocusEnsured");
chat1.minimized = true;
yield promise; // wait for chat2 to get focus.
Assert.notStrictEqual(chat1, chatbar.selectedChat, "chat1 is not marked selected");
Assert.strictEqual(chat2, chatbar.selectedChat, "chat2 is marked selected");
});
// Open 2 chats, select and focus the second. Pressing the TAB key should
// cause focus to move between all elements in our chat window before moving
// to the next chat window.
add_chat_task(function* testTab() {
yield setUp();
function sendTabAndWaitForFocus(chat, eltid) {
EventUtils.sendKey("tab");
return ContentTask.spawn(chat.content, { eltid: eltid }, function* (args) {
let doc = content.document;
// ideally we would use the 'focus' event here, but that doesn't work
// as expected for the iframe - the iframe itself never gets the focus
// event (apparently the sub-document etc does.)
// So just poll for the correct element getting focus...
yield new Promise(function(resolve, reject) {
let tries = 0;
let interval = content.setInterval(function() {
if (tries >= 30) {
clearInterval(interval);
reject("never got focus");
return;
}
tries++;
let elt = args.eltid ? doc.getElementById(args.eltid) : doc.documentElement;
if (doc.activeElement == elt) {
content.clearInterval(interval);
resolve();
}
info("retrying wait for focus: " + tries);
info("(the active element is " + doc.activeElement + "/" +
doc.activeElement.getAttribute("id") + ")");
}, 100);
info("waiting for element " + args.eltid + " to get focus");
});
});
}
let chat1 = yield promiseOpenChat(CHAT_URL + "#1");
let chat2 = yield promiseOpenChat(CHAT_URL + "#2");
chatbar.selectedChat = chat2;
let promise = promiseOneMessage(chat2.content, "Social:FocusEnsured");
chatbar.focus();
info("waiting for second chat to get focus");
yield promise;
// Our chats have 3 focusable elements, so it takes 4 TABs to move
// to the new chat.
yield sendTabAndWaitForFocus(chat2, "input1");
Assert.ok(isChatFocused(chat2), "new chat still focused after first tab");
yield sendTabAndWaitForFocus(chat2, "input2");
Assert.ok(isChatFocused(chat2), "new chat still focused after tab");
yield sendTabAndWaitForFocus(chat2, "iframe");
Assert.ok(isChatFocused(chat2), "new chat still focused after tab");
// this tab now should move to the next chat, but focus the
// document element itself (hence the null eltid)
yield sendTabAndWaitForFocus(chat1, null);
Assert.ok(isChatFocused(chat1), "first chat is focused");
});
// Open a chat and focus an element other than the first. Move focus to some
// other item (the tab itself in this case), then focus the chatbar - the
// same element that was previously focused should still have focus.
add_chat_task(function* testFocusedElement() {
yield setUp();
// open a chat with focus requested.
let chat = yield promiseOpenChat(CHAT_URL, undefined, true);
yield ContentTask.spawn(chat.content, null, function* () {
content.document.getElementById("input2").focus();
});
// set focus to the main window.
let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
let promise = promiseOneEvent(window, "focus");
Services.focus.moveFocus(window, null, Services.focus.MOVEFOCUS_ROOT, 0);
yield promise;
promise = promiseOneMessage(chat.content, "Social:FocusEnsured");
chatbar.focus();
yield promise;
yield ContentTask.spawn(chat.content, null, function* () {
Assert.equal(content.document.activeElement.getAttribute("id"), "input2",
"correct input field still has focus");
});
});

Просмотреть файл

@ -1,135 +0,0 @@
/* 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/. */
var chatbar = document.getElementById("pinnedchats");
function promiseNewWindowLoaded() {
return new Promise(resolve => {
Services.wm.addListener({
onWindowTitleChange: function() {},
onCloseWindow: function(xulwindow) {},
onOpenWindow: function(xulwindow) {
var domwindow = xulwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
Services.wm.removeListener(this);
// wait for load to ensure the window is ready for us to test
domwindow.addEventListener("load", function _load(event) {
let doc = domwindow.document;
if (event.target != doc)
return;
domwindow.removeEventListener("load", _load);
resolve(domwindow);
});
},
});
});
}
add_chat_task(function* testTearoffChat() {
let chatbox = yield promiseOpenChat("http://example.com");
Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
let chatTitle = yield ContentTask.spawn(chatbox.content, null, function* () {
let chatDoc = content.document;
// Mutate the chat document a bit before we tear it off.
let div = chatDoc.createElement("div");
div.setAttribute("id", "testdiv");
div.setAttribute("test", "1");
chatDoc.body.appendChild(div);
return chatDoc.title;
});
Assert.equal(chatbox.getAttribute("label"), chatTitle,
"the new chatbox should show the title of the chat window");
// chatbox is open, lets detach. The new chat window will be caught in
// the window watcher below
let promise = promiseNewWindowLoaded();
let swap = document.getAnonymousElementByAttribute(chatbox, "anonid", "swap");
swap.click();
// and wait for the new window.
let domwindow = yield promise;
Assert.equal(domwindow.document.documentElement.getAttribute("windowtype"), "Social:Chat", "Social:Chat window opened");
Assert.equal(numChatsInWindow(window), 0, "should be no chats in the chat bar");
// get the chatbox from the new window.
chatbox = domwindow.document.getElementById("chatter")
Assert.equal(chatbox.getAttribute("label"), chatTitle, "window should have same title as chat");
yield ContentTask.spawn(chatbox.content, null, function* () {
let div = content.document.getElementById("testdiv");
Assert.equal(div.getAttribute("test"), "1", "docshell should have been swapped");
div.setAttribute("test", "2");
});
// swap the window back to the chatbar
promise = promiseOneEvent(domwindow, "unload");
swap = domwindow.document.getAnonymousElementByAttribute(chatbox, "anonid", "swap");
swap.click();
yield promise;
Assert.equal(numChatsInWindow(window), 1, "chat should be docked back in the window");
chatbox = chatbar.selectedChat;
Assert.equal(chatbox.getAttribute("label"), chatTitle,
"the new chatbox should show the title of the chat window again");
yield ContentTask.spawn(chatbox.content, null, function* () {
let div = content.document.getElementById("testdiv");
Assert.equal(div.getAttribute("test"), "2", "docshell should have been swapped");
});
});
// Similar test but with 2 chats.
add_chat_task(function* testReattachTwice() {
let chatbox1 = yield promiseOpenChat("http://example.com#1");
let chatbox2 = yield promiseOpenChat("http://example.com#2");
Assert.equal(numChatsInWindow(window), 2, "both chats should be docked in the window");
info("chatboxes are open, detach from window");
let promise = promiseNewWindowLoaded();
document.getAnonymousElementByAttribute(chatbox1, "anonid", "swap").click();
let domwindow1 = yield promise;
chatbox1 = domwindow1.document.getElementById("chatter");
Assert.equal(numChatsInWindow(window), 1, "only second chat should be docked in the window");
promise = promiseNewWindowLoaded();
document.getAnonymousElementByAttribute(chatbox2, "anonid", "swap").click();
let domwindow2 = yield promise;
chatbox2 = domwindow2.document.getElementById("chatter");
Assert.equal(numChatsInWindow(window), 0, "should be no docked chats");
promise = promiseOneEvent(domwindow2, "unload");
domwindow2.document.getAnonymousElementByAttribute(chatbox2, "anonid", "swap").click();
yield promise;
Assert.equal(numChatsInWindow(window), 1, "one chat should be docked back in the window");
promise = promiseOneEvent(domwindow1, "unload");
domwindow1.document.getAnonymousElementByAttribute(chatbox1, "anonid", "swap").click();
yield promise;
Assert.equal(numChatsInWindow(window), 2, "both chats should be docked back in the window");
});
// Check that Chat.closeAll() also closes detached windows.
add_chat_task(function* testCloseAll() {
let chatbox1 = yield promiseOpenChat("http://example.com#1");
let chatbox2 = yield promiseOpenChat("http://example.com#2");
let promise = promiseNewWindowLoaded();
document.getAnonymousElementByAttribute(chatbox1, "anonid", "swap").click();
let domwindow = yield promise;
chatbox1 = domwindow.document.getElementById("chatter");
let promiseWindowUnload = promiseOneEvent(domwindow, "unload");
Assert.equal(numChatsInWindow(window), 1, "second chat should still be docked");
Chat.closeAll("http://example.com");
yield promiseWindowUnload;
Assert.equal(numChatsInWindow(window), 0, "should be no chats left");
});

Просмотреть файл

@ -1,14 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<title>test chat window</title>
</head>
<body>
<p>This is a test chat window.</p>
<!-- a couple of input fields to help with focus testing -->
<input id="input1"/>
<input id="input2"/>
<!-- an iframe here so this one page generates multiple load events -->
<iframe id="iframe" src="data:text/plain:this is an iframe"></iframe>
</body>
</html>

Просмотреть файл

@ -1,130 +0,0 @@
/* 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/. */
// Utility functions for Chat tests.
var Chat = Cu.import("resource:///modules/Chat.jsm", {}).Chat;
const kDefaultButtonSet = new Set(["minimize", "swap", "close"]);
function promiseOpenChat(url, mode, focus, buttonSet = null) {
let uri = Services.io.newURI(url, null, null);
let origin = uri.prePath;
let title = origin;
return new Promise(resolve => {
// we just through a few hoops to ensure the content document is fully
// loaded, otherwise tests that rely on that content may intermittently fail.
let callback = function(chatbox) {
let mm = chatbox.content.messageManager;
mm.sendAsyncMessage("WaitForDOMContentLoaded");
mm.addMessageListener("DOMContentLoaded", function cb() {
mm.removeMessageListener("DOMContentLoaded", cb);
resolve(chatbox);
});
}
let chatbox = Chat.open(null, {
origin: origin,
title: title,
url: url,
mode: mode,
focus: focus
}, callback);
if (buttonSet) {
chatbox.setAttribute("buttonSet", buttonSet);
}
});
}
// Opens a chat, returns a promise resolved when the chat callback fired.
function promiseOpenChatCallback(url, mode) {
let uri = Services.io.newURI(url, null, null);
let origin = uri.prePath;
let title = origin;
return new Promise(resolve => {
Chat.open(null, { origin, title, url, mode }, resolve);
});
}
// Opens a chat, returns the chat window's promise which fires when the chat
// starts loading.
function promiseOneEvent(target, eventName, capture) {
return new Promise(resolve => {
target.addEventListener(eventName, function handler(event) {
target.removeEventListener(eventName, handler, capture);
resolve();
}, capture);
});
}
function promiseOneMessage(target, messageName) {
return new Promise(resolve => {
let mm = target.messageManager;
mm.addMessageListener(messageName, function handler() {
mm.removeMessageListener(messageName, handler);
resolve();
});
});
}
// Return the number of chats in a browser window.
function numChatsInWindow(win) {
let chatbar = win.document.getElementById("pinnedchats");
return chatbar.childElementCount;
}
function promiseWaitForFocus() {
return new Promise(resolve => waitForFocus(resolve));
}
// A simple way to clean up after each test.
function add_chat_task(genFunction) {
add_task(function* () {
info("Starting chat test " + genFunction.name);
try {
yield genFunction();
} finally {
info("Finished chat test " + genFunction.name + " - cleaning up.");
// close all docked chats.
while (chatbar.childNodes.length) {
chatbar.childNodes[0].close();
}
// and non-docked chats.
let winEnum = Services.wm.getEnumerator("Social:Chat");
while (winEnum.hasMoreElements()) {
let win = winEnum.getNext();
if (win.closed) {
continue;
}
win.close();
}
}
});
}
function waitForCondition(condition, nextTest, errorMsg) {
var tries = 0;
var interval = setInterval(function() {
if (tries >= 100) {
ok(false, errorMsg);
moveOn();
}
var conditionPassed;
try {
conditionPassed = condition();
} catch (e) {
ok(false, e + "\n" + e.stack);
conditionPassed = false;
}
if (conditionPassed) {
moveOn();
}
tries++;
}, 100);
var moveOn = function() { clearInterval(interval); nextTest(); };
}
function promiseWaitForCondition(aConditionFn) {
return new Promise((resolve, reject) => {
waitForCondition(aConditionFn, resolve, "Condition didn't pass.");
});
}

Просмотреть файл

@ -2,7 +2,6 @@
skip-if = buildapp == "mulet"
support-files =
blocklist.xml
checked.jpg
head.js
opengraph/og_invalid_url.html
opengraph/opengraph.html
@ -15,15 +14,7 @@ support-files =
social_activate.html
social_activate_basic.html
social_activate_iframe.html
social_chat.html
social_crash_content_helper.js
social_flyout.html
social_mark.html
social_panel.html
social_postActivation.html
social_sidebar.html
social_sidebar_empty.html
unchecked.jpg
!/browser/base/content/test/plugins/blockNoPlugins.xml
[browser_aboutHome_activation.js]
@ -31,18 +22,3 @@ support-files =
[browser_blocklist.js]
[browser_share.js]
[browser_social_activation.js]
[browser_social_chatwindow.js]
[browser_social_chatwindow_resize.js]
[browser_social_chatwindowfocus.js]
skip-if = asan # Bug 1260177
[browser_social_contextmenu.js]
skip-if = (os == 'linux' && e10s) # Bug 1072669 context menu relies on target element
[browser_social_errorPage.js]
[browser_social_flyout.js]
[browser_social_isVisible.js]
[browser_social_marks.js]
[browser_social_marks_context.js]
[browser_social_multiprovider.js]
[browser_social_sidebar.js]
[browser_social_status.js]
[browser_social_window.js]

Просмотреть файл

@ -2,7 +2,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
@ -17,7 +17,7 @@ var snippet =
' "iconURL": "chrome://branding/content/icon16.png",' +
' "icon32URL": "chrome://branding/content/icon32.png",' +
' "icon64URL": "chrome://branding/content/icon64.png",' +
' "sidebarURL": "https://example.com/browser/browser/base/content/test/social/social_sidebar_empty.html",' +
' "shareURL": "https://example.com/browser/browser/base/content/test/social/social_share.html",' +
' "postActivationURL": "https://example.com/browser/browser/base/content/test/social/social_postActivation.html",' +
' };' +
' function activateProvider(node) {' +
@ -39,7 +39,7 @@ var snippet2 =
' "iconURL": "chrome://branding/content/icon16.png",' +
' "icon32URL": "chrome://branding/content/icon32.png",' +
' "icon64URL": "chrome://branding/content/icon64.png",' +
' "sidebarURL": "https://example.com/browser/browser/base/content/test/social/social_sidebar_empty.html",' +
' "shareURL": "https://example.com/browser/browser/base/content/test/social/social_share.html",' +
' "postActivationURL": "https://example.com/browser/browser/base/content/test/social/social_postActivation.html",' +
' "oneclick": true' +
' };' +
@ -101,10 +101,8 @@ function test()
yield new Promise(resolve => {
activateProvider(tab, test.panel).then(() => {
ok(SocialSidebar.provider, "provider activated");
checkSocialUI();
is(gBrowser.currentURI.spec, SocialSidebar.provider.manifest.postActivationURL, "postActivationURL was loaded");
SocialService.uninstallProvider(SocialSidebar.provider.origin, function () {
SocialService.uninstallProvider("https://example.com", function () {
info("provider uninstalled");
resolve();
});
@ -210,14 +208,12 @@ function sendActivationEvent(tab) {
function activateProvider(tab, expectPanel, aCallback) {
return new Promise(resolve => {
if (expectPanel) {
ensureEventFired(PopupNotifications.panel, "popupshown").then(() => {
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
let panel = document.getElementById("servicesInstall-notification");
panel.button.click();
});
}
waitForProviderLoad().then(() => {
ok(SocialSidebar.provider, "new provider is active");
ok(SocialSidebar.opened, "sidebar is open");
checkSocialUI();
resolve();
});
@ -229,6 +225,5 @@ function waitForProviderLoad(cb) {
return Promise.all([
promiseObserverNotified("social:provider-enabled"),
ensureFrameLoaded(gBrowser, "https://example.com/browser/browser/base/content/test/social/social_postActivation.html"),
ensureFrameLoaded(SocialSidebar.browser)
]);
}

Просмотреть файл

@ -1,23 +1,23 @@
var AddonManager = Cu.import("resource://gre/modules/AddonManager.jsm", {}).AddonManager;
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
var manifest = {
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar_empty.html",
shareURL: "https://example.com/browser/browser/base/content/test/social/social_share.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
var manifest2 = { // used for testing install
name: "provider 2",
origin: "https://test1.example.com",
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar_empty.html",
shareURL: "https://test1.example.com/browser/browser/base/content/test/social/social_share.html",
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png",
version: "1.0"
};
var manifestUpgrade = { // used for testing install
name: "provider 3",
origin: "https://test2.example.com",
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html",
shareURL: "https://test2.example.com/browser/browser/base/content/test/social/social_share.html",
iconURL: "https://test2.example.com/browser/browser/base/content/test/general/moz.png",
version: "1.0"
};

Просмотреть файл

@ -4,7 +4,7 @@
// a place for miscellaneous social tests
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
var blocklistURL = "http://example.com/browser/browser/base/content/test/social/blocklist.xml";
@ -12,13 +12,13 @@ var blocklistURL = "http://example.com/browser/browser/base/content/test/social/
var manifest = { // normal provider
name: "provider ok",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
shareURL: "https://example.com/browser/browser/base/content/test/social/social_share.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
var manifest_bad = { // normal provider
name: "provider blocked",
origin: "https://test1.example.com",
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html",
shareURL: "https://test1.example.com/browser/browser/base/content/test/social/social_share.html",
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png"
};

Просмотреть файл

@ -1,5 +1,5 @@
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
var baseURL = "https://example.com/browser/browser/base/content/test/social/";

Просмотреть файл

@ -10,7 +10,7 @@
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: Assert is null");
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
var tabsToRemove = [];
@ -73,7 +73,6 @@ function activateIFrameProvider(domain, callback) {
function waitForProviderLoad(origin) {
return Promise.all([
ensureFrameLoaded(gBrowser, origin + "/browser/browser/base/content/test/social/social_postActivation.html"),
ensureFrameLoaded(SocialSidebar.browser)
]);
}
@ -113,6 +112,7 @@ function clickAddonRemoveButton(tab, aCallback) {
}
function activateOneProvider(manifest, finishActivation, aCallback) {
info("activating provider "+manifest.name);
let panel = document.getElementById("servicesInstall-notification");
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
ok(!panel.hidden, "servicesInstall-notification panel opened");
@ -128,8 +128,6 @@ function activateOneProvider(manifest, finishActivation, aCallback) {
executeSoon(aCallback);
} else {
waitForProviderLoad(manifest.origin).then(() => {
is(SocialSidebar.provider.origin, manifest.origin, "new provider is active");
ok(SocialSidebar.opened, "sidebar is open");
checkSocialUI();
executeSoon(aCallback);
});
@ -147,19 +145,19 @@ var gProviders = [
{
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar_empty.html?provider1",
shareURL: "https://example.com/browser/browser/base/content/test/social/social_share.html?provider1",
iconURL: "chrome://branding/content/icon48.png"
},
{
name: "provider 2",
origin: "https://test1.example.com",
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar_empty.html?provider2",
shareURL: "https://test1.example.com/browser/browser/base/content/test/social/social_share.html?provider2",
iconURL: "chrome://branding/content/icon64.png"
},
{
name: "provider 3",
origin: "https://test2.example.com",
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar_empty.html?provider2",
shareURL: "https://test2.example.com/browser/browser/base/content/test/social/social_share.html?provider2",
iconURL: "chrome://branding/content/about-logo.png"
}
];
@ -191,7 +189,6 @@ var tests = {
testIFrameActivation: function(next) {
activateIFrameProvider(gTestDomains[0], function() {
is(SocialUI.enabled, false, "SocialUI is not enabled");
ok(!SocialSidebar.provider, "provider is not installed");
let panel = document.getElementById("servicesInstall-notification");
ok(panel.hidden, "activation panel still hidden");
checkSocialUI();
@ -203,7 +200,6 @@ var tests = {
// first up we add a manifest entry for a single provider.
activateOneProvider(gProviders[0], false, function() {
// we deactivated leaving no providers left, so Social is disabled.
ok(!SocialSidebar.provider, "should be no provider left after disabling");
checkSocialUI();
next();
});
@ -221,7 +217,6 @@ var tests = {
// activate the last provider.
activateOneProvider(gProviders[2], false, function() {
// we deactivated - the first provider should be enabled.
is(SocialSidebar.provider.origin, Social.providers[1].origin, "original provider should have been reactivated");
checkSocialUI();
next();
});

Просмотреть файл

@ -1,141 +0,0 @@
/* 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/. */
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
var manifests = [
{
name: "provider@example.com",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html?example.com",
iconURL: "chrome://branding/content/icon48.png"
},
{
name: "provider@test1",
origin: "https://test1.example.com",
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html?test1",
iconURL: "chrome://branding/content/icon48.png"
},
{
name: "provider@test2",
origin: "https://test2.example.com",
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html?test2",
iconURL: "chrome://branding/content/icon48.png"
}
];
var chatId = 0;
function openChat(provider) {
return new Promise(resolve => {
SocialSidebar.provider = provider;
let chatUrl = provider.origin + "/browser/browser/base/content/test/social/social_chat.html";
let url = chatUrl + "?id=" + (chatId++);
makeChat("normal", "chat " + chatId, (cb) => { resolve(cb); });
});
}
function windowHasChats(win) {
return !!getChatBar().firstElementChild;
}
function test() {
requestLongerTimeout(2); // only debug builds seem to need more time...
waitForExplicitFinish();
let frameScript = "data:,(" + function frame_script() {
addMessageListener("socialTest-CloseSelf", function(e) {
content.close();
}, true);
}.toString() + ")();";
let mm = getGroupMessageManager("social");
mm.loadFrameScript(frameScript, true);
let oldwidth = window.outerWidth; // we futz with these, so we restore them
let oldleft = window.screenX;
window.moveTo(0, window.screenY)
let postSubTest = function(cb) {
let chats = document.getElementById("pinnedchats");
ok(chats.children.length == 0, "no chatty children left behind");
cb();
};
runSocialTestWithProvider(manifests, function (finishcb) {
ok(Social.enabled, "Social is enabled");
SocialSidebar.show();
runSocialTests(tests, undefined, postSubTest, function() {
window.moveTo(oldleft, window.screenY)
window.resizeTo(oldwidth, window.outerHeight);
mm.removeDelayedFrameScript(frameScript);
finishcb();
});
});
}
var tests = {
testOpenCloseChat: function(next) {
openChat(SocialSidebar.provider).then((cb) => {
BrowserTestUtils.waitForCondition(() => { return cb.minimized; },
"chatbox is minimized").then(() => {
ok(cb.minimized, "chat is minimized after toggle");
BrowserTestUtils.waitForCondition(() => { return !cb.minimized; },
"chatbox is not minimized").then(() => {
ok(!cb.minimized, "chat is not minimized after toggle");
promiseNodeRemoved(cb).then(next);
let mm = cb.content.messageManager;
mm.sendAsyncMessage("socialTest-CloseSelf", {});
info("close chat window requested");
});
cb.toggle();
});
ok(!cb.minimized, "chat is not minimized on open");
// toggle to minimize chat
cb.toggle();
});
},
// Check what happens when you close the only visible chat.
testCloseOnlyVisible: function(next) {
let chatbar = getChatBar();
let chatWidth = undefined;
let num = 0;
is(chatbar.childNodes.length, 0, "chatbar starting empty");
is(chatbar.menupopup.childNodes.length, 0, "popup starting empty");
makeChat("normal", "first chat", function() {
// got the first one.
checkPopup();
ok(chatbar.menupopup.parentNode.collapsed, "menu selection isn't visible");
// we kinda cheat here and get the width of the first chat, assuming
// that all future chats will have the same width when open.
chatWidth = chatbar.calcTotalWidthOf(chatbar.selectedChat);
let desired = chatWidth * 1.5;
resizeWindowToChatAreaWidth(desired, function(sizedOk) {
ok(sizedOk, "can't do any tests without this width");
checkPopup();
makeChat("normal", "second chat", function() {
is(chatbar.childNodes.length, 2, "now have 2 chats");
let first = chatbar.childNodes[0];
let second = chatbar.childNodes[1];
is(chatbar.selectedChat, first, "first chat is selected");
ok(second.collapsed, "second chat is currently collapsed");
// closing the first chat will leave enough room for the second
// chat to appear, and thus become selected.
chatbar.selectedChat.close();
is(chatbar.selectedChat, second, "second chat is selected");
Task.spawn(closeAllChats).then(next);
});
});
});
},
testShowWhenCollapsed: function(next) {
get3ChatsForCollapsing("normal", function(first, second, third) {
let chatbar = getChatBar();
chatbar.showChat(first);
ok(!first.collapsed, "first should no longer be collapsed");
is(second.collapsed || third.collapsed, true, "one of the others should be collapsed");
Task.spawn(closeAllChats).then(next);
});
}
}

Просмотреть файл

@ -1,82 +0,0 @@
/* 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/. */
function test() {
requestLongerTimeout(2); // only debug builds seem to need more time...
waitForExplicitFinish();
let manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar_empty.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png",
// added for test purposes
chatURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar_empty.html"
};
let oldwidth = window.outerWidth; // we futz with these, so we restore them
let oldleft = window.screenX;
window.moveTo(0, window.screenY)
let postSubTest = function(cb) {
let chats = document.getElementById("pinnedchats");
ok(chats.children.length == 0, "no chatty children left behind");
cb();
};
runSocialTestWithProvider(manifest, function (finishcb) {
let sbrowser = document.getElementById("social-sidebar-browser");
ensureFrameLoaded(sbrowser).then(() => {
let provider = SocialSidebar.provider;
provider.chatURL = manifest.chatURL;
ok(provider, "provider is set");
ok(provider.chatURL, "provider has chatURL");
// executeSoon to let the browser UI observers run first
runSocialTests(tests, undefined, postSubTest, function() {
window.moveTo(oldleft, window.screenY)
window.resizeTo(oldwidth, window.outerHeight);
finishcb();
});
});
SocialSidebar.show();
});
}
var tests = {
// resize and collapse testing.
testBrowserResize: function(next, mode) {
let chats = document.getElementById("pinnedchats");
get3ChatsForCollapsing(mode || "normal", function(first, second, third) {
let chatWidth = chats.getTotalChildWidth(first);
ok(chatWidth, "have a chatwidth");
let popupWidth = getPopupWidth();
ok(popupWidth, "have a popupwidth");
info("starting resize tests - each chat's width is " + chatWidth +
" and the popup width is " + popupWidth);
// Note that due to a difference between "device", "app" and "css" pixels
// we allow use 2 pixels as the minimum size difference.
resizeAndCheckWidths(first, second, third, [
[chatWidth-2, 1, "to < 1 chat width - only last should be visible."],
[chatWidth+2, 1, "2 pixels more then one fully exposed (not counting popup) - still only 1."],
[chatWidth+popupWidth+2, 1, "2 pixels more than one fully exposed (including popup) - still only 1."],
[chatWidth*2-2, 1, "second not showing by 2 pixels (not counting popup) - only 1 exposed."],
[chatWidth*2+popupWidth-2, 1, "second not showing by 2 pixelx (including popup) - only 1 exposed."],
[chatWidth*2+popupWidth+2, 2, "big enough to fit 2 - nub remains visible as first is still hidden"],
[chatWidth*3+popupWidth-2, 2, "one smaller than the size necessary to display all three - first still hidden"],
[chatWidth*3+popupWidth+2, 3, "big enough to fit all - all exposed (which removes the nub)"],
[chatWidth*3+2, 3, "now the nub is hidden we can resize back down to chatWidth*3 before overflow."],
[chatWidth*3-2, 2, "2 pixels less and the first is again collapsed (and the nub re-appears)"],
[chatWidth*2+popupWidth+2, 2, "back down to just big enough to fit 2"],
[chatWidth*2+popupWidth-2, 1, "back down to just not enough to fit 2"],
[chatWidth*3+popupWidth+2, 3, "now a large jump to make all 3 visible (ie, affects 2)"],
[chatWidth*1.5, 1, "and a large jump back down to 1 visible (ie, affects 2)"],
], function() {
Task.spawn(closeAllChats).then(next);
});
});
},
testBrowserResizeMinimized: function(next) {
this.testBrowserResize(next);
}
}

Просмотреть файл

@ -1,66 +0,0 @@
/* 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/. */
function isChatFocused(chat) {
return getChatBar()._isChatFocused(chat);
}
var manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
function test() {
waitForExplicitFinish();
// Note that (probably) due to bug 604289, if a tab is focused but the
// focused element is null, our chat windows can "steal" focus. This is
// avoided if we explicitly focus an element in the tab.
// So we load a page with an <input> field and focus that before testing.
let url = "data:text/html;charset=utf-8," + encodeURI('<input id="theinput">');
let tab = gBrowser.selectedTab = gBrowser.addTab(url, {skipAnimation: true});
let browser = tab.linkedBrowser;
browser.addEventListener("load", function tabLoad(event) {
browser.removeEventListener("load", tabLoad, true);
// before every test we focus the input field.
let preSubTest = function(cb) {
ContentTask.spawn(browser, null, function* () {
content.focus();
content.document.getElementById("theinput").focus();
yield ContentTaskUtils.waitForCondition(
() => Services.focus.focusedWindow == content, "tab should have focus");
}).then(cb);
}
let postSubTest = function(cb) {
Task.spawn(closeAllChats).then(cb);
}
// and run the tests.
runSocialTestWithProvider(manifest, function (finishcb) {
SocialSidebar.show();
runSocialTests(tests, preSubTest, postSubTest, function () {
BrowserTestUtils.removeTab(tab).then(finishcb);
});
});
}, true);
}
var tests = {
// In this test we arrange for the sidebar to open the chat via a simulated
// click. This should cause the new chat to be opened and focused.
testFocusWhenViaUser: function(next) {
ensureFrameLoaded(document.getElementById("social-sidebar-browser")).then(() => {
let chatbar = getChatBar();
openChatViaUser();
ok(chatbar.firstElementChild, "chat opened");
BrowserTestUtils.waitForCondition(() => isChatFocused(chatbar.selectedChat),
"chat should be focused").then(() => {
is(chatbar.selectedChat, chatbar.firstElementChild, "chat is selected");
next();
});
});
},
};

Просмотреть файл

@ -1,74 +0,0 @@
/* 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/. */
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
var manifest = { // used for testing install
name: "provider test1",
origin: "https://test1.example.com",
markURL: "https://test1.example.com/browser/browser/base/content/test/social/social_mark.html?url=%{url}",
markedIcon: "https://test1.example.com/browser/browser/base/content/test/social/unchecked.jpg",
unmarkedIcon: "https://test1.example.com/browser/browser/base/content/test/social/checked.jpg",
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png",
version: "1.0"
};
function test() {
waitForExplicitFinish();
let frameScript = "data:,(" + function frame_script() {
addEventListener("OpenGraphData", function (aEvent) {
sendAsyncMessage("sharedata", aEvent.detail);
}, true, true);
}.toString() + ")();";
let mm = getGroupMessageManager("social");
mm.loadFrameScript(frameScript, true);
runSocialTestWithProvider(manifest, function (finishcb) {
runSocialTests(tests, undefined, undefined, function () {
mm.removeDelayedFrameScript(frameScript);
finishcb();
});
});
}
var tests = {
testMarkMicroformats: function(next) {
// emulates context menu action using target element, calling SocialMarks.markLink
let provider = Social._getProviderFromOrigin(manifest.origin);
let target, testTab;
// browser_share tests microformats on the full page, this is testing a
// specific target element.
let expecting = JSON.stringify({
"url": "https://example.com/browser/browser/base/content/test/social/microformats.html",
"microformats": {
"items": [{
"type": ["h-review"],
"properties": {
"rating": ["4.5"]
}
}
],
"rels": {},
"rel-urls": {}
}
});
let mm = getGroupMessageManager("social");
mm.addMessageListener("sharedata", function handler(msg) {
is(msg.data, expecting, "microformats data ok");
mm.removeMessageListener("sharedata", handler);
BrowserTestUtils.removeTab(testTab).then(next);
});
let url = "https://example.com/browser/browser/base/content/test/social/microformats.html"
BrowserTestUtils.openNewForegroundTab(gBrowser, url).then(tab => {
testTab = tab;
let doc = tab.linkedBrowser.contentDocument;
target = doc.getElementById("test-review");
SocialMarks.markLink(manifest.origin, url, target);
});
}
}

Просмотреть файл

@ -1,187 +0,0 @@
/* 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/. */
function gc() {
Cu.forceGC();
let wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
wu.garbageCollect();
}
var openChatWindow = Cu.import("resource://gre/modules/MozSocialAPI.jsm", {}).openChatWindow;
function openPanel(url, panelCallback, loadCallback) {
// open a flyout
SocialFlyout.open(url, 0, panelCallback);
// wait for both open and loaded before callback. Since the test doesn't close
// the panel between opens, we cannot rely on events here. We need to ensure
// popupshown happens before we finish out the tests.
BrowserTestUtils.waitForCondition(function() {
return SocialFlyout.panel.state == "open" &&
SocialFlyout.iframe.contentDocument.readyState == "complete";
},"flyout is open and loaded").then(() => { executeSoon(loadCallback) });
}
function openChat(url, panelCallback, loadCallback) {
// open a chat window
let chatbar = getChatBar();
openChatWindow(null, SocialSidebar.provider, url, panelCallback);
chatbar.firstChild.addEventListener("DOMContentLoaded", function panelLoad() {
chatbar.firstChild.removeEventListener("DOMContentLoaded", panelLoad, true);
executeSoon(loadCallback);
}, true);
}
function onSidebarLoad(callback) {
let sbrowser = document.getElementById("social-sidebar-browser");
sbrowser.addEventListener("load", function load() {
sbrowser.removeEventListener("load", load, true);
executeSoon(callback);
}, true);
}
var manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar_empty.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
function test() {
waitForExplicitFinish();
runSocialTestWithProvider(manifest, function (finishcb) {
runSocialTests(tests, undefined, function(next) { goOnline().then(next) }, finishcb);
});
}
var tests = {
testSidebar: function(next) {
let sbrowser = document.getElementById("social-sidebar-browser");
onSidebarLoad(function() {
ok(sbrowser.contentDocument.documentURI.indexOf("about:socialerror?mode=tryAgainOnly")==0, "sidebar is on social error page");
gc();
// Add a new load listener, then find and click the "try again" button.
onSidebarLoad(function() {
// should still be on the error page.
ok(sbrowser.contentDocument.documentURI.indexOf("about:socialerror?mode=tryAgainOnly")==0, "sidebar is still on social error page");
// go online and try again - this should work.
goOnline().then(function () {
onSidebarLoad(function() {
// should now be on the correct page.
is(sbrowser.contentDocument.documentURI, manifest.sidebarURL, "sidebar is now on social sidebar page");
next();
});
sbrowser.contentDocument.getElementById("btnTryAgain").click();
});
});
sbrowser.contentDocument.getElementById("btnTryAgain").click();
});
// go offline then attempt to load the sidebar - it should fail.
goOffline().then(function() {
SocialSidebar.show();
});
},
testFlyout: function(next) {
let panelCallbackCount = 0;
let panel = document.getElementById("social-flyout-panel");
goOffline().then(function() {
openPanel(
manifest.sidebarURL, /* empty html page */
function() { // the panel api callback
panelCallbackCount++;
},
function() { // the "load" callback.
todo_is(panelCallbackCount, 0, "Bug 833207 - should be no callback when error page loads.");
let href = panel.firstChild.contentDocument.documentURI;
ok(href.indexOf("about:socialerror?mode=compactInfo")==0, "flyout is on social error page");
// Bug 832943 - the listeners previously stopped working after a GC, so
// force a GC now and try again.
gc();
openPanel(
manifest.sidebarURL, /* empty html page */
function() { // the panel api callback
panelCallbackCount++;
},
function() { // the "load" callback.
todo_is(panelCallbackCount, 0, "Bug 833207 - should be no callback when error page loads.");
let href = panel.firstChild.contentDocument.documentURI;
ok(href.indexOf("about:socialerror?mode=compactInfo")==0, "flyout is on social error page");
gc();
SocialFlyout.unload();
next();
}
);
}
);
});
},
testChatWindow: function(next) {
todo(false, "Bug 1245799 is needed to make error pages work again for chat windows.");
next();
return;
let panelCallbackCount = 0;
// chatwindow tests throw errors, which muddy test output, if the worker
// doesn't get test-init
goOffline().then(function() {
openChat(
manifest.sidebarURL, /* empty html page */
function() { // the panel api callback
panelCallbackCount++;
},
function() { // the "load" callback.
todo_is(panelCallbackCount, 0, "Bug 833207 - should be no callback when error page loads.");
let chat = getChatBar().selectedChat;
BrowserTestUtils.waitForCondition(() => chat.content != null && chat.contentDocument.documentURI.indexOf("about:socialerror?mode=tryAgainOnly")==0,
"error page didn't appear").then(() => {
chat.close();
next();
});
}
);
});
},
testChatWindowAfterTearOff: function(next) {
todo(false, "Bug 1245799 is needed to make error pages work again for chat windows.");
next();
return;
// Ensure that the error listener survives the chat window being detached.
let url = manifest.sidebarURL; /* empty html page */
let panelCallbackCount = 0;
// chatwindow tests throw errors, which muddy test output, if the worker
// doesn't get test-init
// open a chat while we are still online.
openChat(
url,
null,
function() { // the "load" callback.
let chat = getChatBar().selectedChat;
is(chat.contentDocument.documentURI, url, "correct url loaded");
// toggle to a detached window.
chat.swapWindows().then(chat => {
ok(!!chat.content, "we have chat content 1");
BrowserTestUtils.waitForCondition(() => chat.content != null && chat.contentDocument.readyState == "complete",
"swapped window loaded").then(() => {
// now go offline and reload the chat - about:socialerror should be loaded.
goOffline().then(() => {
ok(!!chat.content, "we have chat content 2");
chat.contentDocument.location.reload();
info("chat reload called");
BrowserTestUtils.waitForCondition(() => chat.contentDocument.documentURI.indexOf("about:socialerror?mode=tryAgainOnly")==0,
"error page didn't appear").then(() => {
chat.close();
next();
});
});
});
});
}
);
}
}

Просмотреть файл

@ -1,102 +0,0 @@
/* 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/. */
function test() {
waitForExplicitFinish();
let frameScript = "data:,(" + function frame_script() {
addMessageListener("socialTest-CloseSelf", function(e) {
content.close();
});
addMessageListener("socialTest-sendEvent", function(msg) {
let data = msg.data;
let evt = content.document.createEvent("CustomEvent");
evt.initCustomEvent(data.name, true, true, JSON.stringify(data.data));
content.document.documentElement.dispatchEvent(evt);
});
}.toString() + ")();";
let mm = getGroupMessageManager("social");
mm.loadFrameScript(frameScript, true);
let manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
runSocialTestWithProvider(manifest, function (finishcb) {
SocialSidebar.show();
ensureFrameLoaded(SocialSidebar.browser, manifest.sidebarURL).then(() => {
// disable transitions for the test
registerCleanupFunction(function () {
SocialFlyout.panel.removeAttribute("animate");
});
SocialFlyout.panel.setAttribute("animate", "false");
runSocialTests(tests, undefined, undefined, finishcb);
});
});
}
var tests = {
testResizeFlyout: function(next) {
let panel = document.getElementById("social-flyout-panel");
BrowserTestUtils.waitForEvent(panel, "popupshown").then(() => {
is(panel.firstChild.contentDocument.readyState, "complete", "panel is loaded prior to showing");
// The width of the flyout should be 400px initially
let iframe = panel.firstChild;
let body = iframe.contentDocument.body;
let cs = iframe.contentWindow.getComputedStyle(body);
is(cs.width, "400px", "should be 400px wide");
is(iframe.boxObject.width, 400, "iframe should now be 400px wide");
is(cs.height, "400px", "should be 400px high");
is(iframe.boxObject.height, 400, "iframe should now be 400px high");
BrowserTestUtils.waitForEvent(iframe.contentWindow, "resize").then(() => {
cs = iframe.contentWindow.getComputedStyle(body);
is(cs.width, "500px", "should now be 500px wide");
is(iframe.boxObject.width, 500, "iframe should now be 500px wide");
is(cs.height, "500px", "should now be 500px high");
is(iframe.boxObject.height, 500, "iframe should now be 500px high");
BrowserTestUtils.waitForEvent(panel, "popuphidden").then(next);
panel.hidePopup();
});
SocialFlyout.dispatchPanelEvent("socialTest-MakeWider");
});
SocialSidebar.browser.messageManager.sendAsyncMessage("socialTest-sendEvent", { name: "test-flyout-open", data: {} });
},
testCloseSelf: function(next) {
let panel = document.getElementById("social-flyout-panel");
BrowserTestUtils.waitForEvent(panel, "popupshown").then(() => {
is(panel.firstChild.contentDocument.readyState, "complete", "panel is loaded prior to showing");
BrowserTestUtils.waitForEvent(panel, "popuphidden").then(next);
let mm = panel.firstChild.messageManager;
mm.sendAsyncMessage("socialTest-CloseSelf", {});
});
SocialSidebar.browser.messageManager.sendAsyncMessage("socialTest-sendEvent", { name: "test-flyout-open", data: {} });
},
testCloseOnLinkTraversal: function(next) {
BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen", true).then(event => {
BrowserTestUtils.waitForCondition(function() { return panel.state == "closed" },
"panel should close after tab open").then(() => {
BrowserTestUtils.removeTab(event.target).then(next);
});
});
let panel = document.getElementById("social-flyout-panel");
BrowserTestUtils.waitForEvent(panel, "popupshown").then(() => {
is(panel.firstChild.contentDocument.readyState, "complete", "panel is loaded prior to showing");
is(panel.state, "open", "flyout should be open");
let iframe = panel.firstChild;
iframe.contentDocument.getElementById('traversal').click();
});
SocialSidebar.browser.messageManager.sendAsyncMessage("socialTest-sendEvent", { name: "test-flyout-open", data: {} });
}
}

Просмотреть файл

@ -1,51 +0,0 @@
/* 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/. */
function test() {
waitForExplicitFinish();
let manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
let frameScript = "data:,(" + function frame_script() {
addEventListener("visibilitychange", function() {
sendAsyncMessage("visibility", content.document.hidden ? "hidden" : "shown");
});
}.toString() + ")();";
let mm = getGroupMessageManager("social");
mm.loadFrameScript(frameScript, true);
registerCleanupFunction(function () {
mm.removeDelayedFrameScript(frameScript);
});
runSocialTestWithProvider(manifest, function (finishcb) {
runSocialTests(tests, undefined, undefined, finishcb);
});
}
var tests = {
testIsVisible: function(next) {
let mm = getGroupMessageManager("social");
mm.addMessageListener("visibility", function handler(msg) {
mm.removeMessageListener("visibility", handler);
is(msg.data, "shown", "sidebar is visible");
next();
});
SocialSidebar.show();
},
testIsNotVisible: function(next) {
let mm = getGroupMessageManager("social");
mm.addMessageListener("visibility", function handler(msg) {
mm.removeMessageListener("visibility", handler);
is(msg.data, "hidden", "sidebar is hidden");
next();
});
SocialSidebar.hide();
}
}

Просмотреть файл

@ -1,232 +0,0 @@
/* 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/. */
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
var manifest2 = { // used for testing install
name: "provider test1",
origin: "https://test1.example.com",
markURL: "https://test1.example.com/browser/browser/base/content/test/social/social_mark.html?url=%{url}",
markedIcon: "https://test1.example.com/browser/browser/base/content/test/social/unchecked.jpg",
unmarkedIcon: "https://test1.example.com/browser/browser/base/content/test/social/checked.jpg",
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png",
version: "1.0"
};
var manifest3 = { // used for testing install
name: "provider test2",
origin: "https://test2.example.com",
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html",
iconURL: "https://test2.example.com/browser/browser/base/content/test/general/moz.png",
version: "1.0"
};
function test() {
waitForExplicitFinish();
let frameScript = "data:,(" + function frame_script() {
addEventListener("visibilitychange", function() {
sendAsyncMessage("visibility", content.document.hidden ? "hidden" : "shown");
});
}.toString() + ")();";
let mm = getGroupMessageManager("social");
mm.loadFrameScript(frameScript, true);
PopupNotifications.panel.setAttribute("animate", "false");
registerCleanupFunction(function () {
PopupNotifications.panel.removeAttribute("animate");
mm.removeDelayedFrameScript(frameScript);
});
runSocialTests(tests, undefined, undefined, finish);
}
var tests = {
testButtonDisabledOnActivate: function(next) {
// starting on about:blank page, share should be visible but disabled when
// adding provider
is(gBrowser.selectedBrowser.currentURI.spec, "about:blank");
SocialService.addProvider(manifest2, function(provider) {
is(provider.origin, manifest2.origin, "provider is installed");
let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin);
let widget = CustomizableUI.getWidget(id).forWindow(window)
ok(widget.node, "button added to widget set");
// bypass widget go directly to dom, check attribute states
let button = document.getElementById(id);
is(button.disabled, true, "mark button is disabled");
// verify the attribute for proper css
is(button.getAttribute("disabled"), "true", "mark button attribute is disabled");
// button should be visible
is(button.hidden, false, "mark button is visible");
checkSocialUI(window);
SocialService.disableProvider(manifest2.origin, next);
});
},
testNoButtonOnEnable: function(next) {
// we expect the addon install dialog to appear, we need to accept the
// install from the dialog.
let panel = document.getElementById("servicesInstall-notification");
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
info("servicesInstall-notification panel opened");
panel.button.click();
});
let activationURL = manifest3.origin + "/browser/browser/base/content/test/social/social_activate.html"
BrowserTestUtils.openNewForegroundTab(gBrowser, activationURL).then(tab => {
let doc = tab.linkedBrowser.contentDocument;
let data = {
origin: doc.nodePrincipal.origin,
url: doc.location.href,
manifest: manifest3,
window: window
}
Social.installProvider(data, function(addonManifest) {
// enable the provider so we know the button would have appeared
SocialService.enableProvider(manifest3.origin, function(provider) {
is(provider.origin, manifest3.origin, "provider is installed");
let id = SocialMarks._toolbarHelper.idFromOrigin(provider.origin);
let widget = CustomizableUI.getWidget(id);
ok(!widget || !widget.forWindow(window).node, "no button added to widget set");
Social.uninstallProvider(manifest3.origin, function() {
BrowserTestUtils.removeTab(tab).then(next);
});
});
});
});
},
testButtonOnEnable: function(next) {
let panel = document.getElementById("servicesInstall-notification");
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
info("servicesInstall-notification panel opened");
panel.button.click();
});
// enable the provider now
let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
BrowserTestUtils.openNewForegroundTab(gBrowser, activationURL).then(tab => {
let doc = tab.linkedBrowser.contentDocument;
let data = {
origin: doc.nodePrincipal.origin,
url: doc.location.href,
manifest: manifest2,
window: window
}
Social.installProvider(data, function(addonManifest) {
SocialService.enableProvider(manifest2.origin, function(provider) {
is(provider.origin, manifest2.origin, "provider is installed");
let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin);
let widget = CustomizableUI.getWidget(id).forWindow(window)
ok(widget.node, "button added to widget set");
// bypass widget go directly to dom, check attribute states
let button = document.getElementById(id);
is(button.disabled, false, "mark button is disabled");
// verify the attribute for proper css
ok(!button.hasAttribute("disabled"), "mark button attribute is disabled");
// button should be visible
is(button.hidden, false, "mark button is visible");
checkSocialUI(window);
BrowserTestUtils.removeTab(tab).then(next);
});
});
});
},
testMarkPanel: function(next) {
// click on panel to open and wait for visibility
let provider = Social._getProviderFromOrigin(manifest2.origin);
ok(provider.enabled, "provider is enabled");
let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin);
let widget = CustomizableUI.getWidget(id);
let btn = widget.forWindow(window).node;
ok(btn, "got a mark button");
let ourTab;
BrowserTestUtils.waitForEvent(btn.panel, "popupshown").then(() => {
info("marks panel shown");
let doc = btn.contentDocument;
let unmarkBtn = doc.getElementById("unmark");
ok(unmarkBtn, "testMarkPanel - got the panel unmark button");
EventUtils.sendMouseEvent({type: "click"}, unmarkBtn, btn.contentWindow);
});
BrowserTestUtils.waitForEvent(btn.panel, "popuphidden").then(() => {
BrowserTestUtils.removeTab(ourTab).then(() => {
ok(btn.disabled, "button is disabled");
next();
});
});
// verify markbutton is disabled when there is no browser url
ok(btn.disabled, "button is disabled");
let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
BrowserTestUtils.openNewForegroundTab(gBrowser, activationURL).then(tab => {
ourTab = tab;
ok(!btn.disabled, "button is enabled");
// first click marks the page, second click opens the page. We have to
// synthesize so the command event happens
EventUtils.synthesizeMouseAtCenter(btn, {});
// wait for the button to be marked, click to open panel
is(btn.panel.state, "closed", "panel should not be visible yet");
BrowserTestUtils.waitForCondition(() => btn.isMarked, "button is marked").then(() => {
EventUtils.synthesizeMouseAtCenter(btn, {});
});
});
},
testMarkPanelOffline: function(next) {
// click on panel to open and wait for visibility
let provider = Social._getProviderFromOrigin(manifest2.origin);
ok(provider.enabled, "provider is enabled");
let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin);
let widget = CustomizableUI.getWidget(id);
let btn = widget.forWindow(window).node;
ok(btn, "got a mark button");
// verify markbutton is disabled when there is no browser url
ok(btn.disabled, "button is disabled");
let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html";
BrowserTestUtils.openNewForegroundTab(gBrowser, activationURL).then(tab => {
ok(!btn.disabled, "button is enabled");
goOffline().then(function() {
info("testing offline error page");
// wait for popupshown
BrowserTestUtils.waitForEvent(btn.panel, "popupshown").then(() => {
info("marks panel is open");
ensureFrameLoaded(btn.content).then(() => {
is(btn.contentDocument.documentURI.indexOf("about:socialerror?mode=tryAgainOnly"), 0, "social error page is showing "+btn.contentDocument.documentURI);
// cleanup after the page has been unmarked
BrowserTestUtils.removeTab(tab).then(() => {
ok(btn.disabled, "button is disabled");
goOnline().then(next);
});
});
});
btn.markCurrentPage();
});
});
},
testButtonOnDisable: function(next) {
// enable the provider now
let provider = Social._getProviderFromOrigin(manifest2.origin);
ok(provider, "provider is installed");
SocialService.disableProvider(manifest2.origin, function() {
let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin);
BrowserTestUtils.waitForCondition(() => {
// getWidget now returns null since we've destroyed the widget
return !CustomizableUI.getWidget(id)
}, "button does not exist after disabling the provider").then(() => {
checkSocialUI(window);
Social.uninstallProvider(manifest2.origin, next);
});
});
}
}

Просмотреть файл

@ -1,106 +0,0 @@
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
function makeMarkProvider(origin) {
return { // used for testing install
name: "mark provider " + origin,
origin: "https://" + origin + ".example.com",
markURL: "https://" + origin + ".example.com/browser/browser/base/content/test/social/social_mark.html?url=%{url}",
markedIcon: "https://" + origin + ".example.com/browser/browser/base/content/test/social/unchecked.jpg",
unmarkedIcon: "https://" + origin + ".example.com/browser/browser/base/content/test/social/checked.jpg",
iconURL: "https://" + origin + ".example.com/browser/browser/base/content/test/general/moz.png",
version: "1.0"
}
}
function test() {
waitForExplicitFinish();
PopupNotifications.panel.setAttribute("animate", "false");
registerCleanupFunction(function () {
PopupNotifications.panel.removeAttribute("animate");
});
runSocialTests(tests, undefined, undefined, finish);
}
var tests = {
testContextSubmenu: function(next) {
// install 4 providers to test that the menu's are added as submenus
let manifests = [
makeMarkProvider("sub1.test1"),
makeMarkProvider("sub2.test1"),
makeMarkProvider("sub1.test2"),
makeMarkProvider("sub2.test2")
];
let installed = [];
let markLinkMenu = document.getElementById("context-marklinkMenu").firstChild;
let markPageMenu = document.getElementById("context-markpageMenu").firstChild;
function addProviders(callback) {
let manifest = manifests.pop();
if (!manifest) {
info("INSTALLATION FINISHED");
executeSoon(callback);
return;
}
info("INSTALLING " + manifest.origin);
let panel = document.getElementById("servicesInstall-notification");
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
info("servicesInstall-notification panel opened");
panel.button.click();
});
let activationURL = manifest.origin + "/browser/browser/base/content/test/social/social_activate.html"
let id = SocialMarks._toolbarHelper.idFromOrigin(manifest.origin);
let toolbar = document.getElementById("nav-bar");
BrowserTestUtils.openNewForegroundTab(gBrowser, activationURL).then(tab => {
let doc = tab.linkedBrowser.contentDocument;
let data = {
origin: doc.nodePrincipal.origin,
url: doc.location.href,
manifest: manifest,
window: window
}
Social.installProvider(data, function(addonManifest) {
// enable the provider so we know the button would have appeared
SocialService.enableProvider(manifest.origin, function(provider) {
BrowserTestUtils.waitForCondition(() => { return CustomizableUI.getWidget(id) },
"button exists after enabling social").then(() => {
BrowserTestUtils.removeTab(tab).then(() => {
installed.push(manifest.origin);
// checkSocialUI will properly check where the menus are located
checkSocialUI(window);
executeSoon(function() {
addProviders(callback);
});
});
});
});
});
});
}
function removeProviders(callback) {
let origin = installed.pop();
if (!origin) {
executeSoon(callback);
return;
}
Social.uninstallProvider(origin, function(provider) {
executeSoon(function() {
removeProviders(callback);
});
});
}
addProviders(function() {
removeProviders(function() {
is(SocialMarks.getProviders().length, 0, "mark providers removed");
is(markLinkMenu.childNodes.length, 0, "marklink menu ok");
is(markPageMenu.childNodes.length, 0, "markpage menu ok");
checkSocialUI(window);
next();
});
});
}
}

Просмотреть файл

@ -1,78 +0,0 @@
/* 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/. */
function test() {
waitForExplicitFinish();
runSocialTestWithProvider(gProviders, function (finishcb) {
SocialSidebar.provider = Social.providers[0];
SocialSidebar.show();
is(Social.providers[0].origin, SocialSidebar.provider.origin, "selected provider in sidebar");
runSocialTests(tests, undefined, undefined, finishcb);
});
}
var gProviders = [
{
name: "provider 1",
origin: "https://test1.example.com",
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider1",
iconURL: "chrome://branding/content/icon48.png"
},
{
name: "provider 2",
origin: "https://test2.example.com",
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider2",
iconURL: "chrome://branding/content/icon48.png"
}
];
var tests = {
testProviderSwitch: function(next) {
let sbrowser = document.getElementById("social-sidebar-browser");
let menu = document.getElementById("social-statusarea-popup");
let button = document.getElementById("social-sidebar-button");
function checkProviderMenu(selectedProvider) {
let menuProviders = menu.querySelectorAll(".social-provider-menuitem");
is(menuProviders.length, gProviders.length, "correct number of providers listed in the menu");
// Find the selectedProvider's menu item
let el = menu.getElementsByAttribute("origin", selectedProvider.origin);
is(el.length, 1, "selected provider menu item exists");
is(el[0].getAttribute("checked"), "true", "selected provider menu item is checked");
}
// the menu is not populated until onpopupshowing, so wait for popupshown
BrowserTestUtils.waitForEvent(menu, "popupshown", true).then(()=>{
menu.hidePopup(); // doesn't need visibility
// first provider should already be visible in the sidebar
is(Social.providers[0].origin, SocialSidebar.provider.origin, "selected provider in sidebar");
checkProviderMenu(Social.providers[0]);
// Now activate "provider 2"
BrowserTestUtils.waitForEvent(sbrowser, "load", true).then(()=>{
checkUIStateMatchesProvider(Social.providers[1]);
BrowserTestUtils.waitForEvent(sbrowser, "load", true).then(()=>{
checkUIStateMatchesProvider(Social.providers[0]);
next();
});
// show the menu again so the menu is updated with the correct commands
BrowserTestUtils.waitForEvent(menu, "popupshown", true).then(()=>{
// click on the provider menuitem to switch providers
let el = menu.getElementsByAttribute("origin", Social.providers[0].origin);
is(el.length, 1, "selected provider menu item exists");
EventUtils.synthesizeMouseAtCenter(el[0], {});
});
EventUtils.synthesizeMouseAtCenter(button, {});
});
SocialSidebar.provider = Social.providers[1];
});
EventUtils.synthesizeMouseAtCenter(button, {});
}
}
function checkUIStateMatchesProvider(provider) {
// Sidebar
is(document.getElementById("social-sidebar-browser").getAttribute("src"), provider.sidebarURL, "side bar URL is set");
}

Просмотреть файл

@ -1,98 +0,0 @@
/* 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/. */
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
var manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
function test() {
waitForExplicitFinish();
let frameScript = "data:,(" + function frame_script() {
addEventListener("visibilitychange", function() {
sendAsyncMessage("visibility", content.document.hidden ? "hidden" : "shown");
});
}.toString() + ")();";
let mm = getGroupMessageManager("social");
mm.loadFrameScript(frameScript, true);
registerCleanupFunction(function () {
mm.removeDelayedFrameScript(frameScript);
});
SocialService.addProvider(manifest, function() {
// the test will remove the provider
doTest();
});
}
function doTest() {
ok(SocialSidebar.canShow, "social sidebar should be able to be shown");
ok(!SocialSidebar.opened, "social sidebar should not be open by default");
let command = document.getElementById("Social:ToggleSidebar");
let sidebar = document.getElementById("social-sidebar-box");
let browser = sidebar.lastChild;
ok(!browser.docShellIsActive, "sidebar is not active");
is(sidebar.hidden, true, "sidebar should be hidden");
is(command.getAttribute("checked"), "false", "toggle command should be unchecked");
function checkShown(shouldBeShown) {
is(command.getAttribute("checked"), shouldBeShown ? "true" : "false",
"toggle command should be " + (shouldBeShown ? "checked" : "unchecked"));
is(sidebar.hidden, !shouldBeShown,
"sidebar should be " + (shouldBeShown ? "visible" : "hidden"));
is(browser.docShellIsActive, shouldBeShown, "sidebar isActive in correct state");
if (shouldBeShown) {
is(browser.getAttribute('src'), SocialSidebar.provider.sidebarURL, "sidebar url should be set");
// We don't currently check docShellIsActive as this is only set
// after load event fires, and the tests below explicitly wait for this
// anyway.
}
else {
ok(!browser.docShellIsActive, "sidebar should have an inactive docshell");
// sidebar will only be immediately unloaded (and thus set to
// about:blank) when canShow is false.
if (SocialSidebar.canShow) {
// should not have unloaded so will still be the provider URL.
is(browser.getAttribute('src'), SocialSidebar.provider.sidebarURL, "sidebar url should be set");
} else {
// should have been an immediate unload.
is(browser.getAttribute('src'), "about:blank", "sidebar url should be blank");
}
}
}
ensureFrameLoaded(browser).then(() => {
// First check the the sidebar is initially visible, and loaded
ok(!command.hidden, "toggle command should be visible");
let mm = getGroupMessageManager("social");
mm.addMessageListener("visibility", function shown(msg) {
if (msg.data == "shown") {
mm.removeMessageListener("visibility", shown);
checkShown(true);
info("Toggling sidebar to closed");
SocialSidebar.toggleSidebar();
}
});
mm.addMessageListener("visibility", function handler(msg) {
if (msg.data == "hidden") {
mm.removeMessageListener("visibility", handler);
// disable social.
SocialService.disableProvider(SocialSidebar.provider.origin, function() {
checkShown(false);
is(Social.providers.length, 0, "no providers left");
defaultFinishChecks();
// Finish the test
executeSoon(finish);
});
}
});
});
SocialSidebar.show();
}

Просмотреть файл

@ -1,216 +0,0 @@
/* 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/. */
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
var manifest = { // builtin provider
name: "provider example.com",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
var manifest2 = { // used for testing install
name: "provider test1",
origin: "https://test1.example.com",
statusURL: "https://test1.example.com/browser/browser/base/content/test/social/social_panel.html",
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png",
version: "1.0"
};
var manifest3 = { // used for testing install
name: "provider test2",
origin: "https://test2.example.com",
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html",
iconURL: "https://test2.example.com/browser/browser/base/content/test/general/moz.png",
version: "1.0"
};
function openWindowAndWaitForInit(callback) {
let topic = "browser-delayed-startup-finished";
let w = OpenBrowserWindow();
Services.obs.addObserver(function providerSet(subject, topic, data) {
Services.obs.removeObserver(providerSet, topic);
executeSoon(() => callback(w));
}, topic, false);
}
function test() {
waitForExplicitFinish();
let frameScript = "data:,(" + function frame_script() {
addMessageListener("socialTest-sendEvent", function(msg) {
let data = msg.data;
let evt = content.document.createEvent("CustomEvent");
evt.initCustomEvent(data.name, true, true, JSON.stringify(data.data));
content.document.documentElement.dispatchEvent(evt);
});
}.toString() + ")();";
let mm = getGroupMessageManager("social");
mm.loadFrameScript(frameScript, true);
PopupNotifications.panel.setAttribute("animate", "false");
registerCleanupFunction(function () {
PopupNotifications.panel.removeAttribute("animate");
mm.removeDelayedFrameScript(frameScript);
});
runSocialTestWithProvider(manifest, function (finishcb) {
runSocialTests(tests, undefined, undefined, function () {
Services.prefs.clearUserPref("social.remote-install.enabled");
// just in case the tests failed, clear these here as well
Services.prefs.clearUserPref("social.whitelist");
CustomizableUI.reset();
finishcb();
});
});
}
var tests = {
testNoButtonOnEnable: function(next) {
// we expect the addon install dialog to appear, we need to accept the
// install from the dialog.
let panel = document.getElementById("servicesInstall-notification");
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
info("servicesInstall-notification panel opened");
panel.button.click();
})
let activationURL = manifest3.origin + "/browser/browser/base/content/test/social/social_activate.html"
BrowserTestUtils.openNewForegroundTab(gBrowser, activationURL).then(tab => {
let doc = tab.linkedBrowser.contentDocument;
let data = {
origin: doc.nodePrincipal.origin,
url: doc.location.href,
manifest: manifest3,
window: window
}
Social.installProvider(data, function(addonManifest) {
// enable the provider so we know the button would have appeared
SocialService.enableProvider(manifest3.origin, function(provider) {
is(provider.origin, manifest3.origin, "provider is installed");
let id = SocialStatus._toolbarHelper.idFromOrigin(provider.origin);
let widget = CustomizableUI.getWidget(id);
ok(!widget || !widget.forWindow(window).node, "no button added to widget set");
Social.uninstallProvider(manifest3.origin, function() {
BrowserTestUtils.removeTab(tab).then(next);
});
});
});
});
},
testButtonOnEnable: function(next) {
let panel = document.getElementById("servicesInstall-notification");
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
info("servicesInstall-notification panel opened");
panel.button.click();
});
// enable the provider now
let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
BrowserTestUtils.openNewForegroundTab(gBrowser, activationURL).then(tab => {
let doc = tab.linkedBrowser.contentDocument;
let data = {
origin: doc.nodePrincipal.origin,
url: doc.location.href,
manifest: manifest2,
window: window
}
Social.installProvider(data, function(addonManifest) {
SocialService.enableProvider(manifest2.origin, function(provider) {
is(provider.origin, manifest2.origin, "provider is installed");
let id = SocialStatus._toolbarHelper.idFromOrigin(manifest2.origin);
let widget = CustomizableUI.getWidget(id).forWindow(window);
ok(widget.node, "button added to widget set");
checkSocialUI(window);
BrowserTestUtils.removeTab(tab).then(next);
});
});
});
},
testStatusPanel: function(next) {
let icon = {
name: "testIcon",
iconURL: "chrome://browser/skin/Info.png",
counter: 1
};
// click on panel to open and wait for visibility
let provider = Social._getProviderFromOrigin(manifest2.origin);
let id = SocialStatus._toolbarHelper.idFromOrigin(manifest2.origin);
let widget = CustomizableUI.getWidget(id);
let btn = widget.forWindow(window).node;
// Disable the transition
let panel = document.getElementById("social-notification-panel");
panel.setAttribute("animate", "false");
BrowserTestUtils.waitForEvent(panel, "popupshown").then(() => {
ensureFrameLoaded(panel.firstChild).then(() => {
let mm = panel.firstChild.messageManager;
mm.sendAsyncMessage("socialTest-sendEvent", { name: "Social:Notification", data: icon });
BrowserTestUtils.waitForCondition(
() => { return btn.getAttribute("badge"); }, "button updated by notification").then(() => {
is(btn.style.listStyleImage, "url(\"" + icon.iconURL + "\")", "notification icon updated");
panel.hidePopup();
});
});
});
BrowserTestUtils.waitForEvent(panel, "popuphidden").then(() => {
panel.removeAttribute("animate");
next();
});
btn.click(); // open the panel
},
testPanelOffline: function(next) {
// click on panel to open and wait for visibility
let provider = Social._getProviderFromOrigin(manifest2.origin);
ok(provider.enabled, "provider is enabled");
let id = SocialStatus._toolbarHelper.idFromOrigin(manifest2.origin);
let widget = CustomizableUI.getWidget(id);
let btn = widget.forWindow(window).node;
ok(btn, "got a status button");
let frameId = btn.getAttribute("notificationFrameId");
let frame = document.getElementById(frameId);
goOffline().then(function() {
info("testing offline error page");
// wait for popupshown
let panel = document.getElementById("social-notification-panel");
BrowserTestUtils.waitForEvent(panel, "popupshown").then(() => {
ensureFrameLoaded(frame).then(() => {
is(frame.contentDocument.documentURI.indexOf("about:socialerror?mode=tryAgainOnly"), 0, "social error page is showing "+frame.contentDocument.documentURI);
// We got our error page, reset to avoid test leak.
BrowserTestUtils.waitForEvent(frame, "load", true).then(() => {
is(frame.contentDocument.documentURI, "about:blank", "closing error panel");
BrowserTestUtils.waitForEvent(panel, "popuphidden").then(next);
panel.hidePopup();
});
goOnline().then(() => {
info("resetting error panel");
frame.setAttribute("src", "about:blank");
});
});
});
// reload after going offline, wait for unload to open panel
BrowserTestUtils.waitForEvent(frame, "unload", true).then(() => {
btn.click();
});
frame.contentDocument.location.reload();
});
},
testButtonOnDisable: function(next) {
// enable the provider now
let provider = Social._getProviderFromOrigin(manifest2.origin);
ok(provider, "provider is installed");
SocialService.disableProvider(manifest2.origin, function() {
let id = SocialStatus._toolbarHelper.idFromOrigin(manifest2.origin);
BrowserTestUtils.waitForCondition(() => { return !document.getElementById(id) },
"button does not exist after disabling the provider").then(() => {
Social.uninstallProvider(manifest2.origin, next);
});
});
}
}

Просмотреть файл

@ -1,251 +0,0 @@
// 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/.
// Test the top-level window UI for social.
var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
// This function should "reset" Social such that the next time Social.init()
// is called (eg, when a new window is opened), it re-performs all
// initialization.
function resetSocial() {
Social.initialized = false;
Social.providers = [];
// *sob* - listeners keep getting added...
SocialService._providerListeners.clear();
}
var createdWindows = [];
function openWindowAndWaitForInit(parentWin, callback) {
// this notification tells us SocialUI.init() has been run...
let topic = "browser-delayed-startup-finished";
let w = parentWin.OpenBrowserWindow();
createdWindows.push(w);
Services.obs.addObserver(function providerSet(subject, topic, data) {
Services.obs.removeObserver(providerSet, topic);
info(topic + " observer was notified - continuing test");
executeSoon(() => callback(w));
}, topic, false);
}
function closeWindow(w, cb) {
waitForNotification("domwindowclosed", cb);
w.close();
}
function closeOneWindow(cb) {
let w = createdWindows.pop();
if (!w || w.closed) {
cb();
return;
}
closeWindow(w, function() {
closeOneWindow(cb);
});
w.close();
}
function postTestCleanup(cb) {
closeOneWindow(cb);
}
var manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
var manifest2 = { // used for testing install
name: "provider test1",
origin: "https://test1.example.com",
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html",
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png",
};
function test() {
waitForExplicitFinish();
requestLongerTimeout(2);
runSocialTests(tests, undefined, postTestCleanup);
}
var tests = {
// check when social is totally disabled at startup (ie, no providers enabled)
testInactiveStartup: function(cbnext) {
is(Social.providers.length, 0, "needs zero providers to start this test.");
ok(!SocialService.hasEnabledProviders, "no providers are enabled");
resetSocial();
openWindowAndWaitForInit(window, function(w1) {
checkSocialUI(w1);
// Now social is (re-)initialized, open a secondary window and check that.
openWindowAndWaitForInit(window, function(w2) {
checkSocialUI(w2);
checkSocialUI(w1);
cbnext();
});
});
},
// Check when providers are enabled and social is turned on at startup.
testEnabledStartup: function(cbnext) {
setManifestPref("social.manifest.test", manifest);
ok(!SocialSidebar.opened, "sidebar is closed initially");
SocialService.addProvider(manifest, function() {
SocialService.addProvider(manifest2, function (provider) {
SocialSidebar.show();
BrowserTestUtils.waitForCondition(
() => SocialSidebar.opened, "sidebar did not open").then(() => {
ok(SocialSidebar.opened, "first window sidebar is open");
openWindowAndWaitForInit(window, function(w1) {
ok(w1.SocialSidebar.opened, "new window sidebar is open");
ok(SocialService.hasEnabledProviders, "providers are enabled");
checkSocialUI(w1);
// now init is complete, open a second window
openWindowAndWaitForInit(window, function(w2) {
ok(w1.SocialSidebar.opened, "w1 sidebar is open");
ok(w2.SocialSidebar.opened, "w2 sidebar is open");
checkSocialUI(w2);
checkSocialUI(w1);
// disable social and re-check
SocialService.disableProvider(manifest.origin, function() {
SocialService.disableProvider(manifest2.origin, function() {
ok(!Social.enabled, "social is disabled");
is(Social.providers.length, 0, "no providers");
ok(!w1.SocialSidebar.opened, "w1 sidebar is closed");
ok(!w2.SocialSidebar.opened, "w2 sidebar is closed");
checkSocialUI(w2);
checkSocialUI(w1);
Services.prefs.clearUserPref("social.manifest.test");
cbnext();
});
});
});
});
});
}, cbnext);
}, cbnext);
},
testGlobalState: function(cbnext) {
setManifestPref("social.manifest.test", manifest);
ok(!SocialSidebar.opened, "sidebar is closed initially");
ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "global state unset");
// mimick no session state in opener so we exercise the global state via pref
SessionStore.deleteWindowValue(window, "socialSidebar");
ok(!SessionStore.getWindowValue(window, "socialSidebar"), "window state unset");
SocialService.addProvider(manifest, function() {
openWindowAndWaitForInit(window, function(w1) {
w1.SocialSidebar.show();
BrowserTestUtils.waitForCondition(() => w1.SocialSidebar.opened, "sidebar opened").then(() => {
ok(Services.prefs.prefHasUserValue("social.sidebar.provider"), "global state set");
ok(!SocialSidebar.opened, "1. main sidebar is still closed");
ok(w1.SocialSidebar.opened, "1. window sidebar is open");
closeWindow(w1, function() {
// this time, the global state should cause the sidebar to be opened
// in the new window
openWindowAndWaitForInit(window, function(w1) {
ok(!SocialSidebar.opened, "2. main sidebar is still closed");
ok(w1.SocialSidebar.opened, "2. window sidebar is open");
w1.SocialSidebar.hide();
ok(!w1.SocialSidebar.opened, "2. window sidebar is closed");
ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "2. global state unset");
// global state should now be no sidebar gets opened on new window
closeWindow(w1, function() {
ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "3. global state unset");
ok(!SocialSidebar.opened, "3. main sidebar is still closed");
openWindowAndWaitForInit(window, function(w1) {
ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "4. global state unset");
ok(!SocialSidebar.opened, "4. main sidebar is still closed");
ok(!w1.SocialSidebar.opened, "4. window sidebar is closed");
SocialService.disableProvider(manifest.origin, function() {
Services.prefs.clearUserPref("social.manifest.test");
cbnext();
});
});
});
});
});
});
});
});
},
// Check per window sidebar functionality, including migration from using
// prefs to using session state, and state inheritance of windows (new windows
// inherit state from the opener).
testPerWindowSidebar: function(cbnext) {
function finishCheck() {
// disable social and re-check
SocialService.disableProvider(manifest.origin, function() {
SocialService.disableProvider(manifest2.origin, function() {
ok(!Social.enabled, "social is disabled");
is(Social.providers.length, 0, "no providers");
Services.prefs.clearUserPref("social.manifest.test");
cbnext();
});
});
}
setManifestPref("social.manifest.test", manifest);
ok(!SocialSidebar.opened, "sidebar is closed initially");
SocialService.addProvider(manifest, function() {
SocialService.addProvider(manifest2, function (provider) {
// test the migration of the social.sidebar.open pref. We'll set a user
// level pref to indicate it was open (along with the old
// social.provider.current pref), then we'll open a window. During the
// restoreState of the window, those prefs should be migrated, and the
// sidebar should be opened. Both prefs are then removed.
Services.prefs.setCharPref("social.provider.current", "https://example.com");
Services.prefs.setBoolPref("social.sidebar.open", true);
openWindowAndWaitForInit(window, function(w1) {
ok(w1.SocialSidebar.opened, "new window sidebar is open");
ok(SocialService.hasEnabledProviders, "providers are enabled");
ok(!Services.prefs.prefHasUserValue("social.provider.current"), "social.provider.current pref removed");
ok(!Services.prefs.prefHasUserValue("social.sidebar.open"), "social.sidebar.open pref removed");
checkSocialUI(w1);
// now init is complete, open a second window, it's state should be the same as the opener
openWindowAndWaitForInit(w1, function(w2) {
ok(w1.SocialSidebar.opened, "w1 sidebar is open");
ok(w2.SocialSidebar.opened, "w2 sidebar is open");
checkSocialUI(w2);
checkSocialUI(w1);
// change the sidebar in w2
w2.SocialSidebar.show(manifest2.origin);
let sbrowser1 = w1.document.getElementById("social-sidebar-browser");
is(manifest.origin, sbrowser1.getAttribute("origin"), "w1 sidebar origin matches");
let sbrowser2 = w2.document.getElementById("social-sidebar-browser");
is(manifest2.origin, sbrowser2.getAttribute("origin"), "w2 sidebar origin matches");
// hide sidebar, w1 sidebar should still be open
w2.SocialSidebar.hide();
ok(w1.SocialSidebar.opened, "w1 sidebar is opened");
ok(!w2.SocialSidebar.opened, "w2 sidebar is closed");
ok(sbrowser2.parentNode.hidden, "w2 sidebar is hidden");
// open a 3rd window from w2, it should inherit the state of w2
openWindowAndWaitForInit(w2, function(w3) {
// since the sidebar is not open, we need to ensure the provider
// is selected to test we inherited the provider from the opener
w3.SocialSidebar.ensureProvider();
is(w3.SocialSidebar.provider, w2.SocialSidebar.provider, "w3 has same provider as w2");
ok(!w3.SocialSidebar.opened, "w2 sidebar is closed");
// open a 4th window from w1, it should inherit the state of w1
openWindowAndWaitForInit(w1, function(w4) {
is(w4.SocialSidebar.provider, w1.SocialSidebar.provider, "w4 has same provider as w1");
ok(w4.SocialSidebar.opened, "w4 sidebar is opened");
finishCheck();
});
});
});
});
}, cbnext);
}, cbnext);
}
}

Двоичные данные
browser/base/content/test/social/checked.jpg

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 785 B

Просмотреть файл

@ -56,17 +56,15 @@ function defaultFinishChecks() {
function runSocialTestWithProvider(manifest, callback, finishcallback) {
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
let SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
let manifests = Array.isArray(manifest) ? manifest : [manifest];
// Check that none of the provider's content ends up in history.
function finishCleanUp() {
ok(!SocialSidebar.provider, "no provider in sidebar");
SessionStore.setWindowValue(window, "socialSidebar", "");
for (let i = 0; i < manifests.length; i++) {
let m = manifests[i];
for (let what of ['sidebarURL', 'iconURL', 'shareURL', 'markURL']) {
for (let what of ['iconURL', 'shareURL']) {
if (m[what]) {
yield promiseSocialUrlNotRemembered(m[what]);
}
@ -195,14 +193,7 @@ function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
// A fairly large hammer which checks all aspects of the SocialUI for
// internal consistency.
function checkSocialUI(win) {
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
win = win || window;
let doc = win.document;
let enabled = win.SocialUI.enabled;
let active = Social.providers.length > 0 && !win.SocialUI._chromeless &&
!PrivateBrowsingUtils.isWindowPrivate(win);
let sidebarEnabled = win.SocialSidebar.provider ? enabled : false;
let SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
// if we have enabled providers, we should also have instances of those
// providers
if (SocialService.hasEnabledProviders) {
@ -210,78 +201,6 @@ function checkSocialUI(win) {
} else {
is(Social.providers.length, 0, "providers are not enabled");
}
// some local helpers to avoid log-spew for the many checks made here.
let numGoodTests = 0, numTests = 0;
function _ok(what, msg) {
numTests++;
if (!ok)
ok(what, msg)
else
++numGoodTests;
}
function _is(a, b, msg) {
numTests++;
if (a != b)
is(a, b, msg)
else
++numGoodTests;
}
function isbool(a, b, msg) {
_is(!!a, !!b, msg);
}
isbool(win.SocialSidebar.canShow, sidebarEnabled, "social sidebar active?");
let contextMenus = [
{
type: "link",
id: "context-marklinkMenu",
label: "social.marklinkMenu.label"
},
{
type: "page",
id: "context-markpageMenu",
label: "social.markpageMenu.label"
}
];
for (let c of contextMenus) {
let leMenu = document.getElementById(c.id);
let parent, menus;
let markProviders = SocialMarks.getProviders();
if (markProviders.length > SocialMarks.MENU_LIMIT) {
// menus should be in a submenu, not in the top level of the context menu
parent = leMenu.firstChild;
menus = document.getElementsByClassName("context-mark" + c.type);
_is(menus.length, 0, "menu's are not in main context menu\n");
menus = parent.childNodes;
_is(menus.length, markProviders.length, c.id + " menu exists for each mark provider");
} else {
// menus should be in the top level of the context menu, not in a submenu
parent = leMenu.parentNode;
menus = document.getElementsByClassName("context-mark" + c.type);
_is(menus.length, markProviders.length, c.id + " menu exists for each mark provider");
menus = leMenu.firstChild.childNodes;
_is(menus.length, 0, "menu's are not in context submenu\n");
}
for (let m of menus)
_is(m.parentNode, parent, "menu has correct parent");
}
// and for good measure, check all the social commands.
isbool(!doc.getElementById("Social:ToggleSidebar").hidden, sidebarEnabled, "Social:ToggleSidebar visible?");
isbool(!doc.getElementById("Social:ToggleNotifications").hidden, enabled, "Social:ToggleNotifications visible?");
// and report on overall success of failure of the various checks here.
is(numGoodTests, numTests, "The Social UI tests succeeded.")
}
function waitForNotification(topic, cb) {
function observer(subject, topic, data) {
Services.obs.removeObserver(observer, topic);
cb();
}
Services.obs.addObserver(observer, topic, false);
}
function setManifestPref(name, manifest) {
@ -297,32 +216,6 @@ function getManifestPrefname(aManifest) {
return "social.manifest." + originUri.hostPort.replace('.','-');
}
function setBuiltinManifestPref(name, manifest) {
// we set this as a default pref, it must not be a user pref
manifest.builtin = true;
let string = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(manifest);
Services.prefs.getDefaultBranch(null).setComplexValue(name, Ci.nsISupportsString, string);
// verify this is set on the default branch
let stored = Services.prefs.getComplexValue(name, Ci.nsISupportsString).data;
is(stored, string.data, "manifest '"+name+"' stored in default prefs");
// don't dirty our manifest, we'll need it without this flag later
delete manifest.builtin;
// verify we DO NOT have a user-level pref
ok(!Services.prefs.prefHasUserValue(name), "manifest '"+name+"' is not in user-prefs");
}
function resetBuiltinManifestPref(name) {
Services.prefs.getDefaultBranch(null).deleteBranch(name);
is(Services.prefs.getDefaultBranch(null).getPrefType(name),
Services.prefs.PREF_INVALID, "default manifest removed");
}
function ensureEventFired(elem, event) {
return BrowserTestUtils.waitForEvent(elem, event, true);
}
function ensureFrameLoaded(frame, uri) {
return new Promise(resolve => {
if (frame.contentDocument && frame.contentDocument.readyState == "complete" &&
@ -339,243 +232,6 @@ function ensureFrameLoaded(frame, uri) {
});
}
// chat test help functions
// And lots of helpers for the resize tests.
function get3ChatsForCollapsing(mode, cb) {
// We make one chat, then measure its size. We then resize the browser to
// ensure a second can be created fully visible but a third can not - then
// create the other 2. first will will be collapsed, second fully visible
// and the third also visible and the "selected" one.
let chatbar = getChatBar();
let chatWidth = undefined;
let num = 0;
is(chatbar.childNodes.length, 0, "chatbar starting empty");
is(chatbar.menupopup.childNodes.length, 0, "popup starting empty");
makeChat(mode, "first chat", function() {
// got the first one.
checkPopup();
ok(chatbar.menupopup.parentNode.collapsed, "menu selection isn't visible");
// we kinda cheat here and get the width of the first chat, assuming
// that all future chats will have the same width when open.
chatWidth = chatbar.calcTotalWidthOf(chatbar.selectedChat);
let desired = chatWidth * 2.5;
resizeWindowToChatAreaWidth(desired, function(sizedOk) {
ok(sizedOk, "can't do any tests without this width");
checkPopup();
makeChat(mode, "second chat", function() {
is(chatbar.childNodes.length, 2, "now have 2 chats");
checkPopup();
// and create the third.
makeChat(mode, "third chat", function() {
is(chatbar.childNodes.length, 3, "now have 3 chats");
checkPopup();
// XXX - this is a hacky implementation detail around the order of
// the chats. Ideally things would be a little more sane wrt the
// other in which the children were created.
let second = chatbar.childNodes[2];
let first = chatbar.childNodes[1];
let third = chatbar.childNodes[0];
is(first.collapsed, true, "first collapsed state as promised");
is(second.collapsed, false, "second collapsed state as promised");
is(third.collapsed, false, "third collapsed state as promised");
is(chatbar.selectedChat, third, "third is selected as promised")
info("have 3 chats for collapse testing - starting actual test...");
cb(first, second, third);
}, mode);
}, mode);
});
}, mode);
}
function makeChat(mode, uniqueid, cb) {
info("making a chat window '" + uniqueid +"'");
let provider = SocialSidebar.provider;
let chatUrl = provider.origin + "/browser/browser/base/content/test/social/social_chat.html";
// chatURL is not a part of the provider class, but is added by tests if we
// want to use a specific url (different than above) for testing
if (provider.chatURL) {
chatUrl = provider.chatURL;
}
// Note that we use promiseChatLoaded instead of the callback to ensure the
// content has started loading.
let chatbox = getChatBar().openChat({
origin: provider.origin,
title: provider.name,url: chatUrl + "?id=" + uniqueid,
mode: mode
});
chatbox.promiseChatLoaded.then(
() => {
info("chat window has opened");
chatbox.content.messageManager.sendAsyncMessage("Social:SetDocumentTitle", {
title: uniqueid
});
cb(chatbox);
});
}
function checkPopup() {
// popup only showing if any collapsed popup children.
let chatbar = getChatBar();
let numCollapsed = 0;
for (let chat of chatbar.childNodes) {
if (chat.collapsed) {
numCollapsed += 1;
// and it have a menuitem weakmap
is(chatbar.menuitemMap.get(chat).nodeName, "menuitem", "collapsed chat has a menu item");
} else {
ok(!chatbar.menuitemMap.has(chat), "open chat has no menu item");
}
}
is(chatbar.menupopup.parentNode.collapsed, numCollapsed == 0, "popup matches child collapsed state");
is(chatbar.menupopup.childNodes.length, numCollapsed, "popup has correct count of children");
// todo - check each individual elt is what we expect?
}
// Resize the main window so the chat area's boxObject is |desired| wide.
// Does a callback passing |true| if the window is now big enough or false
// if we couldn't resize large enough to satisfy the test requirement.
function resizeWindowToChatAreaWidth(desired, cb, count = 0) {
let current = getChatBar().getBoundingClientRect().width;
let delta = desired - current;
info(count + ": resizing window so chat area is " + desired + " wide, currently it is "
+ current + ". Screen avail is " + window.screen.availWidth
+ ", current outer width is " + window.outerWidth);
// WTF? Sometimes we will get fractional values due to the - err - magic
// of DevPointsPerCSSPixel etc, so we allow a couple of pixels difference.
let widthDeltaCloseEnough = function(d) {
return Math.abs(d) < 2;
}
// attempting to resize by (0,0), unsurprisingly, doesn't cause a resize
// event - so just callback saying all is well.
if (widthDeltaCloseEnough(delta)) {
info(count + ": skipping this as screen width is close enough");
executeSoon(function() {
cb(true);
});
return;
}
// On lo-res screens we may already be maxed out but still smaller than the
// requested size, so asking to resize up also will not cause a resize event.
// So just callback now saying the test must be skipped.
if (window.screen.availWidth - window.outerWidth < delta) {
info(count + ": skipping this as screen available width is less than necessary");
executeSoon(function() {
cb(false);
});
return;
}
function resize_handler(event) {
// we did resize - but did we get far enough to be able to continue?
let newSize = getChatBar().getBoundingClientRect().width;
let sizedOk = widthDeltaCloseEnough(newSize - desired);
if (!sizedOk)
return;
window.removeEventListener("resize", resize_handler, true);
info(count + ": resized window width is " + newSize);
executeSoon(function() {
cb(sizedOk);
});
}
// Otherwise we request resize and expect a resize event
window.addEventListener("resize", resize_handler, true);
window.resizeBy(delta, 0);
}
function resizeAndCheckWidths(first, second, third, checks, cb) {
if (checks.length == 0) {
cb(); // nothing more to check!
return;
}
let count = checks.length;
let [width, numExpectedVisible, why] = checks.shift();
info("<< Check " + count + ": " + why);
info(count + ": " + "resizing window to " + width + ", expect " + numExpectedVisible + " visible items");
resizeWindowToChatAreaWidth(width, function(sizedOk) {
checkPopup();
ok(sizedOk, count+": window resized correctly");
function collapsedObserver(r, m) {
if ([first, second, third].filter(item => !item.collapsed).length == numExpectedVisible) {
if (m) {
m.disconnect();
}
ok(true, count + ": " + "correct number of chats visible");
info(">> Check " + count);
executeSoon(function() {
resizeAndCheckWidths(first, second, third, checks, cb);
});
}
}
let m = new MutationObserver(collapsedObserver);
m.observe(first, {attributes: true });
m.observe(second, {attributes: true });
m.observe(third, {attributes: true });
// and just in case we are already at the right size, explicitly call the
// observer.
collapsedObserver(undefined, m);
}, count);
}
function getChatBar() {
let cb = document.getElementById("pinnedchats");
cb.hidden = false;
return cb;
}
function getPopupWidth() {
let chatbar = getChatBar();
let popup = chatbar.menupopup;
ok(!popup.parentNode.collapsed, "asking for popup width when it is visible");
let cs = document.defaultView.getComputedStyle(popup.parentNode);
let margins = parseInt(cs.marginLeft) + parseInt(cs.marginRight);
return popup.parentNode.getBoundingClientRect().width + margins;
}
function promiseNodeRemoved(aNode) {
return new Promise(resolve => {
let parent = aNode.parentNode;
let observer = new MutationObserver(function onMutatations(mutations) {
for (let mutation of mutations) {
for (let i = 0; i < mutation.removedNodes.length; i++) {
let node = mutation.removedNodes.item(i);
if (node != aNode) {
continue;
}
observer.disconnect();
resolve();
}
}
});
observer.observe(parent, {childList: true});
});
}
function promiseCloseChat(chat) {
let promise = promiseNodeRemoved(chat);
chat.close();
return promise;
}
function closeAllChats() {
let chatbar = getChatBar();
while (chatbar.selectedChat) {
yield promiseCloseChat(chatbar.selectedChat);
}
}
function openChatViaUser() {
let sidebarDoc = document.getElementById("social-sidebar-browser").contentDocument;
let button = sidebarDoc.getElementById("chat-opener");
// Note we must use synthesizeMouseAtCenter() rather than calling
// .click() directly as this causes nsIDOMWindowUtils.isHandlingUserInput
// to be true.
EventUtils.synthesizeMouseAtCenter(button, {}, sidebarDoc.defaultView);
}
// Support for going on and offline.
// (via browser/base/content/test/browser_bookmark_titles.js)
var origProxyType = Services.prefs.getIntPref('network.proxy.type');

Просмотреть файл

@ -13,8 +13,7 @@ var data = {
"icon64URL": "chrome://branding/content/icon64.png",
// at least one of these must be defined
"sidebarURL": "/browser/browser/base/content/test/social/social_sidebar.html",
"statusURL": "/browser/browser/base/content/test/social/social_panel.html",
"shareURL": "/browser/browser/base/content/test/social/social_share.html",
"postActivationURL": "/browser/browser/base/content/test/social/social_postActivation.html",
// should be available for display purposes

Просмотреть файл

@ -13,7 +13,7 @@ var data = {
"icon64URL": "chrome://branding/content/icon64.png",
// at least one of these must be defined
"sidebarURL": "/browser/browser/base/content/test/social/social_sidebar_empty.html",
"shareURL": "/browser/browser/base/content/test/social/social_share.html",
"postActivationURL": "/browser/browser/base/content/test/social/social_postActivation.html",
// should be available for display purposes

Просмотреть файл

@ -1,15 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<title>test chat window</title>
</head>
<body>
<p>This is a test social chat window.</p>
<!-- a couple of input fields to help with focus testing -->
<input id="input1"/>
<input id="input2"/>
<!-- an iframe here so this one page generates multiple load events -->
<iframe id="iframe" src="data:text/plain:this is an iframe"></iframe>
</body>
</html>

Просмотреть файл

@ -1,25 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<script>
window.addEventListener("socialTest-MakeWider", function(e) {
document.body.setAttribute("style", "width: 500px; height: 500px; margin: 0; overflow: hidden;");
document.body.offsetWidth; // force a layout flush
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent("SocialTest-DoneMakeWider", true, true, {});
document.documentElement.dispatchEvent(evt);
}, false);
window.addEventListener("socialTest-CloseSelf", function(e) {
window.close();
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent("SocialTest-DoneCloseSelf", true, true, {});
document.documentElement.dispatchEvent(evt);
}, false);
</script>
</head>
<body style="width: 400px; height: 400px; margin: 0; overflow: hidden;">
<p>This is a test social flyout panel.</p>
<a id="traversal" href="https://test.example.com">test link</a>
</body>
</html>

Просмотреть файл

@ -1,41 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link id="siteicon" rel="icon" href="./icon.png"/>
<title>Demo Mark Window</title>
<script type="text/javascript">
function updateTextNode(parent, text) {
var textNode = parent.childNodes[0];
if (textNode)
parent.removeChild(textNode);
textNode = document.createTextNode(text);
parent.appendChild(textNode);
}
function onLoad() {
updateTextNode(document.getElementById("shared"), location.search);
socialMarkUpdate(true);
}
function socialMarkUpdate(isMarked) {
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent("socialMarkUpdate", true, true, JSON.stringify({marked: isMarked}));
document.documentElement.dispatchEvent(evt);
}
var shareData;
addEventListener("OpenGraphData", function(e) {
shareData = JSON.parse(e.detail);
updateTextNode(document.getElementById("shared"), shareData.url);
socialMarkUpdate(true);
});
</script>
</head>
<body onload="onLoad()">
<div id="content">
<h3>This window shows the mark data</h3>
<div>Page Marked: <div id="shared" class="textbox"></div></div>
<button id="unmark" onclick="socialMarkUpdate(false); window.close()">Unmark</button>
<button onclick="window.close();">Close</button>
</div>
</body>
</html>

Просмотреть файл

@ -1,8 +0,0 @@
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is a test social panel.</p>
</body>
</html>

Просмотреть файл

@ -1,17 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<script>
addEventListener("test-flyout-open", function(e) {
navigator.mozSocial.openPanel("social_flyout.html");
}, false);
addEventListener("test-flyout-close", function(e) {
navigator.mozSocial.closePanel();
}, false);
</script>
</head>
<body>
<p>This is a test social sidebar.</p>
<button id="chat-opener" onclick="navigator.mozSocial.openChatWindow('./social_chat.html');"/>
</body>
</html>

Просмотреть файл

@ -1,8 +0,0 @@
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is a test social sidebar.</p>
</body>
</html>

Двоичные данные
browser/base/content/test/social/unchecked.jpg

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 779 B

Просмотреть файл

@ -101,7 +101,6 @@ browser.jar:
#endif
content/browser/browser-thumbnails.js (content/browser-thumbnails.js)
content/browser/browser-trackingprotection.js (content/browser-trackingprotection.js)
* content/browser/chatWindow.xul (content/chatWindow.xul)
content/browser/tab-content.js (content/tab-content.js)
content/browser/content.js (content/content.js)
content/browser/social-content.js (content/social-content.js)
@ -189,8 +188,6 @@ browser.jar:
#ifdef XP_WIN
content/browser/win6BrowserOverlay.xul (content/win6BrowserOverlay.xul)
#endif
content/browser/socialmarks.xml (content/socialmarks.xml)
content/browser/socialchat.xml (content/socialchat.xml)
# the following files are browser-specific overrides
* content/browser/license.html (/toolkit/content/license.html)
% override chrome://global/content/license.html chrome://browser/content/license.html

Просмотреть файл

@ -16,7 +16,6 @@ MOCHITEST_CHROME_MANIFESTS += [
BROWSER_CHROME_MANIFESTS += [
'content/test/alerts/browser.ini',
'content/test/chat/browser.ini',
'content/test/general/browser.ini',
'content/test/newtab/browser.ini',
'content/test/plugins/browser.ini',

Просмотреть файл

@ -549,14 +549,8 @@ const CustomizableWidgets = [
let win = doc.defaultView;
let menu = doc.getElementById("viewSidebarMenu");
// First clear any existing menuitems then populate. Social sidebar
// options may not have been added yet, so we do that here. Add it to the
// First clear any existing menuitems then populate. Add it to the
// standard menu first, then copy all sidebar options to the panel.
win.SocialSidebar.clearProviderMenus();
let providerMenuSeps = menu.getElementsByClassName("social-provider-menu");
if (providerMenuSeps.length > 0)
win.SocialSidebar.populateProviderMenu(providerMenuSeps[0]);
let sidebarItems = doc.getElementById("PanelUI-sidebarItems");
clearSubview(sidebarItems);
fillSubviewFromMenuItems([...menu.children], sidebarItems);
@ -573,7 +567,7 @@ const CustomizableWidgets = [
node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label"));
node.setAttribute("tooltiptext", CustomizableUI.getLocalizedProperty(this, "tooltiptext"));
node.setAttribute("removable", "true");
node.setAttribute("observes", "Social:PageShareOrMark");
node.setAttribute("observes", "Social:PageShareable");
node.setAttribute("command", "Social:SharePage");
let listener = {

Просмотреть файл

@ -1236,6 +1236,11 @@ DownloadsPlacesView.prototype = {
// nsIController
doCommand(aCommand) {
// Commands may be invoked with keyboard shortcuts even if disabled.
if (!this.isCommandEnabled(aCommand)) {
return;
}
// If this command is not selection-specific, execute it.
if (aCommand in this) {
this[aCommand]();

Просмотреть файл

@ -18,11 +18,11 @@
<content orient="horizontal"
align="center"
onclick="DownloadsView.onDownloadClick(event);">
<xul:stack class="downloadStackIcon">
<xul:stack>
<xul:image class="downloadTypeIcon"
validate="always"
xbl:inherits="src=image"/>
<xul:image class="downloadTypeIcon blockedIcon" />
<xul:image class="downloadBlockedBadge" />
</xul:stack>
<xul:vbox pack="center"
flex="1"

Просмотреть файл

@ -61,7 +61,7 @@ richlistitem.download button {
.download-state:not(:-moz-any([state="6"], /* Blocked (parental) */
[state="8"], /* Blocked (dirty) */
[state="9"]) /* Blocked (policy) */)
.downloadTypeIcon.blockedIcon,
.downloadBlockedBadge,
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
[state="5"], /* Starting (queued) */

Просмотреть файл

@ -135,7 +135,9 @@
onkeydown="DownloadsSummary.onKeyDown(event);"
onclick="DownloadsSummary.onClick(event);">
<image class="downloadTypeIcon" />
<vbox id="downloadsSummaryChildBox">
<vbox pack="center"
class="downloadContainer"
style="width: &downloadDetails.width;">
<description id="downloadsSummaryDescription"
style="min-width: &downloadsSummary.minWidth2;"/>
<progressmeter id="downloadsSummaryProgress"
@ -144,7 +146,6 @@
max="100"
mode="normal" />
<description id="downloadsSummaryDetails"
style="width: &downloadDetails.width;"
crop="end"/>
</vbox>
</hbox>

Просмотреть файл

@ -95,7 +95,7 @@ function* runTest(options) {
browser.test.assertEq(`rgba(${color},255)`, `rgba(${[...imageData]})`, `${format} image color is correct at (${x}, ${y})`);
} else {
// Allow for some deviation in JPEG version due to lossy compression.
const SLOP = 2;
const SLOP = 3;
browser.test.log(`Testing ${format} image color at (${x}, ${y}), have rgba(${[...imageData]}), expecting approx. rgba(${color},255)`);

Просмотреть файл

@ -33,7 +33,7 @@ var gMigrationBundle = null;
XPCOMUtils.defineLazyGetter(this, "gAvailableMigratorKeys", function() {
if (AppConstants.platform == "win") {
return [
"firefox", "edge", "ie", "chrome", "chromium", "safari", "360se",
"firefox", "edge", "ie", "chrome", "chromium", "360se",
"canary"
];
}
@ -547,7 +547,7 @@ this.MigrationUtils = Object.freeze({
* @param aKey internal name of the migration source.
* Supported values: ie (windows),
* edge (windows),
* safari (mac/windows),
* safari (mac),
* canary (mac/windows),
* chrome (mac/windows/linux),
* chromium (mac/windows/linux),

Просмотреть файл

@ -346,22 +346,6 @@ Preferences.prototype = {
this._set("WebKitDisplayImagesKey", "permissions.default.image",
webkitVal => webkitVal ? 1 : 2);
if (AppConstants.platform == "win") {
// Cookie-accept policy.
// For the OS X version, see WebFoundationCookieBehavior.
// Setting Safari Firefox
// Always Accept 0 0
// Accept from Originating 2 1
// Never Accept 1 2
let firefoxVal = 0;
if (webkitVal != 0) {
firefoxVal = webkitVal == 1 ? 2 : 1;
}
this._set("WebKitCookieStorageAcceptPolicy",
"network.cookie.cookieBehavior",
firefoxVal);
}
this._migrateFontSettings();
yield this._migrateDownloadsFolder();
@ -493,17 +477,10 @@ Preferences.prototype = {
},
_migrateDownloadsFolder: Task.async(function* () {
// Windows Safari uses DownloadPath while Mac uses DownloadsPath.
// Check both for future compatibility.
let key;
if (this._dict.has("DownloadsPath"))
key = "DownloadsPath";
else if (this._dict.has("DownloadPath"))
key = "DownloadPath";
else
if (!this._dict.has("DownloadsPath"))
return;
let downloadsFolder = FileUtils.File(this._dict.get(key));
let downloadsFolder = FileUtils.File(this._dict.get("DownloadsPath"));
// If the download folder is set to the Desktop or to ~/Downloads, set the
// folderList pref appropriately so that "Desktop"/Downloads is shown with
@ -552,7 +529,6 @@ SearchStrings.prototype = {
// On OS X, the cookie-accept policy preference is stored in a separate
// property list.
// For the Windows version, check Preferences.migrate.
function WebFoundationCookieBehavior(aWebFoundationFile) {
this._file = aWebFoundationFile;
}
@ -590,12 +566,7 @@ function SafariProfileMigrator() {
SafariProfileMigrator.prototype = Object.create(MigratorPrototype);
SafariProfileMigrator.prototype.getResources = function SM_getResources() {
let profileDir;
if (AppConstants.platform == "macosx") {
profileDir = FileUtils.getDir("ULibDir", ["Safari"], false);
} else {
profileDir = FileUtils.getDir("AppData", ["Apple Computer", "Safari"], false);
}
let profileDir = FileUtils.getDir("ULibDir", ["Safari"], false);
if (!profileDir.exists())
return null;
@ -617,12 +588,7 @@ SafariProfileMigrator.prototype.getResources = function SM_getResources() {
// Apple may fix this at some point.
pushProfileFileResource("ReadingList.plist", Bookmarks);
let prefsDir;
if (AppConstants.platform == "macosx") {
prefsDir = FileUtils.getDir("UsrPrfs", [], false);
} else {
prefsDir = FileUtils.getDir("AppData", ["Apple Computer", "Preferences"], false);
}
let prefsDir = FileUtils.getDir("UsrPrfs", [], false);
let prefs = this.mainPreferencesPropertyList;
if (prefs) {
@ -630,24 +596,15 @@ SafariProfileMigrator.prototype.getResources = function SM_getResources() {
resources.push(new SearchStrings(prefs));
}
if (AppConstants.platform == "macosx") {
// On OS X, the cookie-accept policy preference is stored in a separate
// property list.
let wfFile = FileUtils.getFile("UsrPrfs", ["com.apple.WebFoundation.plist"]);
if (wfFile.exists())
resources.push(new WebFoundationCookieBehavior(wfFile));
}
let wfFile = FileUtils.getFile("UsrPrfs", ["com.apple.WebFoundation.plist"]);
if (wfFile.exists())
resources.push(new WebFoundationCookieBehavior(wfFile));
return resources;
};
SafariProfileMigrator.prototype.getLastUsedDate = function SM_getLastUsedDate() {
let profileDir;
if (AppConstants.platform == "macosx") {
profileDir = FileUtils.getDir("ULibDir", ["Safari"], false);
} else {
profileDir = FileUtils.getDir("AppData", ["Apple Computer", "Safari"], false);
}
let profileDir = FileUtils.getDir("ULibDir", ["Safari"], false);
let datePromises = ["Bookmarks.plist", "History.plist"].map(file => {
let path = OS.Path.join(profileDir.path, file);
return OS.File.stat(path).catch(_ => null).then(info => {
@ -662,12 +619,7 @@ SafariProfileMigrator.prototype.getLastUsedDate = function SM_getLastUsedDate()
Object.defineProperty(SafariProfileMigrator.prototype, "mainPreferencesPropertyList", {
get: function get_mainPreferencesPropertyList() {
if (this._mainPreferencesPropertyList === undefined) {
let file;
if (AppConstants.platform == "macosx") {
file = FileUtils.getDir("UsrPrfs", [], false);
} else {
file = FileUtils.getDir("AppData", ["Apple Computer", "Preferences"], false);
}
let file = FileUtils.getDir("UsrPrfs", [], false);
if (file.exists()) {
file.append("com.apple.Safari.plist");
if (file.exists()) {

Просмотреть файл

@ -39,7 +39,6 @@
<radio id="ie" label="&importFromIE.label;" accesskey="&importFromIE.accesskey;"/>
<radio id="chrome" label="&importFromChrome.label;" accesskey="&importFromChrome.accesskey;"/>
<radio id="chromium" label="&importFromChromium.label;" accesskey="&importFromChromium.accesskey;"/>
<radio id="safari" label="&importFromSafari.label;" accesskey="&importFromSafari.accesskey;"/>
<radio id="canary" label="&importFromCanary.label;" accesskey="&importFromCanary.accesskey;"/>
<radio id="360se" label="&importFrom360se.label;" accesskey="&importFrom360se.accesskey;"/>
#elifdef XP_MACOSX

Просмотреть файл

@ -39,13 +39,11 @@ if CONFIG['OS_ARCH'] == 'WINNT':
'360seProfileMigrator.js',
'EdgeProfileMigrator.js',
'IEProfileMigrator.js',
'SafariProfileMigrator.js',
]
EXTRA_JS_MODULES += [
'ESEDBReader.jsm',
'MSMigrationUtils.jsm',
]
DEFINES['HAS_SAFARI_MIGRATOR'] = True
DEFINES['HAS_360SE_MIGRATOR'] = True
DEFINES['HAS_IE_MIGRATOR'] = True
DEFINES['HAS_EDGE_MIGRATOR'] = True

Просмотреть файл

@ -96,7 +96,10 @@ TabListView.prototype = {
}
}
if (this.list.firstChild) {
this.list.firstChild.querySelector(".item.tab:first-child .item-title").setAttribute("tabindex", 2);
const firstTab = this.list.firstChild.querySelector(".item.tab:first-child .item-title");
if (firstTab) {
firstTab.setAttribute("tabindex", 2);
}
}
},

2
browser/extensions/pocket/bootstrap.js поставляемый
Просмотреть файл

@ -15,7 +15,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
"resource://gre/modules/SocialService.jsm");
"resource:///modules/SocialService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode",

Просмотреть файл

@ -490,7 +490,6 @@
@RESPATH@/browser/components/360seProfileMigrator.js
@RESPATH@/browser/components/EdgeProfileMigrator.js
@RESPATH@/browser/components/IEProfileMigrator.js
@RESPATH@/browser/components/SafariProfileMigrator.js
#endif
#ifdef XP_MACOSX
@RESPATH@/browser/components/SafariProfileMigrator.js
@ -723,7 +722,7 @@
@RESPATH@/res/fonts/*
@RESPATH@/res/dtd/*
@RESPATH@/res/html/*
#if defined(XP_MACOSX) || defined(XP_WIN)
#if defined(XP_MACOSX)
; For SafariProfileMigrator.js.
@RESPATH@/res/langGroups.properties
#endif

Просмотреть файл

@ -161,7 +161,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY bookmarkThisPageCmd.label "Bookmark This Page">
<!ENTITY editThisBookmarkCmd.label "Edit This Bookmark">
<!ENTITY bookmarkThisPageCmd.commandkey "d">
<!ENTITY markPageCmd.commandkey "l">
<!-- LOCALIZATION NOTE (findShareServices.label):
- Use the unicode ellipsis char, \u2026,
- or use "..." if \u2026 doesn't suit traditions in your locale. -->
@ -774,22 +773,8 @@ you can use these alternative items. Otherwise, their values should be empty. -
<!ENTITY syncReAuthItem.accesskey "R">
<!ENTITY syncToolbarButton.label "Sync">
<!ENTITY socialToolbar.title "Social Toolbar Button">
<!ENTITY social.ok.label "OK">
<!ENTITY social.ok.accesskey "O">
<!ENTITY social.toggleSidebar.label "Show sidebar">
<!ENTITY social.toggleSidebar.accesskey "s">
<!ENTITY social.addons.label "Manage Services…">
<!ENTITY social.toggleNotifications.label "Show desktop notifications">
<!ENTITY social.toggleNotifications.accesskey "n">
<!ENTITY social.learnMore.label "Learn more…">
<!ENTITY social.learnMore.accesskey "l">
<!ENTITY social.directory.label "Activations Directory">
<!ENTITY social.directory.text "You can activate Share services from the directory.">
<!ENTITY social.directory.button "Take me there!">
@ -810,15 +795,6 @@ you can use these alternative items. Otherwise, their values should be empty. -
<!ENTITY customizeMode.lwthemes.menuGetMore "Get More Themes">
<!ENTITY customizeMode.lwthemes.menuGetMore.accessKey "G">
<!ENTITY social.chatBar.commandkey "c">
<!ENTITY social.chatBar.label "Focus chats">
<!ENTITY social.chatBar.accesskey "c">
<!ENTITY social.markpageMenu.accesskey "P">
<!ENTITY social.markpageMenu.label "Save Page To…">
<!ENTITY social.marklinkMenu.accesskey "L">
<!ENTITY social.marklinkMenu.label "Save Link To…">
<!ENTITY getUserMedia.selectCamera.label "Camera to share:">
<!ENTITY getUserMedia.selectCamera.accesskey "C">
<!ENTITY getUserMedia.selectMicrophone.label "Microphone to share:">

Просмотреть файл

@ -1,323 +0,0 @@
/* 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/. */
"use strict";
// A module for working with chat windows.
this.EXPORTED_SYMBOLS = ["Chat", "kDefaultButtonSet"];
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const kDefaultButtonSet = new Set(["minimize", "swap", "close"]);
const kHiddenDefaultButtons = new Set(["minimize", "close"]);
var gCustomButtons = new Map();
// A couple of internal helper function.
function isWindowChromeless(win) {
// XXX - stolen from browser-social.js, but there's no obvious place to
// put this so it can be shared.
// Is this a popup window that doesn't want chrome shown?
let docElem = win.document.documentElement;
// extrachrome is not restored during session restore, so we need
// to check for the toolbar as well.
let chromeless = docElem.getAttribute("chromehidden").includes("extrachrome") ||
docElem.getAttribute('chromehidden').includes("toolbar");
return chromeless;
}
function isWindowGoodForChats(win) {
return !win.closed &&
!!win.document.getElementById("pinnedchats") &&
!isWindowChromeless(win) &&
!PrivateBrowsingUtils.isWindowPrivate(win);
}
function getChromeWindow(contentWin) {
return contentWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
}
/*
* The exported Chat object
*/
var Chat = {
/**
* Iterator of <chatbox> elements from this module in all windows.
*/
get chatboxes() {
return function*() {
let winEnum = Services.wm.getEnumerator("navigator:browser");
while (winEnum.hasMoreElements()) {
let win = winEnum.getNext();
let chatbar = win.document.getElementById("pinnedchats");
if (!chatbar)
continue;
// Make a new array instead of the live NodeList so this iterator can be
// used for closing/deleting.
let chatboxes = [...chatbar.children];
for (let chatbox of chatboxes) {
yield chatbox;
}
}
// include standalone chat windows
winEnum = Services.wm.getEnumerator("Social:Chat");
while (winEnum.hasMoreElements()) {
let win = winEnum.getNext();
if (win.closed)
continue;
yield win.document.getElementById("chatter");
}
}();
},
/**
* Open a new chatbox.
*
* @param contentWindow [optional]
* The content window that requested this chat. May be null.
* @param options
* Object that may contain the following properties:
* - origin
* The origin for the chat. This is primarily used as an identifier
* to help identify all chats from the same provider.
* - title
* The title to be used if a new chat window is created.
* - url
* The URL for the that. Should be under the origin. If an existing
* chatbox exists with the same URL, it will be reused and returned.
* - mode [optional]
* May be undefined or 'minimized'
* - focus [optional]
* Indicates if the chatbox should be focused. If undefined the chat
* will be focused if the window is currently handling user input (ie,
* if the chat is being opened as a direct result of user input)
* - remote [optional]
* Indicates if the chatbox browser should use the remote bindings
* to run in the content process when TRUE.
* @param callback
* Function to be invoked once the chat constructed. The chatbox binding
* is passed as the first argument.
*
* @return A chatbox binding. This binding has a number of promises which
* can be used to determine when the chatbox is being created and
* has loaded. Will return null if no chat can be created (Which
* should only happen in edge-cases)
*/
open: function(contentWindow, options, callback) {
let chromeWindow = this.findChromeWindowForChats(contentWindow);
if (!chromeWindow) {
Cu.reportError("Failed to open a chat window - no host window could be found.");
return null;
}
let chatbar = chromeWindow.document.getElementById("pinnedchats");
chatbar.hidden = false;
if (options.remote) {
// Double check that current window can handle remote browser elements.
let browser = chromeWindow.gBrowser && chromeWindow.gBrowser.selectedBrowser;
if (!browser || browser.getAttribute("remote") != "true") {
options.remote = false;
}
}
let chatbox = chatbar.openChat(options, callback);
// getAttention is ignored if the target window is already foreground, so
// we can call it unconditionally.
chromeWindow.getAttention();
// If focus is undefined we want automatic focus handling, and only focus
// if a direct result of user action.
if (!("focus" in options)) {
let dwu = chromeWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
options.focus = dwu.isHandlingUserInput;
}
if (options.focus) {
chatbar.focus();
}
return chatbox;
},
/**
* Close all chats from the specified origin.
*
* @param origin
* The origin from which all chats should be closed.
*/
closeAll: function(origin) {
for (let chatbox of this.chatboxes) {
if (chatbox.content.getAttribute("origin") != origin) {
continue;
}
chatbox.close();
}
},
/**
* Focus the chatbar associated with a window
*
* @param window
*/
focus: function(win) {
let chatbar = win.document.getElementById("pinnedchats");
if (chatbar && !chatbar.hidden) {
chatbar.focus();
}
},
// This is exported as socialchat.xml needs to find a window when a chat
// is re-docked.
findChromeWindowForChats: function(preferredWindow) {
if (preferredWindow) {
preferredWindow = getChromeWindow(preferredWindow);
if (isWindowGoodForChats(preferredWindow)) {
return preferredWindow;
}
}
// no good - we just use the "most recent" browser window which can host
// chats (we used to try and "group" all chats in the same browser window,
// but that didn't work out so well - see bug 835111
// Try first the most recent window as getMostRecentWindow works
// even on platforms where getZOrderDOMWindowEnumerator is broken
// (ie. Linux). This will handle most cases, but won't work if the
// foreground window is a popup.
let mostRecent = Services.wm.getMostRecentWindow("navigator:browser");
if (isWindowGoodForChats(mostRecent))
return mostRecent;
let topMost, enumerator;
// *sigh* - getZOrderDOMWindowEnumerator is broken except on Mac and
// Windows. We use BROKEN_WM_Z_ORDER as that is what some other code uses
// and a few bugs recommend searching mxr for this symbol to identify the
// workarounds - we want this code to be hit in such searches.
let os = Services.appinfo.OS;
const BROKEN_WM_Z_ORDER = os != "WINNT" && os != "Darwin";
if (BROKEN_WM_Z_ORDER) {
// this is oldest to newest and no way to change the order.
enumerator = Services.wm.getEnumerator("navigator:browser");
} else {
// here we explicitly ask for bottom-to-top so we can use the same logic
// where BROKEN_WM_Z_ORDER is true.
enumerator = Services.wm.getZOrderDOMWindowEnumerator("navigator:browser", false);
}
while (enumerator.hasMoreElements()) {
let win = enumerator.getNext();
if (!win.closed && isWindowGoodForChats(win))
topMost = win;
}
return topMost;
},
/**
* Adds a button to the collection of custom buttons that can be added to the
* titlebar of a chatbox.
* For the button to be visible, `Chat#loadButtonSet` has to be called with
* the new buttons' ID in the buttonSet argument.
*
* @param {Object} button Button object that may contain the following fields:
* - {String} id Button identifier.
* - {Function} [onBuild] Function that returns a valid DOM node to
* represent the button.
* - {Function} [onCommand] Callback function that is invoked when the DOM
* node is clicked.
*/
registerButton: function(button) {
if (gCustomButtons.has(button.id))
return;
gCustomButtons.set(button.id, button);
},
/**
* Load a set of predefined buttons in a chatbox' titlebar.
*
* @param {XULDOMNode} chatbox Chatbox XUL element.
* @param {Set|String} buttonSet Set of buttons to show in the titlebar. This
* may be a comma-separated string or a predefined
* set object.
*/
loadButtonSet: function(chatbox, buttonSet = kDefaultButtonSet) {
if (!buttonSet)
return;
// When the buttonSet is coming from an XML attribute, it will be a string.
if (typeof buttonSet == "string") {
buttonSet = buttonSet.split(",").map(button => button.trim());
}
// Make sure to keep the current set around.
chatbox.setAttribute("buttonSet", [...buttonSet].join(","));
let isUndocked = !chatbox.chatbar;
let document = chatbox.ownerDocument;
let titlebarNode = document.getAnonymousElementByAttribute(chatbox, "class",
"chat-titlebar");
let buttonsSeen = new Set();
for (let buttonId of buttonSet) {
buttonId = buttonId.trim();
buttonsSeen.add(buttonId);
let nodes, node;
if (kDefaultButtonSet.has(buttonId)) {
node = document.getAnonymousElementByAttribute(chatbox, "anonid", buttonId);
if (!node)
continue;
node.hidden = isUndocked && kHiddenDefaultButtons.has(buttonId) ? true : false;
} else if (gCustomButtons.has(buttonId)) {
let button = gCustomButtons.get(buttonId);
let buttonClass = "chat-" + buttonId;
// Custom buttons are not defined in the chatbox binding, thus not
// anonymous elements.
nodes = titlebarNode.getElementsByClassName(buttonClass);
node = nodes && nodes.length ? nodes[0] : null;
if (!node) {
// Allow custom buttons to build their own button node.
if (button.onBuild) {
node = button.onBuild(chatbox);
} else {
// We can also build a normal toolbarbutton to insert.
node = document.createElementNS(kNSXUL, "toolbarbutton");
node.classList.add(buttonClass);
node.classList.add("chat-toolbarbutton");
}
if (button.onCommand) {
node.addEventListener("command", e => {
button.onCommand(e, chatbox);
});
}
titlebarNode.appendChild(node);
}
// When the chat is undocked and the button wants to be visible then, it
// will be.
node.hidden = isUndocked && !button.visibleWhenUndocked;
} else {
Cu.reportError("Chatbox button '" + buttonId + "' could not be found!\n");
}
}
// Hide any button that is part of the default set, but not of the current set.
for (let button of kDefaultButtonSet) {
if (!buttonsSeen.has(button))
document.getAnonymousElementByAttribute(chatbox, "anonid", button).hidden = true;
}
}
};

Просмотреть файл

@ -4,8 +4,7 @@
"use strict";
this.EXPORTED_SYMBOLS = ["Social", "CreateSocialStatusWidget",
"CreateSocialMarkWidget", "OpenGraphBuilder",
this.EXPORTED_SYMBOLS = ["Social", "OpenGraphBuilder",
"DynamicResizeWatcher", "sizeSocialPanelToContent"];
const Ci = Components.interfaces;
@ -23,7 +22,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
"resource://gre/modules/SocialService.jsm");
"resource:///modules/SocialService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PageMetadata",
"resource://gre/modules/PageMetadata.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
@ -32,46 +31,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
function promiseSetAnnotation(aURI, providerList) {
let deferred = Promise.defer();
// Delaying to catch issues with asynchronous behavior while waiting
// to implement asynchronous annotations in bug 699844.
Services.tm.mainThread.dispatch(function() {
try {
if (providerList && providerList.length > 0) {
PlacesUtils.annotations.setPageAnnotation(
aURI, "social/mark", JSON.stringify(providerList), 0,
PlacesUtils.annotations.EXPIRE_WITH_HISTORY);
} else {
PlacesUtils.annotations.removePageAnnotation(aURI, "social/mark");
}
} catch (e) {
Cu.reportError("SocialAnnotation failed: " + e);
}
deferred.resolve();
}, Ci.nsIThread.DISPATCH_NORMAL);
return deferred.promise;
}
function promiseGetAnnotation(aURI) {
let deferred = Promise.defer();
// Delaying to catch issues with asynchronous behavior while waiting
// to implement asynchronous annotations in bug 699844.
Services.tm.mainThread.dispatch(function() {
let val = null;
try {
val = PlacesUtils.annotations.getPageAnnotation(aURI, "social/mark");
} catch (ex) { }
deferred.resolve(val);
}, Ci.nsIThread.DISPATCH_NORMAL);
return deferred.promise;
}
this.Social = {
initialized: false,
lastEventReceived: 0,
@ -149,11 +108,6 @@ this.Social = {
return !this._disabledForSafeMode && this.providers.length > 0;
},
toggleNotifications: function SocialNotifications_toggle() {
let prefValue = Services.prefs.getBoolPref("social.toast-notifications.enabled");
Services.prefs.setBoolPref("social.toast-notifications.enabled", !prefValue);
},
_getProviderFromOrigin: function (origin) {
for (let p of this.providers) {
if (p.origin == origin) {
@ -180,139 +134,9 @@ this.Social = {
// It's OK if the provider has already been activated - we still get called
// back with it.
SocialService.enableProvider(origin, callback);
},
// Page Marking functionality
isURIMarked: function(origin, aURI, aCallback) {
promiseGetAnnotation(aURI).then(function(val) {
if (val) {
let providerList = JSON.parse(val);
val = providerList.indexOf(origin) >= 0;
}
aCallback(!!val);
}).then(null, Cu.reportError);
},
markURI: function(origin, aURI, aCallback) {
// update or set our annotation
promiseGetAnnotation(aURI).then(function(val) {
let providerList = val ? JSON.parse(val) : [];
let marked = providerList.indexOf(origin) >= 0;
if (marked)
return;
providerList.push(origin);
// we allow marking links in a page that may not have been visited yet.
// make sure there is a history entry for the uri, then annotate it.
let place = {
uri: aURI,
visits: [{
visitDate: Date.now() + 1000,
transitionType: Ci.nsINavHistoryService.TRANSITION_LINK
}]
};
PlacesUtils.asyncHistory.updatePlaces(place, {
handleError: () => Cu.reportError("couldn't update history for socialmark annotation"),
handleResult: function () {},
handleCompletion: function () {
promiseSetAnnotation(aURI, providerList).then(function() {
if (aCallback)
schedule(function() { aCallback(true); } );
}).then(null, Cu.reportError);
}
});
}).then(null, Cu.reportError);
},
unmarkURI: function(origin, aURI, aCallback) {
// this should not be called if this.provider or the port is null
// set our annotation
promiseGetAnnotation(aURI).then(function(val) {
let providerList = val ? JSON.parse(val) : [];
let marked = providerList.indexOf(origin) >= 0;
if (marked) {
// remove the annotation
providerList.splice(providerList.indexOf(origin), 1);
promiseSetAnnotation(aURI, providerList).then(function() {
if (aCallback)
schedule(function() { aCallback(false); } );
}).then(null, Cu.reportError);
}
}).then(null, Cu.reportError);
}
};
function schedule(callback) {
Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
}
function CreateSocialStatusWidget(aId, aProvider) {
if (!aProvider.statusURL)
return;
let widget = CustomizableUI.getWidget(aId);
// The widget is only null if we've created then destroyed the widget.
// Once we've actually called createWidget the provider will be set to
// PROVIDER_API.
if (widget && widget.provider == CustomizableUI.PROVIDER_API)
return;
CustomizableUI.createWidget({
id: aId,
type: "custom",
removable: true,
defaultArea: CustomizableUI.AREA_NAVBAR,
onBuild: function(aDocument) {
let node = aDocument.createElement("toolbarbutton");
node.id = this.id;
node.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional social-status-button badged-button");
node.style.listStyleImage = "url(" + (aProvider.icon32URL || aProvider.iconURL) + ")";
node.setAttribute("origin", aProvider.origin);
node.setAttribute("label", aProvider.name);
node.setAttribute("tooltiptext", aProvider.name);
node.setAttribute("oncommand", "SocialStatus.showPopup(this);");
node.setAttribute("constrain-size", "true");
return node;
}
});
}
function CreateSocialMarkWidget(aId, aProvider) {
if (!aProvider.markURL)
return;
let widget = CustomizableUI.getWidget(aId);
// The widget is only null if we've created then destroyed the widget.
// Once we've actually called createWidget the provider will be set to
// PROVIDER_API.
if (widget && widget.provider == CustomizableUI.PROVIDER_API)
return;
CustomizableUI.createWidget({
id: aId,
type: "custom",
removable: true,
defaultArea: CustomizableUI.AREA_NAVBAR,
onBuild: function(aDocument) {
let node = aDocument.createElement("toolbarbutton");
node.id = this.id;
node.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional social-mark-button");
node.setAttribute("type", "socialmark");
node.setAttribute("constrain-size", "true");
node.style.listStyleImage = "url(" + (aProvider.unmarkedIcon || aProvider.icon32URL || aProvider.iconURL) + ")";
node.setAttribute("origin", aProvider.origin);
let window = aDocument.defaultView;
let menuLabel = window.gNavigatorBundle.getFormattedString("social.markpageMenu.label", [aProvider.name]);
node.setAttribute("label", menuLabel);
node.setAttribute("tooltiptext", menuLabel);
node.setAttribute("observes", "Social:PageShareOrMark");
return node;
}
});
}
function sizeSocialPanelToContent(panel, iframe, requestedSize) {
let doc = iframe.contentDocument;
if (!doc || !doc.body) {

Просмотреть файл

@ -16,8 +16,6 @@ const ADDON_TYPE_SERVICE = "service";
const ID_SUFFIX = "@services.mozilla.org";
const STRING_TYPE_NAME = "type.%ID%.name";
XPCOMUtils.defineLazyModuleGetter(this, "MozSocialAPI", "resource://gre/modules/MozSocialAPI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "closeAllChatWindows", "resource://gre/modules/MozSocialAPI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask", "resource://gre/modules/DeferredTask.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "etld",
@ -141,7 +139,6 @@ XPCOMUtils.defineLazyGetter(SocialServiceInternal, "providers", function () {
try {
if (ActiveProviders.has(manifest.origin)) {
// enable the api when a provider is enabled
MozSocialAPI.enabled = true;
let provider = new SocialProvider(manifest);
providers[provider.origin] = provider;
}
@ -404,7 +401,6 @@ this.SocialService = {
throw new Error("SocialService.addProvider: provider with this origin already exists");
// enable the api when a provider is enabled
MozSocialAPI.enabled = true;
let provider = new SocialProvider(manifest);
SocialServiceInternal.providers[provider.origin] = provider;
ActiveProviders.add(provider.origin);
@ -434,8 +430,6 @@ this.SocialService = {
ActiveProviders.delete(provider.origin);
delete SocialServiceInternal.providers[origin];
// disable the api if we have no enabled providers
MozSocialAPI.enabled = SocialServiceInternal.enabled;
if (addon) {
// we have to do this now so the addon manager ui will update an uninstall
@ -503,7 +497,7 @@ this.SocialService = {
},
_manifestFromData: function(type, data, installOrigin) {
let featureURLs = ['sidebarURL', 'shareURL', 'statusURL', 'markURL'];
let featureURLs = ['shareURL'];
let resolveURLs = featureURLs.concat(['postActivationURL']);
if (type == 'directory' || type == 'internal') {
@ -704,12 +698,7 @@ function SocialProvider(input) {
this.iconURL = input.iconURL;
this.icon32URL = input.icon32URL;
this.icon64URL = input.icon64URL;
this.sidebarURL = input.sidebarURL;
this.shareURL = input.shareURL;
this.statusURL = input.statusURL;
this.markURL = input.markURL;
this.markedIcon = input.markedIcon;
this.unmarkedIcon = input.unmarkedIcon;
this.postActivationURL = input.postActivationURL;
this.origin = input.origin;
let originUri = Services.io.newURI(input.origin, null, null);
@ -764,29 +753,11 @@ SocialProvider.prototype = {
return undefined;
},
// Map of objects describing the provider's notification icons, whose
// properties include:
// name, iconURL, counter, contentPanel
// See https://developer.mozilla.org/en-US/docs/Social_API
ambientNotificationIcons: null,
// Called by the workerAPI to add/update a notification icon.
setAmbientNotification: function(notification) {
if (!this.ambientNotificationIcons[notification.name] &&
Object.keys(this.ambientNotificationIcons).length >= 3) {
throw new Error("ambient notification limit reached");
}
this.ambientNotificationIcons[notification.name] = notification;
Services.obs.notifyObservers(null, "social:ambient-notification-changed", this.origin);
},
// Internal helper methods
_activate: function _activate() {
},
_terminate: function _terminate() {
closeAllChatWindows(this);
this.errorState = null;
},

Просмотреть файл

@ -18,7 +18,6 @@ EXTRA_JS_MODULES += [
'BrowserUsageTelemetry.jsm',
'CaptivePortalWatcher.jsm',
'CastingApps.jsm',
'Chat.jsm',
'ContentClick.jsm',
'ContentCrashHandlers.jsm',
'ContentLinkHandler.jsm',
@ -44,6 +43,7 @@ EXTRA_JS_MODULES += [
'SelfSupportBackend.jsm',
'SitePermissions.jsm',
'Social.jsm',
'SocialService.jsm',
'TabGroupsMigrator.jsm',
'TransientPrefs.jsm',
'URLBarZoom.jsm',

Просмотреть файл

@ -116,7 +116,7 @@ function do_initialize_social(enabledOnStartup, cb) {
}
// import and initialize everything
SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
do_check_eq(enabledOnStartup, SocialService.hasEnabledProviders, "Service has enabled providers");
Social = Cu.import("resource:///modules/Social.jsm", {}).Social;
do_check_false(Social.initialized, "Social is not initialized");
@ -125,3 +125,86 @@ function do_initialize_social(enabledOnStartup, cb) {
if (!enabledOnStartup)
do_execute_soon(cb);
}
function AsyncRunner() {
do_test_pending();
do_register_cleanup(() => this.destroy());
this._callbacks = {
done: do_test_finished,
error: function (err) {
// xpcshell test functions like do_check_eq throw NS_ERROR_ABORT on
// failure. Ignore those so they aren't rethrown here.
if (err !== Cr.NS_ERROR_ABORT) {
if (err.stack) {
err = err + " - See following stack:\n" + err.stack +
"\nUseless do_throw stack";
}
do_throw(err);
}
},
consoleError: function (scriptErr) {
// Try to ensure the error is related to the test.
let filename = scriptErr.sourceName || scriptErr.toString() || "";
if (filename.indexOf("/toolkit/components/social/") >= 0)
do_throw(scriptErr);
},
};
this._iteratorQueue = [];
// This catches errors reported to the console, e.g., via Cu.reportError, but
// not on the runner's stack.
Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService).
registerListener(this);
}
AsyncRunner.prototype = {
appendIterator: function appendIterator(iter) {
this._iteratorQueue.push(iter);
},
next: function next(arg) {
if (!this._iteratorQueue.length) {
this.destroy();
this._callbacks.done();
return;
}
try {
var { done, value: val } = this._iteratorQueue[0].next(arg);
if (done) {
this._iteratorQueue.shift();
this.next();
return;
}
}
catch (err) {
this._callbacks.error(err);
}
// val is an iterator => prepend it to the queue and start on it
// val is otherwise truthy => call next
if (val) {
if (typeof(val) != "boolean")
this._iteratorQueue.unshift(val);
this.next();
}
},
destroy: function destroy() {
Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService).
unregisterListener(this);
this.destroy = function alreadyDestroyed() {};
},
observe: function observe(msg) {
if (msg instanceof Ci.nsIScriptError &&
!(msg.flags & Ci.nsIScriptError.warningFlag))
{
this._callbacks.consoleError(msg);
}
},
};

Просмотреть файл

@ -16,17 +16,16 @@ function run_test() {
{ // normal provider
name: "provider 1",
origin: "https://example1.com",
sidebarURL: "https://example1.com/sidebar/",
shareURL: "https://example1.com/share/",
},
{ // provider without workerURL
name: "provider 2",
origin: "https://example2.com",
sidebarURL: "https://example2.com/sidebar/",
shareURL: "https://example2.com/share/",
}
];
Cu.import("resource://gre/modules/SocialService.jsm");
Cu.import("resource://gre/modules/MozSocialAPI.jsm");
Cu.import("resource:///modules/SocialService.jsm");
let runner = new AsyncRunner();
let next = runner.next.bind(runner);
@ -45,7 +44,6 @@ function* testAddProviders(manifests, next) {
do_check_false(SocialService.enabled);
let provider = yield SocialService.addProvider(manifests[0], next);
do_check_true(SocialService.enabled);
do_check_true(MozSocialAPI._enabled);
do_check_false(provider.enabled);
provider = yield SocialService.addProvider(manifests[1], next);
do_check_false(provider.enabled);
@ -152,7 +150,7 @@ function* testOrderedProviders(manifests, next) {
let startDate = Date.now() * 1000;
for (let i = 0; i < 10; i++) {
visits.push({
uri: Services.io.newURI(providers[1].sidebarURL + i, null, null),
uri: Services.io.newURI(providers[1].shareURL + i, null, null),
visitDate: startDate + i
});
}

Просмотреть файл

@ -22,7 +22,7 @@ function run_test() {
DEFAULT_PREFS.setCharPref(manifest.origin, JSON.stringify(manifest));
Services.prefs.setBoolPref("social.active", true);
Cu.import("resource://gre/modules/SocialService.jsm");
Cu.import("resource:///modules/SocialService.jsm");
let runner = new AsyncRunner();
let next = runner.next.bind(runner);

Просмотреть файл

@ -32,7 +32,7 @@ function run_test() {
Services.prefs.setComplexValue("social.activeProviders",
Ci.nsISupportsString, activeVal);
Cu.import("resource://gre/modules/SocialService.jsm");
Cu.import("resource:///modules/SocialService.jsm");
let runner = new AsyncRunner();
let next = runner.next.bind(runner);

Просмотреть файл

@ -33,7 +33,7 @@ function run_test() {
// b) unset social.enabled
Services.prefs.setBoolPref("social.enabled", false);
Cu.import("resource://gre/modules/SocialService.jsm");
Cu.import("resource:///modules/SocialService.jsm");
let runner = new AsyncRunner();
let next = runner.next.bind(runner);

Просмотреть файл

@ -19,7 +19,7 @@ function testStartupEnabled() {
}
function testDisableAfterStartup() {
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
let SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
SocialService.disableProvider(Social.providers[0].origin, function() {
do_wait_observer("social:providers-changed", function() {
do_check_eq(Social.enabled, false, "Social is disabled");

Просмотреть файл

@ -7,3 +7,7 @@ support-files = blocklist.xml
[test_social.js]
[test_socialDisabledStartup.js]
[test_SocialService.js]
[test_SocialServiceMigration21.js]
[test_SocialServiceMigration22.js]
[test_SocialServiceMigration29.js]

Просмотреть файл

@ -1408,6 +1408,7 @@ html|span.ac-emphasize-text-url {
}
/* social share panel */
%include ../shared/social/social.inc.css
.social-share-frame {
border-top: 1px solid #f8f8f8;
@ -1456,12 +1457,6 @@ html|span.ac-emphasize-text-url {
max-height: 16px;
}
/* social recommending panel */
#social-mark-button {
-moz-image-region: rect(0, 16px, 16px, 0);
}
/* bookmarks menu-button */
#bookmarks-menu-button[cui-areatype="toolbar"] > .toolbarbutton-menubutton-dropmarker {
@ -1835,30 +1830,6 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton:not(:h
margin-inline-end: 2px;
}
/* social toolbar provider menu */
#social-statusarea-popup {
margin-top: 0;
margin-left: -12px;
margin-right: -12px;
}
.social-statusarea-user {
list-style-image:url("chrome://global/skin/icons/information-32.png");
}
.social-statusarea-user-portrait {
width: 32px;
height: 32px;
border-radius: 2px;
margin: 10px;
}
.social-panel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
%include ../shared/social/chat.inc.css
/* Customization mode */
%include ../shared/customizableui/customizeMode.inc.css

Просмотреть файл

@ -2032,7 +2032,6 @@ html|span.ac-emphasize-text-url {
#share-container {
min-width: 756px;
background-color: white;
background-repeat: no-repeat;
background-position: center center;
}
@ -2047,9 +2046,7 @@ html|span.ac-emphasize-text-url {
opacity: 0;
}
#manage-share-providers,
#social-sidebar-button:hover,
#social-sidebar-button:hover:active {
#manage-share-providers {
-moz-image-region: rect(18px, 468px, 36px, 450px);
}
@ -2078,12 +2075,6 @@ html|span.ac-emphasize-text-url {
max-height: 16px;
}
/* social recommending panel */
#social-mark-button {
-moz-image-region: rect(0, 16px, 16px, 0);
}
/* BOOKMARKING PANEL */
#editBookmarkPanelStarIcon {
list-style-image: url("chrome://browser/skin/places/starred48.png");
@ -2983,10 +2974,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
0 0 3px 2px -moz-mac-focusring;
}
#social-notification-icon > .toolbarbutton-icon {
height: 16px;
}
/* Translation */
%include ../shared/translation/infobar.inc.css
@ -3242,29 +3229,8 @@ menulist.translate-infobar-element > .menulist-dropmarker {
border-radius: 1px;
}
/* === end of social toolbar button === */
/* === social toolbar provider menu === */
.social-statusarea-user {
list-style-image:url("chrome://global/skin/icons/information-32.png");
}
.social-statusarea-user-portrait {
width: 32px;
height: 32px;
margin: 4px;
margin-inline-start: 0;
}
.social-panel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
/* fixup rounded corners for osx panels */
.social-panel > .social-panel-frame {
border-radius: inherit;
}
/* Share */
%include ../shared/social/social.inc.css
#social-share-panel {
min-height: 100px;
@ -3290,10 +3256,6 @@ menulist.translate-infobar-element > .menulist-dropmarker {
border-top-right-radius: inherit;
}
/* === end of social toolbar provider menu === */
%include ../shared/social/chat.inc.css
/* Customization mode */
%include ../shared/customizableui/customizeMode.inc.css

Просмотреть файл

@ -31,17 +31,13 @@
}
%endif
.downloadStackIcon {
--inline-offset: 8px;
--block-offset: 4px;
--icon-size: 32px;
}
.downloadTypeIcon {
margin-inline-end: 8px;
width: calc(var(--icon-size) + var(--inline-offset));
height: calc(var(--icon-size) + var(--block-offset));
padding: var(--block-offset) var(--inline-offset) 0 0;
margin-top: 8px;
margin-inline-end: 12px;
margin-bottom: 8px;
margin-inline-start: 0;
width: 32px;
height: 32px;
}
%ifdef XP_WIN
@ -52,18 +48,21 @@
}
%endif
.blockedIcon {
--overlay-image-dimensions: top right / 16px no-repeat;
padding: 0;
background: url("chrome://browser/skin/downloads/download-blocked.svg") var(--overlay-image-dimensions);
.downloadBlockedBadge {
margin: 0 4px;
background: url("chrome://browser/skin/downloads/download-blocked.svg") top right / 16px no-repeat;
}
@item@[verdict="PotentiallyUnwanted"] .blockedIcon {
background: url("chrome://browser/skin/warning.svg") var(--overlay-image-dimensions);
.downloadBlockedBadge:-moz-locale-dir(rtl) {
background-position-x: left;
}
@item@[verdict="Uncommon"] .blockedIcon {
background: url("chrome://browser/skin/info.svg") var(--overlay-image-dimensions);
@item@[verdict="PotentiallyUnwanted"] .downloadBlockedBadge {
background-image: url("chrome://browser/skin/warning.svg");
}
@item@[verdict="Uncommon"] .downloadBlockedBadge {
background-image: url("chrome://browser/skin/info.svg");
}
.downloadTarget {

Просмотреть файл

@ -127,23 +127,11 @@ toolbarseparator.downloadsDropmarkerSplitter {
}
#downloadsSummary {
--summary-padding-end: 38px;
--summary-padding-start: 12px;
padding: 8px var(--summary-padding-end) 8px var(--summary-padding-start);
padding: 0 12px;
cursor: pointer;
-moz-user-focus: normal;
}
#downloadsSummary:-moz-locale-dir(rtl) {
padding-right: var(--summary-padding-start);
padding-left: var(--summary-padding-end);
}
#downloadsSummaryChildBox {
-moz-margin-start: var(--summary-padding-start);
-moz-margin-end: var(--summary-padding-end);
}
#downloadsSummary > .downloadTypeIcon {
list-style-image: url("chrome://browser/skin/downloads/download-summary.png");
}
@ -186,31 +174,29 @@ richlistitem[type="download"]:last-child {
}
.downloadTypeIcon {
--inline-offset: 8px;
--block-offset: 4px;
--icon-size: 32px;
margin-top: 8px;
margin-inline-end: 12px;
margin-bottom: 8px;
margin-inline-start: 0;
width: 32px;
height: 32px;
}
.downloadTypeIcon {
margin-inline-end: 8px;
/* Prevent flickering when changing states. */
width: calc(var(--icon-size) + var(--inline-offset));
height: calc(var(--icon-size) + var(--block-offset));
padding: var(--block-offset) var(--inline-offset) 0 0;
.downloadBlockedBadge {
margin: 0 4px;
background: url("chrome://browser/skin/downloads/download-blocked.svg") top right / 16px no-repeat;
}
.blockedIcon {
--overlay-image-dimensions: top right / 16px no-repeat;
padding: 0;
background: url("chrome://browser/skin/downloads/download-blocked.svg") var(--overlay-image-dimensions);
.downloadBlockedBadge:-moz-locale-dir(rtl) {
background-position-x: left;
}
@item@[verdict="PotentiallyUnwanted"] .blockedIcon {
background: url("chrome://browser/skin/warning.svg") var(--overlay-image-dimensions);
@item@[verdict="PotentiallyUnwanted"] .downloadBlockedBadge {
background-image: url("chrome://browser/skin/warning.svg");
}
@item@[verdict="Uncommon"] .blockedIcon {
background: url("chrome://browser/skin/info.svg") var(--overlay-image-dimensions);
@item@[verdict="Uncommon"] .downloadBlockedBadge {
background-image: url("chrome://browser/skin/info.svg");
}
/* We hold .downloadTarget, .downloadProgress and .downloadDetails inside of

Просмотреть файл

@ -101,7 +101,6 @@
skin/classic/browser/search-indicator-magnifying-glass.svg (../shared/search/search-indicator-magnifying-glass.svg)
skin/classic/browser/search-arrow-go.svg (../shared/search/search-arrow-go.svg)
skin/classic/browser/gear.svg (../shared/search/gear.svg)
skin/classic/browser/social/chat-icons.svg (../shared/social/chat-icons.svg)
skin/classic/browser/social/gear_default.png (../shared/social/gear_default.png)
skin/classic/browser/social/gear_clicked.png (../shared/social/gear_clicked.png)
skin/classic/browser/tabbrowser/connecting.png (../shared/tabbrowser/connecting.png)

Просмотреть файл

@ -1,51 +0,0 @@
<?xml version="1.0"?>
<!-- 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/. -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-3 -3 16 16">
<style>
use:not(:target) {
display: none;
}
use {
fill: #666;
}
use[id$="-hover"] {
fill: #4a4a4a;
}
use[id$="-active"] {
fill: #4a4a4a;
}
use[id$="-disabled"] {
fill: #666;
}
use[id$="-white"] {
fill: #fff;
}
</style>
<defs>
<polygon id="close-shape" points="10,1.717 8.336,0.049 5.024,3.369 1.663,0 0,1.668 3.36,5.037 0.098,8.307 1.762,9.975 5.025,6.705 8.311,10 9.975,8.332 6.688,5.037"/>
<path id="dropdown-shape" fill-rule="evenodd" d="M9,3L4.984,7L1,3H9z"/>
<g id="expand-shape">
<path fill-rule="evenodd" d="M9.429,7.072v2.143c0,0.531-0.188,0.985-0.566,1.363c-0.377,0.377-0.832,0.565-1.363,0.565H1.929 c-0.531,0-0.986-0.188-1.363-0.565C0.188,10.2,0,9.746,0,9.214V3.643c0-0.531,0.188-0.985,0.566-1.362 c0.377-0.378,0.832-0.566,1.363-0.566h4.714c0.062,0,0.114,0.021,0.154,0.061s0.06,0.092,0.06,0.154v0.428 c0,0.063-0.02,0.114-0.06,0.154S6.705,2.572,6.643,2.572H1.929c-0.295,0-0.547,0.104-0.757,0.314S0.857,3.348,0.857,3.643v5.571 c0,0.295,0.105,0.547,0.315,0.757s0.462,0.314,0.757,0.314H7.5c0.294,0,0.547-0.104,0.757-0.314 c0.209-0.21,0.314-0.462,0.314-0.757V7.072c0-0.062,0.02-0.114,0.061-0.154c0.04-0.04,0.091-0.061,0.154-0.061h0.428 c0.062,0,0.114,0.021,0.154,0.061S9.429,7.009,9.429,7.072z"/>
<path fill-rule="evenodd" d="M7.07,5.82L6.179,4.93C6.127,4.878,6.101,4.818,6.101,4.75s0.026-0.128,0.079-0.18l2.594-2.594L7.648,0.852 C7.549,0.753,7.5,0.636,7.5,0.5s0.049-0.252,0.148-0.351S7.864,0,8,0h3.5c0.136,0,0.252,0.05,0.351,0.149S12,0.365,12,0.5V4 c0,0.136-0.05,0.253-0.149,0.351C11.752,4.451,11.635,4.5,11.5,4.5c-0.136,0-0.253-0.05-0.352-0.149l-1.124-1.125L7.429,5.82 c-0.052,0.052-0.112,0.079-0.18,0.079"/>
</g>
<rect id="minimize-shape" y="7.5" width="10" height="2.2"/>
<path id="exit-shape" fill-rule="evenodd" d="M5.01905144,3.00017279 C5.01277908,3.00005776 5.0064926,3 5.00019251,3 L1.99980749,3 C1.44371665,3 1,3.44762906 1,3.99980749 L1,7.00019251 C1,7.55628335 1.44762906,8 1.99980749,8 L5.00019251,8 C5.00649341,8 5.01277988,7.99994253 5.01905144,7.99982809 L5.01905144,8.5391818 C5.01905144,10.078915 5.37554713,10.2645548 5.81530684,9.9314625 L10.8239665,6.13769619 C11.2653143,5.80340108 11.2637262,5.26455476 10.8239665,4.93146254 L5.81530684,1.13769619 C5.37395904,0.80340108 5.01905144,0.98023404 5.01905144,1.52997693 L5.01905144,3.00017279 Z M-1,1 L4,1 L4,2 L0,2 L0,9 L4,9 L4,10.0100024 L-1,10.0100021 L-1,1 Z" />
</defs>
<use id="close" xlink:href="#close-shape"/>
<use id="close-active" xlink:href="#close-shape"/>
<use id="close-disabled" xlink:href="#close-shape"/>
<use id="close-hover" xlink:href="#close-shape"/>
<use id="exit-white" xlink:href="#exit-shape"/>
<use id="expand" xlink:href="#expand-shape"/>
<use id="expand-active" xlink:href="#expand-shape"/>
<use id="expand-disabled" xlink:href="#expand-shape"/>
<use id="expand-hover" xlink:href="#expand-shape"/>
<use id="expand-white" xlink:href="#expand-shape"/>
<use id="minimize" xlink:href="#minimize-shape"/>
<use id="minimize-active" xlink:href="#minimize-shape"/>
<use id="minimize-disabled" xlink:href="#minimize-shape"/>
<use id="minimize-hover" xlink:href="#minimize-shape"/>
<use id="minimize-white" xlink:href="#minimize-shape"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 3.6 KiB

Просмотреть файл

@ -1,238 +0,0 @@
%if 0
/* 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/. */
%endif
#social-sidebar-header {
padding: 3px;
}
#manage-share-providers,
#social-sidebar-button {
list-style-image: url("chrome://browser/skin/Toolbar.png");
-moz-image-region: rect(0, 468px, 18px, 450px);
}
#social-sidebar-button {
-moz-appearance: none;
border: none;
padding: 0;
margin: 2px;
}
#manage-share-providers > .toolbarbutton-icon,
#social-sidebar-button > .toolbarbutton-icon {
min-height: 18px;
min-width: 18px;
}
#social-sidebar-button > .toolbarbutton-menu-dropmarker {
display: none;
}
#social-sidebar-button[loading="true"] {
list-style-image: url("chrome://global/skin/icons/loading.png");
}
#social-sidebar-favico {
max-height: 16px;
max-width: 16px;
padding: 0;
margin: 2px;
}
.chat-status-icon {
max-height: 16px;
max-width: 16px;
padding: 0;
}
.chat-toolbarbutton {
-moz-appearance: none;
border: none;
padding: 0 3px;
margin: 0;
background: none;
}
.chat-toolbarbutton > .toolbarbutton-text {
display: none;
}
.chat-toolbarbutton > .toolbarbutton-icon {
width: 16px;
height: 16px;
}
.chat-close-button {
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#close");
}
.chat-close-button:hover {
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#close-hover");
}
.chat-close-button:hover:active {
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#close-active");
}
.chat-minimize-button {
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#minimize");
}
.chat-minimize-button:hover {
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#minimize-hover");
}
.chat-minimize-button:hover:active {
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#minimize-active");
}
.chat-swap-button {
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#expand");
transform: rotate(180deg);
}
.chat-swap-button:hover {
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#expand-hover");
}
.chat-swap-button:hover:active {
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#expand-active");
}
chatbar > chatbox > .chat-titlebar > .chat-swap-button {
transform: none;
}
.chat-title {
color: #666;
text-shadow: none;
cursor: inherit;
}
.chat-titlebar {
height: 26px;
min-height: 26px;
width: 100%;
margin: 0;
padding: 5px 4px;
border: 1px solid #ebebeb;
border-bottom: 0;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
cursor: pointer;
background-color: #ebebeb;
}
.chat-titlebar[selected] {
background-color: #f0f0f0;
}
.chat-titlebar > .notification-anchor-icon {
margin-left: 2px;
margin-right: 2px;
}
.chat-titlebar[minimized="true"] {
border-bottom: none;
}
.chat-titlebar[activity] {
background-image: radial-gradient(ellipse closest-side at center, rgb(255,255,255), transparent);
background-repeat: no-repeat;
background-size: 100% 20px;
background-position: 0 -10px;
}
.chat-frame {
padding: 0;
margin: 0;
overflow: hidden;
}
.chatbar-button {
list-style-image: url("chrome://browser/skin/social/services-16.png");
margin: 0;
padding: 2px;
height: 21px;
width: 21px;
border: 1px solid #ccc;
border-bottom: none;
background-color: #d9d9d9;
background-image: linear-gradient(rgba(255,255,255,.43), transparent);
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
@media (min-resolution: 2dppx) {
.chatbar-button {
list-style-image: url("chrome://browser/skin/social/services-16@2x.png");
}
}
.chatbar-button:hover,
.chatbar-button[open="true"] {
background-color: #f0f0f0;
}
.chatbar-button[activity]:not([open]) {
background-image: radial-gradient(circle farthest-corner at center 2px, rgb(254,254,255) 3%, rgba(210,235,255,0.9) 12%, rgba(148,205,253,0.6) 30%, rgba(148,205,253,0.2) 70%);
}
.chatbar-button > .toolbarbutton-icon {
width: 16px;
}
.chatbar-button > menupopup > .menuitem-iconic > .menu-iconic-left > .menu-iconic-icon {
width: auto;
height: auto;
max-height: 16px;
max-width: 16px;
}
.chatbar-button[open="true"] {
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
}
.chatbar-button > .toolbarbutton-text,
.chatbar-button > .toolbarbutton-menu-dropmarker {
display: none;
}
.chatbar-button > menupopup > menuitem[activity] {
font-weight: bold;
}
.chatbar-innerbox {
background: transparent;
overflow: hidden;
}
chatbar {
margin-inline-end: 20px;
}
chatbox {
margin-inline-start: 4px;
background-color: transparent;
}
chatbar > chatbox {
/* Apply the same border-radius as the .chat-titlebar to make the box-shadow
go round nicely. */
border-top-left-radius: 4px;
border-top-right-radius: 4px;
box-shadow: 0 0 5px rgba(0,0,0,.3);
/* Offset the chatbox the same amount as the box-shadows' spread, to make it
visible. */
margin-inline-end: 5px;
}
window > chatbox {
margin-inline-start: 0px;
margin: 0px;
border: none;
padding: 0px;
border-radius: 4px;
}

Просмотреть файл

@ -0,0 +1,23 @@
%if 0
/* 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/. */
%endif
#manage-share-providers {
list-style-image: url("chrome://browser/skin/Toolbar.png");
-moz-image-region: rect(0, 468px, 18px, 450px);
}
#manage-share-providers > .toolbarbutton-icon {
min-height: 18px;
min-width: 18px;
}
.social-panel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
/* fixup corners for share panel */
.social-panel > .social-panel-frame {
border-radius: inherit;
}

Просмотреть файл

@ -54,9 +54,7 @@
}
.sidebar-splitter,
#appcontent ~ .sidebar-splitter,
.chatbar-button,
chatbar > chatbox {
#appcontent ~ .sidebar-splitter {
border-color: #A9B7C9;
}

Просмотреть файл

@ -1877,6 +1877,11 @@ html|span.ac-emphasize-text-url {
}
/* social share panel */
%include ../shared/social/social.inc.css
.social-panel-frame {
border-radius: inherit;
}
.social-share-frame {
min-width: 756px;
@ -1923,12 +1928,6 @@ html|span.ac-emphasize-text-url {
max-height: 16px;
}
/* fixup corners for share panel */
.social-panel > .social-panel-frame {
border-radius: inherit;
}
#social-share-panel {
min-height: 100px;
min-width: 766px;
@ -1952,12 +1951,6 @@ html|span.ac-emphasize-text-url {
border-top-right-radius: inherit;
}
/* social recommending panel */
#social-mark-button {
-moz-image-region: rect(0, 16px, 16px, 0);
}
/* bookmarks menu-button */
#nav-bar #bookmarks-menu-button[cui-areatype="toolbar"]:not([overflowedItem=true]) > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
@ -2524,53 +2517,6 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton {
margin-inline-end: 5px;
}
/* social toolbar provider menu */
.social-statusarea-popup {
margin-top: 0;
margin-left: -12px;
margin-right: -12px;
}
.social-statusarea-user {
-moz-appearance: none;
border-bottom: 1px solid rgb(221,221,221);
background-color: -moz-Dialog;
position: relative;
cursor: pointer;
list-style-image:url("chrome://global/skin/icons/information-32.png");
}
.social-statusarea-user-portrait {
width: 32px;
height: 32px;
border-radius: 2px;
margin: 10px;
}
.social-statusarea-loggedInStatus {
-moz-appearance: none;
background: transparent;
border: none;
color: -moz-nativehyperlinktext;
min-width: 0;
margin: 0 6px;
list-style-image: none;
}
.social-statusarea-user[_moz-menuactive] > vbox > .social-statusarea-loggedInStatus {
text-decoration: underline;
}
.social-panel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
.social-panel-frame {
border-radius: inherit;
}
%include ../shared/social/chat.inc.css
/* Customization mode */
%include ../shared/customizableui/customizeMode.inc.css

Просмотреть файл

@ -322,7 +322,9 @@
</tabpanel>
</tabpanels>
</tabbox>
<splitter class="devtools-horizontal-splitter"/>
<splitter id="workers-splitter"
class="devtools-horizontal-splitter"
hidden="true" />
<tabbox id="sources-pane"
class="devtools-sidebar-tabs"
flex="1">

Просмотреть файл

@ -20,6 +20,7 @@ WorkersView.prototype = Heritage.extend(WidgetMethods, {
}
document.getElementById("workers-pane").removeAttribute("hidden");
document.getElementById("workers-splitter").removeAttribute("hidden");
this.widget = new SideMenuWidget(document.getElementById("workers"), {
showArrows: true,

Просмотреть файл

@ -9,3 +9,4 @@ support-files =
[browser_net_har_copy_all_as_har.js]
[browser_net_har_post_data.js]
[browser_net_har_throttle_upload.js]

Просмотреть файл

@ -0,0 +1,72 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test timing of upload when throttling.
"use strict";
add_task(function* () {
yield throttleUploadTest(true);
yield throttleUploadTest(false);
});
function* throttleUploadTest(actuallyThrottle) {
let [ , debuggee, monitor ] = yield initNetMonitor(
HAR_EXAMPLE_URL + "html_har_post-data-test-page.html");
info("Starting test... (actuallyThrottle = " + actuallyThrottle + ")");
let { NetMonitorView } = monitor.panelWin;
let { RequestsMenu } = NetMonitorView;
const size = 4096;
const uploadSize = actuallyThrottle ? size / 3 : 0;
const request = {
"NetworkMonitor.throttleData": {
roundTripTimeMean: 0,
roundTripTimeMax: 0,
downloadBPSMean: 200000,
downloadBPSMax: 200000,
uploadBPSMean: uploadSize,
uploadBPSMax: uploadSize,
},
};
let client = monitor._controller.webConsoleClient;
info("sending throttle request");
let deferred = promise.defer();
client.setPreferences(request, response => {
deferred.resolve(response);
});
yield deferred.promise;
RequestsMenu.lazyUpdate = false;
// Execute one POST request on the page and wait till its done.
debuggee.executeTest2(size);
yield waitForNetworkEvents(monitor, 0, 1);
// Copy HAR into the clipboard (asynchronous).
let jsonString = yield RequestsMenu.copyAllAsHar();
let har = JSON.parse(jsonString);
// Check out the HAR log.
isnot(har.log, null, "The HAR log must exist");
is(har.log.pages.length, 1, "There must be one page");
is(har.log.entries.length, 1, "There must be one request");
let entry = har.log.entries[0];
is(entry.request.postData.text, "x".repeat(size),
"Check post data payload");
const wasTwoSeconds = entry.timings.send >= 2000;
if (actuallyThrottle) {
ok(wasTwoSeconds, "upload should have taken more than 2 seconds");
} else {
ok(!wasTwoSeconds, "upload should not have taken more than 2 seconds");
}
// Clean up
yield teardown(monitor);
}

Просмотреть файл

@ -27,6 +27,12 @@
var data = "{'first': 'John', 'last': 'Doe'}";
post(url, data);
}
function executeTest2(size) {
var url = "html_har_post-data-test-page.html";
var data = "x".repeat(size);
post(url, data);
}
</script>
</body>

Просмотреть файл

@ -2061,7 +2061,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
*/
_createWaterfallView: function (item, timings, fromCache) {
let { target } = item;
let sections = ["dns", "connect", "send", "wait", "receive"];
let sections = ["blocked", "dns", "connect", "send", "wait", "receive"];
// Skipping "blocked" because it doesn't work yet.
let timingsNode = $(".requests-menu-timings", target);

Просмотреть файл

@ -27,10 +27,6 @@
overflow: auto;
}
#timings-summary-blocked {
display: none; /* This doesn't work yet. */
}
#network-statistics-charts {
overflow: auto;
}

Просмотреть файл

@ -140,6 +140,7 @@ skip-if = (e10s && debug && os == 'mac') # Bug 1253037
[browser_net_statistics-03.js]
[browser_net_status-codes.js]
[browser_net_streaming-response.js]
[browser_net_throttle.js]
[browser_net_timeline_ticks.js]
[browser_net_timing-division.js]
[browser_net_persistent_logs.js]

Просмотреть файл

@ -0,0 +1,60 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Network throttling integration test.
"use strict";
add_task(function* () {
yield throttleTest(true);
yield throttleTest(false);
});
function* throttleTest(actuallyThrottle) {
requestLongerTimeout(2);
let [, , monitor] = yield initNetMonitor(SIMPLE_URL);
const {ACTIVITY_TYPE, NetMonitorController, NetMonitorView} =
monitor.panelWin;
info("Starting test... (actuallyThrottle = " + actuallyThrottle + ")");
// When throttling, must be smaller than the length of the content
// of SIMPLE_URL in bytes.
const size = actuallyThrottle ? 200 : 0;
const request = {
"NetworkMonitor.throttleData": {
roundTripTimeMean: 0,
roundTripTimeMax: 0,
downloadBPSMean: size,
downloadBPSMax: size,
uploadBPSMean: 10000,
uploadBPSMax: 10000,
},
};
let client = monitor._controller.webConsoleClient;
info("sending throttle request");
let deferred = promise.defer();
client.setPreferences(request, response => {
deferred.resolve(response);
});
yield deferred.promise;
let eventPromise =
monitor.panelWin.once(monitor.panelWin.EVENTS.RECEIVED_EVENT_TIMINGS);
yield NetMonitorController
.triggerActivity(ACTIVITY_TYPE.RELOAD.WITH_CACHE_DISABLED);
yield eventPromise;
let requestItem = NetMonitorView.RequestsMenu.getItemAtIndex(0);
const reportedOneSecond = requestItem.attachment.eventTimings.timings.receive > 1000;
if (actuallyThrottle) {
ok(reportedOneSecond, "download reported as taking more than one second");
} else {
ok(!reportedOneSecond, "download reported as taking less than one second");
}
yield teardown(monitor);
}

Просмотреть файл

@ -1,33 +0,0 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<title>Network Monitor Test Page</title>
</head>
<body>
<p>HAR POST data test</p>
<script type="text/javascript">
function post(aAddress, aData) {
var xhr = new XMLHttpRequest();
xhr.open("POST", aAddress, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(aData);
}
function executeTest() {
var url = "sjs_simple-test-server.sjs";
var data = "{'first': 'John', 'last': 'Doe'}";
post(url, data);
}
</script>
</body>
</html>

Просмотреть файл

@ -389,6 +389,7 @@ WebConsoleFrame.prototype = {
_destroyer: null,
_saveRequestAndResponseBodies: true,
_throttleData: null,
// Chevron width at the starting of Web Console's input box.
_chevronWidth: 0,
@ -426,6 +427,36 @@ WebConsoleFrame.prototype = {
return deferred.promise;
},
/**
* Setter for throttling data.
*
* @param boolean value
* The new value you want to set; @see NetworkThrottleManager.
*/
setThrottleData: function(value) {
if (!this.webConsoleClient) {
// Don't continue if the webconsole disconnected.
return promise.resolve(null);
}
let deferred = promise.defer();
let toSet = {
"NetworkMonitor.throttleData": value,
};
// Make sure the web console client connection is established first.
this.webConsoleClient.setPreferences(toSet, response => {
if (!response.error) {
this._throttleData = value;
deferred.resolve(response);
} else {
deferred.reject(response.error);
}
});
return deferred.promise;
},
/**
* Getter for the persistent logging preference.
* @type boolean

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше