зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to m-c. a=merge
This commit is contained in:
Коммит
44f6964ba9
|
@ -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="©EmailCmd.label;"
|
||||
accesskey="©EmailCmd.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
Двоичные данные
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
Двоичные данные
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче