merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-10-06 11:54:45 +02:00
commit 94701a0be5
113 changed files with 862 additions and 405 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1182727 - Changed toolchain, needs clobber again :(
Bug 1210755 - Android build: Switch to Android 6.0 SDK / API 23

View File

@ -713,7 +713,6 @@
<image id="default-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="identity-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="push-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="login-fill-notification-icon" class="notification-anchor-icon" role="button"/>

View File

@ -6,6 +6,7 @@
position="after_start"
hidden="true"
orient="vertical"
noautofocus="true"
role="alert"/>
<popupnotification id="webRTC-shareDevices-notification" hidden="true">

View File

@ -0,0 +1,7 @@
[DEFAULT]
support-files =
file_dom_notifications.html
[browser_notification_open_settings.js]
[browser_notification_tab_switching.js]
skip-if = buildapp == 'mulet' || e10s # Bug 1100662 - content access causing uncaught exception - Error: cannot ipc non-cpow object at chrome://mochitests/content/browser/browser/base/content/test/general/browser_notification_tab_switching.js:32 (or in RemoteAddonsChild.jsm)

View File

@ -0,0 +1,18 @@
"use strict";
add_task(function* test_settingsOpen() {
info("Opening a dummy tab so openPreferences=>switchToTabHavingURI doesn't use the blank tab.");
yield BrowserTestUtils.withNewTab({
gBrowser,
url: "about:robots"
}, function* dummyTabTask(aBrowser) {
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:preferences#content");
info("simulate a notifications-open-settings notification");
let uri = NetUtil.newURI("https://example.com");
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
Services.obs.notifyObservers(principal, "notifications-open-settings", null);
let tab = yield tabPromise;
ok(tab, "The notification settings tab opened");
BrowserTestUtils.removeTab(tab);
});
});

View File

@ -6,7 +6,7 @@
var tab;
var notification;
var notificationURL = "http://example.org/browser/browser/base/content/test/general/file_dom_notifications.html";
var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
var newWindowOpenedFromTab;
function test () {
@ -58,7 +58,7 @@ function onAlertShowing() {
info("Notification alert showing");
notification.removeEventListener("show", onAlertShowing);
let alertWindow = findChromeWindowByURI("chrome://global/content/alerts/alert.xul");
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
if (!alertWindow) {
todo(false, "Notifications don't use XUL windows on all platforms.");
notification.close();

View File

@ -1,5 +1,6 @@
<html>
<head>
<meta charset="utf-8">
<script>
"use strict";

View File

@ -62,7 +62,6 @@ support-files =
file_bug970276_favicon1.ico
file_bug970276_favicon2.ico
file_documentnavigation_frameset.html
file_dom_notifications.html
file_double_close_tab.html
file_favicon_change.html
file_favicon_change_not_in_document.html
@ -338,8 +337,6 @@ skip-if = os != "win" # The Fitts Law menu button is only supported on Windows (
skip-if = e10s # Bug 1100664 - test directly access content docShells (TypeError: gBrowser.docShell is null)
[browser_mixedcontent_securityflags.js]
tags = mcb
[browser_notification_tab_switching.js]
skip-if = buildapp == 'mulet' || e10s # Bug 1100662 - content access causing uncaught exception - Error: cannot ipc non-cpow object at chrome://mochitests/content/browser/browser/base/content/test/general/browser_notification_tab_switching.js:32 (or in RemoteAddonsChild.jsm)
[browser_offlineQuotaNotification.js]
skip-if = buildapp == 'mulet' || e10s # Bug 1093603 - test breaks with PopupNotifications.panel.firstElementChild is null
[browser_overflowScroll.js]

View File

@ -59,16 +59,6 @@ function whenDelayedStartupFinished(aWindow, aCallback) {
}, "browser-delayed-startup-finished", false);
}
function findChromeWindowByURI(aURI) {
let windows = Services.wm.getEnumerator(null);
while (windows.hasMoreElements()) {
let win = windows.getNext();
if (win.location.href == aURI)
return win;
}
return null;
}
function updateTabContextMenu(tab) {
let menu = document.getElementById("tabContextMenu");
if (!tab)

View File

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

View File

@ -147,7 +147,8 @@ loop.store.ConversationAppStore = (function() {
this._dispatcher.dispatch(new loop.shared.actions.HangupCall());
break;
case "room":
if (this._activeRoomStore.getStoreState().used) {
if (this._activeRoomStore.getStoreState().used &&
!this._storeState.showFeedbackForm) {
this._dispatcher.dispatch(new loop.shared.actions.LeaveRoom());
} else {
loop.shared.mixins.WindowCloseMixin.closeWindow();

View File

@ -404,6 +404,8 @@ loop.conversationViews = (function(mozL10n) {
case FAILURE_DETAILS.TOS_FAILURE:
return mozL10n.get("tos_failure_message",
{ clientShortname: mozL10n.get("clientShortname2") });
case FAILURE_DETAILS.ICE_FAILED:
return mozL10n.get("ice_failure_message");
default:
return mozL10n.get("generic_failure_message");
}

View File

@ -404,6 +404,8 @@ loop.conversationViews = (function(mozL10n) {
case FAILURE_DETAILS.TOS_FAILURE:
return mozL10n.get("tos_failure_message",
{ clientShortname: mozL10n.get("clientShortname2") });
case FAILURE_DETAILS.ICE_FAILED:
return mozL10n.get("ice_failure_message");
default:
return mozL10n.get("generic_failure_message");
}

View File

@ -8,6 +8,7 @@ loop.roomViews = (function(mozL10n) {
var ROOM_STATES = loop.store.ROOM_STATES;
var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
var sharedActions = loop.shared.actions;
var sharedMixins = loop.shared.mixins;
var sharedUtils = loop.shared.utils;
@ -99,6 +100,14 @@ loop.roomViews = (function(mozL10n) {
{ id: "feedback" },
{ id: "help" }
];
var btnTitle;
if (this.props.failureReason === FAILURE_DETAILS.ICE_FAILED) {
btnTitle = mozL10n.get("retry_call_button");
} else {
btnTitle = mozL10n.get("rejoin_button");
}
return (
React.createElement("div", {className: "room-failure"},
React.createElement(loop.conversationViews.FailureInfoView, {
@ -106,7 +115,7 @@ loop.roomViews = (function(mozL10n) {
React.createElement("div", {className: "btn-group call-action-group"},
React.createElement("button", {className: "btn btn-info btn-rejoin",
onClick: this.handleRejoinCall},
mozL10n.get("rejoin_button")
btnTitle
)
),
React.createElement(loop.shared.views.SettingsControlButton, {

View File

@ -8,6 +8,7 @@ loop.roomViews = (function(mozL10n) {
var ROOM_STATES = loop.store.ROOM_STATES;
var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
var sharedActions = loop.shared.actions;
var sharedMixins = loop.shared.mixins;
var sharedUtils = loop.shared.utils;
@ -99,6 +100,14 @@ loop.roomViews = (function(mozL10n) {
{ id: "feedback" },
{ id: "help" }
];
var btnTitle;
if (this.props.failureReason === FAILURE_DETAILS.ICE_FAILED) {
btnTitle = mozL10n.get("retry_call_button");
} else {
btnTitle = mozL10n.get("rejoin_button");
}
return (
<div className="room-failure">
<loop.conversationViews.FailureInfoView
@ -106,7 +115,7 @@ loop.roomViews = (function(mozL10n) {
<div className="btn-group call-action-group">
<button className="btn btn-info btn-rejoin"
onClick={this.handleRejoinCall}>
{mozL10n.get("rejoin_button")}
{btnTitle}
</button>
</div>
<loop.shared.views.SettingsControlButton

View File

@ -928,6 +928,13 @@ loop.OTSdkDriver = (function() {
_onOTException: function(event) {
switch (event.code) {
case OT.ExceptionCodes.PUBLISHER_ICE_WORKFLOW_FAILED:
case OT.ExceptionCodes.SUBSCRIBER_ICE_WORKFLOW_FAILED:
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
reason: FAILURE_DETAILS.ICE_FAILED
}));
this._notifyMetricsEvent("sdk.exception." + event.code);
break;
case OT.ExceptionCodes.UNABLE_TO_PUBLISH:
if (event.message === "GetUserMedia") {
// We free up the publisher here in case the store wants to try

View File

@ -84,7 +84,8 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
// TOS_FAILURE reflects the sdk error code 1026:
// https://tokbox.com/developer/sdks/js/reference/ExceptionEvent.html
TOS_FAILURE: "reason-tos-failure",
UNKNOWN: "reason-unknown"
UNKNOWN: "reason-unknown",
ICE_FAILED: "reason-ice-failed"
};
var ROOM_INFO_FAILURES = {

View File

@ -158,6 +158,8 @@ loop.standaloneRoomViews = (function(mozL10n) {
case FAILURE_DETAILS.TOS_FAILURE:
return mozL10n.get("tos_failure_message",
{ clientShortname: mozL10n.get("clientShortname2") });
case FAILURE_DETAILS.ICE_FAILED:
return mozL10n.get("rooms_ice_failure_message");
default:
return mozL10n.get("status_error");
}

View File

@ -158,6 +158,8 @@ loop.standaloneRoomViews = (function(mozL10n) {
case FAILURE_DETAILS.TOS_FAILURE:
return mozL10n.get("tos_failure_message",
{ clientShortname: mozL10n.get("clientShortname2") });
case FAILURE_DETAILS.ICE_FAILED:
return mozL10n.get("rooms_ice_failure_message");
default:
return mozL10n.get("status_error");
}

View File

@ -72,6 +72,7 @@ rooms_unavailable_notification_message=Sorry, you cannot join this conversation.
rooms_media_denied_message=We could not get access to your microphone or camera. Please reload the page to try again.
room_information_failure_not_available=No information about this conversation is available. Please request a new link from the person who sent it to you.
room_information_failure_unsupported_browser=Your browser cannot access any information about this conversation. Please make sure you're using the latest version.
rooms_ice_failure_message=Connection failed. Your firewall may be blocking calls.
## LOCALIZATION_NOTE(rooms_read_while_wait_offer): This string is followed by a
# tile/offer image and title that are provided by a separate service that has

View File

@ -250,6 +250,19 @@ describe("loop.store.ConversationAppStore", function () {
sinon.assert.notCalled(loop.shared.mixins.WindowCloseMixin.closeWindow);
});
it("should close the window when a room was used and it showed feedback", function() {
store.setStoreState({
showFeedbackForm: true,
windowType: "room"
});
roomUsed = true;
store.LoopHangupNowHandler();
sinon.assert.notCalled(dispatcher.dispatch);
sinon.assert.calledOnce(loop.shared.mixins.WindowCloseMixin.closeWindow);
});
it("should close the window when a room was not used", function() {
store.setStoreState({ windowType: "room" });

View File

@ -351,6 +351,16 @@ describe("loop.conversationViews", function () {
expect(extraFailureMessage.textContent).eql("Fake failure message");
});
it("should display an ICE failure message", function() {
view = mountTestComponent({
failureReason: FAILURE_DETAILS.ICE_FAILED
});
var message = view.getDOMNode().querySelector(".failure-info-message");
expect(message.textContent).eql("ice_failure_message");
});
});
describe("DirectCallFailureView", function() {

View File

@ -142,7 +142,7 @@ describe("loop.roomViews", function () {
function mountTestComponent(props) {
props = _.extend({
dispatcher: dispatcher,
failureReason: FAILURE_DETAILS.UNKNOWN,
failureReason: props && props.failureReason || FAILURE_DETAILS.UNKNOWN,
mozLoop: fakeMozLoop
});
return TestUtils.renderIntoDocument(
@ -177,6 +177,16 @@ describe("loop.roomViews", function () {
new sharedActions.JoinRoom());
});
it("should render retry button when an ice failure is dispatched", function() {
view = mountTestComponent({
failureReason: FAILURE_DETAILS.ICE_FAILED
});
var retryBtn = view.getDOMNode().querySelector(".btn-rejoin");
expect(retryBtn.textContent).eql("retry_call_button");
});
it("should play a failure sound, once", function() {
view = mountTestComponent();

View File

@ -1661,6 +1661,51 @@ describe("loop.OTSdkDriver", function () {
}));
});
});
describe("ICE failed", function() {
it("should dispatch a ConnectionFailure action (Publisher)", function() {
sdk.trigger("exception", {
code: OT.ExceptionCodes.PUBLISHER_ICE_WORKFLOW_FAILED,
message: "ICE failed"
});
sinon.assert.calledTwice(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.ConnectionFailure({
reason: FAILURE_DETAILS.ICE_FAILED
}));
});
it("should dispatch a ConnectionFailure action (Subscriber)", function() {
sdk.trigger("exception", {
code: OT.ExceptionCodes.SUBSCRIBER_ICE_WORKFLOW_FAILED,
message: "ICE failed"
});
sinon.assert.calledTwice(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.ConnectionFailure({
reason: FAILURE_DETAILS.ICE_FAILED
}));
});
it("should notify metrics", function() {
sdk.trigger("exception", {
code: OT.ExceptionCodes.PUBLISHER_ICE_WORKFLOW_FAILED,
message: "ICE failed"
});
sinon.assert.calledTwice(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.ConnectionStatus({
event: "sdk.exception." + OT.ExceptionCodes.PUBLISHER_ICE_WORKFLOW_FAILED,
state: "starting",
connections: 0,
sendStreams: 0,
recvStreams: 0
}));
});
});
});
});

View File

@ -652,6 +652,17 @@ describe("loop.standaloneRoomViews", function() {
TestUtils.findRenderedComponentWithType(view,
loop.standaloneRoomViews.StandaloneRoomFailureView);
});
it("should display ICE failure message", function() {
activeRoomStore.setStoreState({
roomState: ROOM_STATES.FAILED,
failureReason: FAILURE_DETAILS.ICE_FAILED
});
var ice_failed_message = view.getDOMNode().querySelector(".failed-room-message").textContent;
expect(ice_failed_message).eql("rooms_ice_failure_message");
expect(view.getDOMNode().querySelector(".btn-info")).not.eql(null);
});
});
describe("Join button", function() {

View File

@ -276,6 +276,9 @@ BrowserGlue.prototype = {
// nsIObserver implementation
observe: function BG_observe(subject, topic, data) {
switch (topic) {
case "notifications-open-settings":
this._openPreferences("content");
break;
case "prefservice:after-app-defaults":
this._onAppDefaults();
break;
@ -591,6 +594,7 @@ BrowserGlue.prototype = {
// initialization (called on application startup)
_init: function BG__init() {
let os = Services.obs;
os.addObserver(this, "notifications-open-settings", false);
os.addObserver(this, "prefservice:after-app-defaults", false);
os.addObserver(this, "final-ui-startup", false);
os.addObserver(this, "browser-delayed-startup-finished", false);
@ -639,6 +643,7 @@ BrowserGlue.prototype = {
// cleanup (called on application shutdown)
_dispose: function BG__dispose() {
let os = Services.obs;
os.removeObserver(this, "notifications-open-settings");
os.removeObserver(this, "prefservice:after-app-defaults");
os.removeObserver(this, "final-ui-startup");
os.removeObserver(this, "sessionstore-windows-restored");
@ -2361,6 +2366,19 @@ BrowserGlue.prototype = {
}
}),
/**
* Open preferences even if there are no open windows.
*/
_openPreferences(...args) {
if (Services.appShell.hiddenDOMWindow.openPreferences) {
Services.appShell.hiddenDOMWindow.openPreferences(...args);
return;
}
let chromeWindow = RecentWindow.getMostRecentBrowserWindow();
chromeWindow.openPreferences(...args);
},
#ifdef MOZ_SERVICES_SYNC
/**
* Called as an observer when Sync's "display URI" notification is fired.
@ -2534,38 +2552,6 @@ ContentPermissionPrompt.prototype = {
mainAction, secondaryActions, aOptions);
},
_promptPush : function(aRequest) {
var message = gBrowserBundle.GetStringFromName("push.enablePush2");
var actions = [
{
stringId: "push.alwaysAllow",
action: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: null,
callback: function() {}
},
{
stringId: "push.allowForSession",
action: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: Ci.nsIPermissionManager.EXPIRE_SESSION,
callback: function() {}
},
{
stringId: "push.alwaysBlock",
action: Ci.nsIPermissionManager.DENY_ACTION,
expireType: null,
callback: function() {}
}]
var options = {
learnMoreURL: Services.urlFormatter.formatURLPref("browser.push.warning.infoURL"),
};
this._showPrompt(aRequest, message, "push", actions, "push",
"push-notification-icon", options);
},
_promptGeo : function(aRequest) {
var secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
@ -2620,12 +2606,6 @@ ContentPermissionPrompt.prototype = {
var message = gBrowserBundle.GetStringFromName("webNotifications.showFromSite2");
var actions = [
{
stringId: "webNotifications.showForSession",
action: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: Ci.nsIPermissionManager.EXPIRE_SESSION,
callback: function() {},
},
{
stringId: "webNotifications.alwaysShow",
action: Ci.nsIPermissionManager.ALLOW_ACTION,
@ -2640,9 +2620,13 @@ ContentPermissionPrompt.prototype = {
},
];
var options = {
learnMoreURL: Services.urlFormatter.formatURLPref("browser.push.warning.infoURL"),
};
this._showPrompt(aRequest, message, "desktop-notification", actions,
"web-notifications",
"web-notifications-notification-icon", null);
"web-notifications-notification-icon", options);
},
_promptPointerLock: function CPP_promtPointerLock(aRequest, autoAllow) {
@ -2713,7 +2697,6 @@ ContentPermissionPrompt.prototype = {
const kFeatureKeys = { "geolocation" : "geo",
"desktop-notification" : "desktop-notification",
"pointerLock" : "pointerLock",
"push" : "push"
};
// Make sure that we support the request.
@ -2764,9 +2747,6 @@ ContentPermissionPrompt.prototype = {
case "pointerLock":
this._promptPointerLock(request, autoAllow);
break;
case "push":
this._promptPush(request);
break;
}
},

View File

@ -46,7 +46,7 @@ var gVisitStmt = gPlacesDatabase.createAsyncStatement(
* Permission types that should be tested with testExactPermission, as opposed
* to testPermission. This is based on what consumers use to test these permissions.
*/
var TEST_EXACT_PERM_TYPES = ["geo", "camera", "microphone"];
var TEST_EXACT_PERM_TYPES = ["geo", "camera", "microphone", "desktop-notification"];
/**
* Site object represents a single site, uniquely identified by a principal.
@ -321,16 +321,9 @@ var PermissionDefaults = {
Services.prefs.setBoolPref("dom.disable_open_during_load", value);
},
get push() {
if (!Services.prefs.getBoolPref("dom.push.enabled")) {
return this.DENY;
}
get ["desktop-notification"]() {
return this.UNKNOWN;
},
set push(aValue) {
let value = (aValue != this.DENY);
Services.prefs.setBoolPref("dom.push.enabled", value);
},
get camera() {
return this.UNKNOWN;
},
@ -384,17 +377,18 @@ var AboutPermissions = {
* Potential future additions: "sts/use", "sts/subd"
*/
_supportedPermissions: ["password", "cookie", "geo", "indexedDB", "popup",
"camera", "microphone", "push"],
"camera", "microphone", "desktop-notification"],
/**
* Permissions that don't have a global "Allow" option.
*/
_noGlobalAllow: ["geo", "indexedDB", "camera", "microphone", "push"],
_noGlobalAllow: ["geo", "indexedDB", "camera", "microphone",
"desktop-notification"],
/**
* Permissions that don't have a global "Deny" option.
*/
_noGlobalDeny: ["camera", "microphone"],
_noGlobalDeny: ["camera", "microphone", "desktop-notification"],
_stringBundle: Services.strings.
createBundle("chrome://browser/locale/preferences/aboutPermissions.properties"),

View File

@ -239,21 +239,21 @@
</vbox>
</hbox>
<!-- Push Notifications -->
<hbox id="push-pref-item"
<!-- Notifications -->
<hbox id="desktop-notification-pref-item"
class="pref-item" align="top">
<image class="pref-icon" type="push"/>
<image class="pref-icon" type="desktop-notification"/>
<vbox>
<label class="pref-title" value="&push.label;"/>
<label class="pref-title" value="&desktop-notification.label;"/>
<hbox align="center">
<menulist id="push-menulist"
<menulist id="desktop-notification-menulist"
class="pref-menulist"
type="push"
type="desktop-notification"
oncommand="AboutPermissions.onPermissionCommand(event);">
<menupopup>
<menuitem id="push-0" value="0" label="&permission.alwaysAsk;"/>
<menuitem id="push-1" value="1" label="&permission.allow;"/>
<menuitem id="push-2" value="2" label="&permission.block;"/>
<menuitem id="desktop-notification-0" value="0" label="&permission.alwaysAsk;"/>
<menuitem id="desktop-notification-1" value="1" label="&permission.allow;"/>
<menuitem id="desktop-notification-2" value="2" label="&permission.block;"/>
</menupopup>
</menulist>
</hbox>

View File

@ -28,7 +28,7 @@ const TEST_PERMS = {
"password": PERM_ALLOW,
"cookie": PERM_ALLOW,
"geo": PERM_UNKNOWN,
"push": PERM_DENY,
"desktop-notification": PERM_UNKNOWN,
"indexedDB": PERM_UNKNOWN,
"popup": PERM_DENY,
"camera": PERM_UNKNOWN,

View File

@ -119,9 +119,6 @@
<field name="FormHistory" readonly="true">
(Components.utils.import("resource://gre/modules/FormHistory.jsm", {})).FormHistory;
</field>
<field name="PlacesUtils" readonly="true">
(Components.utils.import("resource://gre/modules/PlacesUtils.jsm", {})).PlacesUtils;
</field>
<property name="engines" readonly="true">
<getter><![CDATA[
@ -1445,7 +1442,7 @@
button.id = "searchbar-engine-one-off-item-" + currentEngine.name.replace(/ /g, '-');
let uri = "chrome://browser/skin/search-engine-placeholder.png";
if (currentEngine.iconURI)
uri = PlacesUtils.getImageURLForResolution(window, currentEngine.iconURI.spec);
uri = currentEngine.iconURI.spec;
button.setAttribute("image", uri);
button.setAttribute("tooltiptext", currentEngine.name);
button.engine = currentEngine;

View File

@ -375,23 +375,12 @@ geolocation.neverShareLocation.accesskey=N
geolocation.shareWithSite2=Would you like to share your location with this site?
geolocation.shareWithFile2=Would you like to share your location with this file?
webNotifications.showForSession=Show for this session
webNotifications.showForSession.accesskey=s
webNotifications.alwaysShow=Always Show Notifications
webNotifications.alwaysShow.accesskey=A
webNotifications.neverShow=Always Block Notifications
webNotifications.neverShow.accesskey=N
webNotifications.showFromSite2=Would you like to show notifications from this site?
# Push Notifications
push.allowForSession=Allow for Session
push.allowForSession.accesskey=S
push.alwaysAllow=Always Allow Push Notifications
push.alwaysAllow.accesskey=A
push.alwaysBlock=Always Block Push Notifications
push.alwaysBlock.accesskey=B
push.enablePush2=Would you like to allow Push Notifications for this site?
# Pointer lock UI
pointerLock.allow2=Hide pointer

View File

@ -298,6 +298,7 @@ cannot_start_call_session_not_ready=Can't start call, session is not ready.
network_disconnected=The network connection terminated abruptly.
connection_error_see_console_notification=Call failed; see console for details.
no_media_failure_message=No camera or microphone found.
ice_failure_message=Connection failed. Your firewall may be blocking calls.
## LOCALIZATION NOTE (legal_text_and_links3): In this item, don't translate the
## parts between {{..}} because these will be replaced with links with the labels

View File

@ -41,7 +41,7 @@
<!ENTITY popup.label "Open Pop-up Windows">
<!ENTITY push.label "Receive Push Notifications">
<!ENTITY desktop-notification.label "Show Notifications">
<!ENTITY camera.label "Use the Camera">
<!ENTITY microphone.label "Use the Microphone">

View File

@ -17,4 +17,3 @@ permission.popup.label = Open Pop-up Windows
permission.geo.label = Access Your Location
permission.indexedDB.label = Maintain Offline Storage
permission.pointerLock.label = Hide the Mouse Pointer
permission.push.label = Receive Push Notifications

View File

@ -161,7 +161,9 @@ var gPermissionObject = {
}
},
"desktop-notification": {},
"desktop-notification": {
exactHostMatch: true
},
"camera": {},
"microphone": {},
@ -188,9 +190,5 @@ var gPermissionObject = {
"pointerLock": {
exactHostMatch: true
},
"push": {
exactHostMatch: true
}
};

View File

@ -8,7 +8,6 @@ Components.utils.import("resource:///modules/SitePermissions.jsm");
add_task(function* testPermissionsListing() {
Assert.deepEqual(SitePermissions.listPermissions().sort(),
["camera","cookie","desktop-notification","geo","image",
"indexedDB","install","microphone","pointerLock","popup",
"push"],
"indexedDB","install","microphone","pointerLock","popup"],
"Correct list of all permissions");
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -23,8 +23,6 @@ browser.jar:
skin/classic/browser/content-contextmenu.svg
skin/classic/browser/Geolocation-16.png
skin/classic/browser/Geolocation-64.png
skin/classic/browser/Push-16.png
skin/classic/browser/Push-64.png
skin/classic/browser/Info.png
skin/classic/browser/menuPanel.png
skin/classic/browser/menuPanel@2x.png
@ -38,8 +36,6 @@ browser.jar:
skin/classic/browser/menuPanel-small@2x.png
skin/classic/browser/monitor.png
skin/classic/browser/monitor_16-10.png
skin/classic/browser/notification-16.png
skin/classic/browser/notification-64.png
* skin/classic/browser/pageInfo.css
skin/classic/browser/pageInfo.png
skin/classic/browser/page-livemarks.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -94,8 +94,8 @@
.pref-icon[type="geo"] {
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.pref-icon[type="push"] {
list-style-image: url(chrome://browser/skin/Push-64.png);
.pref-icon[type="desktop-notification"] {
list-style-image: url(chrome://browser/skin/web-notifications-icon.svg);
}
.pref-icon[type="indexedDB"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -25,10 +25,6 @@ browser.jar:
skin/classic/browser/Geolocation-16@2x.png
skin/classic/browser/Geolocation-64.png
skin/classic/browser/Geolocation-64@2x.png
skin/classic/browser/Push-16.png
skin/classic/browser/Push-16@2x.png
skin/classic/browser/Push-64.png
skin/classic/browser/Push-64@2x.png
skin/classic/browser/Info.png
skin/classic/browser/keyhole-circle.png
skin/classic/browser/keyhole-circle@2x.png
@ -36,10 +32,6 @@ browser.jar:
skin/classic/browser/subtle-pattern.png
skin/classic/browser/menu-back.png
skin/classic/browser/menu-forward.png
skin/classic/browser/notification-16.png
skin/classic/browser/notification-16@2x.png
skin/classic/browser/notification-64.png
skin/classic/browser/notification-64@2x.png
skin/classic/browser/menuPanel.png
skin/classic/browser/menuPanel@2x.png
skin/classic/browser/menuPanel-customize.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -104,8 +104,8 @@
.pref-icon[type="geo"] {
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.pref-icon[type="push"] {
list-style-image: url(chrome://browser/skin/Push-64.png);
.pref-icon[type="desktop-notification"] {
list-style-image: url(chrome://browser/skin/web-notifications-icon.svg);
}
.pref-icon[type="indexedDB"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);

View File

@ -127,6 +127,8 @@
skin/classic/browser/notification-pluginAlert@2x.png (../shared/plugins/notification-pluginAlert@2x.png)
skin/classic/browser/notification-pluginBlocked.png (../shared/plugins/notification-pluginBlocked.png)
skin/classic/browser/notification-pluginBlocked@2x.png (../shared/plugins/notification-pluginBlocked@2x.png)
skin/classic/browser/web-notifications-icon.svg (../shared/web-notifications-icon.svg)
skin/classic/browser/web-notifications-tray.svg (../shared/web-notifications-tray.svg)
skin/classic/browser/webRTC-shareDevice-16.png (../shared/webrtc/webRTC-shareDevice-16.png)
skin/classic/browser/webRTC-shareDevice-16@2x.png (../shared/webrtc/webRTC-shareDevice-16@2x.png)
skin/classic/browser/webRTC-shareDevice-64.png (../shared/webrtc/webRTC-shareDevice-64.png)

View File

@ -14,10 +14,6 @@
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.popup-notification-icon[popupid="push"] {
list-style-image: url(chrome://browser/skin/Push-64.png);
}
.popup-notification-icon[popupid="xpinstall-disabled"],
.popup-notification-icon[popupid="addon-install-blocked"],
.popup-notification-icon[popupid="addon-install-origin-blocked"] {
@ -53,7 +49,7 @@
}
.popup-notification-icon[popupid="web-notifications"] {
list-style-image: url(chrome://browser/skin/notification-64.png);
list-style-image: url(chrome://browser/skin/web-notifications-icon.svg);
}
.popup-notification-icon[popupid="indexedDB-permissions-prompt"],
@ -142,10 +138,6 @@
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
}
#push-notification-icon {
list-style-image: url(chrome://browser/skin/Push-16.png);
}
#addons-notification-icon {
list-style-image: url(chrome://browser/skin/addons/addon-install-anchor.svg#default);
}
@ -254,7 +246,18 @@
.web-notifications-notification-icon,
#web-notifications-notification-icon {
list-style-image: url(chrome://browser/skin/notification-16.png);
list-style-image: url(chrome://browser/skin/web-notifications-tray.svg);
-moz-image-region: rect(0, 16px, 16px, 0);
}
.web-notifications-notification-icon:hover,
#web-notifications-notification-icon:hover {
-moz-image-region: rect(0, 32px, 16px, 16px);
}
.web-notifications-notification-icon:hover:active,
#web-notifications-notification-icon:hover:active {
-moz-image-region: rect(0, 48px, 16px, 32px);
}
.pointerLock-notification-icon,
@ -369,10 +372,6 @@
list-style-image: url(chrome://browser/skin/Geolocation-16@2x.png);
}
#push-notification-icon {
list-style-image: url(chrome://browser/skin/Push-16@2x.png);
}
.indexedDB-notification-icon,
#indexedDB-notification-icon {
list-style-image: url(chrome://global/skin/icons/question-32.png);
@ -412,11 +411,6 @@
-moz-image-region: rect(0, 96px, 32px, 64px);
}
.web-notifications-notification-icon,
#web-notifications-notification-icon {
list-style-image: url(chrome://browser/skin/notification-16@2x.png);
}
.pointerLock-notification-icon,
#pointerLock-notification-icon {
list-style-image: url(chrome://browser/skin/pointerLock-16@2x.png);
@ -438,14 +432,6 @@
list-style-image: url(chrome://browser/skin/Geolocation-64@2x.png);
}
.popup-notification-icon[popupid="push"] {
list-style-image: url(chrome://browser/skin/Push-64@2x.png);
}
.popup-notification-icon[popupid="web-notifications"] {
list-style-image: url(chrome://browser/skin/notification-64@2x.png);
}
.popup-notification-icon[popupid="pointerLock"] {
list-style-image: url(chrome://browser/skin/pointerLock-64@2x.png);
}

View File

@ -84,7 +84,7 @@
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#minimize-hover");
}
:hover,:hover:active) {
.chat-minimize-button:hover:active {
list-style-image: url("chrome://browser/skin/social/chat-icons.svg#minimize-active");
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-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/. -->
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid" width="64" height="64" viewBox="0 0 64 64">
<defs>
<style>
.icon {
fill: #a6a6a6;
fill-rule: evenodd;
}
</style>
</defs>
<path d="M57,48 L46,48 L46,60.016 L32.482,48 L7,48 C5.343,48 4,46.657 4,45 L4,11.031 C4,9.374 5.343,8.031 7,8.031 L57,8.031 C58.657,8.031 60,9.374 60,11.031 L60,45 C60,46.657 58.657,48 57,48 ZM36,16.031 C36,14.927 35.105,14.031 34,14.031 L30,14.031 C28.895,14.031 28,14.927 28,16.031 L28,30.031 C28,31.136 28.895,32.031 30,32.031 L34,32.031 C35.105,32.031 36,31.136 36,30.031 L36,16.031 ZM36,37.5 C36,36.672 35.328,36 34.5,36 L29.5,36 C28.672,36 28,36.672 28,37.5 L28,40.5 C28,41.328 28.672,42 29.5,42 L34.5,42 C35.328,42 36,41.328 36,40.5 L36,37.5 Z" class="icon"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-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/. -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="16" viewBox="0 0 96 32">
<defs>
<style>
.style-icon-notification {
fill: #666666;
}
.style-icon-notification.hover {
fill: #808080;
}
.style-icon-notification.active {
fill: #4d4d4d;
}
</style>
<path id="shape-notifcations-push" d="M27,23.969 L24,23.969 L24,29.977 L17.241,23.969 L5,23.969 C3.343,23.969 2,22.626 2,20.969 L2,6.969 C2,5.312 3.343,3.969 5,3.969 L27,3.969 C28.657,3.969 30,5.312 30,6.969 L30,20.969 C30,22.626 28.657,23.969 27,23.969 ZM18,8.969 C18,7.864 17.105,6.969 16,6.969 C14.895,6.969 14,7.864 14,8.969 L14,13.969 C14,15.073 14.895,15.969 16,15.969 C17.105,15.969 18,15.073 18,13.969 L18,8.969 ZM16.5,17.969 L15.5,17.969 C14.672,17.969 14,18.640 14,19.469 C14,20.297 14.672,20.969 15.5,20.969 L16.5,20.969 C17.328,20.969 18,20.297 18,19.469 C18,18.640 17.328,17.969 16.5,17.969 Z"/>
</defs>
<use xlink:href="#shape-notifcations-push" class="style-icon-notification"/>
<use xlink:href="#shape-notifcations-push" transform="translate(32)" class="style-icon-notification hover"/>
<use xlink:href="#shape-notifcations-push" transform="translate(64)" class="style-icon-notification active"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -25,8 +25,6 @@ browser.jar:
skin/classic/browser/content-contextmenu.svg
skin/classic/browser/Geolocation-16.png
skin/classic/browser/Geolocation-64.png
skin/classic/browser/Push-16.png
skin/classic/browser/Push-64.png
skin/classic/browser/Info.png
skin/classic/browser/Info-XP.png
skin/classic/browser/keyhole-forward-mask.svg
@ -53,8 +51,6 @@ browser.jar:
skin/classic/browser/menuPanel-small-aero@2x.png
skin/classic/browser/monitor.png
skin/classic/browser/monitor_16-10.png
skin/classic/browser/notification-16.png
skin/classic/browser/notification-64.png
skin/classic/browser/pageInfo.css
skin/classic/browser/pageInfo.png
skin/classic/browser/pageInfo-XP.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -98,8 +98,8 @@
.pref-icon[type="geo"] {
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.pref-icon[type="push"] {
list-style-image: url(chrome://browser/skin/Push-64.png);
.pref-icon[type="desktop-notification"] {
list-style-image: url(chrome://browser/skin/web-notifications-icon.svg);
}
.pref-icon[type="indexedDB"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);

View File

@ -295,8 +295,9 @@ AC_DEFUN([MOZ_ANDROID_GOOGLE_PLAY_SERVICES],
if test -n "$MOZ_NATIVE_DEVICES" ; then
AC_SUBST(MOZ_NATIVE_DEVICES)
MOZ_ANDROID_AAR(play-services-base, 7.8.0, google, com/google/android/gms)
MOZ_ANDROID_AAR(play-services-cast, 7.8.0, google, com/google/android/gms)
MOZ_ANDROID_AAR(play-services-base, 8.1.0, google, com/google/android/gms)
MOZ_ANDROID_AAR(play-services-basement, 8.1.0, google, com/google/android/gms)
MOZ_ANDROID_AAR(play-services-cast, 8.1.0, google, com/google/android/gms)
MOZ_ANDROID_AAR(mediarouter-v7, 22.2.1, android, com/android/support, REQUIRED_INTERNAL_IMPL)
fi

View File

@ -4095,7 +4095,7 @@ if test -z "$gonkdir" ; then
;;
esac
MOZ_ANDROID_SDK(22, 22.0.1)
MOZ_ANDROID_SDK(23, 23.0.1)
;;
esac
fi

View File

@ -10,7 +10,7 @@ const {Connection} = require("devtools/shared/client/connection-manager");
const {RuntimeTypes} = require("devtools/client/webide/modules/runtimes");
const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/webide.properties");
const UNRESTRICTED_HELP_URL = "https://developer.mozilla.org/docs/Tools/WebIDE#Unrestricted_app_debugging_%28including_certified_apps.2C_main_process.2C_etc.%29";
const UNRESTRICTED_HELP_URL = "https://developer.mozilla.org/docs/Tools/WebIDE/Running_and_debugging_apps#Unrestricted_app_debugging_%28including_certified_apps_main_process_etc.%29";
window.addEventListener("load", function onLoad() {
window.removeEventListener("load", onLoad);

View File

@ -1161,6 +1161,15 @@ NotificationObserver::Observe(nsISupports* aSubject, const char* aTopic,
}
permissionManager->RemoveFromPrincipal(mPrincipal, "desktop-notification");
return NS_OK;
} else if (!strcmp("alertsettingscallback", aTopic)) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (!obs) {
return NS_ERROR_FAILURE;
}
// Notify other observers so they can show settings UI.
obs->NotifyObservers(mPrincipal, "notifications-open-settings", nullptr);
return NS_OK;
}
return mObserver->Observe(aSubject, aTopic, aData);
@ -1630,9 +1639,9 @@ Notification::GetPermissionInternal(nsIPrincipal* aPrincipal,
nsCOMPtr<nsIPermissionManager> permissionManager =
services::GetPermissionManager();
permissionManager->TestPermissionFromPrincipal(aPrincipal,
"desktop-notification",
&permission);
permissionManager->TestExactPermissionFromPrincipal(aPrincipal,
"desktop-notification",
&permission);
// Convert the result to one of the enum types.
switch (permission) {

View File

@ -12,7 +12,8 @@ namespace dom {
const char* kPermissionTypes[] = {
"geo",
"desktop-notification",
"push",
// Alias `push` to `desktop-notification`.
"desktop-notification",
"midi"
};

View File

@ -23,7 +23,7 @@ SimpleTest.waitForExplicitFinish();
const PERMISSIONS = [
{ name: 'geolocation', perm: 'geo' },
{ name: 'notifications', perm: 'desktop-notification' },
{ name: 'push', perm: 'push' },
{ name: 'push', perm: 'desktop-notification' },
];
const UNSUPPORTED_PERMISSIONS = [

View File

@ -67,13 +67,13 @@ Push.prototype = {
askPermission: function (aAllowCallback, aCancelCallback) {
debug("askPermission");
let principal = this._window.document.nodePrincipal;
let type = "push";
let permValue =
Services.perms.testExactPermissionFromPrincipal(principal, type);
let permValue = Services.perms.testExactPermissionFromPrincipal(
this._principal,
"desktop-notification"
);
if (permValue == Ci.nsIPermissionManager.ALLOW_ACTION) {
aAllowCallback();
aAllowCallback();
return;
}
@ -83,8 +83,8 @@ Push.prototype = {
}
// Create an array with a single nsIContentPermissionType element.
type = {
type: "push",
let type = {
type: "desktop-notification",
access: null,
options: [],
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionType])
@ -95,7 +95,7 @@ Push.prototype = {
// create a nsIContentPermissionRequest
let request = {
types: typeArray,
principal: principal,
principal: this._principal,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionRequest]),
allow: function() {
let histogram = Services.telemetry.getHistogramById("PUSH_API_PERMISSION_GRANTED");
@ -182,11 +182,8 @@ Push.prototype = {
let permission = Ci.nsIPermissionManager.DENY_ACTION;
try {
let permissionManager = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
permission =
permissionManager.testExactPermissionFromPrincipal(this._principal,
"push");
permission = Services.perms.testExactPermissionFromPrincipal(
this._principal, "desktop-notification");
} catch(e) {
reject();
return;

View File

@ -592,7 +592,7 @@ public:
uint32_t permission = nsIPermissionManager::DENY_ACTION;
nsresult rv = permManager->TestExactPermissionFromPrincipal(
principal,
"push",
"desktop-notification",
&permission);
if (NS_WARN_IF(NS_FAILED(rv)) || permission != nsIPermissionManager::ALLOW_ACTION) {
@ -732,28 +732,20 @@ public:
mozilla::services::GetPermissionManager();
nsresult rv = NS_ERROR_FAILURE;
PushPermissionState state = PushPermissionState::Denied;
PushPermissionState state = PushPermissionState::Prompt;
if (permManager) {
uint32_t permission = nsIPermissionManager::DENY_ACTION;
uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
rv = permManager->TestExactPermissionFromPrincipal(
mProxy->GetWorkerPrivate()->GetPrincipal(),
"push",
"desktop-notification",
&permission);
if (NS_SUCCEEDED(rv)) {
switch (permission) {
case nsIPermissionManager::ALLOW_ACTION:
state = PushPermissionState::Granted;
break;
case nsIPermissionManager::DENY_ACTION:
state = PushPermissionState::Denied;
break;
case nsIPermissionManager::PROMPT_ACTION:
state = PushPermissionState::Prompt;
break;
default:
MOZ_CRASH("Unexpected case!");
if (permission == nsIPermissionManager::ALLOW_ACTION) {
state = PushPermissionState::Granted;
} else if (permission == nsIPermissionManager::DENY_ACTION) {
state = PushPermissionState::Denied;
}
}
}

View File

@ -160,21 +160,13 @@ PushRecord.prototype = {
return false;
},
/**
* Returns the push permission state for the principal associated with
* this registration.
*/
pushPermission() {
return Services.perms.testExactPermissionFromPrincipal(
this.principal, "push");
},
/**
* Indicates whether the registration can deliver push messages to its
* associated service worker.
*/
hasPermission() {
let permission = this.pushPermission();
let permission = Services.perms.testExactPermissionFromPrincipal(
this.principal, "desktop-notification");
return permission == Ci.nsIPermissionManager.ALLOW_ACTION;
},

View File

@ -179,7 +179,7 @@ http://creativecommons.org/licenses/publicdomain/
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
SpecialPowers.addPermission('push', true, document);
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>
</body>

View File

@ -65,7 +65,7 @@ http://creativecommons.org/licenses/publicdomain/
}).then(SimpleTest.finish);
}
SpecialPowers.addPermission('push', false, document);
SpecialPowers.addPermission("desktop-notification", false, document);
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],

View File

@ -125,7 +125,7 @@ http://creativecommons.org/licenses/publicdomain/
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
SpecialPowers.addPermission('push', true, document);
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>
</body>

View File

@ -119,7 +119,7 @@ http://creativecommons.org/licenses/publicdomain/
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
SpecialPowers.addPermission('push', true, document);
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>
</body>

View File

@ -107,7 +107,7 @@ var defaultServerURL = SpecialPowers.getCharPref("dom.push.serverURL");
["dom.serviceWorkers.testing.enabled", true],
["dom.push.serverURL", "wss://something.org"]
]}, runTest);
SpecialPowers.addPermission('push', true, document);
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>
</body>

View File

@ -71,13 +71,33 @@ http://creativecommons.org/licenses/publicdomain/
}
function checkPermissionState(swr) {
return swr.pushManager.permissionState().then(function(state) {
ok(state === "denied", "permissionState() should resolve to denied.");
return swr;
}).catch(function(e) {
ok(false, "permissionState() should resolve to denied.");
return swr;
});
var permissionManager = SpecialPowers.Ci.nsIPermissionManager;
var tests = [{
action: permissionManager.ALLOW_ACTION,
state: "granted",
}, {
action: permissionManager.DENY_ACTION,
state: "denied",
}, {
action: permissionManager.PROMPT_ACTION,
state: "prompt",
}, {
action: permissionManager.UNKNOWN_ACTION,
state: "prompt",
}];
return tests.reduce((promise, test) => {
return promise.then(function() {
if (test.action == permissionManager.UNKNOWN_ACTION) {
SpecialPowers.removePermission("desktop-notification", document);
} else {
SpecialPowers.addPermission("desktop-notification",
test.action, document);
}
return swr.pushManager.permissionState().then(state => {
is(state, test.state, JSON.stringify(test));
});
});
}, Promise.resolve());
}
function runTest() {
@ -91,7 +111,7 @@ http://creativecommons.org/licenses/publicdomain/
}).then(SimpleTest.finish);
}
SpecialPowers.addPermission('push', false, document);
SpecialPowers.addPermission("desktop-notification", false, document);
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],

View File

@ -131,7 +131,7 @@ http://creativecommons.org/licenses/publicdomain/
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
SpecialPowers.addPermission('push', true, document);
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>
</body>

View File

@ -293,7 +293,7 @@ http://creativecommons.org/licenses/publicdomain/
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
SpecialPowers.addPermission('push', true, document);
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>
</body>

View File

@ -85,7 +85,7 @@ http://creativecommons.org/licenses/publicdomain/
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
SpecialPowers.addPermission('push', true, document);
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>
</body>

View File

@ -66,6 +66,7 @@ JAVA_CLASSPATH += \
ifdef MOZ_NATIVE_DEVICES
JAVA_CLASSPATH += \
$(ANDROID_PLAY_SERVICES_BASE_AAR_LIB) \
$(ANDROID_PLAY_SERVICES_BASEMENT_AAR_LIB) \
$(ANDROID_PLAY_SERVICES_CAST_AAR_LIB) \
$(ANDROID_MEDIAROUTER_V7_AAR_LIB) \
$(ANDROID_MEDIAROUTER_V7_AAR_INTERNAL_LIB) \
@ -86,6 +87,7 @@ java_bundled_libs := \
ifdef MOZ_NATIVE_DEVICES
java_bundled_libs += \
$(ANDROID_PLAY_SERVICES_BASE_AAR_LIB) \
$(ANDROID_PLAY_SERVICES_BASEMENT_AAR_LIB) \
$(ANDROID_PLAY_SERVICES_CAST_AAR_LIB) \
$(ANDROID_MEDIAROUTER_V7_AAR_LIB) \
$(ANDROID_MEDIAROUTER_V7_AAR_INTERNAL_LIB) \
@ -372,6 +374,7 @@ generated/android/support/v7/appcompat/R.java: .aapt.deps ;
generated/android/support/v7/mediarouter/R.java: .aapt.deps ;
generated/android/support/v7/recyclerview/R.java: .aapt.deps ;
generated/com/google/android/gms/R.java: .aapt.deps ;
generated/com/google/android/gms/base/R.java: .aapt.deps ;
generated/com/google/android/gms/cast/R.java: .aapt.deps ;
gecko.ap_: .aapt.deps ;

View File

@ -14,6 +14,7 @@ import java.util.Locale;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.annotation.RobocopTarget;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.GeckoAppShell;
@ -25,6 +26,7 @@ import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserContract.History;
import org.mozilla.gecko.db.BrowserContract.URLColumns;
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
@ -35,6 +37,7 @@ import org.mozilla.gecko.util.StringUtils;
import org.mozilla.gecko.util.ThreadUtils;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
@ -94,6 +97,7 @@ public class BrowserSearch extends HomeFragment
// AsyncTask loader ID for suggestion query
private static final int LOADER_ID_SUGGESTION = 1;
private static final int LOADER_ID_SAVED_SUGGESTION = 2;
// Timeout for the suggestion client to respond
private static final int SUGGESTION_TIMEOUT = 3000;
@ -137,6 +141,9 @@ public class BrowserSearch extends HomeFragment
// Access to this member must only occur from the UI thread.
private List<SearchEngine> mSearchEngines;
// Search history suggestions
private ArrayList<String> mSearchHistorySuggestions;
// Track the locale that was last in use when we filled mSearchEngines.
// Access to this member must only occur from the UI thread.
private Locale mLastLocale;
@ -148,7 +155,8 @@ public class BrowserSearch extends HomeFragment
private CursorLoaderCallbacks mCursorLoaderCallbacks;
// Callbacks used for the search suggestion loader
private SuggestionLoaderCallbacks mSuggestionLoaderCallbacks;
private SearchEngineSuggestionLoaderCallbacks mSearchEngineSuggestionLoaderCallbacks;
private SearchHistorySuggestionLoaderCallbacks mSearchHistorySuggestionLoaderCallback;
// Autocomplete handler used when filtering results
private AutocompleteHandler mAutocompleteHandler;
@ -220,6 +228,7 @@ public class BrowserSearch extends HomeFragment
super.onCreate(savedInstanceState);
mSearchEngines = new ArrayList<SearchEngine>();
mSearchHistorySuggestions = new ArrayList<>();
}
@Override
@ -355,7 +364,8 @@ public class BrowserSearch extends HomeFragment
mList.setAdapter(mAdapter);
// Only create an instance when we need it
mSuggestionLoaderCallbacks = null;
mSearchEngineSuggestionLoaderCallbacks = null;
mSearchHistorySuggestionLoaderCallback = null;
// Create callbacks before the initial loader is started
mCursorLoaderCallbacks = new CursorLoaderCallbacks();
@ -519,11 +529,20 @@ public class BrowserSearch extends HomeFragment
return;
}
if (mSuggestionLoaderCallbacks == null) {
mSuggestionLoaderCallbacks = new SuggestionLoaderCallbacks();
// Suggestions from search engine
if (mSearchEngineSuggestionLoaderCallbacks == null) {
mSearchEngineSuggestionLoaderCallbacks = new SearchEngineSuggestionLoaderCallbacks();
}
getLoaderManager().restartLoader(LOADER_ID_SUGGESTION, null, mSearchEngineSuggestionLoaderCallbacks);
getLoaderManager().restartLoader(LOADER_ID_SUGGESTION, null, mSuggestionLoaderCallbacks);
// Start search history suggestions query only in nightly. Bug 1201325
if (AppConstants.NIGHTLY_BUILD) {
// Saved suggestions
if (mSearchHistorySuggestionLoaderCallback == null) {
mSearchHistorySuggestionLoaderCallback = new SearchHistorySuggestionLoaderCallbacks();
}
getLoaderManager().restartLoader(LOADER_ID_SAVED_SUGGESTION, null, mSearchHistorySuggestionLoaderCallback);
}
}
private void setSuggestions(ArrayList<String> suggestions) {
@ -533,6 +552,13 @@ public class BrowserSearch extends HomeFragment
mAdapter.notifyDataSetChanged();
}
private void setSavedSuggestions(ArrayList<String> savedSuggestions) {
ThreadUtils.assertOnUiThread();
mSearchHistorySuggestions = savedSuggestions;
mAdapter.notifyDataSetChanged();
}
private void setSearchEngines(JSONObject data) {
ThreadUtils.assertOnUiThread();
@ -788,22 +814,15 @@ public class BrowserSearch extends HomeFragment
}
}
private static class SuggestionAsyncLoader extends AsyncTaskLoader<ArrayList<String>> {
private final SuggestClient mSuggestClient;
private final String mSearchTerm;
abstract private static class SuggestionAsyncLoader extends AsyncTaskLoader<ArrayList<String>> {
protected final String mSearchTerm;
private ArrayList<String> mSuggestions;
public SuggestionAsyncLoader(Context context, SuggestClient suggestClient, String searchTerm) {
public SuggestionAsyncLoader(Context context, String searchTerm) {
super(context);
mSuggestClient = suggestClient;
mSearchTerm = searchTerm;
}
@Override
public ArrayList<String> loadInBackground() {
return mSuggestClient.query(mSearchTerm);
}
@Override
public void deliverResult(ArrayList<String> suggestions) {
mSuggestions = suggestions;
@ -838,6 +857,58 @@ public class BrowserSearch extends HomeFragment
}
}
private static class SearchEngineSuggestionAsyncLoader extends SuggestionAsyncLoader {
private final SuggestClient mSuggestClient;
public SearchEngineSuggestionAsyncLoader(Context context, SuggestClient suggestClient, String searchTerm) {
super(context, searchTerm);
mSuggestClient = suggestClient;
}
@Override
public ArrayList<String> loadInBackground() {
return mSuggestClient.query(mSearchTerm);
}
}
private static class SearchHistorySuggestionAsyncLoader extends SuggestionAsyncLoader {
public SearchHistorySuggestionAsyncLoader(Context context, String searchTerm) {
super(context, searchTerm);
}
@Override
public ArrayList<String> loadInBackground() {
final ContentResolver cr = getContext().getContentResolver();
String[] columns = new String[] { BrowserContract.SearchHistory.QUERY };
String actualQuery = BrowserContract.SearchHistory.QUERY + " LIKE ?";
String[] queryArgs = new String[] { '%' + mSearchTerm + '%' };
final int maxSavedSuggestions = getContext().getResources().getInteger(R.integer.max_saved_suggestions);
final String sortOrderAndLimit = BrowserContract.SearchHistory.DATE +" DESC LIMIT " + maxSavedSuggestions;
final Cursor result = cr.query(BrowserContract.SearchHistory.CONTENT_URI, columns, actualQuery, queryArgs, sortOrderAndLimit);
if (result == null) {
return new ArrayList<>();
}
final ArrayList<String> savedSuggestions = new ArrayList<>();
try {
if (result.moveToFirst()) {
final int searchColumn = result.getColumnIndexOrThrow(BrowserContract.SearchHistory.QUERY);
do {
final String savedSearch = result.getString(searchColumn);
savedSuggestions.add(savedSearch);
} while (result.moveToNext());
}
} finally {
result.close();
}
return savedSuggestions;
}
}
private class SearchAdapter extends MultiTypeCursorAdapter {
private static final int ROW_SEARCH = 0;
private static final int ROW_STANDARD = 1;
@ -915,8 +986,9 @@ public class BrowserSearch extends HomeFragment
row.setSearchTerm(mSearchTerm);
final SearchEngine engine = mSearchEngines.get(position);
final boolean animate = (mAnimateSuggestions && engine.hasSuggestions());
row.updateSuggestions(mSuggestionsEnabled, engine, mSearchTerm, animate);
final boolean haveSuggestions = (engine.hasSuggestions() || !mSearchHistorySuggestions.isEmpty());
final boolean animate = (mAnimateSuggestions && haveSuggestions);
row.updateSuggestions(mSuggestionsEnabled, engine, mSearchHistorySuggestions, animate);
if (animate) {
// Only animate suggestions the first time they are shown
mAnimateSuggestions = false;
@ -955,13 +1027,13 @@ public class BrowserSearch extends HomeFragment
}
}
private class SuggestionLoaderCallbacks implements LoaderCallbacks<ArrayList<String>> {
private class SearchEngineSuggestionLoaderCallbacks implements LoaderCallbacks<ArrayList<String>> {
@Override
public Loader<ArrayList<String>> onCreateLoader(int id, Bundle args) {
// mSuggestClient is set to null in onDestroyView(), so using it
// safely here relies on the fact that onCreateLoader() is called
// synchronously in restartLoader().
return new SuggestionAsyncLoader(getActivity(), mSuggestClient, mSearchTerm);
return new SearchEngineSuggestionAsyncLoader(getActivity(), mSuggestClient, mSearchTerm);
}
@Override
@ -975,6 +1047,26 @@ public class BrowserSearch extends HomeFragment
}
}
private class SearchHistorySuggestionLoaderCallbacks implements LoaderCallbacks<ArrayList<String>> {
@Override
public Loader<ArrayList<String>> onCreateLoader(int id, Bundle args) {
// mSuggestClient is set to null in onDestroyView(), so using it
// safely here relies on the fact that onCreateLoader() is called
// synchronously in restartLoader().
return new SearchHistorySuggestionAsyncLoader(getActivity(), mSearchTerm);
}
@Override
public void onLoadFinished(Loader<ArrayList<String>> loader, ArrayList<String> suggestions) {
setSavedSuggestions(suggestions);
}
@Override
public void onLoaderReset(Loader<ArrayList<String>> loader) {
setSavedSuggestions(new ArrayList<String>());
}
}
private static class ListSelectionListener implements View.OnFocusChangeListener,
AdapterView.OnItemSelectedListener {
private SearchEngineRow mSelectedEngineRow;

View File

@ -6,7 +6,6 @@
package org.mozilla.gecko.home;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.db.BrowserContract.SearchHistory;
import org.mozilla.gecko.GeckoSharedPrefs;
import org.mozilla.gecko.R;
import org.mozilla.gecko.Telemetry;
@ -22,8 +21,6 @@ import org.mozilla.gecko.widget.AnimatedHeightLayout;
import org.mozilla.gecko.widget.FaviconView;
import org.mozilla.gecko.widget.FlowLayout;
import android.database.Cursor;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
@ -37,6 +34,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.EnumSet;
import java.util.List;
class SearchEngineRow extends AnimatedHeightLayout {
// Duration for fade-in animation
@ -242,55 +240,26 @@ class SearchEngineRow extends AnimatedHeightLayout {
/**
* Displays search suggestions from previous searches.
*
* @param c The Cursor to iterate over for saved search suggestion to display
* @param savedSuggestions The List to iterate over for saved search suggestions to display
* @param suggestionCounter global index of where to start adding suggestion "buttons" in the search engine row
* @param animate whether or not to animate suggestions for visual polish
* @param recycledSuggestionCount How many suggestion "button" views we could recycle from previous calls
*/
private void updateFromSavedSearches(Cursor c, boolean animate, int suggestionCounter, int recycledSuggestionCount) {
if (c == null) {
private void updateFromSavedSearches(List<String> savedSuggestions, boolean animate, int suggestionCounter, int recycledSuggestionCount) {
if (savedSuggestions == null || savedSuggestions.isEmpty()) {
return;
}
try {
if (c.moveToFirst()) {
final int searchColumn = c.getColumnIndexOrThrow(SearchHistory.QUERY);
final int historyStartIndex = suggestionCounter;
do {
final String savedSearch = c.getString(searchColumn);
// suggestionCounter counts all suggestions (from history and the search engine)
// but we want the relative position of the history item in telemetry
String telemetryTag = "history." + (suggestionCounter - historyStartIndex);
bindSuggestionView(savedSearch, animate, recycledSuggestionCount, suggestionCounter, true, telemetryTag);
++suggestionCounter;
} while (c.moveToNext());
}
} finally {
c.close();
final int historyStartIndex = suggestionCounter;
for (String suggestion : savedSuggestions) {
String telemetryTag = "history." + (suggestionCounter - historyStartIndex);
bindSuggestionView(suggestion, animate, recycledSuggestionCount, suggestionCounter, true, telemetryTag);
++suggestionCounter;
}
hideRecycledSuggestions(suggestionCounter, recycledSuggestionCount);
}
/**
* Gets matching suggestions from search history.
*
* @param searchTerm the string with which to look for matches in the saved searches
* @return matching prior searches that contain searchTerm
*/
private Cursor getSavedSearches(String searchTerm) {
if (!AppConstants.NIGHTLY_BUILD) {
return null;
}
final ContentResolver cr = getContext().getContentResolver();
String[] columns = new String[] { SearchHistory.QUERY };
String actualQuery = SearchHistory.QUERY + " LIKE ?";
String[] queryArgs = new String[] { '%' + searchTerm + '%' };
String sortOrderAndLimit = SearchHistory.DATE +" DESC LIMIT " + mMaxSavedSuggestions;
return cr.query(SearchHistory.CONTENT_URI, columns, actualQuery, queryArgs, sortOrderAndLimit);
}
/**
* Displays suggestions supplied by the search engine, relative to number of suggestions from search history.
*
@ -341,10 +310,10 @@ class SearchEngineRow extends AnimatedHeightLayout {
*
* @param searchSuggestionsEnabled whether or not suggestions from the default search engine are enabled
* @param searchEngine the search engine to use throughout the SearchEngineRow class
* @param searchTerm the text from the url to get suggestions on
* @param searchHistorySuggestions search history suggestions
* @param animate whether or not to use animations
**/
public void updateSuggestions(boolean searchSuggestionsEnabled, SearchEngine searchEngine, String searchTerm, boolean animate) {
public void updateSuggestions(boolean searchSuggestionsEnabled, SearchEngine searchEngine, List<String> searchHistorySuggestions, boolean animate) {
mSearchEngine = searchEngine;
// Set the search engine icon (e.g., Google) for the row.
mIconView.updateAndScaleImage(mSearchEngine.getIcon(), mSearchEngine.getEngineIdentifier());
@ -363,25 +332,12 @@ class SearchEngineRow extends AnimatedHeightLayout {
final boolean savedSearchesEnabled = prefs.getBoolean(GeckoPreferences.PREFS_HISTORY_SAVED_SEARCH, true);
if (searchSuggestionsEnabled && savedSearchesEnabled) {
final Cursor c = getSavedSearches(searchTerm);
try {
final int savedSearchCount = (c != null) ? c.getCount() : 0;
final int suggestionViewCount = updateFromSearchEngine(animate, recycledSuggestionCount, savedSearchCount);
updateFromSavedSearches(c, animate, suggestionViewCount, recycledSuggestionCount);
} finally {
if (c != null) {
c.close();
}
}
final int savedSearchCount = (searchHistorySuggestions != null) ? searchHistorySuggestions.size() : 0;
final int suggestionViewCount = updateFromSearchEngine(animate, recycledSuggestionCount, savedSearchCount);
updateFromSavedSearches(searchHistorySuggestions, animate, suggestionViewCount, recycledSuggestionCount);
} else if (savedSearchesEnabled) {
final Cursor c = getSavedSearches(searchTerm);
try {
updateFromSavedSearches(c, animate, 0, recycledSuggestionCount);
} finally {
if (c != null) {
c.close();
}
}
updateFromSavedSearches(searchHistorySuggestions, animate, 0, recycledSuggestionCount);
} else if (searchSuggestionsEnabled) {
updateFromSearchEngine(animate, recycledSuggestionCount, 0);
}

View File

@ -225,6 +225,10 @@
<!ENTITY pref_donottrack_title "Do not track">
<!ENTITY pref_donottrack_summary "&brandShortName; will tell sites that you do not want to be tracked">
<!ENTITY pref_tracking_protection_enabled "Enabled">
<!ENTITY pref_tracking_protection_enabled_pb "Enabled in Private Browsing">
<!ENTITY pref_tracking_protection_disabled "Disabled">
<!ENTITY tracking_protection_prompt_title "Now with Tracking Protection">
<!ENTITY tracking_protection_prompt_text "Actively block tracking elements so you don\'t have to worry.">
<!ENTITY tracking_protection_prompt_tip_text "Visit Privacy settings to learn more">

View File

@ -654,6 +654,7 @@ moz_native_devices_jars = [
CONFIG['ANDROID_MEDIAROUTER_V7_AAR_LIB'],
CONFIG['ANDROID_MEDIAROUTER_V7_AAR_INTERNAL_LIB'],
CONFIG['ANDROID_PLAY_SERVICES_BASE_AAR_LIB'],
CONFIG['ANDROID_PLAY_SERVICES_BASEMENT_AAR_LIB'],
CONFIG['ANDROID_PLAY_SERVICES_CAST_AAR_LIB'],
]
moz_native_devices_sources = [
@ -672,8 +673,13 @@ if CONFIG['MOZ_NATIVE_DEVICES']:
resjar.generated_sources += ['android/support/v7/mediarouter/R.java']
if CONFIG['ANDROID_PLAY_SERVICES_BASE_AAR']:
ANDROID_EXTRA_PACKAGES += ['com.google.android.gms']
ANDROID_EXTRA_PACKAGES += ['com.google.android.gms.base']
ANDROID_EXTRA_RES_DIRS += ['%' + CONFIG['ANDROID_PLAY_SERVICES_BASE_AAR_RES']]
resjar.generated_sources += ['com/google/android/gms/base/R.java']
if CONFIG['ANDROID_PLAY_SERVICES_BASEMENT_AAR']:
ANDROID_EXTRA_PACKAGES += ['com.google.android.gms']
ANDROID_EXTRA_RES_DIRS += ['%' + CONFIG['ANDROID_PLAY_SERVICES_BASEMENT_AAR_RES']]
resjar.generated_sources += ['com/google/android/gms/R.java']
if CONFIG['ANDROID_PLAY_SERVICES_CAST_AAR']:

View File

@ -128,6 +128,8 @@ OnSharedPreferenceChangeListener
private static final String PREFS_DEVTOOLS_REMOTE_WIFI_ENABLED = "devtools.remote.wifi.enabled";
private static final String PREFS_DISPLAY_TITLEBAR_MODE = "browser.chrome.titlebarMode";
private static final String PREFS_SYNC = NON_PREF_PREFIX + "sync";
private static final String PREFS_TRACKING_PROTECTION = "privacy.trackingprotection.state";
private static final String PREFS_TRACKING_PROTECTION_PB = "privacy.trackingprotection.pbmode.enabled";
public static final String PREFS_OPEN_URLS_IN_PRIVATE = NON_PREF_PREFIX + "openExternalURLsPrivately";
public static final String PREFS_VOICE_INPUT_ENABLED = NON_PREF_PREFIX + "voice_input_enabled";
public static final String PREFS_QRCODE_ENABLED = NON_PREF_PREFIX + "qrcode_enabled";
@ -772,6 +774,20 @@ OnSharedPreferenceChangeListener
i--;
continue;
}
} else if (PREFS_TRACKING_PROTECTION.equals(key)) {
// Remove UI for global TP pref in non-Nightly builds.
if (!AppConstants.NIGHTLY_BUILD) {
preferences.removePreference(pref);
i--;
continue;
}
} else if (PREFS_TRACKING_PROTECTION_PB.equals(key)) {
// Remove UI for private-browsing-only TP pref in Nightly builds.
if (AppConstants.NIGHTLY_BUILD) {
preferences.removePreference(pref);
i--;
continue;
}
} else if (PREFS_TELEMETRY_ENABLED.equals(key)) {
if (!AppConstants.MOZ_TELEMETRY_REPORTING) {
preferences.removePreference(pref);

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-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/.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle" >
<stroke android:width="1dp"
android:color="@color/divider_light" />
<padding android:top="1dp" />
</shape>
</item>
<item>
<selector>
<item android:state_pressed="true"
android:drawable="@color/toolbar_grey_pressed" />
<item android:drawable="@color/toolbar_grey"/>
</selector>
</item>
</layer-list>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-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/. -->
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/clear_history_button"
style="@style/Widget.Home.ActionButton"
android:text="@string/home_clear_history_button"
android:visibility="gone" />

View File

@ -10,16 +10,6 @@
<include layout="@layout/home_list"/>
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/home_button_bar_bg">
<Button android:id="@+id/clear_history_button"
style="@style/Widget.Home.ActionButton"
android:text="@string/home_clear_history_button"
android:gravity="center"
android:visibility="gone"/>
</LinearLayout>
<include layout="@layout/home_history_clear_button"/>
</LinearLayout>

View File

@ -41,13 +41,6 @@
</LinearLayout>
<Button android:id="@+id/clear_history_button"
style="@style/Widget.Home.ActionButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/home_button_bar_bg"
android:text="@string/home_clear_history_button"
android:gravity="center"
android:visibility="gone"/>
<include layout="@layout/home_history_clear_button"/>
</LinearLayout>

View File

@ -13,10 +13,6 @@
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="TextAppearance.Widget.Home.PageTitle" parent="TextAppearance.Medium">
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="TextAppearance.FirstrunTextLight">
<item name="android:fontFamily">sans-serif-light</item>
</style>

View File

@ -50,6 +50,16 @@
<item>@string/pref_cookies_not_accept_foreign</item>
<item>@string/pref_cookies_disabled</item>
</string-array>
<string-array name="pref_tracking_protection_values">
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
<string-array name="pref_tracking_protection_entries">
<item>@string/pref_tracking_protection_enabled</item>
<item>@string/pref_tracking_protection_enabled_pb</item>
<item>@string/pref_tracking_protection_disabled</item>
</string-array>
<string-array name="pref_cookies_values">
<item>0</item>
<item>1</item>

View File

@ -258,21 +258,18 @@
<item name="android:paddingRight">10dip</item>
</style>
<style name="Widget.Home.PageButton">
<style name="Widget.Home.ActionButton">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">40dip</item>
<item name="android:textAppearance">@style/TextAppearance.Widget.Home.PageTitle</item>
<item name="android:background">@drawable/action_bar_button</item>
<item name="android:layout_height">48dp</item>
<item name="android:textColor">@color/text_and_tabs_tray_grey</item>
<item name="android:textSize">14sp</item>
<item name="android:background">@drawable/home_history_clear_button_bg</item>
<item name="android:focusable">true</item>
<item name="android:gravity">center|left</item>
<item name="android:gravity">center</item>
<item name="android:paddingLeft">10dip</item>
<item name="android:paddingRight">10dip</item>
</style>
<style name="Widget.Home.ActionButton" parent="Widget.Home.PageButton">
<item name="android:textAppearance">@style/TextAppearance.Widget.Home.PageAction</item>
</style>
<style name="Widget.Home.ActionItem">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">40dip</item>
@ -401,12 +398,6 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="TextAppearance.Widget.Home.PageTitle" parent="TextAppearance.Medium" />
<style name="TextAppearance.Widget.Home.PageAction" parent="TextAppearance.Small">
<item name="android:textColor">#00ACFF</item>
</style>
<style name="TextAppearance.Widget.Home.ItemTitle" parent="TextAppearance.Medium"/>
<style name="TextAppearance.Widget.Home.ItemDescription" parent="TextAppearance.Micro">

View File

@ -13,6 +13,12 @@
android:summary="@string/pref_tracking_protection_summary"
android:persistent="false" />
<ListPreference android:key="privacy.trackingprotection.state"
android:title="@string/pref_tracking_protection_title"
android:entries="@array/pref_tracking_protection_entries"
android:entryValues="@array/pref_tracking_protection_values"
android:persistent="false" />
<org.mozilla.gecko.preferences.AlignRightLinkPreference
android:key="android.not_a_preference.trackingprotection.learn_more"
android:title="@string/pref_learn_more"

View File

@ -216,6 +216,10 @@
<string name="pref_donottrack_title">&pref_donottrack_title;</string>
<string name="pref_donottrack_summary">&pref_donottrack_summary;</string>
<string name="pref_tracking_protection_enabled">&pref_tracking_protection_enabled;</string>
<string name="pref_tracking_protection_enabled_pb">&pref_tracking_protection_enabled_pb;</string>
<string name="pref_tracking_protection_disabled">&pref_tracking_protection_disabled;</string>
<string name="pref_char_encoding">&pref_char_encoding;</string>
<string name="pref_char_encoding_on">&pref_char_encoding_on;</string>
<string name="pref_char_encoding_off">&pref_char_encoding_off;</string>

View File

@ -1414,6 +1414,11 @@ var BrowserApp = {
}, this);
},
// These values come from pref_tracking_protection_entries in arrays.xml.
PREF_TRACKING_PROTECTION_ENABLED: "2",
PREF_TRACKING_PROTECTION_ENABLED_PB: "1",
PREF_TRACKING_PROTECTION_DISABLED: "0",
handlePreferencesRequest: function handlePreferencesRequest(aRequestId,
aPrefNames,
aListen) {
@ -1452,6 +1457,18 @@ var BrowserApp = {
pref.value = MasterPassword.enabled;
prefs.push(pref);
continue;
case "privacy.trackingprotection.state": {
pref.type = "string";
if (Services.prefs.getBoolPref("privacy.trackingprotection.enabled")) {
pref.value = this.PREF_TRACKING_PROTECTION_ENABLED;
} else if (Services.prefs.getBoolPref("privacy.trackingprotection.pbmode.enabled")) {
pref.value = this.PREF_TRACKING_PROTECTION_ENABLED_PB;
} else {
pref.value = this.PREF_TRACKING_PROTECTION_DISABLED;
}
prefs.push(pref);
continue;
}
// Crash reporter submit pref must be fetched from nsICrashReporter service.
case "datareporting.crashreporter.submitEnabled":
let crashReporterBuilt = "nsICrashReporter" in Ci && Services.appinfo instanceof Ci.nsICrashReporter;
@ -1534,6 +1551,29 @@ var BrowserApp = {
MasterPassword.setPassword(json.value);
return;
// "privacy.trackingprotection.state" is not a "real" pref name, but it's used in the setting menu.
// By default "privacy.trackingprotection.pbmode.enabled" is true,
// and "privacy.trackingprotection.enabled" is false.
case "privacy.trackingprotection.state": {
switch (json.value) {
// Tracking protection disabled.
case this.PREF_TRACKING_PROTECTION_DISABLED:
Services.prefs.setBoolPref("privacy.trackingprotection.pbmode.enabled", false);
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", false);
break;
// Tracking protection only in private browsing,
case this.PREF_TRACKING_PROTECTION_ENABLED_PB:
Services.prefs.setBoolPref("privacy.trackingprotection.pbmode.enabled", true);
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", false);
break;
// Tracking protection everywhere.
case this.PREF_TRACKING_PROTECTION_ENABLED:
Services.prefs.setBoolPref("privacy.trackingprotection.pbmode.enabled", true);
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true);
break;
}
return;
}
// Enabling or disabling suggestions will prevent future prompts
case SearchEngines.PREF_SUGGEST_ENABLED:
Services.prefs.setBoolPref(SearchEngines.PREF_SUGGEST_PROMPTED, true);

View File

@ -1,8 +1,8 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
targetSdkVersion 22

View File

@ -1,8 +1,8 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
targetSdkVersion 22
@ -76,8 +76,9 @@ dependencies {
if (mozconfig.substs.MOZ_NATIVE_DEVICES) {
compile 'com.android.support:mediarouter-v7:22.2.1'
compile 'com.google.android.gms:play-services-base:7.8.0'
compile 'com.google.android.gms:play-services-cast:7.8.0'
compile 'com.google.android.gms:play-services-basement:8.1.0'
compile 'com.google.android.gms:play-services-base:8.1.0'
compile 'com.google.android.gms:play-services-cast:8.1.0'
}
compile project(':branding')

View File

@ -1,8 +1,8 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
targetSdkVersion 22

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