Merge mozilla-central to mozilla-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-03-21 15:20:35 +01:00
commit ce96bf1ad5
41 changed files with 512 additions and 84 deletions

View File

@ -19,11 +19,11 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2c06eb8cfc7eee1021c868a6a8b030242007b684"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc13cdff437c3df45374f5622094a3565a414d5b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="456499c44d1ef39b602ea02e9ed460b6aab85b44"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="0f9f3d948d6ba25c47fbec29e2eff02c8590e2e2"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
<!-- Stock Android things -->

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2c06eb8cfc7eee1021c868a6a8b030242007b684"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cc13cdff437c3df45374f5622094a3565a414d5b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="a9e08b91e9cd1f0930f16cfc49ec72f63575d5fe">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2c06eb8cfc7eee1021c868a6a8b030242007b684"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cc13cdff437c3df45374f5622094a3565a414d5b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>

View File

@ -19,11 +19,11 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2c06eb8cfc7eee1021c868a6a8b030242007b684"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc13cdff437c3df45374f5622094a3565a414d5b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="456499c44d1ef39b602ea02e9ed460b6aab85b44"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="0f9f3d948d6ba25c47fbec29e2eff02c8590e2e2"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
<!-- Stock Android things -->

View File

@ -4,6 +4,6 @@
"branch": "",
"revision": ""
},
"revision": "a9008fd903e2b258d481ef072353b5219f74c158",
"revision": "3045bf73d5cc752ba8c548d82ea567987743c3bd",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2c06eb8cfc7eee1021c868a6a8b030242007b684"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc13cdff437c3df45374f5622094a3565a414d5b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2c06eb8cfc7eee1021c868a6a8b030242007b684"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc13cdff437c3df45374f5622094a3565a414d5b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2c06eb8cfc7eee1021c868a6a8b030242007b684"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc13cdff437c3df45374f5622094a3565a414d5b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2c06eb8cfc7eee1021c868a6a8b030242007b684"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc13cdff437c3df45374f5622094a3565a414d5b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2c06eb8cfc7eee1021c868a6a8b030242007b684"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="cc13cdff437c3df45374f5622094a3565a414d5b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2c06eb8cfc7eee1021c868a6a8b030242007b684"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc13cdff437c3df45374f5622094a3565a414d5b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -4,6 +4,20 @@
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");
let service = Cc["@mozilla.org/weave/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject;
if (!service.allowPasswordsEngine) {
let checkbox = document.getElementById("fxa-pweng-chk");
checkbox.checked = false;
checkbox.disabled = true;
}
addEventListener("dialogaccept", function () {
window.arguments[0].accepted = true;
});

View File

@ -44,7 +44,8 @@
<checkbox label="&engine.bookmarks.label;"
accesskey="&engine.bookmarks.accesskey;"
preference="engine.bookmarks"/>
<checkbox label="&engine.passwords.label;"
<checkbox id="fxa-pweng-chk"
label="&engine.passwords.label;"
accesskey="&engine.passwords.accesskey;"
preference="engine.passwords"/>
<checkbox label="&engine.history.label;"

View File

@ -87,6 +87,12 @@ let gSyncUtils = {
this._openLink(Weave.Svc.Prefs.get(root + "privacyURL"));
},
openMPInfoPage: function (event) {
event.stopPropagation();
let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
this._openLink(baseURL + "sync-master-password");
},
openFirstSyncProgressPage: function () {
this._openLink("about:sync-progress");
},

View File

@ -173,6 +173,9 @@ var gSecurityPane = {
this.changeMasterPassword();
this._initMasterPasswordUI();
// We might want to hide sync's password engine.
gSyncPane.updateWeavePrefs();
},
/**

View File

@ -154,6 +154,17 @@ let gSyncPane = {
for (let checkbox of engines.querySelectorAll("checkbox")) {
checkbox.disabled = enginesListDisabled;
}
let checkbox = document.getElementById("fxa-pweng-chk");
let help = document.getElementById("fxa-pweng-help");
let allowPasswordsEngine = service.allowPasswordsEngine;
if (!allowPasswordsEngine) {
checkbox.checked = false;
}
checkbox.disabled = !allowPasswordsEngine;
help.hidden = allowPasswordsEngine;
});
// If fxAccountEnabled is false and we are in a "not configured" state,
// then fxAccounts is probably fully disabled rather than just unconfigured,

View File

@ -267,9 +267,23 @@
<checkbox label="&engine.bookmarks.label;"
accesskey="&engine.bookmarks.accesskey;"
preference="engine.bookmarks"/>
<checkbox label="&engine.passwords.label;"
accesskey="&engine.passwords.accesskey;"
preference="engine.passwords"/>
<hbox>
<checkbox id="fxa-pweng-chk"
label="&engine.passwords.label;"
accesskey="&engine.passwords.accesskey;"
preference="engine.passwords"/>
<vbox id="fxa-pweng-help">
<spacer flex="1"/>
<hbox id="fxa-pweng-help-link">
<label value=" ["/>
<label class="text-link" value="?"
onclick="gSyncUtils.openMPInfoPage(event);"/>
<label value="]"/>
</hbox>
<spacer flex="1"/>
</vbox>
</hbox>
<checkbox label="&engine.history.label;"
accesskey="&engine.history.accesskey;"
preference="engine.history"/>

View File

@ -215,10 +215,20 @@ let SyncHandler = {
*/
let SessionHistoryListener = {
init: function () {
// The frame tree observer is needed to handle navigating away from
// an about page. Currently nsISHistoryListener does not have
// OnHistoryNewEntry() called for about pages because the history entry is
// modified to point at the new page. Once Bug 981900 lands the frame tree
// observer can be removed.
gFrameTree.addObserver(this);
addEventListener("load", this, true);
addEventListener("hashchange", this, true);
Services.obs.addObserver(this, "browser:purge-session-history", false);
// By adding the SHistoryListener immediately, we will unfortunately be
// notified of every history entry as the tab is restored. We don't bother
// waiting to add the listener later because these notifications are cheap.
// We will likely only collect once since we are batching collection on
// a delay.
docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory.
addSHistoryListener(this);
// Collect data if we start with a non-empty shistory.
if (!SessionHistory.isEmpty(docShell)) {
@ -227,22 +237,9 @@ let SessionHistoryListener = {
},
uninit: function () {
Services.obs.removeObserver(this, "browser:purge-session-history");
},
observe: function () {
// We need to use setTimeout() here because we listen for
// "browser:purge-session-history". When that is fired all observers are
// expected to purge their data. We can't expect to be called *after* the
// observer in browser.xml that clears session history so we need to wait
// a tick before actually collecting data.
setTimeout(() => this.collect(), 0);
},
handleEvent: function (event) {
// We are only interested in "load" events from subframes.
if (event.type == "hashchange" || event.target != content.document) {
this.collect();
let sessionHistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
if (sessionHistory) {
sessionHistory.removeSHistoryListener(this);
}
},
@ -258,7 +255,41 @@ let SessionHistoryListener = {
onFrameTreeReset: function () {
this.collect();
}
},
OnHistoryNewEntry: function (newURI) {
this.collect();
},
OnHistoryGoBack: function (backURI) {
this.collect();
return true;
},
OnHistoryGoForward: function (forwardURI) {
this.collect();
return true;
},
OnHistoryGotoIndex: function (index, gotoURI) {
this.collect();
return true;
},
OnHistoryPurge: function (numEntries) {
this.collect();
return true;
},
OnHistoryReload: function (reloadURI, reloadFlags) {
this.collect();
return true;
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsISHistoryListener,
Ci.nsISupportsWeakReference
])
};
/**

View File

@ -165,3 +165,71 @@ add_task(function test_subframes() {
// Cleanup.
gBrowser.removeTab(tab);
});
/**
* Ensure that navigating from an about page invalidates shistory.
*/
add_task(function test_about_page_navigate() {
// Create a new tab.
let tab = gBrowser.addTab("about:blank");
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// Check that we have a single shistory entry.
SyncHandlers.get(browser).flush();
let {entries} = JSON.parse(ss.getTabState(tab));
is(entries.length, 1, "there is one shistory entry");
is(entries[0].url, "about:blank", "url is correct");
browser.loadURI("about:robots");
yield promiseBrowserLoaded(browser);
// Check that we have changed the history entry.
SyncHandlers.get(browser).flush();
let {entries} = JSON.parse(ss.getTabState(tab));
is(entries.length, 1, "there is one shistory entry");
is(entries[0].url, "about:robots", "url is correct");
// Cleanup.
gBrowser.removeTab(tab);
});
/**
* Ensure that history.pushState and history.replaceState invalidate shistory.
*/
add_task(function test_pushstate_replacestate() {
// Create a new tab.
let tab = gBrowser.addTab("http://example.com/1");
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// Check that we have a single shistory entry.
SyncHandlers.get(browser).flush();
let {entries} = JSON.parse(ss.getTabState(tab));
is(entries.length, 1, "there is one shistory entry");
is(entries[0].url, "http://example.com/1", "url is correct");
browser.messageManager.
sendAsyncMessage("ss-test:historyPushState", {url: 'test-entry/'});
yield promiseContentMessage(browser, "ss-test:historyPushState");
// Check that we have added the history entry.
SyncHandlers.get(browser).flush();
let {entries} = JSON.parse(ss.getTabState(tab));
is(entries.length, 2, "there is another shistory entry");
is(entries[1].url, "http://example.com/test-entry/", "url is correct");
// Disabled until replaceState invalidation is supported. See Bug 967028.
// browser.messageManager.
// sendAsyncMessage("ss-test:historyReplaceState", {url: 'test-entry2/'});
// yield promiseContentMessage(browser, "ss-test:historyReplaceState");
// // Check that we have modified the history entry.
// SyncHandlers.get(browser).flush();
// let {entries} = JSON.parse(ss.getTabState(tab));
// is(entries.length, 2, "there is still two shistory entries");
// is(entries[1].url, "http://example.com/test-entry/test-entry2/", "url is correct");
// Cleanup.
gBrowser.removeTab(tab);
});

View File

@ -163,3 +163,17 @@ addMessageListener("ss-test:click", function ({data}) {
content.document.getElementById(data.id).click();
sendAsyncMessage("ss-test:click");
});
addMessageListener("ss-test:historyPushState", function ({data}) {
content.window.history.
pushState(data.stateObj || {}, data.title || "", data.url);
sendAsyncMessage("ss-test:historyPushState");
});
addMessageListener("ss-test:historyReplaceState", function ({data}) {
content.window.history.
replaceState(data.stateObj || {}, data.title || "", data.url);
sendAsyncMessage("ss-test:historyReplaceState");
});

View File

@ -165,4 +165,8 @@ label.small {
margin-bottom: 0.6em;
}
#fxa-pweng-help-link > label {
margin: 0;
}
%endif

View File

@ -230,4 +230,8 @@ html|a.inline-link:-moz-focusring {
margin-bottom: 0.6em;
}
#fxa-pweng-help-link > label {
margin: 0;
}
%endif

View File

@ -233,7 +233,7 @@ toolbarpaletteitem[place="toolbar"] {
max-width: 24px;
min-width: 24px;
max-height: 24px;
height: 24px;
min-height: 24px;
padding: 4px;
}

View File

@ -855,11 +855,16 @@ toolbarpaletteitem[place="palette"] > #search-container {
border-color: hsla(210,4%,10%,0);
border-bottom-color: hsla(210,4%,10%,.1);
padding: 0;
margin-bottom: -1px;
transition-property: background-color, border-color;
transition-duration: 150ms;
}
/* Make direct siblings overlap borders: */
.toolbaritem-combined-buttons + .toolbaritem-combined-buttons@inAnyPanel@ {
margin-top: -1px;
border-top-color: transparent !important;
}
.toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton {
border: 0;
padding: .5em;

View File

@ -1681,7 +1681,7 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon {
}
.panel-promo-box {
margin: 10px -4px -4px;
margin: 10px -10px -10px;
padding: 8px 10px;
border-top: 1px solid ThreeDShadow;
background-image: linear-gradient(hsla(0,0%,0%,.15), hsla(0,0%,0%,.08) 6px);
@ -2186,19 +2186,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
}
/* Notification icon box */
#notification-popup > .panel-arrowcontainer > .panel-arrowcontent {
padding: 10px;
}
#notification-popup .popup-notification-closebutton {
-moz-margin-end: -14px;
margin-top: -10px;
}
#notification-popup .panel-promo-box {
margin: 10px -10px -10px;
}
#notification-popup-box {
position: relative;
background-color: #fff;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -155,4 +155,8 @@ label.small {
margin-bottom: 0.6em;
}
#fxa-pweng-help-link > label {
margin: 0;
}
%endif

View File

@ -180,4 +180,10 @@ BluetoothHfpManager::DisconnectSco()
return false;
}
void
BluetoothHfpManager::Reset()
{
MOZ_ASSERT(NS_IsMainThread());
}
NS_IMPL_ISUPPORTS1(BluetoothHfpManager, nsIObserver)

View File

@ -19,6 +19,7 @@ import org.mozilla.gecko.fxa.login.State;
import org.mozilla.gecko.fxa.login.State.StateLabel;
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
@ -63,6 +64,8 @@ public class FxAccountConfirmAccountActivity extends FxAccountAbstractActivity i
@Override
public void onClick(View v) {
ActivityUtils.openURLInFennec(v.getContext(), null);
setResult(Activity.RESULT_OK);
finish();
}
});
}

View File

@ -37,6 +37,7 @@
<activity
android:theme="@style/FxAccountTheme"
android:name="org.mozilla.gecko.fxa.activities.FxAccountConfirmAccountActivity"
android:noHistory="true"
android:windowSoftInputMode="adjustResize">
</activity>
@ -49,6 +50,7 @@
<activity
android:theme="@style/FxAccountTheme"
android:name="org.mozilla.gecko.fxa.activities.FxAccountVerifiedAccountActivity"
android:noHistory="true"
android:windowSoftInputMode="adjustResize">
</activity>
@ -61,5 +63,6 @@
<activity
android:theme="@style/FxAccountTheme"
android:name="org.mozilla.gecko.fxa.activities.FxAccountCreateAccountNotAllowedActivity"
android:noHistory="true"
android:windowSoftInputMode="adjustResize">
</activity>

View File

@ -117,6 +117,16 @@ WeaveService.prototype = {
return fxAccountsEnabled;
},
/**
* Returns whether the password engine is allowed. We explicitly disallow
* the password engine when a master password is used to ensure those can't
* be accessed without the master key.
*/
get allowPasswordsEngine() {
// This doesn't apply to old-style sync, it's only an issue for FxA.
return !this.fxAccountsEnabled || !Utils.mpEnabled();
},
/**
* Whether Sync appears to be enabled.
*

View File

@ -36,6 +36,28 @@ PasswordEngine.prototype = {
_recordObj: LoginRec,
applyIncomingBatchSize: PASSWORDS_STORE_BATCH_SIZE,
get isAllowed() {
return Cc["@mozilla.org/weave/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject
.allowPasswordsEngine;
},
get enabled() {
// If we are disabled due to !isAllowed(), we must take care to ensure the
// engine has actually had the enabled setter called which reflects this state.
let prefVal = SyncEngine.prototype.__lookupGetter__("enabled").call(this);
let newVal = this.isAllowed && prefVal;
if (newVal != prefVal) {
this.enabled = newVal;
}
return newVal;
},
set enabled(val) {
SyncEngine.prototype.__lookupSetter__("enabled").call(this, this.isAllowed && val);
},
_syncFinish: function _syncFinish() {
SyncEngine.prototype._syncFinish.call(this);

View File

@ -254,25 +254,37 @@ EngineSynchronizer.prototype = {
continue;
}
if (Svc.Prefs.get("engineStatusChanged." + engine.prefName, false)) {
// The engine was disabled locally. Wipe server data and
// disable it everywhere.
this._log.trace("Wiping data for " + engineName + " engine.");
engine.wipeServer();
delete meta.payload.engines[engineName];
meta.changed = true; // TODO: Should we still do this?
// We also here mark the engine as declined, because the pref
// was explicitly changed to false.
// This will be reflected in meta/global in the next stage.
this._log.trace("Engine " + engineName + " was disabled locally. Marking as declined.");
toDecline.add(engineName);
} else {
// The engine was enabled remotely. Enable it locally.
let attemptedEnable = false;
// If the engine was enabled remotely, enable it locally.
if (!Svc.Prefs.get("engineStatusChanged." + engine.prefName, false)) {
this._log.trace("Engine " + engineName + " was enabled. Marking as non-declined.");
toUndecline.add(engineName);
this._log.trace(engineName + " engine was enabled remotely.");
engine.enabled = true;
// Note that setting engine.enabled to true might not have worked for
// the password engine if a master-password is enabled. However, it's
// still OK that we added it to undeclined - the user *tried* to enable
// it remotely - so it still winds up as not being flagged as declined
// even though it's disabled remotely.
attemptedEnable = true;
}
// If either the engine was disabled locally or enabling the engine
// failed (see above re master-password) then wipe server data and
// disable it everywhere.
if (!engine.enabled) {
this._log.trace("Wiping data for " + engineName + " engine.");
engine.wipeServer();
delete meta.payload.engines[engineName];
meta.changed = true; // the new enabled state must propagate
// We also here mark the engine as declined, because the pref
// was explicitly changed to false - unless we tried, and failed,
// to enable it - in which case we leave the declined state alone.
if (!attemptedEnable) {
// This will be reflected in meta/global in the next stage.
this._log.trace("Engine " + engineName + " was disabled locally. Marking as declined.");
toDecline.add(engineName);
}
}
}
@ -290,8 +302,8 @@ EngineSynchronizer.prototype = {
}
}
this.service.engineManager.decline(toDecline);
this.service.engineManager.undecline(toUndecline);
engineManager.decline(toDecline);
engineManager.undecline(toUndecline);
Svc.Prefs.resetBranch("engineStatusChanged.");
this.service._ignorePrefObserver = false;

View File

@ -555,6 +555,22 @@ this.Utils = {
return function innerBind() { return method.apply(object, arguments); };
},
/**
* Is there a master password configured, regardless of current lock state?
*/
mpEnabled: function mpEnabled() {
let modules = Cc["@mozilla.org/security/pkcs11moduledb;1"]
.getService(Ci.nsIPKCS11ModuleDB);
let sdrSlot = modules.findSlotByName("");
let status = sdrSlot.status;
let slots = Ci.nsIPKCS11Slot;
return status != slots.SLOT_UNINITIALIZED && status != slots.SLOT_READY;
},
/**
* Is there a master password configured and currently locked?
*/
mpLocked: function mpLocked() {
let modules = Cc["@mozilla.org/security/pkcs11moduledb;1"]
.getService(Ci.nsIPKCS11ModuleDB);

View File

@ -0,0 +1,130 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/stages/enginesync.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/engines/passwords.js");
Cu.import("resource://services-sync/service.js");
Cu.import("resource://testing-common/services/sync/utils.js");
function run_test() {
initTestLogging("Trace");
run_next_test();
}
add_test(function test_simple() {
Services.prefs.setBoolPref("services.sync.fxaccounts.enabled", true);
// Stub mpEnabled.
let mpEnabledF = Utils.mpEnabled;
let mpEnabled = false;
Utils.mpEnabled = function() mpEnabled;
let manager = Service.engineManager;
Service.engineManager.register(PasswordEngine);
let engine = Service.engineManager.get("passwords");
let wipeCount = 0;
let engineWipeServerF = engine.wipeServer;
engine.wipeServer = function() {
++wipeCount;
}
// A server for the metadata.
let server = new SyncServer();
let johndoe = server.registerUser("johndoe", "password");
johndoe.createContents({
meta: {global: {engines: {passwords: {version: engine.version,
syncID: engine.syncID}}}},
crypto: {},
clients: {}
});
server.start();
setBasicCredentials("johndoe", "password", "abcdeabcdeabcdeabcdeabcdea");
Service.serverURL = server.baseURI;
Service.clusterURL = server.baseURI;
let engineSync = new EngineSynchronizer(Service);
engineSync._log.level = Log.Level.Trace;
function assertEnabled(expected, message) {
Assert.strictEqual(engine.enabled, expected, message);
// The preference *must* reflect the actual state.
Assert.strictEqual(Svc.Prefs.get("engine." + engine.prefName), expected,
message + " (pref should match enabled state)");
}
try {
assertEnabled(true, "password engine should be enabled by default")
let engineMeta = Service.recordManager.get(engine.metaURL);
// This engine should be in the meta/global
Assert.notStrictEqual(engineMeta.payload.engines[engine.name], undefined,
"The engine should appear in the metadata");
Assert.ok(!engineMeta.changed, "the metadata for the password engine hasn't changed");
// (pretend to) enable a master-password
mpEnabled = true;
// The password engine should be locally disabled...
assertEnabled(false, "if mp is locked the engine should be disabled");
// ...but not declined.
Assert.ok(!manager.isDeclined("passwords"), "password engine is not declined");
// Next time a sync would happen, we call _updateEnabledEngines(), which
// would remove the engine from the metadata - call that now.
engineSync._updateEnabledEngines();
// The global meta should no longer list the engine.
engineMeta = Service.recordManager.get(engine.metaURL);
Assert.strictEqual(engineMeta.payload.engines[engine.name], undefined,
"The engine should have vanished");
// And we should have wiped the server data.
Assert.strictEqual(wipeCount, 1, "wipeServer should have been called");
// Now simulate an incoming meta/global indicating the engine should be
// enabled. We should fail to actually enable it - the pref should remain
// false and we wipe the server for anything another device might have
// stored.
let meta = {
payload: {
engines: {
"passwords": {"version":1,"syncID":"yfBi2v7PpFO2"},
},
},
};
engineSync._updateEnabledFromMeta(meta, 3, manager);
Assert.strictEqual(wipeCount, 2, "wipeServer should have been called");
Assert.ok(!manager.isDeclined("passwords"), "password engine is not declined");
assertEnabled(false, "engine still not enabled locally");
// Let's turn the MP off - but *not* re-enable it locally.
mpEnabled = false;
// Just disabling the MP isn't enough to force it back to enabled.
assertEnabled(false, "engine still not enabled locally");
// Another incoming metadata record with the engine enabled should cause
// it to be enabled locally.
meta = {
payload: {
engines: {
"passwords": 1,
},
},
};
engineSync._updateEnabledFromMeta(meta, 3, manager);
Assert.strictEqual(wipeCount, 2, "wipeServer should *not* have been called again");
Assert.ok(!manager.isDeclined("passwords"), "password engine is not declined");
// It should be enabled locally.
assertEnabled(true, "engine now enabled locally");
// Next time a sync starts it should magically re-appear in our meta/global
engine._syncStartup();
//engineSync._updateEnabledEngines();
engineMeta = Service.recordManager.get(engine.metaURL);
Assert.equal(engineMeta.payload.engines[engine.name].version, engine.version,
"The engine should re-appear in the metadata");
} finally {
// restore the damage we did above...
engine.wipeServer = engineWipeServerF;
engine._store.wipe();
// Un-stub mpEnabled.
Utils.mpEnabled = mpEnabledF;
Services.prefs.clearUserPref("services.sync.fxaccounts.enabled");
server.stop(run_next_test);
}
});

View File

@ -169,3 +169,5 @@ skip-if = debug
[test_healthreport.js]
skip-if = ! healthreport
[test_password_mpenabled.js]

View File

@ -167,6 +167,6 @@ XXX: apply styles to all themes until bug 509642 is fixed
%endif
.popup-notification-closebutton {
-moz-margin-end: -8px;
margin-top: -4px;
-moz-margin-end: -14px;
margin-top: -10px;
}

View File

@ -75,7 +75,7 @@ panel[type="arrow"][side="right"] {
}
.panel-arrowcontent {
padding: 4px;
padding: 10px;
color: -moz-FieldText;
background: -moz-field;
background-clip: padding-box;

View File

@ -4,7 +4,7 @@
'use strict';
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
const { Promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
/**
* WebappRT-specific actors.
@ -90,7 +90,7 @@ WebappTabList.prototype.getList = function() {
this._mustNotify = true;
this._checkListening();
return promise.resolve([actor for ([_, actor] of this._actorByBrowser)]);
return Promise.resolve([actor for ([_, actor] of this._actorByBrowser)]);
};
/**

View File

@ -96,8 +96,17 @@ static bool sDevInputAudioJack;
static int32_t sHeadphoneState;
static int32_t sMicrophoneState;
// Amount of time in MS before an input is considered expired.
static const uint64_t kInputExpirationThresholdMs = 1000;
NS_IMPL_ISUPPORTS_INHERITED1(nsAppShell, nsBaseAppShell, nsIObserver)
static uint64_t
nanosecsToMillisecs(nsecs_t nsecs)
{
return nsecs / 1000000;
}
namespace mozilla {
bool ProcessNextEvent()
@ -559,6 +568,10 @@ public:
GeckoInputDispatcher(sp<EventHub> &aEventHub)
: mQueueLock("GeckoInputDispatcher::mQueueMutex")
, mEventHub(aEventHub)
, mTouchDownCount(0)
, mKeyDownCount(0)
, mTouchEventsFiltered(false)
, mKeyEventsFiltered(false)
{}
virtual void dump(String8& dump);
@ -603,6 +616,11 @@ private:
mozilla::Mutex mQueueLock;
std::queue<UserInputData> mEventQueue;
sp<EventHub> mEventHub;
int mTouchDownCount;
int mKeyDownCount;
bool mTouchEventsFiltered;
bool mKeyEventsFiltered;
};
// GeckoInputReaderPolicy
@ -650,6 +668,14 @@ GeckoInputDispatcher::dump(String8& dump)
{
}
static bool
isExpired(const UserInputData& data)
{
uint64_t timeNowMs =
nanosecsToMillisecs(systemTime(SYSTEM_TIME_MONOTONIC));
return (timeNowMs - data.timeMs) > kInputExpirationThresholdMs;
}
void
GeckoInputDispatcher::dispatchOnce()
{
@ -666,9 +692,37 @@ GeckoInputDispatcher::dispatchOnce()
switch (data.type) {
case UserInputData::MOTION_DATA: {
if (!mTouchDownCount) {
// No pending events, the filter state can be updated.
mTouchEventsFiltered = isExpired(data);
}
int32_t action = data.action & AMOTION_EVENT_ACTION_MASK;
switch (action) {
case AMOTION_EVENT_ACTION_DOWN:
case AMOTION_EVENT_ACTION_POINTER_DOWN:
mTouchDownCount++;
break;
case AMOTION_EVENT_ACTION_MOVE:
case AMOTION_EVENT_ACTION_HOVER_MOVE:
// No need to update the count on move.
break;
case AMOTION_EVENT_ACTION_UP:
case AMOTION_EVENT_ACTION_POINTER_UP:
case AMOTION_EVENT_ACTION_OUTSIDE:
case AMOTION_EVENT_ACTION_CANCEL:
mTouchDownCount--;
break;
default:
break;
}
if (mTouchEventsFiltered) {
return;
}
nsEventStatus status = nsEventStatus_eIgnore;
if ((data.action & AMOTION_EVENT_ACTION_MASK) !=
AMOTION_EVENT_ACTION_HOVER_MOVE) {
if (action != AMOTION_EVENT_ACTION_HOVER_MOVE) {
bool captured;
status = sendTouchEvent(data, &captured);
if (captured) {
@ -677,7 +731,7 @@ GeckoInputDispatcher::dispatchOnce()
}
uint32_t msg;
switch (data.action & AMOTION_EVENT_ACTION_MASK) {
switch (action) {
case AMOTION_EVENT_ACTION_DOWN:
msg = NS_MOUSE_BUTTON_DOWN;
break;
@ -703,6 +757,16 @@ GeckoInputDispatcher::dispatchOnce()
break;
}
case UserInputData::KEY_DATA: {
if (!mKeyDownCount) {
// No pending events, the filter state can be updated.
mKeyEventsFiltered = isExpired(data);
}
mKeyDownCount += (data.action == AKEY_EVENT_ACTION_DOWN) ? 1 : -1;
if (mKeyEventsFiltered) {
return;
}
sp<KeyCharacterMap> kcm = mEventHub->getKeyCharacterMap(data.deviceId);
KeyEventDispatcher dispatcher(data, kcm.get());
dispatcher.Dispatch();
@ -716,12 +780,6 @@ GeckoInputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChange
{
}
static uint64_t
nanosecsToMillisecs(nsecs_t nsecs)
{
return nsecs / 1000000;
}
void
GeckoInputDispatcher::notifyKey(const NotifyKeyArgs* args)
{