merge fx-team to mozilla-central a=merge
2
CLOBBER
@ -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
|
||||
|
@ -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"/>
|
||||
|
@ -6,6 +6,7 @@
|
||||
position="after_start"
|
||||
hidden="true"
|
||||
orient="vertical"
|
||||
noautofocus="true"
|
||||
role="alert"/>
|
||||
|
||||
<popupnotification id="webRTC-shareDevices-notification" hidden="true">
|
||||
|
7
browser/base/content/test/alerts/browser.ini
Normal 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)
|
@ -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);
|
||||
});
|
||||
});
|
@ -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();
|
@ -1,5 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
"use strict";
|
||||
|
@ -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]
|
||||
|
@ -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)
|
||||
|
@ -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',
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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, {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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" });
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -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"),
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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">
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
};
|
||||
|
@ -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");
|
||||
});
|
||||
|
Before Width: | Height: | Size: 606 B |
Before Width: | Height: | Size: 7.9 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 610 B |
Before Width: | Height: | Size: 3.3 KiB |
@ -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);
|
||||
|
Before Width: | Height: | Size: 312 B |
Before Width: | Height: | Size: 666 B |
Before Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 26 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 610 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 7.2 KiB |
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
15
browser/themes/shared/web-notifications-icon.svg
Normal 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 |
23
browser/themes/shared/web-notifications-tray.svg
Normal 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 |
Before Width: | Height: | Size: 704 B |
Before Width: | Height: | Size: 8.2 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 514 B |
Before Width: | Height: | Size: 3.2 KiB |
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -12,7 +12,8 @@ namespace dom {
|
||||
const char* kPermissionTypes[] = {
|
||||
"geo",
|
||||
"desktop-notification",
|
||||
"push",
|
||||
// Alias `push` to `desktop-notification`.
|
||||
"desktop-notification",
|
||||
"midi"
|
||||
};
|
||||
|
||||
|
@ -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 = [
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
},
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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],
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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],
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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 ;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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">
|
||||
|
@ -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']:
|
||||
|
@ -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);
|
||||
|
@ -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>
|
@ -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" />
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|