This commit is contained in:
Ryan VanderMeulen 2013-05-07 22:10:19 -04:00
Родитель d706dbcdbb 4ad9b16f8b
Коммит e507d01d4b
528 изменённых файлов: 13847 добавлений и 2829 удалений

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

@ -1084,8 +1084,11 @@ HyperTextAccessible::GetTextAtOffset(int32_t aOffset,
return GetText(*aStartOffset, *aEndOffset, aText);
case BOUNDARY_WORD_END:
*aStartOffset = FindWordBoundary(offset, eDirPrevious, eEndWord);
*aEndOffset = FindWordBoundary(*aStartOffset, eDirNext, eEndWord);
// Ignore the spec and follow what WebKitGtk does because Orca expects it,
// i.e. return a next word at word end offset of the current word
// (WebKitGtk behavior) instead the current word (AKT spec).
*aEndOffset = FindWordBoundary(offset, eDirNext, eEndWord);
*aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eEndWord);
return GetText(*aStartOffset, *aEndOffset, aText);
case BOUNDARY_LINE_START:

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

@ -7,6 +7,8 @@
#include "IUnknownImpl.h"
#include "nsDebug.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif

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

@ -336,19 +336,9 @@
// BOUNDARY_WORD_END
testTextAtOffset(0, BOUNDARY_WORD_END, "oneword", 0, 7, IDs);
testTextAtOffset(8, BOUNDARY_WORD_END, "\n\ntwo", 7, 12,
"div", kOk, kOk, kOk,
"divbr", kTodo, kTodo, kTodo,
"editable", kOk, kOk, kOk,
"editablebr", kTodo, kTodo, kTodo,
"textarea", kOk, kOk, kOk);
testTextAtOffset(9, BOUNDARY_WORD_END, "\n\ntwo", 7, 12,
"div", kOk, kOk, kOk,
"divbr", kTodo, kTodo, kTodo,
"editable", kOk, kOk, kOk,
"editablebr", kTodo, kTodo, kTodo,
"textarea", kOk, kOk, kOk);
testTextAtOffset(12, BOUNDARY_WORD_END, "\n\ntwo", 7, 12, IDs);
testTextAtOffset(8, BOUNDARY_WORD_END, "\n\ntwo", 7, 12, IDs);
testTextAtOffset(9, BOUNDARY_WORD_END, "\n\ntwo", 7, 12, IDs);
testTextAtOffset(12, BOUNDARY_WORD_END, " words", 12, 18, IDs);
testTextAtOffset(13, BOUNDARY_WORD_END, " words", 12, 18,
"div", kOk, kOk, kOk,
"divbr", kOk, kOk, kOk,

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

@ -315,10 +315,10 @@
// BOUNDARY_WORD_END
testTextAtOffset(0, BOUNDARY_WORD_END, "hello", 0, 5, IDs);
testTextAtOffset(1, BOUNDARY_WORD_END, "hello", 0, 5, IDs);
testTextAtOffset(5, BOUNDARY_WORD_END, "hello", 0, 5, IDs);
testTextAtOffset(5, BOUNDARY_WORD_END, " my", 5, 8, IDs);
testTextAtOffset(6, BOUNDARY_WORD_END, " my", 5, 8, IDs);
testTextAtOffset(7, BOUNDARY_WORD_END, " my", 5, 8, IDs);
testTextAtOffset(8, BOUNDARY_WORD_END, " my", 5, 8, IDs);
testTextAtOffset(8, BOUNDARY_WORD_END, " friend", 8, 15, IDs);
testTextAtOffset(9, BOUNDARY_WORD_END, " friend", 8, 15, IDs);
testTextAtOffset(10, BOUNDARY_WORD_END, " friend", 8, 15, IDs);
testTextAtOffset(14, BOUNDARY_WORD_END, " friend", 8, 15, IDs);

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

@ -342,20 +342,21 @@
// BOUNDARY_WORD_END
testTextAtOffset(0, BOUNDARY_WORD_END, "Brave", 0, 5, IDs);
testTextAtOffset(4, BOUNDARY_WORD_END, "Brave", 0, 5, IDs);
testTextAtOffset(5, BOUNDARY_WORD_END, "Brave", 0, 5, IDs);
testTextAtOffset(5, BOUNDARY_WORD_END, " Sir", 5, 9, IDs);
testTextAtOffset(6, BOUNDARY_WORD_END, " Sir", 5, 9, IDs);
testTextAtOffset(8, BOUNDARY_WORD_END, " Sir", 5, 9, IDs);
testTextAtOffset(9, BOUNDARY_WORD_END, " Sir", 5, 9, IDs);
testTextAtOffset(9, BOUNDARY_WORD_END, " Robin", 9, 16, IDs);
testTextAtOffset(10, BOUNDARY_WORD_END, " Robin", 9, 16, IDs);
testTextAtOffset(11, BOUNDARY_WORD_END, " Robin", 9, 16, IDs);
testTextAtOffset(15, BOUNDARY_WORD_END, " Robin", 9, 16, IDs);
testTextAtOffset(16, BOUNDARY_WORD_END, " Robin", 9, 16, IDs);
testTextAtOffset(16, BOUNDARY_WORD_END, " ran", 16, 22, IDs);
testTextAtOffset(17, BOUNDARY_WORD_END, " ran", 16, 22, IDs);
testTextAtOffset(18, BOUNDARY_WORD_END, " ran", 16, 22, IDs);
testTextAtOffset(19, BOUNDARY_WORD_END, " ran", 16, 22, IDs);
testTextAtOffset(20, BOUNDARY_WORD_END, " ran", 16, 22, IDs);
testTextAtOffset(21, BOUNDARY_WORD_END, " ran", 16, 22, IDs);
testTextAtOffset(22, BOUNDARY_WORD_END, " ran", 16, 22, IDs);
testTextAtOffset(22, BOUNDARY_WORD_END, " ran", 16, 22, ["input", "div", "editable"]);
testTextAtOffset(22, BOUNDARY_WORD_END, " ran\n", 16, 23, [ "textarea" ]);
SimpleTest.finish();
}

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

@ -92,6 +92,9 @@ endif
ifeq ($(OS_ARCH),WINNT)
RCINCLUDE = splash.rc
# Rebuild firefox.exe if the manifest changes - it's included by splash.rc.
# (this dependency should really be just for firefox.exe, not other targets)
EXTRA_DEPS += $(PROGRAM).manifest
ifndef GNU_CC
RCFLAGS += -DMOZ_PHOENIX -I$(srcdir)
else

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

@ -26,6 +26,11 @@
</ms_asmv3:requestedPrivileges>
</ms_asmv3:security>
</ms_asmv3:trustInfo>
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</ms_asmv3:windowsSettings>
</ms_asmv3:application>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -47,6 +47,8 @@
let modeMatch = queryString.match(/mode=([^&]+)/);
let mode = modeMatch && modeMatch[1] ? modeMatch[1] : "";
let originMatch = queryString.match(/origin=([^&]+)/);
config.origin = originMatch && originMatch[1] ? decodeURIComponent(originMatch[1]) : "";
switch (mode) {
case "compactInfo":
@ -77,7 +79,11 @@
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
let productName = brandBundle.GetStringFromName("brandShortName");
let providerName = Social && Social.provider && Social.provider.name;
let provider = Social && Social.provider;
if (config.origin) {
provider = Social && Social._getProviderFromOrigin(config.origin);
}
let providerName = provider && provider.name;
// Sets up the error message
let msg = browserBundle.formatStringFromName("social.error.message", [productName, providerName], 2);

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

@ -40,6 +40,10 @@
<menuitem id="context-marklink"
accesskey="&social.marklink.accesskey;"
oncommand="gContextMenu.markLink();"/>
<menuitem id="context-sharelink"
label="&shareLinkCmd.label;"
accesskey="&shareLinkCmd.accesskey;"
oncommand="gContextMenu.shareLink();"/>
<menuitem id="context-savelink"
label="&saveLinkCmd.label;"
accesskey="&saveLinkCmd.accesskey;"
@ -160,6 +164,10 @@
label="&saveImageCmd.label;"
accesskey="&saveImageCmd.accesskey;"
oncommand="gContextMenu.saveMedia();"/>
<menuitem id="context-shareimage"
label="&shareImageCmd.label;"
accesskey="&shareImageCmd.accesskey;"
oncommand="gContextMenu.shareImage();"/>
<menuitem id="context-sendimage"
label="&emailImageCmd.label;"
accesskey="&emailImageCmd.accesskey;"
@ -176,6 +184,10 @@
label="&saveVideoCmd.label;"
accesskey="&saveVideoCmd.accesskey;"
oncommand="gContextMenu.saveMedia();"/>
<menuitem id="context-sharevideo"
label="&shareVideoCmd.label;"
accesskey="&shareVideoCmd.accesskey;"
oncommand="gContextMenu.shareVideo();"/>
<menuitem id="context-saveaudio"
label="&saveAudioCmd.label;"
accesskey="&saveAudioCmd.accesskey;"
@ -228,6 +240,10 @@
<menuitem id="context-markpage"
accesskey="&social.markpage.accesskey;"
command="Social:TogglePageMark"/>
<menuitem id="context-sharepage"
label="&sharePageCmd.label;"
accesskey="&sharePageCmd.accesskey;"
oncommand="SocialShare.sharePage();"/>
<menuitem id="context-savepage"
label="&savePageCmd.label;"
accesskey="&savePageCmd.accesskey2;"
@ -271,6 +287,10 @@
oncommand="AddKeywordForSearchField();"/>
<menuitem id="context-searchselect"
oncommand="BrowserSearch.loadSearchFromContext(getBrowserSelection());"/>
<menuitem id="context-shareselect"
label="&shareSelectCmd.label;"
accesskey="&shareSelectCmd.accesskey;"
oncommand="gContextMenu.shareSelect(getBrowserSelection());"/>
<menuseparator id="frame-sep"/>
<menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;">
<menupopup>

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

@ -39,8 +39,13 @@ var gSafeBrowsing = {
getReportURL: function(name) {
var reportUrl = SafeBrowsing.getReportURL(name);
var pageUrl = gBrowser.currentURI.asciiSpec;
reportUrl += "&url=" + encodeURIComponent(pageUrl);
var pageUri = gBrowser.currentURI.clone();
// Remove the query to avoid including potentially sensitive data
if (pageUri instanceof Ci.nsIURL)
pageUri.query = '';
reportUrl += "&url=" + encodeURIComponent(pageUri.asciiSpec);
return reportUrl;
}

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

@ -110,6 +110,7 @@
<command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
<command id="Browser:ToggleAddonBar" oncommand="toggleAddonBar();"/>
<command id="Social:TogglePageMark" oncommand="SocialMark.togglePageMark();" disabled="true"/>
<command id="Social:SharePage" oncommand="SocialShare.sharePage();" disabled="true"/>
<command id="Social:ToggleSidebar" oncommand="Social.toggleSidebar();"/>
<command id="Social:ToggleNotifications" oncommand="Social.toggleNotifications();" hidden="true"/>
<command id="Social:FocusChat" oncommand="SocialChatBar.focus();" hidden="true" disabled="true"/>

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

@ -7,6 +7,7 @@ let SocialUI,
SocialChatBar,
SocialFlyout,
SocialMark,
SocialShare,
SocialMenu,
SocialToolbar,
SocialSidebar;
@ -20,6 +21,12 @@ const PANEL_MIN_WIDTH = 330;
XPCOMUtils.defineLazyModuleGetter(this, "SharedFrame",
"resource:///modules/SharedFrame.jsm");
XPCOMUtils.defineLazyGetter(this, "OpenGraphBuilder", function() {
let tmp = {};
Cu.import("resource:///modules/Social.jsm", tmp);
return tmp.OpenGraphBuilder;
});
SocialUI = {
// Called on delayed startup to initialize the UI
init: function SocialUI_init() {
@ -43,6 +50,7 @@ SocialUI = {
SocialChatBar.init();
SocialMark.init();
SocialShare.init();
SocialMenu.init();
SocialToolbar.init();
SocialSidebar.init();
@ -87,6 +95,7 @@ SocialUI = {
SocialFlyout.unload();
SocialChatBar.update();
SocialShare.update();
SocialSidebar.update();
SocialMark.update();
SocialToolbar.update();
@ -97,6 +106,7 @@ SocialUI = {
this._updateActiveUI();
// and the multi-provider menu
SocialToolbar.populateProviderMenus();
SocialShare.populateProviderMenu();
break;
// Provider-specific notifications
@ -384,7 +394,13 @@ function sizeSocialPanelToContent(panel, iframe) {
if (!doc || !doc.body) {
return;
}
// We need an element to use for sizing our panel. See if the body defines
// an id for that element, otherwise use the body itself.
let body = doc.body;
let bodyId = body.getAttribute("contentid");
if (bodyId) {
body = doc.getElementById(bodyId) || doc.body;
}
// offsetHeight/Width don't include margins, so account for that.
let cs = doc.defaultView.getComputedStyle(body);
let computedHeight = parseInt(cs.marginTop) + body.offsetHeight + parseInt(cs.marginBottom);
@ -566,6 +582,301 @@ SocialFlyout = {
}
}
SocialShare = {
// Called once, after window load, when the Social.provider object is initialized
init: function() {},
get panel() {
return document.getElementById("social-share-panel");
},
get iframe() {
// first element is our menu vbox.
if (this.panel.childElementCount == 1)
return null;
else
return this.panel.lastChild;
},
_createFrame: function() {
let panel = this.panel;
if (!SocialUI.enabled || this.iframe)
return;
this.panel.hidden = false;
// create and initialize the panel for this window
let iframe = document.createElement("iframe");
iframe.setAttribute("type", "content");
iframe.setAttribute("class", "social-share-frame");
iframe.setAttribute("flex", "1");
panel.appendChild(iframe);
this.populateProviderMenu();
},
getSelectedProvider: function() {
let provider;
let lastProviderOrigin = this.iframe && this.iframe.getAttribute("origin");
if (lastProviderOrigin) {
provider = Social._getProviderFromOrigin(lastProviderOrigin);
}
if (!provider)
provider = Social.provider || Social.defaultProvider;
// if our provider has no shareURL, select the first one that does
if (provider && !provider.shareURL) {
let providers = [p for (p of Social.providers) if (p.shareURL)];
provider = providers.length > 0 && providers[0];
}
return provider;
},
populateProviderMenu: function() {
if (!this.iframe)
return;
let providers = [p for (p of Social.providers) if (p.shareURL)];
let hbox = document.getElementById("social-share-provider-buttons");
// selectable providers are inserted before the provider-menu seperator,
// remove any menuitems in that area
while (hbox.firstChild) {
hbox.removeChild(hbox.firstChild);
}
// reset our share toolbar
// only show a selection if there is more than one
if (!SocialUI.enabled || providers.length < 2) {
this.panel.firstChild.hidden = true;
return;
}
let selectedProvider = this.getSelectedProvider();
for (let provider of providers) {
let button = document.createElement("toolbarbutton");
button.setAttribute("class", "toolbarbutton share-provider-button");
button.setAttribute("type", "radio");
button.setAttribute("group", "share-providers");
button.setAttribute("image", provider.iconURL);
button.setAttribute("tooltiptext", provider.name);
button.setAttribute("origin", provider.origin);
button.setAttribute("oncommand", "SocialShare.sharePage(this.getAttribute('origin')); this.checked=true;");
if (provider == selectedProvider) {
this.defaultButton = button;
}
hbox.appendChild(button);
}
if (!this.defaultButton) {
this.defaultButton = hbox.firstChild
}
this.defaultButton.setAttribute("checked", "true");
this.panel.firstChild.hidden = false;
},
get shareButton() {
return document.getElementById("social-share-button");
},
canSharePage: function(aURI) {
// we do not enable sharing from private sessions
if (PrivateBrowsingUtils.isWindowPrivate(window))
return false;
if (!aURI || !(aURI.schemeIs('http') || aURI.schemeIs('https')))
return false;
// The share button and context menus are disabled if the current tab has
// defined no-store. However, a share from other content is still possible
// (eg. via mozSocial or future use of web activities). If the URI is not
// the current tab URI, we cannot validate the no-store header on the URI.
if (aURI != gBrowser.currentURI)
return true;
// we want to ensure this is a successful load and that the page is locally
// cacheable since that is a common mechanism for sensitive pages to avoid
// storing sensitive data in cache.
let channel = gBrowser.docShell.currentDocumentChannel;
let httpChannel;
try {
httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
} catch (e) {
/* Not an HTTP channel. */
Cu.reportError("cannot share without httpChannel");
return false;
}
// Continue only if we have a 2xx status code.
try {
if (!httpChannel.requestSucceeded)
return false;
} catch (e) {
// Can't get response information from the httpChannel
// because mResponseHead is not available.
return false;
}
// Cache-Control: no-store.
if (httpChannel.isNoStoreResponse()) {
Cu.reportError("cannot share cache-control: no-share");
return false;
}
return true;
},
update: function() {
let shareButton = this.shareButton;
shareButton.hidden = !SocialUI.enabled ||
[p for (p of Social.providers) if (p.shareURL)].length == 0;
shareButton.disabled = shareButton.hidden || !this.canSharePage(gBrowser.currentURI);
// also update the relevent command's disabled state so the keyboard
// shortcut only works when available.
let cmd = document.getElementById("Social:SharePage");
cmd.setAttribute("disabled", shareButton.disabled ? "true" : "false");
},
onShowing: function() {
this.shareButton.setAttribute("open", "true");
},
onHidden: function() {
this.shareButton.removeAttribute("open");
this.iframe.setAttribute("src", "data:text/plain;charset=utf8,")
this.currentShare = null;
},
setErrorMessage: function() {
let iframe = this.iframe;
if (!iframe)
return;
iframe.removeAttribute("src");
iframe.webNavigation.loadURI("about:socialerror?mode=compactInfo&origin=" +
encodeURIComponent(iframe.getAttribute("origin")),
null, null, null, null);
sizeSocialPanelToContent(this.panel, iframe);
},
sharePage: function(providerOrigin, graphData) {
// if providerOrigin is undefined, we use the last-used provider, or the
// current/default provider. The provider selection in the share panel
// will call sharePage with an origin for us to switch to.
this._createFrame();
let iframe = this.iframe;
let provider;
if (providerOrigin)
provider = Social._getProviderFromOrigin(providerOrigin);
else
provider = this.getSelectedProvider();
if (!provider || !provider.shareURL)
return;
// graphData is an optional param that either defines the full set of data
// to be shared, or partial data about the current page. It is set by a call
// in mozSocial API, or via nsContentMenu calls. If it is present, it MUST
// define at least url. If it is undefined, we're sharing the current url in
// the browser tab.
let sharedURI = graphData ? Services.io.newURI(graphData.url, null, null) :
gBrowser.currentURI;
if (!this.canSharePage(sharedURI))
return;
// the point of this action type is that we can use existing share
// endpoints (e.g. oexchange) that do not support additional
// socialapi functionality. One tweak is that we shoot an event
// containing the open graph data.
let pageData = graphData ? graphData : this.currentShare;
if (!pageData || sharedURI == gBrowser.currentURI) {
pageData = OpenGraphBuilder.getData(gBrowser);
if (graphData) {
// overwrite data retreived from page with data given to us as a param
for (let p in graphData) {
pageData[p] = graphData[p];
}
}
}
this.currentShare = pageData;
let shareEndpoint = this._generateShareEndpointURL(provider.shareURL, pageData);
this._dynamicResizer = new DynamicResizeWatcher();
// if we've already loaded this provider/page share endpoint, we don't want
// to add another load event listener.
let reload = true;
let endpointMatch = shareEndpoint == iframe.getAttribute("src");
let docLoaded = iframe.contentDocument && iframe.contentDocument.readyState == "complete";
if (endpointMatch && docLoaded) {
reload = shareEndpoint != iframe.contentDocument.location.spec;
}
if (!reload) {
this._dynamicResizer.start(this.panel, iframe);
iframe.docShell.isActive = true;
iframe.docShell.isAppTab = true;
let evt = iframe.contentDocument.createEvent("CustomEvent");
evt.initCustomEvent("OpenGraphData", true, true, JSON.stringify(pageData));
iframe.contentDocument.documentElement.dispatchEvent(evt);
} else {
// first time load, wait for load and dispatch after load
iframe.addEventListener("load", function panelBrowserOnload(e) {
iframe.removeEventListener("load", panelBrowserOnload, true);
iframe.docShell.isActive = true;
iframe.docShell.isAppTab = true;
setTimeout(function() {
if (SocialShare._dynamicResizer) { // may go null if hidden quickly
SocialShare._dynamicResizer.start(iframe.parentNode, iframe);
}
}, 0);
let evt = iframe.contentDocument.createEvent("CustomEvent");
evt.initCustomEvent("OpenGraphData", true, true, JSON.stringify(pageData));
iframe.contentDocument.documentElement.dispatchEvent(evt);
}, true);
}
// always ensure that origin belongs to the endpoint
let uri = Services.io.newURI(shareEndpoint, null, null);
iframe.setAttribute("origin", provider.origin);
iframe.setAttribute("src", shareEndpoint);
let navBar = document.getElementById("nav-bar");
let anchor = navBar.getAttribute("mode") == "text" ?
document.getAnonymousElementByAttribute(this.shareButton, "class", "toolbarbutton-text") :
document.getAnonymousElementByAttribute(this.shareButton, "class", "toolbarbutton-icon");
this.panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
Social.setErrorListener(iframe, this.setErrorMessage.bind(this));
},
_generateShareEndpointURL: function(shareURL, pageData) {
// support for existing share endpoints by supporting their querystring
// arguments. parse the query string template and do replacements where
// necessary the query names may be different than ours, so we could see
// u=%{url} or url=%{url}
let [shareEndpoint, queryString] = shareURL.split("?");
let query = {};
if (queryString) {
queryString.split('&').forEach(function (val) {
let [name, value] = val.split('=');
let p = /%\{(.+)\}/.exec(value);
if (!p) {
// preserve non-template query vars
query[name] = value;
} else if (pageData[p[1]]) {
query[name] = pageData[p[1]];
} else if (p[1] == "body") {
// build a body for emailers
let body = "";
if (pageData.title)
body += pageData.title + "\n\n";
if (pageData.description)
body += pageData.description + "\n\n";
if (pageData.text)
body += pageData.text + "\n\n";
body += pageData.url;
query["body"] = body;
}
});
}
var str = [];
for (let p in query)
str.push(p + "=" + encodeURIComponent(query[p]));
if (str.length)
shareEndpoint = shareEndpoint + "?" + str.join("&");
return shareEndpoint;
}
};
SocialMark = {
// Called once, after window load, when the Social.provider object is initialized
init: function SSB_init() {
@ -598,7 +909,7 @@ SocialMark = {
return;
this.toggleURIMark(gBrowser.currentURI, aCallback)
},
toggleURIMark: function(aURI, aCallback) {
let update = function(marked) {
this._updateMarkState(marked);
@ -694,13 +1005,17 @@ SocialToolbar = {
// Called when the Social.provider changes
updateProvider: function () {
let provider = Social.provider || Social.defaultProvider;
let provider = Social.provider;
if (provider) {
this.button.setAttribute("label", provider.name);
this.button.setAttribute("tooltiptext", provider.name);
this.button.style.listStyleImage = "url(" + provider.iconURL + ")";
this.updateProfile();
} else {
this.button.setAttribute("label", gNavigatorBundle.getString("service.toolbarbutton.label"));
this.button.setAttribute("tooltiptext", gNavigatorBundle.getString("service.toolbarbutton.tooltiptext"));
this.button.style.removeProperty("list-style-image");
}
this.updateButton();
},
@ -994,11 +1309,12 @@ SocialToolbar = {
menu.removeChild(providerMenuSep.previousSibling);
}
// only show a selection if enabled and there is more than one
if (!SocialUI.enabled || Social.providers.length < 2) {
let providers = [p for (p of Social.providers) if (p.workerURL || p.sidebarURL)];
if (providers.length < 2) {
providerMenuSep.hidden = true;
return;
}
for (let provider of Social.providers) {
for (let provider of providers) {
let menuitem = document.createElement("menuitem");
menuitem.className = "menuitem-iconic social-provider-menuitem";
menuitem.setAttribute("image", provider.iconURL);

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

@ -3406,6 +3406,7 @@ function BrowserToolboxCustomizeDone(aToolboxChanged) {
XULBrowserWindow.asyncUpdateUI();
BookmarksMenuButton.updateStarState();
SocialMark.updateMarkState();
SocialShare.update();
}
TabsInTitlebar.allowedBy("customizing-toolbars", true);
@ -3880,6 +3881,7 @@ var XULBrowserWindow = {
// Update starring UI
BookmarksMenuButton.updateStarState();
SocialMark.updateMarkState();
SocialShare.update();
}
// Show or hide browser chrome based on the whitelist

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

@ -205,6 +205,19 @@
</vbox>
</panel>
<panel id="social-share-panel"
class="social-panel"
type="arrow"
orient="horizontal"
onpopupshowing="SocialShare.onShowing()"
onpopuphidden="SocialShare.onHidden()"
consumeoutsideclicks="true"
hidden="true">
<vbox class="social-share-toolbar">
<vbox id="social-share-provider-buttons" flex="1"/>
</vbox>
</panel>
<panel id="social-notification-panel"
class="social-panel"
type="arrow"
@ -704,6 +717,13 @@
onclick="BrowserGoHome(event);"
aboutHomeOverrideTooltip="&abouthome.pageTitle;"/>
<toolbarbutton id="social-share-button"
class="toolbarbutton-1 chromeclass-toolbar-additional"
hidden="true"
label="&sharePageCmd.label;"
tooltiptext="&sharePageCmd.label;"
command="Social:SharePage"/>
<toolbaritem id="social-toolbar-item"
class="chromeclass-toolbar-additional"
removable="false"
@ -741,7 +761,7 @@
label="&social.toggleNotifications.label;"
accesskey="&social.toggleNotifications.accesskey;"/>
<menuitem class="social-toggle-menuitem" command="Social:Toggle"/>
<menuseparator class="social-statusarea-separator"/>
<menuseparator/>
<menuseparator class="social-provider-menu" hidden="true"/>
<menuitem class="social-addons-menuitem" command="Social:Addons"
label="&social.addons.label;"/>

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

@ -318,6 +318,19 @@ nsContextMenu.prototype = {
}.bind(this));
}
this.showItem("context-marklink", enableLinkMark);
// SocialShare
let shareButton = SocialShare.shareButton;
let shareEnabled = shareButton && !shareButton.disabled && !this.onSocial;
let pageShare = shareEnabled && !(this.isContentSelected ||
this.onTextInput || this.onLink || this.onImage ||
this.onVideo || this.onAudio);
this.showItem("context-sharepage", pageShare);
this.showItem("context-shareselect", shareEnabled && this.isContentSelected);
this.showItem("context-sharelink", shareEnabled && (this.onLink || this.onPlainTextLink) && !this.onMailtoLink);
this.showItem("context-shareimage", shareEnabled && this.onImage);
this.showItem("context-sharevideo", shareEnabled && this.onVideo);
this.setItemAttr("context-sharevideo", "disabled", !this.mediaURL);
},
initSpellingItems: function() {
@ -1498,6 +1511,22 @@ nsContextMenu.prototype = {
SocialMark.toggleURIMark(this.linkURI);
},
shareLink: function CM_shareLink() {
SocialShare.sharePage(null, { url: this.linkURI.spec });
},
shareImage: function CM_shareImage() {
SocialShare.sharePage(null, { url: this.imageURL, previews: [ this.mediaURL ] });
},
shareVideo: function CM_shareVideo() {
SocialShare.sharePage(null, { url: this.mediaURL, source: this.mediaURL });
},
shareSelect: function CM_shareSelect(selection) {
SocialShare.sharePage(null, { url: this.browser.currentURI.spec, text: selection });
},
savePageAs: function CM_savePageAs() {
saveDocument(this.browser.contentDocument);
},

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

@ -120,7 +120,7 @@
</implementation>
<handlers>
<handler event="focus">
<handler event="focus" phase="capturing">
this.parentNode.selectedChat = this;
</handler>
<handler event="DOMTitleChanged"><![CDATA[
@ -155,10 +155,10 @@
<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>
<xul:spacer flex="1" anonid="spacer" class="chatbar-overflow-spacer"/>
<children/>
</xul:hbox>
</content>

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

@ -32,6 +32,7 @@ _BROWSER_FILES = \
browser_social_window.js \
social_activate.html \
social_activate_iframe.html \
browser_share.js \
social_panel.html \
social_mark_image.png \
social_sidebar.html \
@ -39,6 +40,7 @@ _BROWSER_FILES = \
social_flyout.html \
social_window.html \
social_worker.js \
share.html \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,140 @@
let baseURL = "https://example.com/browser/browser/base/content/test/social/";
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",
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
iconURL: "https://example.com/browser/browser/base/content/test/moz.png",
shareURL: "https://example.com/browser/browser/base/content/test/social/share.html"
};
runSocialTestWithProvider(manifest, function (finishcb) {
runSocialTests(tests, undefined, undefined, finishcb);
});
}
let corpus = [
{
url: baseURL+"opengraph/opengraph.html",
options: {
// og:title
title: ">This is my title<",
// og:description
description: "A test corpus file for open graph tags we care about",
//medium: this.getPageMedium(),
//source: this.getSourceURL(),
// og:url
url: "https://www.mozilla.org/",
//shortUrl: this.getShortURL(),
// og:image
previews:["https://www.mozilla.org/favicon.png"],
// og:site_name
siteName: ">My simple test page<"
}
},
{
// tests that og:url doesn't override the page url if it is bad
url: baseURL+"opengraph/og_invalid_url.html",
options: {
description: "A test corpus file for open graph tags passing a bad url",
url: baseURL+"opengraph/og_invalid_url.html",
previews: [],
siteName: "Evil chrome delivering website"
}
},
{
url: baseURL+"opengraph/shorturl_link.html",
options: {
previews: ["http://example.com/1234/56789.jpg"],
url: "http://www.example.com/photos/56789/",
shortUrl: "http://imshort/p/abcde"
}
},
{
url: baseURL+"opengraph/shorturl_linkrel.html",
options: {
previews: ["http://example.com/1234/56789.jpg"],
url: "http://www.example.com/photos/56789/",
shortUrl: "http://imshort/p/abcde"
}
},
{
url: baseURL+"opengraph/shortlink_linkrel.html",
options: {
previews: ["http://example.com/1234/56789.jpg"],
url: "http://www.example.com/photos/56789/",
shortUrl: "http://imshort/p/abcde"
}
}
];
function loadURLInTab(url, callback) {
info("Loading tab with "+url);
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
tab.linkedBrowser.addEventListener("load", function listener() {
is(tab.linkedBrowser.currentURI.spec, url, "tab loaded")
tab.linkedBrowser.removeEventListener("load", listener, true);
callback(tab);
}, true);
}
function hasoptions(testOptions, options) {
let msg;
for (let option in testOptions) {
let data = testOptions[option];
info("data: "+JSON.stringify(data));
let message_data = options[option];
info("message_data: "+JSON.stringify(message_data));
if (Array.isArray(data)) {
// the message may have more array elements than we are testing for, this
// is ok since some of those are hard to test. So we just test that
// anything in our test data IS in the message.
ok(Array.every(data, function(item) { return message_data.indexOf(item) >= 0 }), "option "+option);
} else {
is(message_data, data, "option "+option);
}
}
}
var tests = {
testSharePage: function(next) {
let panel = document.getElementById("social-flyout-panel");
let port = Social.provider.getWorkerPort();
ok(port, "provider has a port");
let testTab;
let testIndex = 0;
let testData = corpus[testIndex++];
function runOneTest() {
loadURLInTab(testData.url, function(tab) {
testTab = tab;
SocialShare.sharePage();
});
}
port.onmessage = function (e) {
let topic = e.data.topic;
switch (topic) {
case "got-sidebar-message":
// open a tab with share data, then open the share panel
runOneTest();
break;
case "got-share-data-message":
gBrowser.removeTab(testTab);
hasoptions(testData.options, e.data.result);
testData = corpus[testIndex++];
if (testData) {
runOneTest();
} else {
next();
}
break;
}
}
port.postMessage({topic: "test-init"});
}
}

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

@ -65,12 +65,16 @@ function startTestAndWaitForSidebar(callback) {
let topic = e.data.topic;
switch (topic) {
case "got-sidebar-message":
// if sidebar loaded too fast, we need a backup ping
case "got-isVisible-response":
isSidebarLoaded = true;
maybeCallback();
break;
case "test-init-done":
if (isSidebarLoaded)
maybeCallback();
else
port.postMessage({topic: "test-isVisible"});
break;
}
}
@ -102,7 +106,7 @@ function test() {
// tab.linkedBrowser.contentWindow.focus()
// but instead we must do:
tab.linkedBrowser.contentDocument.getElementById("theinput").focus();
cb();
waitForCondition(function() isTabFocused(), cb, "tab should have focus");
}
let postSubTest = function(cb) {
window.SocialChatBar.chatbar.removeAll();
@ -138,10 +142,12 @@ var tests = {
ok(isTabFocused(), "tab should still be focused");
// re-request the same chat via user event.
openChatViaUser();
is(SocialChatBar.chatbar.childElementCount, 1, "still exactly 1 chat open");
// should now be focused
ok(isChatFocused(SocialChatBar.chatbar.firstElementChild), "chat should be focused");
next();
waitForCondition(function() isChatFocused(SocialChatBar.chatbar.selectedChat),
function() {
is(SocialChatBar.chatbar.childElementCount, 1, "still exactly 1 chat open");
is(SocialChatBar.chatbar.selectedChat, SocialChatBar.chatbar.firstElementChild, "chat should be selected");
next();
}, "chat should be focused");
});
});
});
@ -153,8 +159,11 @@ var tests = {
startTestAndWaitForSidebar(function(port) {
openChatViaUser();
ok(SocialChatBar.chatbar.firstElementChild, "chat opened");
ok(isChatFocused(SocialChatBar.chatbar.firstElementChild), "chat should be focused");
next();
waitForCondition(function() isChatFocused(SocialChatBar.chatbar.selectedChat),
function() {
is(SocialChatBar.chatbar.selectedChat, SocialChatBar.chatbar.firstElementChild, "chat is selected");
next();
}, "chat should be focused");
});
},
@ -168,10 +177,14 @@ var tests = {
openChatViaWorkerMessage(port, chatUrl, function() {
is(chatbar.childElementCount, 1, "exactly 1 chat open");
ok(chatbar.firstElementChild.minimized, "chat is minimized");
// bug 865086 opening minimized still sets the window as selected
todo(chatbar.selectedChat != chatbar.firstElementChild, "chat is not selected");
ok(isTabFocused(), "tab should be focused");
openChatViaSidebarMessage(port, {stealFocus: 1, id: 1}, function() {
is(chatbar.childElementCount, 1, "still 1 chat open");
ok(!chatbar.firstElementChild.minimized, "chat no longer minimized");
// bug 865086 because we marked it selected on open, it still is
todo(chatbar.selectedChat != chatbar.firstElementChild, "chat is not selected");
ok(isTabFocused(), "tab should still be focused");
next();
});
@ -192,9 +205,13 @@ var tests = {
ok(isTabFocused(), "tab should still be focused");
// pretend we clicked on the titlebar
chatbox.onTitlebarClick({button: 0});
ok(!chatbox.minimized, "chat should have been restored");
ok(isChatFocused(chatbox), "chat should be focused");
next();
waitForCondition(function() isChatFocused(SocialChatBar.chatbar.selectedChat),
function() {
ok(!chatbox.minimized, "chat should have been restored");
ok(isChatFocused(chatbox), "chat should be focused");
is(chatbox, SocialChatBar.chatbar.selectedChat, "chat is marked selected");
next();
}, "chat should have focus");
});
});
},
@ -211,11 +228,19 @@ var tests = {
let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
chatbar.selectedChat = chat1;
chatbar.focus();
ok(isChatFocused(chat1), "first chat should be focused");
chat1.minimized = true;
// minimizing the chat with focus should give it to another.
ok(isChatFocused(chat2), "second chat should be focused");
next();
waitForCondition(function() isChatFocused(chat1),
function() {
is(chat1, SocialChatBar.chatbar.selectedChat, "chat1 is marked selected");
isnot(chat2, SocialChatBar.chatbar.selectedChat, "chat2 is not marked selected");
chat1.minimized = true;
waitForCondition(function() isChatFocused(chat2),
function() {
// minimizing the chat with focus should give it to another.
isnot(chat1, SocialChatBar.chatbar.selectedChat, "chat1 is not marked selected");
is(chat2, SocialChatBar.chatbar.selectedChat, "chat2 is marked selected");
next();
}, "chat2 should have focus");
}, "chat1 should have focus");
});
});
});
@ -269,30 +294,32 @@ var tests = {
let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
chatbar.selectedChat = chat2;
chatbar.focus();
ok(isChatFocused(chat2), "new chat is focused");
// Our chats have 3 focusable elements, so it takes 4 TABs to move
// to the new chat.
sendTabAndWaitForFocus(chat2, "input1", function() {
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input1",
"first input field has focus");
ok(isChatFocused(chat2), "new chat still focused after first tab");
sendTabAndWaitForFocus(chat2, "input2", function() {
ok(isChatFocused(chat2), "new chat still focused after tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"second input field has focus");
sendTabAndWaitForFocus(chat2, "iframe", function() {
waitForCondition(function() isChatFocused(chatbar.selectedChat),
function() {
// Our chats have 3 focusable elements, so it takes 4 TABs to move
// to the new chat.
sendTabAndWaitForFocus(chat2, "input1", function() {
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input1",
"first input field has focus");
ok(isChatFocused(chat2), "new chat still focused after first tab");
sendTabAndWaitForFocus(chat2, "input2", function() {
ok(isChatFocused(chat2), "new chat still focused after tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "iframe",
"iframe has focus");
// this tab now should move to the next chat, but focus the
// document element itself (hence the null eltid)
sendTabAndWaitForFocus(chat1, null, function() {
ok(isChatFocused(chat1), "first chat is focused");
next();
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"second input field has focus");
sendTabAndWaitForFocus(chat2, "iframe", function() {
ok(isChatFocused(chat2), "new chat still focused after tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "iframe",
"iframe has focus");
// this tab now should move to the next chat, but focus the
// document element itself (hence the null eltid)
sendTabAndWaitForFocus(chat1, null, function() {
ok(isChatFocused(chat1), "first chat is focused");
next();
});
});
});
});
});
}, "chat should have focus");
});
});
});
@ -310,17 +337,24 @@ var tests = {
chat.addEventListener("DOMContentLoaded", function DOMContentLoaded() {
chat.removeEventListener("DOMContentLoaded", DOMContentLoaded);
chat.iframe.contentDocument.getElementById("input2").focus();
is(chat.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"correct input field has focus");
// set focus to the tab.
let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
Services.focus.moveFocus(tabb.contentWindow, null, Services.focus.MOVEFOCUS_ROOT, 0);
ok(isTabFocused(), "tab took focus");
chatbar.focus();
ok(isChatFocused(chat), "chat took focus");
is(chat.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"correct input field still has focus");
next();
waitForCondition(function() isChatFocused(chat),
function() {
is(chat.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"correct input field has focus");
// set focus to the tab.
let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
Services.focus.moveFocus(tabb.contentWindow, null, Services.focus.MOVEFOCUS_ROOT, 0);
waitForCondition(function() isTabFocused(),
function() {
chatbar.focus();
waitForCondition(function() isChatFocused(chat),
function() {
is(chat.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"correct input field still has focus");
next();
}, "chat took focus");
}, "tab has focus");
}, "chat took focus");
});
});
},

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

@ -49,7 +49,16 @@ var tests = {
observeProviderSet(function () {
waitForProviderLoad(function() {
checkUIStateMatchesProvider(gProviders[1]);
next();
// disable social, click on the provider menuitem to switch providers
Social.enabled = false;
let menu = document.getElementById("social-statusarea-popup");
let el = menu.getElementsByAttribute("origin", gProviders[0].origin);
is(el.length, 1, "selected provider menu item exists");
el[0].click();
waitForProviderLoad(function() {
checkUIStateMatchesProvider(gProviders[0]);
next();
});
});
});
Social.activateFromOrigin("https://test1.example.com");

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

@ -190,8 +190,13 @@ function checkSocialUI(win) {
isbool(!win.SocialMark.button.hidden, markVisible, "SocialMark button visible?");
isbool(!win.SocialMark.button.disabled, canMark, "SocialMark button enabled?");
isbool(!doc.getElementById("social-toolbar-item").hidden, active, "toolbar items visible?");
if (active)
is(win.SocialToolbar.button.style.listStyleImage, 'url("' + Social.defaultProvider.iconURL + '")', "toolbar button has provider icon");
if (active) {
if (!enabled) {
ok(!win.SocialToolbar.button.style.listStyleImage, "toolbar button is default icon");
} else {
is(win.SocialToolbar.button.style.listStyleImage, 'url("' + Social.defaultProvider.iconURL + '")', "toolbar button has provider icon");
}
}
// the menus should always have the provider name
if (provider) {
for (let id of ["menu_socialSidebar", "menu_socialAmbientMenu"])

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

@ -4,3 +4,4 @@
# 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/.
DIRS += ['opengraph']

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

@ -0,0 +1,24 @@
# 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/.
DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
_BROWSER_FILES = \
opengraph.html \
og_invalid_url.html \
shortlink_linkrel.html \
shorturl_link.html \
shorturl_linkrel.html \
$(NULL)
include $(topsrcdir)/config/rules.mk
libs:: $(_BROWSER_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)

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

@ -1,6 +1,4 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.

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

@ -0,0 +1,11 @@
<html xmlns:og="http://ogp.me/ns#">
<head>
<meta property="og:url" content="chrome://browser/content/aboutDialog.xul"/>
<meta property="og:site_name" content="Evil chrome delivering website"/>
<meta property="og:description"
content="A test corpus file for open graph tags passing a bad url"/>
</head>
<body>
Open Graph Test Page
</body>
</html>

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

@ -0,0 +1,13 @@
<html xmlns:og="http://ogp.me/ns#">
<head>
<meta property="og:title" content="&gt;This is my title&lt;"/>
<meta property="og:url" content="https://www.mozilla.org"/>
<meta property="og:image" content="https://www.mozilla.org/favicon.png"/>
<meta property="og:site_name" content="&#62;My simple test page&#60;"/>
<meta property="og:description"
content="A test corpus file for open graph tags we care about"/>
</head>
<body>
Open Graph Test Page
</body>
</html>

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

@ -0,0 +1,10 @@
<html>
<head>
<link rel="image_src" href="http://example.com/1234/56789.jpg" id="image-src" />
<link id="canonicalurl" rel="canonical" href="http://www.example.com/photos/56789/" />
<link rel="shortlink" href="http://imshort/p/abcde" />
</head>
<body>
link[rel='shortlink']
</body>
</html>

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

@ -0,0 +1,10 @@
<html>
<head>
<link rel="image_src" href="http://example.com/1234/56789.jpg" id="image-src" />
<link id="canonicalurl" rel="canonical" href="http://www.example.com/photos/56789/" />
<link id="shorturl" rev="canonical" type="text/html" href="http://imshort/p/abcde" />
</head>
<body>
link id="shorturl"
</body>
</html>

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

@ -0,0 +1,25 @@
<html>
<head>
<title>Test Image</title>
<meta name="description" content="Iron man in a tutu" />
<meta name="title" content="Test Image" />
<meta name="medium" content="image" />
<link rel="image_src" href="http://example.com/1234/56789.jpg" id="image-src" />
<link id="canonicalurl" rel="canonical" href="http://www.example.com/photos/56789/" />
<link id="shorturl" href="http://imshort/p/abcde" />
<meta property="og:title" content="TestImage" />
<meta property="og:type" content="photos:photo" />
<meta property="og:url" content="http://www.example.com/photos/56789/" />
<meta property="og:site_name" content="My Photo Site" />
<meta property="og:description" content="Iron man in a tutu" />
<meta property="og:image" content="http://example.com/1234/56789.jpg" />
<meta property="og:image:width" content="480" />
<meta property="og:image:height" content="640" />
</head>
<body>
link[rel='shorturl']
</body>
</html>

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

@ -0,0 +1,18 @@
<html>
<head>
<meta charset="utf-8">
<script>
var shareData;
addEventListener("OpenGraphData", function(e) {
shareData = JSON.parse(e.detail);
var port = navigator.mozSocial.getWorker().port;
port.postMessage({topic: "share-data-message", result: shareData});
// share windows self-close
window.close();
})
</script>
</head>
<body>
<p>This is a test social share window.</p>
</body>
</html>

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

@ -133,6 +133,10 @@ onconnect = function(e) {
case "test-isVisible-response":
testPort.postMessage({topic: "got-isVisible-response", result: event.data.result});
break;
case "share-data-message":
if (testPort)
testPort.postMessage({topic:"got-share-data-message", result: event.data.result});
break;
}
}
}

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

@ -12,6 +12,8 @@ include $(DEPTH)/config/autoconf.mk
MOCHITEST_BROWSER_FILES = \
head.js \
browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js \
browser_privatebrowsing_aboutSessionRestore.js \
browser_privatebrowsing_certexceptionsui.js \
browser_privatebrowsing_concurrent.js \
browser_privatebrowsing_concurrent_page.html \
@ -32,6 +34,7 @@ MOCHITEST_BROWSER_FILES = \
browser_privatebrowsing_localStorage_page1.html \
browser_privatebrowsing_localStorage_page2.html \
browser_privatebrowsing_nonbrowser.js \
browser_privatebrowsing_noSessionRestoreMenuOption.js \
browser_privatebrowsing_opendir.js \
browser_privatebrowsing_openlocation.js \
browser_privatebrowsing_openLocationLastURL.js \

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

@ -0,0 +1,46 @@
/* 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/. */
// This test checks that the Session Restore about:home button
// is disabled in private mode
function test() {
waitForExplicitFinish();
function testNoSessionRestoreButton() {
let win = OpenBrowserWindow({private: true});
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
executeSoon(function() {
info("The second private window got loaded");
let newTab = win.gBrowser.addTab("about:home");
win.gBrowser.selectedTab = newTab;
let tabBrowser = win.gBrowser.getBrowserForTab(newTab);
tabBrowser.addEventListener("load", function tabLoadListener() {
tabBrowser.removeEventListener("load", tabLoadListener, true);
executeSoon(function() {
info("about:home got loaded");
let sessionRestoreButton = win.gBrowser
.contentDocument
.getElementById("restorePreviousSession");
is(win.getComputedStyle(sessionRestoreButton).display,
"none", "The Session Restore about:home button should be disabled");
win.close();
finish();
});
}, true);
});
}, false);
}
let win = OpenBrowserWindow({private: true});
win.addEventListener("load", function onload() {
win.removeEventListener("load", onload, false);
executeSoon(function() {
info("The first private window got loaded");
win.close();
testNoSessionRestoreButton();
});
}, false);
}

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

@ -0,0 +1,45 @@
/* 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/. */
// This test checks that the session restore button from about:sessionrestore
// is disabled in private mode
function test() {
waitForExplicitFinish();
function testNoSessionRestoreButton() {
let win = OpenBrowserWindow({private: true});
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
executeSoon(function() {
info("The second private window got loaded");
let newTab = win.gBrowser.addTab("about:sessionrestore");
win.gBrowser.selectedTab = newTab;
let tabBrowser = win.gBrowser.getBrowserForTab(newTab);
tabBrowser.addEventListener("load", function tabLoadListener() {
tabBrowser.removeEventListener("load", tabLoadListener, true);
executeSoon(function() {
info("about:sessionrestore got loaded");
let restoreButton = win.gBrowser.contentDocument
.getElementById("errorTryAgain");
ok(restoreButton.disabled,
"The Restore about:sessionrestore button should be disabled");
win.close();
finish();
});
}, true);
});
}, false);
}
let win = OpenBrowserWindow({private: true});
win.addEventListener("load", function onload() {
win.removeEventListener("load", onload, false);
executeSoon(function() {
info("The first private window got loaded");
win.close();
testNoSessionRestoreButton();
});
}, false);
}

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

@ -0,0 +1,34 @@
/* 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/. */
// This test checks that the Session Restore menu option is not enabled in private mode
function test() {
waitForExplicitFinish();
function testNoSessionRestoreMenuItem() {
let win = OpenBrowserWindow({private: true});
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
ok(true, "The second private window got loaded");
let srCommand = win.document.getElementById("Browser:RestoreLastSession");
ok(srCommand, "The Session Restore command should exist");
is(PrivateBrowsingUtils.isWindowPrivate(win), true,
"PrivateBrowsingUtils should report the correct per-window private browsing status");
is(srCommand.hasAttribute("disabled"), true,
"The Session Restore command should be disabled in private browsing mode");
win.close();
finish();
}, false);
}
let win = OpenBrowserWindow({private: true});
win.addEventListener("load", function onload() {
win.removeEventListener("load", onload, false);
ok(true, "The first private window got loaded");
win.gBrowser.addTab("about:mozilla");
win.close();
testNoSessionRestoreMenuItem();
}, false);
}

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

@ -0,0 +1,25 @@
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding
. $topsrcdir/build/unix/mozconfig.linux32
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
# PGO
mk_add_options MOZ_PGO=1
mk_add_options PROFILE_GEN_SCRIPT='EXTRA_TEST_ARGS=10 $(MAKE) -C $(MOZ_OBJDIR) pgo-profile-run'
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

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

@ -1,25 +1,7 @@
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding
# This make file should be identical to the beta mozconfig, apart from the
# safeguard below
. "$topsrcdir/browser/config/mozconfigs/linux32/beta"
. $topsrcdir/build/unix/mozconfig.linux32
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
# PGO
mk_add_options MOZ_PGO=1
mk_add_options PROFILE_GEN_SCRIPT='EXTRA_TEST_ARGS=10 $(MAKE) -C $(MOZ_OBJDIR) pgo-profile-run'
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"
# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
# defines.sh during the beta cycle
export BUILDING_RELEASE=1

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

@ -0,0 +1,25 @@
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding
. $topsrcdir/build/unix/mozconfig.linux
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
# PGO
mk_add_options MOZ_PGO=1
mk_add_options PROFILE_GEN_SCRIPT='EXTRA_TEST_ARGS=10 $(MAKE) -C $(MOZ_OBJDIR) pgo-profile-run'
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

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

@ -1,25 +1,7 @@
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding
# This make file should be identical to the beta mozconfig, apart from the
# safeguard below
. "$topsrcdir/browser/config/mozconfigs/linux64/beta"
. $topsrcdir/build/unix/mozconfig.linux
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
# PGO
mk_add_options MOZ_PGO=1
mk_add_options PROFILE_GEN_SCRIPT='EXTRA_TEST_ARGS=10 $(MAKE) -C $(MOZ_OBJDIR) pgo-profile-run'
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"
# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
# defines.sh during the beta cycle
export BUILDING_RELEASE=1

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

@ -0,0 +1,21 @@
. $topsrcdir/build/macosx/universal/mozconfig
# Universal builds override the default of browser (bug 575283 comment 29)
ac_add_options --enable-application=browser
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

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

@ -1,21 +1,7 @@
. $topsrcdir/build/macosx/universal/mozconfig
# This make file should be identical to the beta mozconfig, apart from the
# safeguard below
. "$topsrcdir/browser/config/mozconfigs/macosx-universal/beta"
# Universal builds override the default of browser (bug 575283 comment 29)
ac_add_options --enable-application=browser
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"
# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
# defines.sh during the beta cycle
export BUILDING_RELEASE=1

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

@ -0,0 +1,33 @@
. "$topsrcdir/browser/config/mozconfigs/common"
# for pgo
mk_add_options MOZ_PGO=1
mk_add_options PROFILE_GEN_SCRIPT='$(MAKE) -C $(MOZ_OBJDIR) pgo-profile-run'
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-jemalloc
ac_add_options --enable-official-branding
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
else
. $topsrcdir/build/win32/mozconfig.vs2010
fi
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

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

@ -1,33 +1,7 @@
. "$topsrcdir/browser/config/mozconfigs/common"
# This make file should be identical to the beta mozconfig, apart from the
# safeguard below
. "$topsrcdir/browser/config/mozconfigs/win32/beta"
# for pgo
mk_add_options MOZ_PGO=1
mk_add_options PROFILE_GEN_SCRIPT='$(MAKE) -C $(MOZ_OBJDIR) pgo-profile-run'
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-jemalloc
ac_add_options --enable-official-branding
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
else
. $topsrcdir/build/win32/mozconfig.vs2010
fi
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"
# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
# defines.sh during the beta cycle
export BUILDING_RELEASE=1

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

@ -1 +1,2 @@
Content-Type: text/cache-manifest; charset=ISO-8859-1
Last-Modified: Tue, 23 Apr 9998 11:41:13 GMT

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

@ -1 +1,2 @@
Content-Type: text/cache-manifest
Last-Modified: Tue, 23 Apr 9998 11:41:13 GMT

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

@ -15,7 +15,6 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_clean-exit.js \
browser_dbg_cmd.js \
$(browser_dbg_cmd_break.js disabled until bug 722727 is fixed) \
browser_dbg_createChrome.js \
$(browser_dbg_createRemote.js disabled for intermittent failures, bug 753225) \
browser_dbg_debuggerstatement.js \
browser_dbg_listtabs.js \
@ -138,6 +137,14 @@ MOCHITEST_BROWSER_PAGES = \
test-location-changes-bp.html \
$(NULL)
ifneq (Linux,$(OS_ARCH))
MOCHITEST_BROWSER_TESTS += \
browser_dbg_createChrome.js \
$(NULL)
else
$(browser_dbg_createChrome.js disabled to fix for ubuntu hangs, bug 847558)
endif
MOCHITEST_BROWSER_FILES_PARTS = MOCHITEST_BROWSER_TESTS MOCHITEST_BROWSER_PAGES
include $(topsrcdir)/config/rules.mk

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

@ -116,6 +116,17 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY bookmarkThisPageCmd.label "Bookmark This Page">
<!ENTITY bookmarkThisPageCmd.commandkey "d">
<!ENTITY markPageCmd.commandkey "l">
<!ENTITY sharePageCmd.label "Share This Page">
<!ENTITY sharePageCmd.commandkey "S">
<!ENTITY sharePageCmd.accesskey "s">
<!ENTITY shareLinkCmd.label "Share This Link">
<!ENTITY shareLinkCmd.accesskey "s">
<!ENTITY shareImageCmd.label "Share This Image">
<!ENTITY shareImageCmd.accesskey "s">
<!ENTITY shareSelectCmd.label "Share Selection">
<!ENTITY shareSelectCmd.accesskey "s">
<!ENTITY shareVideoCmd.label "Share This Video">
<!ENTITY shareVideoCmd.accesskey "s">
<!ENTITY subscribeToPageMenupopup.label "Subscribe to This Page">
<!ENTITY subscribeToPageMenuitem.label "Subscribe to This Page…">
<!ENTITY addCurPagesCmd.label "Bookmark All Tabs…">

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

@ -375,6 +375,9 @@ fullscreen.entered=%S is now fullscreen.
# LOCALIZATION NOTE (fullscreen.rememberDecision): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
fullscreen.rememberDecision=Remember decision for %S
service.toolbarbutton.label=Services
service.toolbarbutton.tooltiptext=Services
# LOCALIZATION NOTE (social.install.description): %1$S is the hostname of the social provider, %2$S is brandShortName (e.g. Firefox)
service.install.description=Would you like to enable services from %1$S to display in your %2$S toolbar and sidebar?
service.install.ok.label=Enable Services

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

@ -10,6 +10,10 @@ Components.utils.import("resource://services-sync/main.js");
* Wraps a list/grid control implementing nsIDOMXULSelectControlElement and
* fills it with the user's synced tabs.
*
* Note, the Sync module takes care of initializing the sync service. We should
* not make calls that start sync or sync tabs since this module loads really
* early during startup.
*
* @param aSet Control implementing nsIDOMXULSelectControlElement.
* @param aSetUIAccess The UI element that should be hidden when Sync is
* disabled. Must sanely support 'hidden' attribute.
@ -22,13 +26,10 @@ function RemoteTabsView(aSet, aSetUIAccess) {
// Sync uses special voodoo observers.
// If you want to change this code, talk to the fx-si team
Weave.Svc.Obs.add("weave:service:setup-complete", this);
Weave.Svc.Obs.add("weave:service:sync:finish", this);
Weave.Svc.Obs.add("weave:service:start-over", this);
if (this.isSyncEnabled() ) {
this.populateTabs();
this.populateGrid();
this.setUIAccessVisible(true);
}
else {
this.setUIAccessVisible(false);
@ -46,10 +47,6 @@ RemoteTabsView.prototype = {
observe: function(subject, topic, data) {
switch (topic) {
case "weave:service:setup-complete":
this.populateTabs();
this.setUIAccessVisible(true);
break;
case "weave:service:sync:finish":
this.populateGrid();
break;
@ -72,7 +69,7 @@ RemoteTabsView.prototype = {
// Clear grid, We don't know what has happened to tabs since last sync
// Also can result in duplicate tabs(bug 864614)
this._set.clearAll();
let show = false;
for (let [guid, client] in Iterator(tabsEngine.getAllClients())) {
client.tabs.forEach(function({title, urlHistory, icon}) {
let url = urlHistory[0];
@ -80,6 +77,7 @@ RemoteTabsView.prototype = {
return;
}
seenURLs.add(url);
show = true;
// If we wish to group tabs by client, we should be looking for records
// of {type:client, clientName, class:{mobile, desktop}} and will
@ -90,14 +88,10 @@ RemoteTabsView.prototype = {
}, this);
}
},
populateTabs: function populateTabs() {
Weave.Service.scheduler.scheduleNextSync(0);
this.setUIAccessVisible(show);
},
destruct: function destruct() {
Weave.Svc.Obs.remove("weave:service:setup-complete", this);
Weave.Svc.Obs.remove("weave:engine:sync:finish", this);
Weave.Svc.Obs.remove("weave:service:logout:start-over", this);
},

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

@ -257,7 +257,6 @@ TopSitesView.prototype = {
case "MozAppbarDismissing":
// clean up when the context appbar is dismissed - we don't remember selections
this._lastSelectedSites = null;
this._set.clearSelection();
}
},

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

@ -1,3 +1,8 @@
/* 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";
var Appbar = {
get appbar() { return document.getElementById('appbar'); },
get consoleButton() { return document.getElementById('console-button'); },
@ -13,6 +18,7 @@ var Appbar = {
init: function Appbar_init() {
window.addEventListener('MozAppbarShowing', this, false);
window.addEventListener('MozAppbarDismissing', this, false);
window.addEventListener('MozPrecisePointer', this, false);
window.addEventListener('MozImprecisePointer', this, false);
window.addEventListener('MozContextActionsChange', this, false);
@ -40,6 +46,13 @@ var Appbar = {
this._updatePinButton();
this._updateStarButton();
break;
case 'MozAppbarDismissing':
if (this.activeTileset) {
this.activeTileset.clearSelection();
}
this.clearContextualActions();
this.activeTileset = null;
break;
case 'MozPrecisePointer':
case 'MozImprecisePointer':
this._updateZoomButtons();
@ -162,7 +175,8 @@ var Appbar = {
}
}
},
showContextualActions: function(aVerbs){
showContextualActions: function(aVerbs) {
let doc = document;
// button element id to action verb lookup
let buttonsMap = new Map();
@ -195,6 +209,11 @@ var Appbar = {
}
});
},
clearContextualActions: function() {
this.showContextualActions([]);
},
_onTileSelectionChanged: function _onTileSelectionChanged(aEvent){
let activeTileset = aEvent.target;

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

@ -0,0 +1,23 @@
<?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/. -->
<bindings
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="cssthrobberBinding" extends="xul:box">
<content>
<html:div class="progressContainer">
<html:div class="progressBall progressBall" />
<html:div class="progressBall progressBall" />
<html:div class="progressBall progressBall" />
<html:div class="progressBall progressBall" />
<html:div class="progressBall progressBall" />
</html:div>
</content>
</binding>
</bindings>

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

@ -354,14 +354,7 @@ BookmarksView.prototype = {
for (let bookmarkId of this._toRemove) {
this._bookmarkService.removeItem(bookmarkId);
}
this._toRemove = null;
this._set.clearSelection();
// Clear context app bar
let event = document.createEvent("Events");
event.initEvent("MozContextActionsChange", true, false);
this._set.dispatchEvent(event);
}
break;

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

@ -134,7 +134,7 @@ let ScriptContexts = {};
["SSLExceptions", "chrome://browser/content/exceptions.js"],
["ItemPinHelper", "chrome://browser/content/helperui/ItemPinHelper.js"],
#ifdef MOZ_SERVICES_SYNC
["WeaveGlue", "chrome://browser/content/sync.js"],
["Sync", "chrome://browser/content/sync.js"],
["SyncPairDevice", "chrome://browser/content/sync.js"],
["RemoteTabsView", "chrome://browser/content/RemoteTabs.js"],
["RemoteTabsPanelView", "chrome://browser/content/RemoteTabs.js"],

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

@ -77,6 +77,7 @@ var BrowserUI = {
get _back() { return document.getElementById("cmd_back"); },
get _forward() { return document.getElementById("cmd_forward"); },
lastKnownGoodURL: "", //used when the user wants to escape unfinished url entry
init: function() {
// listen content messages
messageManager.addMessageListener("DOMTitleChanged", this);
@ -147,7 +148,7 @@ var BrowserUI = {
FindHelperUI.init();
PdfJs.init();
#ifdef MOZ_SERVICES_SYNC
WeaveGlue.init();
Sync.init();
#endif
} catch(ex) {
Util.dumpLn("Exception in delay load module:", ex.message);
@ -642,6 +643,7 @@ var BrowserUI = {
_setURI: function _setURI(aURL) {
this._edit.value = aURL;
this.lastKnownGoodURL = aURL;
},
_urlbarClicked: function _urlbarClicked() {
@ -727,6 +729,7 @@ var BrowserUI = {
aEvent.preventDefault();
if (this._edit.popupOpen) {
this._edit.value = this.lastKnownGoodURL;
this._edit.closePopup();
StartUI.hide();
ContextUI.dismiss();
@ -747,8 +750,9 @@ var BrowserUI = {
}
// Check open modal elements
if (DialogUI.modals.length > 0)
if (DialogUI.modals.length > 0) {
return;
}
// Check open panel
if (PanelUI.isVisible) {
@ -1041,7 +1045,7 @@ var BrowserUI = {
break;
case "cmd_remoteTabs":
if (Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED) {
WeaveGlue.open();
Sync.open();
} else {
PanelUI.show("remotetabs-container");
}
@ -1478,7 +1482,7 @@ var SyncPanelUI = {
Elements.syncFlyout.addEventListener("PopupChanged", function onShow(aEvent) {
if (aEvent.detail && aEvent.target === Elements.syncFlyout) {
Elements.syncFlyout.removeEventListener("PopupChanged", onShow, false);
WeaveGlue.init();
Sync.init();
}
}, false);
}

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

@ -30,6 +30,10 @@ flyoutpanel {
-moz-binding: url('chrome://browser/content/bindings/flyoutpanel.xml#flyoutpanelBinding');
}
cssthrobber {
-moz-binding: url('chrome://browser/content/bindings/cssthrobber.xml#cssthrobberBinding');
}
settings {
-moz-binding: url("chrome://mozapps/content/extensions/setting.xml#settings");
}

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

@ -8,6 +8,7 @@
<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/forms.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/cssthrobber.css" type="text/css"?>
<!DOCTYPE window [
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
@ -284,7 +285,7 @@
<scrollbox id="snapped-scrollbox" orient="vertical" flex="1">
<vbox id="snapped-topsites">
<label class="meta-section-title" value="&startTopSitesHeader.label;"/>
<richgrid id="snapped-topsites-grid" rows="8" columns="1" flex="1"/>
<richgrid id="snapped-topsites-grid" class="canSnapTiles" rows="8" columns="1" flex="1"/>
</vbox>
<label class="meta-section-title" value="&startBookmarksHeader.label;"
onclick="PanelUI.show('bookmarks-container');"/>
@ -401,19 +402,37 @@
</flyoutpanel>
<flyoutpanel id="sync-flyoutpanel" headertext="&syncHeader.title;">
<setting id="sync-connect" title="&sync.notconnected;" type="control">
<button label="&sync.connect;" oncommand="WeaveGlue.tryConnect();" />
<description>&sync.setup.description;</description>
<description id="sync-accountinfo" collapsed="true"></description>
<description id="sync-lastsync" collapsed="true"></description>
<description id="sync-errordescription" collapsed="true"></description>
<setting id="sync-connect" type="control" collapsed="true">
<button label="&sync.setupbutton.label;" oncommand="Sync.tryConnect();" />
</setting>
<setting id="sync-connected" class="setting-group" title="&sync.connected;" type="control" collapsed="true">
<setting id="sync-connected" class="setting-group" type="control" collapsed="true">
<button id="sync-pairdevice" label="&sync.pair.button;" oncommand="SyncPairDevice.open();" />
</setting>
<setting id="sync-sync" class="setting-subgroup" type="control" collapsed="true">
<button id="sync-syncButton" label="&sync.syncNow2;" oncommand="WeaveGlue.sync();"/>
</setting>
<setting id="sync-device" class="setting-subgroup" type="string" title="&sync.deviceName;" onchange="WeaveGlue.changeName(this);" collapsed="true"/>
<setting id="sync-device" class="setting-subgroup" type="string" title="&sync.deviceName;" onchange="Sync.changeName(this);" collapsed="true"/>
<setting id="sync-disconnect" class="setting-subgroup" type="control" collapsed="true">
<button label="&sync.disconnect;" oncommand="WeaveGlue.disconnect();" />
<button label="&sync.removebutton.label;" oncommand="Sync.onDisconnect();" />
</setting>
<vbox id="sync-disconnectwarnpanel" collapsed="true">
<description id="sync-disconnectwarntitle"></description>
<description id="sync-disconnectwarnmsg">&sync.removewarn.note;</description>
<hbox>
<spacer flex="1" />
<button label="&sync.setup.cancel;" oncommand="Sync.onCancelDisconnect();" />
<button label="&sync.setup.remove;" oncommand="Sync.disconnect();" />
</hbox>
</vbox>
<vbox id="sync-disconnectthrobber" collapsed="true">
<hbox>
<spacer flex="1" />
<cssthrobber id="syncdisconnectthrobber" />
<label>&sync.removethrobber.label;</label>
<spacer flex="1" />
</hbox>
</vbox>
</flyoutpanel>
<flyoutpanel id="prefs-flyoutpanel" headertext="&optionsHeader.title;">
@ -478,12 +497,12 @@
<dialog id="syncsetup-dialog" class="content-dialog" flex="1">
<vbox class="prompt-inner">
<hbox class="prompt-title">
<description>&sync.setup.title;</description>
<description>&sync.setup2.title;</description>
</hbox>
<vbox id="syncsetup-simple" class="syncsetup-page" flex="1">
<scrollbox id="sync-message" class="prompt-message" orient="vertical" flex="1">
<description class="syncsetup-desc" flex="1">&sync.setup.pair2;</description>
<description class="link" flex="1" onclick="WeaveGlue.openTutorial();">&sync.setup.tutorial;</description>
<description class="link" flex="1" onclick="Sync.openTutorial();">&sync.setup.tutorial;</description>
<separator/>
<vbox flex="1" pack="center" align="start">
<description id="syncsetup-code1" class="syncsetup-code">....</description>
@ -491,11 +510,11 @@
<description id="syncsetup-code3" class="syncsetup-code">....</description>
</vbox>
<separator/>
<description class="link" flex="1" onclick="WeaveGlue.openManual();">&sync.fallback;</description>
<description class="link" flex="1" onclick="Sync.openManual();">&sync.fallback;</description>
<separator flex="1"/>
</scrollbox>
<hbox class="prompt-buttons">
<button class="prompt-button" oncommand="WeaveGlue.close();">&sync.setup.cancel;</button>
<button oncommand="Sync.close();">&sync.setup.cancel;</button>
</hbox>
</vbox>
<vbox id="syncsetup-waiting" class="syncsetup-page" flex="1" hidden="true">
@ -505,26 +524,26 @@
<description id="syncsetup-waitingdownload-desc" class="syncsetup-desc" hidden="true" flex="1">&sync.setup.waitingdownload;</description>
</vbox>
<hbox class="prompt-buttons" pack="center" align="end">
<button id="syncsetup-waiting-cancel" class="prompt-button" oncommand="WeaveGlue.close();">&sync.setup.cancel;</button>
<button id="syncsetup-waiting-close" class="prompt-button" hidden="true" oncommand="WeaveGlue.close();">&sync.setup.close;</button>
<button id="syncsetup-waiting-cancel" oncommand="Sync.close();">&sync.setup.cancel;</button>
<button id="syncsetup-waiting-close" hidden="true" oncommand="Sync.close();">&sync.setup.close;</button>
</hbox>
</vbox>
<vbox id="syncsetup-fallback" class="syncsetup-page" flex="1" hidden="true">
<scrollbox class="prompt-message" orient="vertical" flex="1">
<description class="syncsetup-desc" flex="1">&sync.setup.manual;</description>
<separator/>
<textbox id="syncsetup-account" class="prompt-edit" placeholder="&sync.account;" oninput="WeaveGlue.canConnect();"/>
<textbox id="syncsetup-password" class="prompt-edit" placeholder="&sync.password;" type="password" oninput="WeaveGlue.canConnect();"/>
<textbox id="syncsetup-synckey" class="prompt-edit" placeholder="&sync.recoveryKey;" oninput="WeaveGlue.canConnect();"/>
<textbox id="syncsetup-account" class="prompt-edit" placeholder="&sync.account;" oninput="Sync.canConnect();"/>
<textbox id="syncsetup-password" class="prompt-edit" placeholder="&sync.password;" type="password" oninput="Sync.canConnect();"/>
<textbox id="syncsetup-synckey" class="prompt-edit" placeholder="&sync.recoveryKey;" oninput="Sync.canConnect();"/>
<separator class="thin"/>
<checkbox id="syncsetup-usecustomserver" label="&sync.customServer;" oncommand="WeaveGlue.toggleCustomServer();"/>
<checkbox id="syncsetup-usecustomserver" label="&sync.customServer;" oncommand="Sync.toggleCustomServer();"/>
<textbox id="syncsetup-customserver" class="prompt-edit" placeholder="&sync.serverURL;"/>
<separator flex="1"/>
</scrollbox>
<hbox class="prompt-buttons">
<button class="prompt-button" oncommand="WeaveGlue.close();">&sync.setup.cancel;</button>
<button oncommand="Sync.close();">&sync.setup.cancel;</button>
<separator/>
<button id="syncsetup-button-connect" class="prompt-button" oncommand="WeaveGlue.close(); WeaveGlue.connect();">&sync.setup.connect;</button>
<button id="syncsetup-button-connect" oncommand="Sync.close(); Sync.connect();">&sync.setup.connect2;</button>
</hbox>
</vbox>
</vbox>
@ -540,7 +559,7 @@
<vbox id="syncpair-simple" class="syncsetup-page" flex="1">
<vbox id="sync-message" class="prompt-message" orient="vertical" flex="1">
<description class="syncsetup-desc" flex="1">&sync.pair.description;</description>
<description class="link" flex="1" onclick="SyncPairDevice.close(); WeaveGlue.openTutorial();">&sync.setup.tutorial;</description>
<description class="link" flex="1" onclick="SyncPairDevice.close(); Sync.openTutorial();">&sync.setup.tutorial;</description>
<separator/>
<vbox align="center" flex="1">
<textbox id="syncpair-code1" class="syncsetup-code" oninput="SyncPairDevice.onTextBoxInput(this);"/>
@ -549,8 +568,8 @@
</vbox>
</vbox>
<hbox class="prompt-buttons" pack="center">
<button class="prompt-button" oncommand="SyncPairDevice.close();">&sync.setup.cancel;</button>
<button id="syncpair-connectbutton" class="prompt-button" disabled="true" oncommand="SyncPairDevice.connect();">&sync.setup.connect;</button>
<button oncommand="SyncPairDevice.close();">&sync.setup.cancel;</button>
<button id="syncpair-connectbutton" disabled="true" oncommand="SyncPairDevice.connect();">&sync.setup.connect2;</button>
</hbox>
</vbox>
</vbox>

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

@ -194,7 +194,6 @@ HistoryView.prototype = {
this._set.dispatchEvent(event);
this._toRemove = null;
this._set.clearSelection();
}
break;

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

@ -41,7 +41,7 @@
<a name="webservices"/>
<h3>&rights2.webservices-header;</h3>
<p>&rights2.webservices-a;<a href="about:rights#disabling-webservices" onclick="showDisablingServices();">&rights2.webservices-b;</a>&rights2.webservices-c;</p>
<p>&rights2.webservices-a;<a href="about:rights#disabling-webservices" onclick="showDisablingServices();">&rights2.webservices-b;</a>&rights3.webservices-c;</p>
<div id="disabling-webservices-container" style="margin-left:40px;">
<a name="disabling-webservices"/>

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

@ -34,8 +34,8 @@
</vbox>
<hbox id="prompt-confirm-buttons-box" class="prompt-buttons">
<button class="prompt-button button-default" label="&ok.label;" command="cmd_ok"/>
<button class="prompt-button" label="&cancel.label;" command="cmd_cancel"/>
<button class="button-default" label="&ok.label;" command="cmd_ok"/>
<button label="&cancel.label;" command="cmd_cancel"/>
</hbox>
</vbox>
</dialog>

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

@ -36,8 +36,8 @@
</vbox>
<hbox class="prompt-buttons">
<button class="prompt-button" label="&ok.label;" command="cmd_ok"/>
<button class="prompt-button" label="&cancel.label;" command="cmd_cancel"/>
<button label="&ok.label;" command="cmd_ok"/>
<button label="&cancel.label;" command="cmd_cancel"/>
</hbox>
</vbox>
</dialog>

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

@ -56,8 +56,8 @@
</vbox>
<hbox class="prompt-buttons">
<button class="prompt-button button-default" label="&ok.label;" command="cmd_ok"/>
<button class="prompt-button" label="&cancel.label;" command="cmd_cancel"/>
<button class="button-default" label="&ok.label;" command="cmd_ok"/>
<button label="&cancel.label;" command="cmd_cancel"/>
</hbox>
</vbox>
</dialog>

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

@ -34,8 +34,8 @@
</vbox>
<hbox class="prompt-buttons">
<button class="prompt-button button-default" label="&ok.label;" command="cmd_ok"/>
<button class="prompt-button" label="&cancel.label;" command="cmd_cancel"/>
<button class="button-default" label="&ok.label;" command="cmd_ok"/>
<button label="&cancel.label;" command="cmd_cancel"/>
</hbox>
</vbox>
</dialog>

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

@ -66,7 +66,7 @@ Sanitizer.prototype = {
syncAccount: {
clear: function ()
{
WeaveGlue.disconnect();
Sync.disconnect();
},
get canClear()

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

@ -2,7 +2,7 @@
* 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/. */
let WeaveGlue = {
let Sync = {
setupData: null,
_boundOnEngineSync: null, // Needed to unhook the observers in close().
_boundOnServiceSync: null,
@ -12,6 +12,21 @@ let WeaveGlue = {
_progressBar: null,
_progressValue: 0,
_progressMax: null,
_disconnecting: false,
get _isSetup() {
if (Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED) {
return false;
}
// check for issues related to failed logins that do not have anything to
// do with network, server, and other non-client issues. See the login
// failure status codes in sync service.
return (Weave.Status.login != Weave.LOGIN_FAILED_NO_USERNAME &&
Weave.Status.login != Weave.LOGIN_FAILED_NO_PASSWORD &&
Weave.Status.login != Weave.LOGIN_FAILED_NO_PASSPHRASE &&
Weave.Status.login != Weave.LOGIN_FAILED_INVALID_PASSPHRASE &&
Weave.Status.login != Weave.LOGIN_FAILED_LOGIN_REJECTED);
},
init: function init() {
if (this._bundle) {
@ -24,6 +39,7 @@ let WeaveGlue = {
if (service.ready) {
this._init();
Weave.Service.scheduler.scheduleNextSync(10*1000); // ten seconds after we startup
} else {
Services.obs.addObserver(this, "weave:service:ready", false);
service.ensureLoaded();
@ -65,24 +81,18 @@ let WeaveGlue = {
_init: function () {
this._bundle = Services.strings.createBundle("chrome://browser/locale/sync.properties");
this._msg = document.getElementById("prefs-messages");
this._addListeners();
this.setupData = { account: "", password: "" , synckey: "", serverURL: "" };
if (Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED) {
// Put the settings UI into a state of "connecting..." if we are going to auto-connect
this._elements.connect.firstChild.disabled = true;
this._elements.connect.setAttribute("title", this._bundle.GetStringFromName("connecting.label"));
try {
this._elements.device.value = Services.prefs.getCharPref("services.sync.client.name");
} catch(e) {}
} else if (Weave.Status.login != Weave.LOGIN_FAILED_NO_USERNAME) {
if (this._isSetup) {
this.loadSetupData();
}
// Update the state of the ui
this._updateUI();
this._boundOnEngineSync = this.onEngineSync.bind(this);
this._boundOnServiceSync = this.onServiceSync.bind(this);
this._progressBar = document.getElementById("syncsetup-progressbar");
@ -370,40 +380,39 @@ let WeaveGlue = {
Weave.Service.identity.syncKey = this.setupData.synckey;
Weave.Service.persistLogin();
Weave.Svc.Obs.notify("weave:service:setup-complete");
setTimeout(function () { Weave.Service.sync(); }, 0);
this.sync();
},
disconnect: function disconnect() {
// Save credentials for undo
let undoData = this.setupData;
// Remove all credentials
this.setupData = null;
Weave.Service.startOver();
let message = this._bundle.GetStringFromName("notificationDisconnect.label");
let button = this._bundle.GetStringFromName("notificationDisconnect.button");
let buttons = [ {
label: button,
accessKey: "",
callback: function() { WeaveGlue.connect(undoData); }
} ];
this.showMessage(message, "undo-disconnect", buttons);
// Hide the notification when the panel is changed or closed.
let panel = document.getElementById("prefs-container");
panel.addEventListener("ToolPanelHidden", function onHide(aEvent) {
panel.removeEventListener(aEvent.type, onHide, false);
let notification = WeaveGlue._msg.getNotificationWithValue("undo-disconnect");
if (notification)
notification.close();
}, false);
// called when the user taps the disconnect button
onDisconnect: function onDisconnect() {
Weave.Service.logout();
let bundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
let brandName = bundle.GetStringFromName("brandShortName");
let warnStr = this._bundle.formatStringFromName("sync.disconnectPrompt", [brandName], 1);
this._elements.disconnectwarntitle.textContent = warnStr;
this._elements.disconnectwarnpanel.collapsed = false;
},
// called when the user taps the cancel button on
// the disconnect warning panel.
onCancelDisconnect: function onCancelDisconnect() {
this._elements.disconnectwarnpanel.collapsed = true;
this._updateUI();
Weave.Service.login();
},
// called when the user taps the remove button on
// the disconnect warning panel.
disconnect: function disconnect() {
this._elements.disconnectwarnpanel.collapsed = true;
this.setupData = null;
this._disconnecting = true;
this._updateUI();
Weave.Service.startOver();
},
sync: function sync() {
Weave.Service.sync();
Weave.Service.scheduler.scheduleNextSync(0);
},
_addListeners: function _addListeners() {
@ -412,27 +421,23 @@ let WeaveGlue = {
"weave:service:sync:error", "weave:service:login:start",
"weave:service:login:finish", "weave:service:login:error",
"weave:ui:login:error",
"weave:service:start-over", "weave:service:start-over:finish",
"weave:service:logout:finish"];
// For each topic, add WeaveGlue the observer
// For each topic, add Sync the observer
topics.forEach(function(topic) {
Services.obs.addObserver(WeaveGlue, topic, false);
Services.obs.addObserver(Sync, topic, false);
});
// Remove them on unload
addEventListener("unload", function() {
topics.forEach(function(topic) {
Services.obs.removeObserver(WeaveGlue, topic);
Services.obs.removeObserver(Sync, topic);
});
}, false);
},
get _elements() {
// Do a quick test to see if the options exist yet
let syncButton = document.getElementById("sync-syncButton");
if (syncButton == null)
return null;
// Get all the setting nodes from the add-ons display
let elements = {};
let setupids = ["account", "password", "synckey", "usecustomserver", "customserver"];
@ -440,7 +445,9 @@ let WeaveGlue = {
elements[id] = document.getElementById("syncsetup-" + id);
});
let settingids = ["device", "connect", "connected", "disconnect", "sync", "pairdevice"];
let settingids = ["device", "connect", "connected", "disconnect", "lastsync", "pairdevice",
"errordescription", "accountinfo", "disconnectwarnpanel", "disconnectthrobber",
"disconnectwarntitle"];
settingids.forEach(function(id) {
elements[id] = document.getElementById("sync-" + id);
});
@ -450,6 +457,87 @@ let WeaveGlue = {
return this._elements = elements;
},
_updateUI: function _updateUI() {
if (this._elements == null)
return;
let connect = this._elements.connect;
let connected = this._elements.connected;
let device = this._elements.device;
let disconnect = this._elements.disconnect;
let lastsync = this._elements.lastsync;
let pairdevice = this._elements.pairdevice;
let accountinfo = this._elements.accountinfo;
let disconnectthrobber = this._elements.disconnectthrobber;
// This gets updated when an error occurs
this._elements.errordescription.collapsed = true;
let isConfigured = (!this._loginError && this._isSetup);
// If we're in the process of disconnecting we are no longer configured.
if (this._disconnecting) {
isConfigured = false;
// display the throbber with the appropriate message
disconnectthrobber.collapsed = false;
} else {
disconnectthrobber.collapsed = true;
}
connect.collapsed = isConfigured;
connected.collapsed = !isConfigured;
lastsync.collapsed = !isConfigured;
device.collapsed = !isConfigured;
disconnect.collapsed = !isConfigured;
if (this._disconnecting) {
connect.collapsed = true;
}
// Set the device name text edit to configured name or the auto generated
// name if we aren't set up.
try {
device.value = Services.prefs.getCharPref("services.sync.client.name");
} catch(ex) {
device.value = Weave.Service.clientsEngine.localName || "";
}
// Account information header
accountinfo.collapsed = true;
try {
let account = Weave.Service.identity.account;
if (account != null && isConfigured) {
let accountStr = this._bundle.formatStringFromName("account.label", [account], 1);
accountinfo.textContent = accountStr;
accountinfo.collapsed = false;
}
} catch (ex) {}
// If we're already locked, a sync is in progress..
if (Weave.Service.locked && isConfigured) {
connect.firstChild.disabled = true;
}
// Show the day-of-week and time (HH:MM) of last sync
let lastSync = Weave.Svc.Prefs.get("lastSync");
lastsync.textContent = "";
if (lastSync != null) {
let syncDate = new Date(lastSync).toLocaleFormat("%A %I:%M %p");
let dateStr = this._bundle.formatStringFromName("lastSync2.label", [syncDate], 1);
lastsync.textContent = dateStr;
}
// Check the lock again on a timeout since it's set after observers notify
setTimeout(function(self) {
// Prevent certain actions when the service is locked
if (Weave.Service.locked) {
connect.firstChild.disabled = true;
} else {
connect.firstChild.disabled = false;
}
}, 100, this);
},
observe: function observe(aSubject, aTopic, aData) {
if (aTopic == "weave:service:ready") {
Services.obs.removeObserver(this, aTopic);
@ -460,24 +548,27 @@ let WeaveGlue = {
// Make sure we're online when connecting/syncing
Util.forceOnline();
if (aTopic == "weave:service:start-over") {
this._disconnecting = true;
} else if (aTopic == "weave:service:start-over:finish") {
this._disconnecting = false;
}
// Can't do anything before settings are loaded
if (this._elements == null)
return;
// Make some aliases
let connect = this._elements.connect;
let connected = this._elements.connected;
let device = this._elements.device;
let disconnect = this._elements.disconnect;
let sync = this._elements.sync;
let pairdevice = this._elements.pairdevice;
// Update the state of the ui
this._updateUI();
let errormsg = this._elements.errordescription;
let accountinfo = this._elements.accountinfo;
// Show what went wrong with login if necessary
if (aTopic == "weave:ui:login:error") {
this._loginError = true;
connect.setAttribute("desc", Weave.Utils.getErrorString(Weave.Status.login));
} else {
connect.removeAttribute("desc");
errormsg.textContent = Weave.Utils.getErrorString(Weave.Status.login);
errormsg.collapsed = false;
}
if (aTopic == "weave:service:login:finish") {
@ -487,52 +578,11 @@ let WeaveGlue = {
this.loadSetupData();
}
let isConfigured = (!this._loginError && Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED);
connect.collapsed = isConfigured;
connected.collapsed = !isConfigured;
if (!isConfigured) {
connect.setAttribute("title", this._bundle.GetStringFromName("notconnected.label"));
connect.firstChild.disabled = false;
}
sync.collapsed = !isConfigured;
device.collapsed = !isConfigured;
disconnect.collapsed = !isConfigured;
// Check the lock on a timeout because it's set just after notifying
setTimeout(function(self) {
// Prevent certain actions when the service is locked
if (Weave.Service.locked) {
connect.firstChild.disabled = true;
sync.firstChild.disabled = true;
if (aTopic == "weave:service:login:start")
connect.setAttribute("title", self._bundle.GetStringFromName("connecting.label"));
if (aTopic == "weave:service:sync:start")
sync.setAttribute("title", self._bundle.GetStringFromName("lastSyncInProgress2.label"));
} else {
connect.firstChild.disabled = false;
sync.firstChild.disabled = false;
}
}, 0, this);
// Dynamically generate some strings
let accountStr = this._bundle.formatStringFromName("account.label", [Weave.Service.identity.account], 1);
disconnect.setAttribute("title", accountStr);
// Show the day-of-week and time (HH:MM) of last sync
let lastSync = Weave.Svc.Prefs.get("lastSync");
if (lastSync != null) {
let syncDate = new Date(lastSync).toLocaleFormat("%a %H:%M");
let dateStr = this._bundle.formatStringFromName("lastSync2.label", [syncDate], 1);
sync.setAttribute("title", dateStr);
}
// Check for a storage format update, update the user and load the Sync update page
if (aTopic =="weave:service:sync:error") {
errormsg.textContent = Weave.Utils.getErrorString(Weave.Status.sync);
errormsg.collapsed = false;
let clientOutdated = false, remoteOutdated = false;
if (Weave.Status.sync == Weave.VERSION_OUT_OF_DATE) {
clientOutdated = true;
@ -565,8 +615,6 @@ let WeaveGlue = {
Browser.addTab("https://services.mozilla.com/update/", true, Browser.selectedTab);
}
}
device.value = Weave.Service.clientsEngine.localName || "";
},
changeName: function changeName(aInput) {
@ -575,14 +623,6 @@ let WeaveGlue = {
aInput.value = Weave.Service.clientsEngine.localName;
},
showMessage: function showMessage(aMsg, aValue, aButtons) {
let notification = this._msg.getNotificationWithValue(aValue);
if (notification)
return;
this._msg.appendNotification(aMsg, aValue, "", this._msg.PRIORITY_WARNING_LOW, aButtons);
},
_validateServer: function _validateServer(aURL) {
let uri = Weave.Utils.makeURI(aURL);
@ -595,7 +635,7 @@ let WeaveGlue = {
},
openTutorial: function _openTutorial() {
WeaveGlue.close();
Sync.close();
let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
let url = formatter.formatURLPref("app.sync.tutorialURL");

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

@ -26,6 +26,7 @@ chrome.jar:
content/bindings/appbar.xml (content/bindings/appbar.xml)
content/bindings/flyoutpanel.xml (content/bindings/flyoutpanel.xml)
content/bindings/selectionoverlay.xml (content/bindings/selectionoverlay.xml)
content/bindings/cssthrobber.xml (content/bindings/cssthrobber.xml)
content/prompt/alert.xul (content/prompt/alert.xul)
content/prompt/confirm.xul (content/prompt/confirm.xul)

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

@ -1,47 +1,48 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
////////////////////////////////////////////////////////////////////////////////
//// Globals
Components.utils.import("resource://services-sync/main.js");
////////////////////////////////////////////////////////////////////////////////
//// Test(s)
function test() {
is(Weave.Status.checkSetup(), Weave.CLIENT_NOT_CONFIGURED, "Sync should be disabled on start");
// check start page is hidden
let vbox = document.getElementById("start-remotetabs");
ok(vbox.hidden, "remote tabs in the start page should be hidden when sync is not enabled");
// check container link is hidden
let menulink = document.getElementById("menuitem-remotetabs");
ok(menulink.hidden, "link to container should be hidden when sync is not enabled");
// hacky-fake sync setup and enabled. Note the Sync Tracker will spit
// a number of warnings about undefined ids
Weave.Status._authManager.username = "jane doe"; // must set username before key
Weave.Status._authManager.basicPassword = "goatcheesesalad";
Weave.Status._authManager.syncKey = "a-bcdef-abcde-acbde-acbde-acbde";
// check that it worked
isnot(Weave.Status.checkSetup(), Weave.CLIENT_NOT_CONFIGURED, "Sync is enabled");
Weave.Svc.Obs.notify("weave:service:setup-complete");
// start page grid should be visible
ok(vbox, "remote tabs grid is present on start page");
//PanelUI.show("remotetabs-container");
is(vbox.hidden, false, "remote tabs should be visible in start page when sync is enabled");
// container link should be visible
is(menulink.hidden, false, "link to container should be visible when sync is enabled");
// hacky-fake sync disable
Weave.Status._authManager.deleteSyncCredentials();
Weave.Svc.Obs.notify("weave:service:start-over");
is(Weave.Status.checkSetup(), Weave.CLIENT_NOT_CONFIGURED, "Sync has been disabled");
ok(vbox.hidden, "remote tabs in the start page should be hidden when sync is not enabled");
ok(menulink.hidden, "link to container should be hidden when sync is not enabled");
}
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
////////////////////////////////////////////////////////////////////////////////
//// Globals
Components.utils.import("resource://services-sync/main.js");
////////////////////////////////////////////////////////////////////////////////
//// Test(s)
function test() {
runTests();
}
gTests.push({
desc: "Test sync tabs from other devices UI",
run: function run() {
if (StartUI.isStartPageVisible)
return;
yield addTab("about:start");
yield waitForCondition(() => StartUI.isStartPageVisible);
yield hideContextUI();
is(Weave.Status.checkSetup(), Weave.CLIENT_NOT_CONFIGURED, "Sync should be disabled on start");
let vbox = document.getElementById("start-remotetabs");
ok(vbox.hidden, "remote tabs in the start page should be hidden when sync is not enabled");
// check container link is hidden
let menulink = document.getElementById("menuitem-remotetabs");
ok(menulink.hidden, "link to container should be hidden when sync is not enabled");
RemoteTabsStartView._view.setUIAccessVisible(true);
// start page grid should be visible
ok(vbox, "remote tabs grid is present on start page");
is(vbox.hidden, false, "remote tabs should be visible in start page when sync is enabled");
RemoteTabsStartView._view.setUIAccessVisible(false);
ok(vbox.hidden, "remote tabs in the start page should be hidden when sync is not enabled");
ok(menulink.hidden, "link to container should be hidden when sync is not enabled");
}
});

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

@ -1,85 +0,0 @@
/* -*- Mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil; -*- */
/* 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/. */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
function CapturePicker() {
this.messageManager = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
}
CapturePicker.prototype = {
_file: null,
_mode: -1,
_result: -1,
_shown: false,
_title: "",
_type: "",
_window: null,
//
// nsICapturePicker
//
init: function(aWindow, aTitle, aMode) {
this._window = aWindow;
this._title = aTitle;
this._mode = aMode;
},
show: function() {
if (this._shown)
throw Cr.NS_ERROR_UNEXPECTED;
this._shown = true;
let res = this.messageManager.sendSyncMessage("CapturePicker:Show", { title: this._title, mode: this._mode, type: this._type })[0];
if (res.value)
this._file = res.path;
return (res.value ? Ci.nsICapturePicker.RETURN_OK : Ci.nsICapturePicker.RETURN_CANCEL);
},
modeMayBeAvailable: function(aMode) {
if (aMode != Ci.nsICapturePicker.MODE_STILL)
return false;
return true;
},
get file() {
if (this._file) {
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
file.initWithPath(this._file);
let utils = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
return utils.wrapDOMFile(file);
} else {
throw Cr.NS_ERROR_FAILURE;
}
},
get type() {
return this._type;
},
set type(aNewType) {
if (this._shown)
throw Cr.NS_ERROR_UNEXPECTED;
else
this._type = aNewType;
},
// QI
QueryInterface: XPCOMUtils.generateQI([Ci.nsICapturePicker]),
// XPCOMUtils factory
classID: Components.ID("{cb5a47f0-b58c-4fc3-b61a-358ee95f8238}"),
};
var components = [ CapturePicker ];
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);

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

@ -30,7 +30,6 @@ EXTRA_COMPONENTS = \
ContentDispatchChooser.js \
FormAutoComplete.js \
LoginManagerPrompter.js \
CapturePicker.js \
$(NULL)
ifdef MOZ_SAFE_BROWSING

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

@ -419,7 +419,6 @@ Prompt.prototype = {
if (bTitle) {
let button = doc.createElement("button");
button.className = "prompt-button";
this.setLabelForNode(button, bTitle);
if (i == defaultButton) {
button.setAttribute("command", "cmd_ok");

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

@ -3,25 +3,32 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!-- flyout header -->
<!ENTITY syncHeader.title "Sync">
<!ENTITY sync.notconnected "Not connected">
<!ENTITY sync.connect "Connect">
<!ENTITY sync.connected "Connected">
<!ENTITY sync.deviceName "This device">
<!ENTITY sync.disconnect "Disconnect">
<!-- not connected yet -->
<!ENTITY sync.setup.description "Access your bookmarks, passwords, and open tabs across your devices">
<!ENTITY sync.setupbutton.label "Set up Sync">
<!-- sync now button -->
<!ENTITY sync.syncNow2 "Sync now">
<!-- device name text edit -->
<!ENTITY sync.deviceName "This device">
<!-- remove this device button -->
<!ENTITY sync.removebutton.label "Remove this device">
<!ENTITY sync.removewarn.note "Your browser data on this device will remain intact, but you will no longer be able to sync with this account.">
<!ENTITY sync.removethrobber.label "Removing device">
<!ENTITY sync.setup.title "Connect to Sync">
<!ENTITY sync.setup2.title "Set up Sync">
<!ENTITY sync.setup.pair2 "To activate, select &#x0022;Pair a device&#x0022; on your other device.">
<!ENTITY sync.fallback "I'm not near my computer…">
<!ENTITY sync.fallback "Enter or edit account information…">
<!ENTITY sync.setup.manual "Enter your Sync account information">
<!ENTITY sync.account "Account Name">
<!ENTITY sync.password "Password">
<!ENTITY sync.recoveryKey "Recovery Key">
<!ENTITY sync.customServer "Use custom server">
<!ENTITY sync.serverURL "Server URL">
<!ENTITY sync.setup.connect "Connect">
<!ENTITY sync.setup.connect2 "Add device">
<!ENTITY sync.setup.cancel "Cancel">
<!ENTITY sync.setup.remove "Remove">
<!ENTITY sync.setup.tutorial "Show me how">
<!ENTITY sync.setup.waiting2 "Waiting for other device…">

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

@ -2,15 +2,18 @@
# 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/.
# Mobile Sync
# LOCALIZATION NOTE: Used in the default os description when a new account
# is being set up. Should be unique to Metro, so that it does not conflict
# with Desktop. See /services/sync/modules/engines/clients.js locaName.
sync.defaultAccountApplication=Metro %S
sync.disconnectPrompt=Remove Windows 8 style %S from your Sync Account?
# %S is the date and time at which the last sync successfully completed
lastSync2.label=Last sync: %S
lastSyncInProgress2.label=Last sync: in progress…
# %S is the username logged in
account.label=Account: %S
notconnected.label=Not connected
connecting.label=Connecting…
notificationDisconnect.label=Your Firefox Sync account has been removed

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

@ -416,7 +416,6 @@ pref("editor.singleLine.pasteNewlines", 2);
#ifdef MOZ_SERVICES_SYNC
// sync service
pref("services.sync.registerEngines", "Tab,Bookmarks,Form,History,Password,Prefs");
pref("services.sync.autoconnectDelay", 5);
// prefs to sync by default
pref("services.sync.prefs.sync.browser.startup.sessionRestore", true);

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

@ -720,6 +720,31 @@ flyoutpanel > settings:first-child {
width: 400px;
}
#sync-disconnectwarntitle {
font-weight: bold;
}
#sync-disconnectthrobber {
margin-top: 25px;
}
#disconnectthrobber {
width: 25px;
height: 25px;
}
#syncdisconnectthrobber .progressContainer {
width: 25px;
height: 25px;
margin-right: 10px;
}
#syncdisconnectthrobber .progressBall {
margin: 2px;
width: 22px;
height: 22px;
}
/* About flyout pane */
#about-flyoutpanel {
@ -871,6 +896,10 @@ setting[type="radio"] > vbox {
-moz-box-orient: horizontal;
}
[viewstate="snapped"] .canSnapTiles .richgrid-item-desc {
-moz-margin-start: 8px;
}
/* if snapped, hide the fullscreen awesome screen, if viewstate is anything
* other than snapped, hide the snapped awesome screen */
#start[viewstate="snapped"],
@ -1170,17 +1199,3 @@ setting[type="radio"] > vbox {
margin-left: -18px;
pointer-events: auto;
}
/* Capture picker ------------------------------------------------------------- */
#capturepicker-video {
border: @border_width_tiny@ solid white;
}
#capturepicker-container {
margin: @margin_normal@;
}
#capturepicker-container.vertical {
height: 330px;
}

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

@ -0,0 +1,102 @@
/* 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/. */
%filter substitution
%include defines.inc
.progressContainer {
}
.progressBall {
position: absolute;
opacity: 0;
transform: rotate(225deg);
animation: orbit 7.15s infinite;
}
.progressBall:nth-child(1) {
animation-delay: 1.56s;
}
.progressBall:nth-child(2) {
animation-delay: 0.31s;
}
.progressBall:nth-child(3) {
animation-delay: 0.62s;
}
.progressBall:nth-child(4) {
animation-delay: 0.94s;
}
.progressBall:nth-child(5) {
animation-delay: 1.25s;
}
.progressBall:nth-child(1)::after,
.progressBall:nth-child(2)::after,
.progressBall:nth-child(3)::after,
.progressBall:nth-child(4)::after,
.progressBall:nth-child(5)::after {
content: "";
display: block;
width: 5px;
height: 5px;
border-radius: 5px;
position: absolute;
background: #0095dd;
left:0px;
top:0px;
}
@keyframes orbit {
0% {
opacity: 1;
z-index:99;
transform: rotate(180deg);
animation-timing-function: ease-out;
}
7% {
opacity: 1;
transform: rotate(300deg);
animation-timing-function: linear;
origin:0%;
}
30% {
opacity: 1;
transform:rotate(410deg);
animation-timing-function: ease-in-out;
origin:7%;
}
39% {
opacity: 1;
transform: rotate(645deg);
animation-timing-function: linear;
origin:30%;
}
70% {
opacity: 1;
transform: rotate(770deg);
animation-timing-function: ease-out;
origin:39%;
}
75% {
opacity: 1;
transform: rotate(900deg);
animation-timing-function: ease-out;
origin:70%;
}
76%, 100% {
opacity: 0;
transform:rotate(900deg);
}
}

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

@ -9,6 +9,7 @@ chrome.jar:
skin/aboutPage.css (aboutPage.css)
skin/about.css (about.css)
* skin/flyoutpanel.css (flyoutpanel.css)
* skin/cssthrobber.css (cssthrobber.css)
* skin/browser.css (browser.css)
* skin/content.css (content.css)
skin/config.css (config.css)

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

@ -572,7 +572,7 @@ richgriditem[customColor] .richgrid-icon-box {
.richgrid-item-desc {
width: @tile_width@;
font-size: @metro_font_normal@;
margin-left: 0px !important;
margin-left: 0px;
padding-left: 0px !important;
}

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

@ -4,7 +4,7 @@
"use strict";
this.EXPORTED_SYMBOLS = ["Social"];
this.EXPORTED_SYMBOLS = ["Social", "OpenGraphBuilder"];
const Ci = Components.interfaces;
const Cc = Components.classes;
@ -20,6 +20,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
XPCOMUtils.defineLazyServiceGetter(this, "unescapeService",
"@mozilla.org/feed-unescapehtml;1",
"nsIScriptableUnescapeHTML");
// Add a pref observer for the enabled state
function prefObserver(subject, topic, data) {
let enable = Services.prefs.getBoolPref("social.enabled");
@ -434,3 +438,118 @@ SocialErrorListener.prototype = {
onStatusChange: function SPL_onStatusChange() {},
onSecurityChange: function SPL_onSecurityChange() {},
};
this.OpenGraphBuilder = {
getData: function(browser) {
let res = {
url: this._validateURL(browser, browser.currentURI.spec),
title: browser.contentDocument.title,
previews: []
};
this._getMetaData(browser, res);
this._getLinkData(browser, res);
this._getPageData(browser, res);
return res;
},
_getMetaData: function(browser, o) {
// query for standardized meta data
let els = browser.contentDocument
.querySelectorAll("head > meta[property], head > meta[name]");
if (els.length < 1)
return;
let url;
for (let el of els) {
let value = el.getAttribute("content")
if (!value)
continue;
value = unescapeService.unescape(value.trim());
switch (el.getAttribute("property") || el.getAttribute("name")) {
case "title":
case "og:title":
o.title = value;
break;
case "description":
case "og:description":
o.description = value;
break;
case "og:site_name":
o.siteName = value;
break;
case "medium":
case "og:type":
o.medium = value;
break;
case "og:video":
url = this._validateURL(browser, value);
if (url)
o.source = url;
break;
case "og:url":
url = this._validateURL(browser, value);
if (url)
o.url = url;
break;
case "og:image":
url = this._validateURL(browser, value);
if (url)
o.previews.push(url);
break;
}
}
},
_getLinkData: function(browser, o) {
let els = browser.contentDocument
.querySelectorAll("head > link[rel], head > link[id]");
for (let el of els) {
let url = el.getAttribute("href");
if (!url)
continue;
url = this._validateURL(browser, unescapeService.unescape(url.trim()));
switch (el.getAttribute("rel") || el.getAttribute("id")) {
case "shorturl":
case "shortlink":
o.shortUrl = url;
break;
case "canonicalurl":
case "canonical":
o.url = url;
break;
case "image_src":
o.previews.push(url);
break;
}
}
},
// scrape through the page for data we want
_getPageData: function(browser, o) {
if (o.previews.length < 1)
o.previews = this._getImageUrls(browser);
},
_validateURL: function(browser, url) {
let uri = Services.io.newURI(browser.currentURI.resolve(url), null, null);
if (["http", "https", "ftp", "ftps"].indexOf(uri.scheme) < 0)
return null;
uri.userPass = "";
return uri.spec;
},
_getImageUrls: function(browser) {
let l = [];
let els = browser.contentDocument.querySelectorAll("img");
for (let el of els) {
let content = el.getAttribute("src");
if (content) {
l.push(this._validateURL(browser, unescapeService.unescape(content)));
// we don't want a billion images
if (l.length > 5)
break;
}
}
return l;
}
};

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

@ -1441,6 +1441,64 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
list-style-image: url("chrome://browser/skin/Info.png");
}
/* social share panel */
.social-share-frame {
background: linear-gradient(to bottom, rgba(242,242,242,.99), rgba(242,242,242,.95));
border-left: 1px solid #f8f8f8;
width: 330px;
height: 150px;
/* we resize our panels dynamically, make it look nice */
transition: height 100ms ease-out, width 100ms ease-out;
}
#social-share-button {
list-style-image: url("chrome://browser/skin/social/share-button.png");
}
#social-share-button[open],
#social-share-button:hover:active {
list-style-image: url("chrome://browser/skin/social/share-button-active.png");
}
.social-share-toolbar {
border-right: 1px solid #dedede;
background: linear-gradient(to bottom, rgba(247,247,247,.99), rgba(247,247,247,.95));
}
#social-share-provider-buttons {
border-right: 1px solid #fbfbfb;
padding: 6px;
}
#social-share-provider-buttons > .share-provider-button {
padding: 6px;
margin: 0;
border: none;
border-radius: 2px;
}
#social-share-provider-buttons > .share-provider-button[checked],
#social-share-provider-buttons > .share-provider-button:active {
padding: 5px;
border: 1px solid #b5b5b8;
box-shadow: inset 1px 1px 3px rgba(0, 0, 0, 0.2);
}
#social-share-provider-buttons > .share-provider-button[checked] {
background: linear-gradient(to bottom, #d9d9d9, #e3e3e3);
}
#social-share-provider-buttons > .share-provider-button > .toolbarbutton-text {
display: none;
}
#social-share-provider-buttons > .share-provider-button > .toolbarbutton-icon {
width: 16px;
min-height: 16px;
max-height: 16px;
}
/* social recommending panel */
#social-mark-button {
@ -2094,6 +2152,11 @@ toolbar[mode="text"] toolbarbutton.chevron > .toolbarbutton-icon {
-moz-margin-end: 2px;
}
#social-provider-button {
-moz-image-region: rect(0, 16px, 16px, 0);
list-style-image: url(chrome://browser/skin/social/services-16.png);
}
#social-provider-button > .toolbarbutton-menu-dropmarker {
display: none;
}
@ -2189,12 +2252,14 @@ toolbar[iconsize="small"] .toolbarbutton-badge-container {
.chatbar-button {
-moz-appearance: none;
background-color: #d9d9d9;
background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
}
.chatbar-button > .toolbarbutton-icon {
-moz-margin-end: 0;
}
.chatbar-button:hover,
.chatbar-button[open="true"] {
background-color: #f0f0f0;
}

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

@ -105,6 +105,8 @@ browser.jar:
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/social/services-16.png (social/services-16.png)
skin/classic/browser/social/services-64.png (social/services-64.png)
skin/classic/browser/social/share-button.png (social/share-button.png)
skin/classic/browser/social/share-button-active.png (social/share-button-active.png)
skin/classic/browser/social/chat-close.png (social/chat-close.png)
skin/classic/browser/tabbrowser/connecting.png (tabbrowser/connecting.png)
skin/classic/browser/tabbrowser/loading.png (tabbrowser/loading.png)

Двоичные данные
browser/themes/linux/social/share-button-active.png Normal file

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

После

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

Двоичные данные
browser/themes/linux/social/share-button.png Normal file

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

После

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

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

@ -1655,6 +1655,62 @@ window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][s
}
}
/* social share panel */
.social-share-frame {
background: linear-gradient(to bottom, rgba(242,242,242,.99), rgba(242,242,242,.95));
border-left: 1px solid #f8f8f8;
width: 330px;
height: 150px;
/* we resize our panels dynamically, make it look nice */
transition: height 100ms ease-out, width 100ms ease-out;
}
#social-share-button {
list-style-image: url("chrome://browser/skin/social/share-button.png");
}
#social-share-button[open],
#social-share-button:hover:active {
list-style-image: url("chrome://browser/skin/social/share-button-active.png");
}
.social-share-toolbar {
border-right: 1px solid #dedede;
background: linear-gradient(to bottom, rgba(247,247,247,.99), rgba(247,247,247,.95));
}
#social-share-provider-buttons {
border-right: 1px solid #fbfbfb;
padding: 6px;
}
#social-share-provider-buttons > .share-provider-button {
padding: 6px;
margin: 0;
border: none;
border-radius: 2px;
}
#social-share-provider-buttons > .share-provider-button[checked],
#social-share-provider-buttons > .share-provider-button:active {
padding: 5px;
border: 1px solid #b5b5b8;
box-shadow: inset 1px 1px 3px rgba(0, 0, 0, 0.2);
}
#social-share-provider-buttons > .share-provider-button[checked] {
background: linear-gradient(to bottom, #d9d9d9, #e3e3e3);
}
#social-share-provider-buttons > .share-provider-button > .toolbarbutton-text {
display: none;
}
#social-share-provider-buttons > .share-provider-button > .toolbarbutton-icon {
width: 16px;
min-height: 16px;
max-height: 16px;
}
/* social recommending panel */
#social-mark-button {
@ -3628,8 +3684,19 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
border-bottom-right-radius: 3px;
}
#social-toolbar-item > toolbaritem {
margin: 0;
}
#social-provider-button {
-moz-image-region: rect(0, 16px, 16px, 0);
list-style-image: url(chrome://browser/skin/social/services-16.png);
}
@media (min-resolution: 2dppx) {
#social-provider-button {
list-style-image: url(chrome://browser/skin/social/services-16@2x.png);
}
}
#social-provider-button > .toolbarbutton-menu-dropmarker {
@ -3749,10 +3816,36 @@ toolbar[mode="icons"] > *|* > .toolbarbutton-badge[badge]:not([badge=""]):-moz-l
padding: 0;
}
.social-panel-frame {
/* fixup rounded corners for osx panels */
.social-panel > .social-panel-frame {
border-radius: inherit;
}
#social-share-panel {
margin-top: 3px;
max-height: 600px;
min-height: 100px;
max-width: 800px;
min-width: 300px;
}
.social-share-frame {
border-top-left-radius: none;
border-bottom-left-radius: none;
border-top-right-radius: inherit;
border-bottom-right-radius: inherit;
}
#social-share-panel > .social-share-toolbar {
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
}
#social-share-provider-buttons {
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
}
/* === end of social toolbar provider menu === */
%include ../shared/social/chat.inc.css
@ -3768,13 +3861,17 @@ toolbar[mode="icons"] > *|* > .toolbarbutton-badge[badge]:not([badge=""]):-moz-l
.chatbar-button {
background-color: #d9d9d9;
background-image: linear-gradient(rgba(255,255,255,.43), rgba(255,255,255,0));
border-top-left-radius: @toolbarbuttonCornerRadius@;
border-top-right-radius: @toolbarbuttonCornerRadius@;
}
.chatbar-button:hover,
.chatbar-button[open="true"] {
background-color: #f0f0f0;
}
.chatbar-button[activity] {
.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%);
}

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

@ -172,6 +172,8 @@ browser.jar:
skin/classic/browser/social/services-16@2x.png (social/services-16@2x.png)
skin/classic/browser/social/services-64.png (social/services-64.png)
skin/classic/browser/social/services-64@2x.png (social/services-64@2x.png)
skin/classic/browser/social/share-button.png (social/share-button.png)
skin/classic/browser/social/share-button-active.png (social/share-button-active.png)
skin/classic/browser/social/chat-close.png (social/chat-close.png)
skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon.png (tabbrowser/alltabs-box-bkgnd-icon.png)
skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab.png)

Двоичные данные
browser/themes/osx/social/share-button-active.png Normal file

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

После

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

Двоичные данные
browser/themes/osx/social/share-button.png Normal file

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

После

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

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

@ -1,3 +1,3 @@
%filter substitution
%define primaryToolbarButtons #back-button, #forward-button, #reload-button, #stop-button, #home-button, #print-button, #downloads-button, #downloads-indicator, #history-button, #bookmarks-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-in-button, #sync-button, #feed-button, #alltabs-button, #tabview-button, #webrtc-status-button
%define primaryToolbarButtons #back-button, #forward-button, #reload-button, #stop-button, #home-button, #print-button, #downloads-button, #downloads-indicator, #history-button, #bookmarks-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-in-button, #sync-button, #feed-button, #alltabs-button, #tabview-button, #webrtc-status-button, #social-share-button

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

@ -73,13 +73,12 @@
.chatbar-button {
list-style-image: url("chrome://browser/skin/social/services-16.png");
border: none;
margin: 0;
padding: 2px;
height: 21px;
width: 21px;
border-top: 1px solid #ccc;
-moz-border-end: 1px solid #ccc;
border: 1px solid #ccc;
border-bottom: none;
}
@media (min-resolution: 2dppx) {
@ -95,15 +94,6 @@
max-width: 16px;
}
.chatbar-button > .toolbarbutton-icon {
opacity: .6;
}
.chatbar-button:hover > .toolbarbutton-icon,
.chatbar-button[open="true"] > .toolbarbutton-icon {
opacity: 1;
}
.chatbar-button[open="true"] {
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
}

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

@ -1713,6 +1713,93 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
-moz-image-region: rect(0, 48px, 16px, 32px);
}
/* social share panel */
#social-share-panel > iframe {
background: linear-gradient(to bottom, #f0f4f7, #fafbfc);
width: 300px;
height: 150px;
}
#social-share-button {
list-style-image: url(chrome://browser/skin/social/share-button.png);
-moz-image-region: rect(0, 16px, 16px, 0);
}
.social-share-toolbar {
border-right: 1px solid #e2e5e8;
background: linear-gradient(to bottom, #ffffff, #f5f7fa);
}
#social-share-provider-buttons {
padding: 6px;
}
#social-share-provider-buttons > .share-provider-button {
-moz-appearance: none;
padding: 5px;
margin: 1px;
border: none;
background: none;
border-radius: 2px;
}
#social-share-provider-buttons > .share-provider-button[checked="true"]:not([disabled="true"]),
#social-share-provider-buttons > .share-provider-button:hover,
#social-share-provider-buttons > .share-provider-button:active {
padding: 4px;
border: 1px solid #aeb8c1;
box-shadow: inset 1px 1px 1px rgba(10, 31, 51, 0.1);
}
#social-share-provider-buttons > .share-provider-button[checked="true"]:not([disabled="true"]) {
background: linear-gradient(to bottom, rgba(230,232,234,.65), #d2d5d9);
}
#social-share-provider-buttons > .share-provider-button > .toolbarbutton-text {
display: none;
}
#social-share-provider-buttons > .share-provider-button > .toolbarbutton-icon {
width: 16px;
min-height: 16px;
max-height: 16px;
}
/* fixup corners for share panel */
.social-panel > .social-panel-frame {
border-radius: inherit;
}
#social-share-panel {
max-height: 600px;
min-height: 100px;
max-width: 800px;
min-width: 300px;
}
.social-share-frame {
background: linear-gradient(to bottom, #f0f4f7, #fafbfc);
width: 330px;
height: 150px;
border-top-left-radius: none;
border-bottom-left-radius: none;
border-top-right-radius: inherit;
border-bottom-right-radius: inherit;
/* we resize our panels dynamically, make it look nice */
transition: height 100ms ease-out, width 100ms ease-out;
}
#social-share-panel > .social-share-toolbar {
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
}
#social-share-provider-buttons {
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
}
/* social recommending panel */
#social-mark-button {
@ -2765,6 +2852,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
#social-provider-button {
-moz-image-region: rect(0, 16px, 16px, 0);
list-style-image: url(chrome://browser/skin/social/services-16.png);
}
#social-provider-button > .toolbarbutton-menu-dropmarker {
@ -2913,12 +3001,14 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
.chatbar-button {
-moz-appearance: none;
background-color: #c4cfde;
background-image: linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,0));
}
.chatbar-button > .toolbarbutton-icon {
-moz-margin-end: 0;
}
.chatbar-button:hover,
.chatbar-button[open="true"] {
background-color: #dae3f0;
}

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

@ -125,6 +125,8 @@ browser.jar:
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/social/services-16.png (social/services-16.png)
skin/classic/browser/social/services-64.png (social/services-64.png)
skin/classic/browser/social/share-button.png (social/share-button.png)
skin/classic/browser/social/share-button-active.png (social/share-button-active.png)
skin/classic/browser/social/chat-close.png (social/chat-close.png)
skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab.png)
skin/classic/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png)
@ -373,6 +375,8 @@ browser.jar:
skin/classic/aero/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/aero/browser/social/services-16.png (social/services-16.png)
skin/classic/aero/browser/social/services-64.png (social/services-64.png)
skin/classic/aero/browser/social/share-button.png (social/share-button.png)
skin/classic/aero/browser/social/share-button-active.png (social/share-button-active.png)
skin/classic/aero/browser/social/chat-close.png (social/chat-close.png)
skin/classic/aero/browser/tabbrowser/newtab.png (tabbrowser/newtab.png)
skin/classic/aero/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png)

Двоичные данные
browser/themes/windows/social/share-button-active.png Normal file

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

После

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

Двоичные данные
browser/themes/windows/social/share-button.png Normal file

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

После

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

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

@ -93,6 +93,7 @@ _LEAKTEST_DIR = $(DEPTH)/_leaktest
_LEAKTEST_FILES = \
automation.py \
automationutils.py \
$(topsrcdir)/testing/profiles/prefs_general.js \
leaktest.py \
bloatcycle.html \
$(topsrcdir)/build/pgo/server-locations.txt \

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

@ -43,6 +43,8 @@ except:
import mozcrash
# ---------------------------------------------------------------
_DEFAULT_PREFERENCE_FILE = os.path.join(SCRIPT_DIR, 'prefs_general.js')
_DEFAULT_WEB_SERVER = "127.0.0.1"
_DEFAULT_HTTP_PORT = 8888
_DEFAULT_SSL_PORT = 4443
@ -433,11 +435,14 @@ class Automation(object):
manifestFile.write(manifest)
manifestFile.close()
def initializeProfile(self, profileDir, extraPrefs=[],
useServerLocations=False,
initialProfile=None):
def initializeProfile(self, profileDir,
extraPrefs=None,
useServerLocations=False,
initialProfile=None,
prefsPath=_DEFAULT_PREFERENCE_FILE):
" Sets up the standard testing profile."
extraPrefs = extraPrefs or []
prefs = []
# Start with a clean slate.
shutil.rmtree(profileDir, True)
@ -452,125 +457,9 @@ class Automation(object):
self.setupPermissionsDatabase(profileDir,
{'allowXULXBL':[(l.host, 'noxul' not in l.options) for l in locations]});
# NOTE: For refactoring purposes we are temporarily storing these prefs
# in two locations. If you update a pref below, please also update
# it in source/testing/profiles/prefs_general.js.
# See bug 830430 for more details.
part = """\
user_pref("browser.console.showInPanel", true);
user_pref("browser.dom.window.dump.enabled", true);
user_pref("browser.firstrun.show.localepicker", false);
user_pref("browser.firstrun.show.uidiscovery", false);
user_pref("browser.startup.page", 0); // use about:blank, not browser.startup.homepage
user_pref("browser.ui.layout.tablet", 0); // force tablet UI off
user_pref("dom.allow_scripts_to_close_windows", true);
user_pref("dom.disable_open_during_load", false);
user_pref("dom.experimental_forms", true); // on for testing
user_pref("dom.experimental_forms_range", true); // on for testing
user_pref("dom.max_script_run_time", 0); // no slow script dialogs
user_pref("hangmonitor.timeout", 0); // no hang monitor
user_pref("dom.max_chrome_script_run_time", 0);
user_pref("dom.popup_maximum", -1);
user_pref("dom.send_after_paint_to_content", true);
user_pref("dom.successive_dialog_time_limit", 0);
user_pref("signed.applets.codebase_principal_support", true);
user_pref("browser.shell.checkDefaultBrowser", false);
user_pref("shell.checkDefaultClient", false);
user_pref("browser.warnOnQuit", false);
user_pref("accessibility.typeaheadfind.autostart", false);
user_pref("javascript.options.showInConsole", true);
user_pref("devtools.errorconsole.enabled", true);
user_pref("devtools.debugger.remote-port", 6023);
user_pref("layout.debug.enable_data_xbl", true);
user_pref("browser.EULA.override", true);
user_pref("javascript.options.jit_hardening", true);
user_pref("gfx.color_management.force_srgb", true);
user_pref("network.manage-offline-status", false);
user_pref("dom.min_background_timeout_value", 1000);
user_pref("test.mousescroll", true);
user_pref("security.default_personal_cert", "Select Automatically"); // Need to client auth test be w/o any dialogs
user_pref("network.http.prompt-temp-redirect", false);
user_pref("media.cache_size", 100);
user_pref("media.volume_scale", "0.01");
user_pref("security.warn_viewing_mixed", false);
user_pref("app.update.enabled", false);
user_pref("app.update.staging.enabled", false);
user_pref("browser.panorama.experienced_first_run", true); // Assume experienced
user_pref("dom.w3c_touch_events.enabled", 1);
user_pref("dom.undo_manager.enabled", true);
user_pref("dom.webcomponents.enabled", true);
// Set a future policy version to avoid the telemetry prompt.
user_pref("toolkit.telemetry.prompted", 999);
user_pref("toolkit.telemetry.notifiedOptOut", 999);
// Existing tests assume there is no font size inflation.
user_pref("font.size.inflation.emPerLine", 0);
user_pref("font.size.inflation.minTwips", 0);
// Only load extensions from the application and user profile
// AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
user_pref("extensions.enabledScopes", 5);
// Disable metadata caching for installed add-ons by default
user_pref("extensions.getAddons.cache.enabled", false);
// Disable intalling any distribution add-ons
user_pref("extensions.installDistroAddons", false);
user_pref("geo.wifi.uri", "http://%(server)s/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs");
user_pref("geo.wifi.testing", true);
user_pref("geo.ignore.location_filter", true);
user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
// Make url-classifier updates so rare that they won't affect tests
user_pref("urlclassifier.updateinterval", 172800);
// Point the url-classifier to the local testing server for fast failures
user_pref("browser.safebrowsing.gethashURL", "http://%(server)s/safebrowsing-dummy/gethash");
user_pref("browser.safebrowsing.keyURL", "http://%(server)s/safebrowsing-dummy/newkey");
user_pref("browser.safebrowsing.updateURL", "http://%(server)s/safebrowsing-dummy/update");
// Point update checks to the local testing server for fast failures
user_pref("extensions.update.url", "http://%(server)s/extensions-dummy/updateURL");
user_pref("extensions.update.background.url", "http://%(server)s/extensions-dummy/updateBackgroundURL");
user_pref("extensions.blocklist.url", "http://%(server)s/extensions-dummy/blocklistURL");
user_pref("extensions.hotfix.url", "http://%(server)s/extensions-dummy/hotfixURL");
// Turn off extension updates so they don't bother tests
user_pref("extensions.update.enabled", false);
// Make sure opening about:addons won't hit the network
user_pref("extensions.webservice.discoverURL", "http://%(server)s/extensions-dummy/discoveryURL");
// Make sure AddonRepository won't hit the network
user_pref("extensions.getAddons.maxResults", 0);
user_pref("extensions.getAddons.get.url", "http://%(server)s/extensions-dummy/repositoryGetURL");
user_pref("extensions.getAddons.getWithPerformance.url", "http://%(server)s/extensions-dummy/repositoryGetWithPerformanceURL");
user_pref("extensions.getAddons.search.browseURL", "http://%(server)s/extensions-dummy/repositoryBrowseURL");
user_pref("extensions.getAddons.search.url", "http://%(server)s/extensions-dummy/repositorySearchURL");
// Make sure that opening the plugins check page won't hit the network
user_pref("plugins.update.url", "http://%(server)s/plugins-dummy/updateCheckURL");
// Existing tests don't wait for the notification button security delay
user_pref("security.notification_enable_delay", 0);
// Make enablePrivilege continue to work for test code. :-(
user_pref("security.turn_off_all_security_so_that_viruses_can_take_over_this_computer", true);
// In the default configuration, we bypass XBL scopes (a security feature) for
// domains whitelisted for remote XUL, so that intranet apps and such continue
// to work without major rewrites. However, we also use the whitelist mechanism
// to run our XBL tests in automation, in which case we really want to be testing
// the configuration that we ship to users without special whitelisting. So we
// use an additional pref here to allow automation to use the "normal" behavior.
user_pref("dom.use_xbl_scopes_for_remote_xul", true);
// Get network events.
user_pref("network.activity.blipIntervalMilliseconds", 250);
// Don't allow the Data Reporting service to prompt for policy acceptance.
user_pref("datareporting.policy.dataSubmissionPolicyBypassAcceptance", true);
// Point Firefox Health Report at a local server. We don't care if it actually
// works. It just can't hit the default production endpoint.
user_pref("datareporting.healthreport.documentServerURI", "http://%(server)s/healthreport/");
// Make sure CSS error reporting is enabled for tests
user_pref("layout.css.report_errors", true);
""" % { "server" : self.webServer + ":" + str(self.httpPort) }
f = open(prefsPath, 'r')
part = f.read() % {"server" : "%s:%s" % (self.webServer, self.httpPort)}
f.close()
prefs.append(part)
if useServerLocations:
@ -619,16 +508,15 @@ function FindProxyForURL(url, host)
"sslport": self.sslPort }
pacURL = "".join(pacURL.splitlines())
part += """
part = """
user_pref("network.proxy.type", 2);
user_pref("network.proxy.autoconfig_url", "%(pacURL)s");
user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless to others
""" % {"pacURL": pacURL}
prefs.append(part)
else:
part = 'user_pref("network.proxy.type", 0);\n'
prefs.append(part)
prefs.append(part)
for v in extraPrefs:
thispref = v.split("=", 1)

3
build/defines.sh Normal file
Просмотреть файл

@ -0,0 +1,3 @@
# Define indicating that this build is prior to one of the early betas. To be
# unset mid-way through the beta cycle.
EARLY_BETA_OR_EARLIER=1

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

@ -47,6 +47,22 @@ toolkit/library
profile
services
startupcache
browser
toolkit/mozapps/extensions
browser/app
browser/base
browser/components
browser/devtools
browser/locales
browser/modules
browser/themes
toolkit
toolkit/components
toolkit/content
toolkit/crashreporter
toolkit/devtools
toolkit/forgetaboutsite
toolkit/identity
toolkit/modules
toolkit/mozapps/extensions
toolkit/profile
toolkit/themes
toolkit/webapps

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

@ -22,10 +22,17 @@ SEARCH_PATHS = [
'xpcom/idl-parser',
'testing',
'testing/xpcshell',
'testing/marionette/client',
'testing/marionette/client/marionette',
'testing/mozbase/mozcrash',
'testing/mozbase/mozlog',
'testing/mozbase/mozprocess',
'testing/mozbase/mozdevice',
'testing/mozbase/mozfile',
'testing/mozbase/mozhttpd',
'testing/mozbase/mozlog',
'testing/mozbase/moznetwork',
'testing/mozbase/mozprocess',
'testing/mozbase/mozprofile',
'testing/mozbase/mozrunner',
'testing/mozbase/mozinfo',
]
@ -38,6 +45,7 @@ MACH_MODULES = [
'python/mozbuild/mozbuild/config.py',
'python/mozbuild/mozbuild/mach_commands.py',
'python/mozbuild/mozbuild/frontend/mach_commands.py',
'testing/marionette/mach_commands.py',
'testing/mochitest/mach_commands.py',
'testing/xpcshell/mach_commands.py',
'tools/mach_commands.py',

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

@ -25,3 +25,6 @@ if [ -z "$CXX" ]; then
fi
ac_add_options --with-ccache
# Enable ECMAScript Internationalization API
ac_add_options --enable-intl-api

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

@ -120,16 +120,6 @@ class B2GRemoteAutomation(Automation):
self._devicemanager.removeDir(remote_dump_dir)
return crashed
def initializeProfile(self, profileDir, extraPrefs=[],
useServerLocations=False,
initialProfile=None):
# add b2g specific prefs
extraPrefs.extend(["browser.manifestURL='dummy (bug 772307)'"])
return Automation.initializeProfile(self, profileDir,
extraPrefs,
useServerLocations,
initialProfile)
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
# if remote profile is specified, use that instead
if (self._remoteProfile):

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