Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2014-02-07 14:34:33 -05:00
commit cff17d804d
58 changed files with 2023 additions and 1770 deletions

View File

@ -12,7 +12,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="3fc26ae786e3869a7ef1e23afc9807ac1b4741f2"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="260effa7f342db418b8d5a95dc61c6e8dd8d09f4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="49c722fa1a5e1873fa0010829fd97d0b74009ca5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>

View File

@ -11,7 +11,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="3fc26ae786e3869a7ef1e23afc9807ac1b4741f2"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="260effa7f342db418b8d5a95dc61c6e8dd8d09f4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="49c722fa1a5e1873fa0010829fd97d0b74009ca5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="788d9ce293a9b44f64536130cf4ad577e8101dbe"/>

View File

@ -12,7 +12,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="3fc26ae786e3869a7ef1e23afc9807ac1b4741f2"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="260effa7f342db418b8d5a95dc61c6e8dd8d09f4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="49c722fa1a5e1873fa0010829fd97d0b74009ca5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>

View File

@ -1,4 +1,4 @@
{
"revision": "34a411a6261587124fc6746fb18a19c05571437a",
"revision": "e11cf4c78874de3469c4f338cf275aeae31854ee",
"repo_path": "/integration/gaia-central"
}

View File

@ -11,7 +11,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="3fc26ae786e3869a7ef1e23afc9807ac1b4741f2"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="260effa7f342db418b8d5a95dc61c6e8dd8d09f4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="49c722fa1a5e1873fa0010829fd97d0b74009ca5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -10,7 +10,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="3fc26ae786e3869a7ef1e23afc9807ac1b4741f2"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="260effa7f342db418b8d5a95dc61c6e8dd8d09f4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="49c722fa1a5e1873fa0010829fd97d0b74009ca5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -12,7 +12,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="3fc26ae786e3869a7ef1e23afc9807ac1b4741f2"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="260effa7f342db418b8d5a95dc61c6e8dd8d09f4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="49c722fa1a5e1873fa0010829fd97d0b74009ca5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -11,7 +11,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="3fc26ae786e3869a7ef1e23afc9807ac1b4741f2"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="260effa7f342db418b8d5a95dc61c6e8dd8d09f4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="49c722fa1a5e1873fa0010829fd97d0b74009ca5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -11,7 +11,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="3fc26ae786e3869a7ef1e23afc9807ac1b4741f2"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="260effa7f342db418b8d5a95dc61c6e8dd8d09f4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="49c722fa1a5e1873fa0010829fd97d0b74009ca5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="788d9ce293a9b44f64536130cf4ad577e8101dbe"/>

View File

@ -11,7 +11,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="3fc26ae786e3869a7ef1e23afc9807ac1b4741f2"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="260effa7f342db418b8d5a95dc61c6e8dd8d09f4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="49c722fa1a5e1873fa0010829fd97d0b74009ca5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -328,22 +328,6 @@ const PanelUI = {
}
},
/**
* This function can be used as a command event listener for subviews
* so that the panel knows if and when to close itself.
*/
onCommandHandler: function(aEvent) {
let closemenu = aEvent.originalTarget.getAttribute("closemenu");
if (closemenu == "none") {
return;
}
if (closemenu == "single") {
this.showMainView();
return;
}
this.hide();
},
/**
* Open a dialog window that allow the user to customize listed character sets.
*/

View File

@ -120,7 +120,6 @@ support-files =
[browser_console_click_focus.js]
[browser_console_consolejsm_output.js]
[browser_console_dead_objects.js]
skip-if = true # bug 963869
[browser_console_error_source_click.js]
[browser_console_filters.js]
[browser_console_iframe_messages.js]

View File

@ -8,96 +8,89 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-eval-in-stackframe.html";
let gWebConsole, gJSTerm, gVariablesView;
function test()
{
registerCleanupFunction(() => {
gWebConsole = gJSTerm = gVariablesView = null;
});
let hud;
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, consoleOpened);
}, true);
Task.spawn(runner).then(finishTest);
function* runner() {
let {tab} = yield loadTab(TEST_URI);
hud = yield openConsole(tab);
let jsterm = hud.jsterm;
let msg = yield execute("fooObj");
ok(msg, "output message found");
let anchor = msg.querySelector("a");
ok(anchor, "object anchor");
isnot(anchor.textContent.indexOf('testProp: "testValue"'), -1,
"message text check");
msg.scrollIntoView();
executeSoon(() => {
EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow);
});
let vviewVar = yield jsterm.once("variablesview-fetched");
let vview = vviewVar._variablesView;
ok(vview, "variables view object");
let [result] = yield findVariableViewProperties(vviewVar, [
{ name: "testProp", value: "testValue" },
], { webconsole: hud });
let prop = result.matchedProp;
ok(prop, "matched the |testProp| property in the variables view");
is(content.wrappedJSObject.fooObj.testProp, result.value,
"|fooObj.testProp| value is correct");
vview.window.focus();
executeSoon(() => {
EventUtils.synthesizeKey("VK_ESCAPE", {});
});
yield jsterm.once("sidebar-closed");
jsterm.clearOutput();
msg = yield execute("window");
ok(msg, "output message found");
let anchor = msg.querySelector("a");
ok(anchor, "object anchor");
isnot(anchor.textContent.indexOf("Window \u2192 http://example.com/browser/"), -1,
"message text check");
msg.scrollIntoView();
executeSoon(() => {
EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow)
});
vviewVar = yield jsterm.once("variablesview-fetched");
vview = vviewVar._variablesView;
ok(vview, "variables view object");
yield findVariableViewProperties(vviewVar, [
{ name: "foo", value: "globalFooBug783499" },
], { webconsole: hud });
vview.window.focus();
msg.scrollIntoView();
executeSoon(() => {
EventUtils.synthesizeKey("VK_ESCAPE", {});
});
yield jsterm.once("sidebar-closed");
}
function execute(str) {
let deferred = promise.defer();
hud.jsterm.execute(str, (msg) => {
deferred.resolve(msg);
});
return deferred.promise;
}
}
function consoleOpened(hud)
{
gWebConsole = hud;
gJSTerm = hud.jsterm;
gJSTerm.execute("fooObj", onExecuteFooObj);
}
function onExecuteFooObj(msg)
{
ok(msg, "output message found");
let anchor = msg.querySelector("a");
ok(anchor, "object anchor");
isnot(anchor.textContent.indexOf('testProp: "testValue"'), -1,
"message text check");
gJSTerm.once("variablesview-fetched", onFooObjFetch);
EventUtils.synthesizeMouse(anchor, 2, 2, {}, gWebConsole.iframeWindow)
}
function onFooObjFetch(aEvent, aVar)
{
gVariablesView = aVar._variablesView;
ok(gVariablesView, "variables view object");
findVariableViewProperties(aVar, [
{ name: "testProp", value: "testValue" },
], { webconsole: gWebConsole }).then(onTestPropFound);
}
function onTestPropFound(aResults)
{
let prop = aResults[0].matchedProp;
ok(prop, "matched the |testProp| property in the variables view");
is(content.wrappedJSObject.fooObj.testProp, aResults[0].value,
"|fooObj.testProp| value is correct");
gVariablesView.window.focus();
gJSTerm.once("sidebar-closed", onSidebarClosed);
EventUtils.synthesizeKey("VK_ESCAPE", {}, gVariablesView.window);
}
function onSidebarClosed()
{
gJSTerm.clearOutput();
gJSTerm.execute("window", onExecuteWindow);
}
function onExecuteWindow(msg)
{
ok(msg, "output message found");
let anchor = msg.querySelector("a");
ok(anchor, "object anchor");
isnot(anchor.textContent.indexOf("Window \u2192 http://example.com/browser/"), -1,
"message text check");
gJSTerm.once("variablesview-fetched", onWindowFetch);
EventUtils.synthesizeMouse(anchor, 2, 2, {}, gWebConsole.iframeWindow)
}
function onWindowFetch(aEvent, aVar)
{
gVariablesView = aVar._variablesView;
ok(gVariablesView, "variables view object");
findVariableViewProperties(aVar, [
{ name: "foo", value: "globalFooBug783499" },
], { webconsole: gWebConsole }).then(onFooFound);
}
function onFooFound(aResults)
{
gVariablesView.window.focus();
gJSTerm.once("sidebar-closed", finishTest);
EventUtils.synthesizeKey("VK_ESCAPE", {}, gVariablesView.window);
}

View File

@ -4,6 +4,13 @@
*/
// Check that Dead Objects do not break the Web/Browser Consoles. See bug 883649.
// This test does:
// - opens a new tab,
// - opens the Browser Console,
// - stores a reference to the content document of the tab on the chrome window object,
// - closes the tab,
// - tries to use the object that was pointing to the now-defunct content
// document. This is the dead object.
const TEST_URI = "data:text/html;charset=utf8,<p>dead objects!";
@ -11,35 +18,30 @@ function test()
{
let hud = null;
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
info("open the browser console");
HUDService.toggleBrowserConsole().then(onBrowserConsoleOpen);
}, true);
Task.spawn(runner).then(finishTest);
function onBrowserConsoleOpen(aHud)
{
hud = aHud;
function* runner() {
let {tab} = yield loadTab(TEST_URI);
info("open the browser console");
hud = yield HUDService.toggleBrowserConsole();
ok(hud, "browser console opened");
hud.jsterm.clearOutput();
hud.jsterm.execute("Cu = Components.utils;" +
"Cu.import('resource://gre/modules/Services.jsm');" +
"chromeWindow = Services.wm.getMostRecentWindow('navigator:browser');" +
"foobarzTezt = chromeWindow.content.document;" +
"delete chromeWindow", onAddVariable);
}
function onAddVariable()
{
// Add the reference to the content document.
yield execute("Cu = Components.utils;" +
"Cu.import('resource://gre/modules/Services.jsm');" +
"chromeWindow = Services.wm.getMostRecentWindow('navigator:browser');" +
"foobarzTezt = chromeWindow.content.document;" +
"delete chromeWindow");
gBrowser.removeCurrentTab();
hud.jsterm.execute("foobarzTezt", onReadVariable);
}
let msg = yield execute("foobarzTezt");
function onReadVariable(msg)
{
isnot(hud.outputNode.textContent.indexOf("[object DeadObject]"), -1,
"dead object found");
@ -49,38 +51,36 @@ function test()
EventUtils.synthesizeKey(c, {}, hud.iframeWindow);
}
hud.jsterm.execute(null, () => {
// executeSoon() is needed to get out of the execute() event loop.
executeSoon(onReadProperty.bind(null, msg));
});
}
yield execute();
function onReadProperty(deadObjectMessage)
{
isnot(hud.outputNode.textContent.indexOf("can't access dead object"), -1,
"'cannot access dead object' message found");
// Click the second execute output.
let clickable = deadObjectMessage.querySelector("a");
let clickable = msg.querySelector("a");
ok(clickable, "clickable object found");
isnot(clickable.textContent.indexOf("[object DeadObject]"), -1,
"message text check");
hud.jsterm.once("variablesview-fetched", onFetched);
EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow);
}
msg.scrollIntoView();
function onFetched()
{
executeSoon(() => {
EventUtils.synthesizeMouseAtCenter(clickable, {}, hud.iframeWindow);
});
yield hud.jsterm.once("variablesview-fetched");
ok(true, "variables view fetched");
hud.jsterm.execute("delete window.foobarzTezt; 2013-26", onCalcResult);
msg = yield execute("delete window.foobarzTezt; 2013-26");
isnot(msg.textContent.indexOf("1987"), -1, "result message found");
}
function onCalcResult()
{
isnot(hud.outputNode.textContent.indexOf("1987"), -1, "result message found");
// executeSoon() is needed to get out of the execute() event loop.
executeSoon(finishTest);
function execute(str) {
let deferred = promise.defer();
hud.jsterm.execute(str, (msg) => {
deferred.resolve(msg);
});
return deferred.promise;
}
}

View File

@ -407,7 +407,8 @@ this.UITour = {
teardownTour: function(aWindow, aWindowClosing = false) {
aWindow.gBrowser.tabContainer.removeEventListener("TabSelect", this);
aWindow.PanelUI.panel.removeEventListener("popuphiding", this.onAppMenuHiding);
aWindow.PanelUI.panel.removeEventListener("popuphiding", this.hidePanelAnnotations);
aWindow.PanelUI.panel.removeEventListener("ViewShowing", this.hidePanelAnnotations);
aWindow.removeEventListener("SSWindowClosing", this);
let originTabs = this.originTabs.get(aWindow);
@ -821,7 +822,8 @@ this.UITour = {
if (aMenuName == "appMenu") {
aWindow.PanelUI.panel.setAttribute("noautohide", "true");
aWindow.PanelUI.panel.addEventListener("popuphiding", this.onAppMenuHiding);
aWindow.PanelUI.panel.addEventListener("popuphiding", this.hidePanelAnnotations);
aWindow.PanelUI.panel.addEventListener("ViewShowing", this.hidePanelAnnotations);
if (aOpenCallback) {
aWindow.PanelUI.panel.addEventListener("popupshown", onPopupShown);
}
@ -846,7 +848,7 @@ this.UITour = {
}
},
onAppMenuHiding: function(aEvent) {
hidePanelAnnotations: function(aEvent) {
let win = aEvent.target.ownerDocument.defaultView;
let annotationElements = new Map([
// [annotationElement (panel), method to hide the annotation]

View File

@ -96,6 +96,44 @@ let tests = [
}, "Highlight should be shown after showHighlight() for fixed panel items");
},
function test_highlight_panel_open_subview(done) {
gContentAPI.showHighlight("customize");
gContentAPI.showInfo("backForward", "test title", "test text");
waitForElementToBeVisible(highlight, function checkPanelIsOpen() {
isnot(PanelUI.panel.state, "closed", "Panel should have opened");
// Click the help button which should open the subview in the panel menu.
let helpButton = document.getElementById("PanelUI-help");
EventUtils.synthesizeMouseAtCenter(helpButton, {});
waitForElementToBeHidden(highlight, function highlightHidden() {
is(PanelUI.panel.state, "open",
"Panel should have stayed open when the subview opened");
is(tooltip.state, "open", "The info panel should have remained open");
PanelUI.hide();
done();
}, "Highlight should have disappeared when the subview opened");
}, "Highlight should be shown after showHighlight() for fixed panel items");
},
function test_info_panel_open_subview(done) {
gContentAPI.showHighlight("urlbar");
gContentAPI.showInfo("customize", "customize me!", "Open a subview");
waitForElementToBeVisible(tooltip, function checkPanelIsOpen() {
isnot(PanelUI.panel.state, "closed", "Panel should have opened");
// Click the help button which should open the subview in the panel menu.
let helpButton = document.getElementById("PanelUI-help");
EventUtils.synthesizeMouseAtCenter(helpButton, {});
waitForElementToBeHidden(tooltip, function tooltipHidden() {
is(PanelUI.panel.state, "open",
"Panel should have stayed open when the subview opened");
is(highlight.parentElement.state, "open", "The highlight should have remained open");
PanelUI.hide();
done();
}, "Tooltip should have disappeared when the subview opened");
}, "Highlight should be shown after showHighlight() for fixed panel items");
},
function test_info_move_outside_panel(done) {
gContentAPI.showInfo("addons", "test title", "test text");
gContentAPI.showHighlight("urlbar");

View File

@ -132,11 +132,14 @@
#TabsToolbar:not(:-moz-lwtheme) {
background-color: transparent !important;
color: black;
text-shadow: 0 0 .5em white, 0 0 .5em white, 0 1px 0 rgba(255,255,255,.4);
border-left-style: none !important;
border-right-style: none !important;
}
#toolbar-menubar:not(:-moz-lwtheme) {
text-shadow: 0 0 .5em white, 0 0 .5em white, 0 1px 0 rgba(255,255,255,.4);
}
/* Vertical toolbar border */
#main-window[sizemode=normal] #navigator-toolbox::after,
#main-window[sizemode=normal] #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
@ -197,10 +200,6 @@
border-radius: 4px;
}
.tabbrowser-tab:not(:-moz-lwtheme) {
text-shadow: none;
}
#ctrlTab-panel {
background: transparent;
-moz-appearance: -moz-win-glass;

View File

@ -244,16 +244,43 @@ OpusTrackEncoder::GetMetadata()
nsresult
OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
{
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
// Wait until initialized or cancelled.
while (!mCanceled && !mInitialized) {
mReentrantMonitor.Wait();
}
if (mCanceled || mEncodingComplete) {
return NS_ERROR_FAILURE;
}
}
// calculation below depends on the truth that mInitialized is true.
MOZ_ASSERT(mInitialized);
// re-sampled frames left last time which didn't fit into an Opus packet duration.
const int framesLeft = mResampledLeftover.Length() / mChannels;
// When framesLeft is 0, (GetPacketDuration() - framesLeft) is a multiple
// of kOpusSamplingRate. There is not precision loss in the integer division
// in computing framesToFetch. If frameLeft > 0, we need to add 1 to
// framesToFetch to ensure there will be at least n frames after re-sampling.
const int frameRoundUp = framesLeft ? 1 : 0;
MOZ_ASSERT(GetPacketDuration() >= framesLeft);
// Try to fetch m frames such that there will be n frames
// where (n + frameLeft) >= GetPacketDuration() after re-sampling.
const int framesToFetch = !mResampler ? GetPacketDuration()
: (GetPacketDuration() - framesLeft) * mSamplingRate / kOpusSamplingRate
+ frameRoundUp;
{
// Move all the samples from mRawSegment to mSourceSegment. We only hold
// the monitor in this block.
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
// Wait if mEncoder is not initialized, or when not enough raw data, but is
// not the end of stream nor is being canceled.
while (!mCanceled && (!mInitialized || (mRawSegment.GetDuration() +
mSourceSegment.GetDuration() < GetPacketDuration() &&
!mEndOfStream))) {
// Wait until enough raw data, end of stream or cancelled.
while (!mCanceled && mRawSegment.GetDuration() +
mSourceSegment.GetDuration() < framesToFetch &&
!mEndOfStream) {
mReentrantMonitor.Wait();
}
@ -276,13 +303,14 @@ OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
pcm.SetLength(GetPacketDuration() * mChannels);
AudioSegment::ChunkIterator iter(mSourceSegment);
int frameCopied = 0;
while (!iter.IsEnded() && frameCopied < GetPacketDuration()) {
while (!iter.IsEnded() && frameCopied < framesToFetch) {
AudioChunk chunk = *iter;
// Chunk to the required frame size.
int frameToCopy = chunk.GetDuration();
if (frameCopied + frameToCopy > GetPacketDuration()) {
frameToCopy = GetPacketDuration() - frameCopied;
if (frameCopied + frameToCopy > framesToFetch) {
frameToCopy = framesToFetch - frameCopied;
}
if (!chunk.IsNull()) {
@ -300,6 +328,7 @@ OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
nsRefPtr<EncodedFrame> audiodata = new EncodedFrame();
audiodata->SetFrameType(EncodedFrame::AUDIO_FRAME);
int framesInPCM = frameCopied;
if (mResampler) {
nsAutoTArray<AudioDataValue, 9600> resamplingDest;
// We want to consume all the input data, so we slightly oversize the
@ -322,9 +351,25 @@ OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
out, &outframes);
#endif
pcm = resamplingDest;
MOZ_ASSERT(pcm.Length() >= mResampledLeftover.Length());
PodCopy(pcm.Elements(), mResampledLeftover.Elements(),
mResampledLeftover.Length());
uint32_t outframesToCopy = std::min(outframes,
static_cast<uint32_t>(GetPacketDuration() - framesLeft));
MOZ_ASSERT(pcm.Length() - mResampledLeftover.Length() >=
outframesToCopy * mChannels);
PodCopy(pcm.Elements() + mResampledLeftover.Length(),
resamplingDest.Elements(), outframesToCopy * mChannels);
int frameLeftover = outframes - outframesToCopy;
mResampledLeftover.SetLength(frameLeftover * mChannels);
PodCopy(mResampledLeftover.Elements(),
resamplingDest.Elements() + outframesToCopy * mChannels,
mResampledLeftover.Length());
// This is always at 48000Hz.
audiodata->SetDuration(outframes);
framesInPCM = framesLeft + outframesToCopy;
audiodata->SetDuration(framesInPCM);
} else {
// The ogg time stamping and pre-skip is always timed at 48000.
audiodata->SetDuration(frameCopied * (kOpusSamplingRate / mSamplingRate));
@ -342,11 +387,13 @@ OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
LOG("[Opus] Done encoding.");
}
MOZ_ASSERT(mEndOfStream || framesInPCM == GetPacketDuration());
// Append null data to pcm buffer if the leftover data is not enough for
// opus encoder.
if (frameCopied < GetPacketDuration() && mEndOfStream) {
memset(pcm.Elements() + frameCopied * mChannels, 0,
(GetPacketDuration()-frameCopied)*mChannels*sizeof(AudioDataValue));
if (framesInPCM < GetPacketDuration() && mEndOfStream) {
PodZero(pcm.Elements() + framesInPCM * mChannels,
(GetPacketDuration() - framesInPCM) * mChannels);
}
nsTArray<uint8_t> frameData;
// Encode the data with Opus Encoder.
@ -372,6 +419,7 @@ OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
speex_resampler_destroy(mResampler);
mResampler = nullptr;
}
mResampledLeftover.SetLength(0);
}
audiodata->SwapInFrameData(frameData);

View File

@ -74,6 +74,12 @@ private:
* resampled.
*/
SpeexResamplerState* mResampler;
/**
* Store the resampled frames that don't fit into an Opus packet duration.
* They will be prepended to the resampled frames next encoding cycle.
*/
nsTArray<AudioDataValue> mResampledLeftover;
};
}

View File

@ -1799,6 +1799,7 @@ Navigator::HasIccManagerSupport(JSContext* /* unused */,
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
return win && CheckPermission(win, "mobileconnection");
}
#endif // MOZ_B2G_RIL
/* static */
bool
@ -1819,7 +1820,6 @@ Navigator::HasWifiManagerSupport(JSContext* /* unused */,
permMgr->TestPermissionFromPrincipal(principal, "wifi-manage", &permission);
return nsIPermissionManager::ALLOW_ACTION == permission;
}
#endif // MOZ_B2G_RIL
#ifdef MOZ_B2G_BT
/* static */

View File

@ -264,9 +264,9 @@ public:
JSObject* aGlobal);
static bool HasIccManagerSupport(JSContext* /* unused */,
JSObject* aGlobal);
static bool HasWifiManagerSupport(JSContext* /* unused */,
JSObject* aGlobal);
#endif // MOZ_B2G_RIL
static bool HasWifiManagerSupport(JSContext* /* unused */,
JSObject* aGlobal);
#ifdef MOZ_B2G_BT
static bool HasBluetoothSupport(JSContext* /* unused */, JSObject* aGlobal);
#endif // MOZ_B2G_BT

View File

@ -971,6 +971,13 @@ ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
return;
}
#ifdef MOZ_NUWA_PROCESS
// Do not attempt to change the priority of the Nuwa process
if (mContentParent->IsNuwaProcess()) {
return;
}
#endif
if (aBackgroundLRU > 0 &&
aPriority == PROCESS_PRIORITY_BACKGROUND &&
mPriority == PROCESS_PRIORITY_BACKGROUND) {

File diff suppressed because it is too large Load Diff

View File

@ -3811,37 +3811,39 @@ let RIL = {
debug("handle supp svc notification: " + JSON.stringify(info));
}
if (info.notificationType !== 1) {
// We haven't supported MO intermediate result code, i.e.
// info.notificationType === 0, which refers to code1 defined in 3GPP
// 27.007 7.17. We only support partial MT unsolicited result code,
// referring to code2, for now.
return;
}
let notification = null;
let callIndex = -1;
if (info.notificationType === 0) {
// MO intermediate result code. Refer to code1 defined in 3GPP 27.007
// 7.17.
} else if (info.notificationType === 1) {
// MT unsolicited result code. Refer to code2 defined in 3GPP 27.007 7.17.
switch (info.code) {
case SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD:
case SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED:
notification = GECKO_SUPP_SVC_NOTIFICATION_FROM_CODE2[info.code];
break;
default:
// Notification type not supported.
return;
}
switch (info.code) {
case SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD:
case SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED:
notification = GECKO_SUPP_SVC_NOTIFICATION_FROM_CODE2[info.code];
break;
default:
// Notification type not supported.
return;
}
// Get the target call object for this notification.
let currentCallIndexes = Object.keys(this.currentCalls);
if (currentCallIndexes.length === 1) {
// Only one call exists. This should be the target.
callIndex = currentCallIndexes[0];
} else {
// Find the call in |currentCalls| by the given number.
if (info.number) {
for each (let currentCall in this.currentCalls) {
if (currentCall.number == info.number) {
callIndex = currentCall.callIndex;
break;
}
// Get the target call object for this notification.
let currentCallIndexes = Object.keys(this.currentCalls);
if (currentCallIndexes.length === 1) {
// Only one call exists. This should be the target.
callIndex = currentCallIndexes[0];
} else {
// Find the call in |currentCalls| by the given number.
if (info.number) {
for each (let currentCall in this.currentCalls) {
if (currentCall.number == info.number) {
callIndex = currentCall.callIndex;
break;
}
}
}

View File

@ -315,7 +315,10 @@ TelephonyProvider.prototype = {
case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED:
return nsITelephonyProvider.NOTIFICATION_REMOTE_RESUMED;
default:
throw new Error("Unknown rilSuppSvcNotification: " + aNotification);
if (DEBUG) {
debug("Unknown rilSuppSvcNotification: " + aNotification);
}
return;
}
},

View File

@ -23,204 +23,13 @@
#include "DBusThread.h"
#include "RawDBusConnection.h"
#include "DBusUtils.h"
#include <dbus/dbus.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/select.h>
#include <sys/types.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <poll.h>
#include <list>
#include "base/eintr_wrapper.h"
#include "base/message_loop.h"
#include "nsTArray.h"
#include "nsDataHashtable.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/NullPtr.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Monitor.h"
#include "mozilla/FileUtils.h"
#include "nsThreadUtils.h"
#include "nsIThread.h"
#include "nsXULAppAPI.h"
#include "nsServiceManagerUtils.h"
#include "nsCOMPtr.h"
#undef CHROMIUM_LOG
#if defined(MOZ_WIDGET_GONK)
#include <android/log.h>
#define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GonkDBus", args);
#else
#define BTDEBUG true
#define CHROMIUM_LOG(args...) if (BTDEBUG) printf(args);
#endif
namespace mozilla {
namespace ipc {
class DBusWatcher : public MessageLoopForIO::Watcher
{
public:
DBusWatcher(RawDBusConnection* aConnection, DBusWatch* aWatch)
: mConnection(aConnection),
mWatch(aWatch)
{
MOZ_ASSERT(mConnection);
MOZ_ASSERT(mWatch);
}
~DBusWatcher()
{ }
void StartWatching();
void StopWatching();
static void FreeFunction(void* aData);
static dbus_bool_t AddWatchFunction(DBusWatch* aWatch, void* aData);
static void RemoveWatchFunction(DBusWatch* aWatch, void* aData);
static void ToggleWatchFunction(DBusWatch* aWatch, void* aData);
RawDBusConnection* GetConnection();
private:
void OnFileCanReadWithoutBlocking(int aFd);
void OnFileCanWriteWithoutBlocking(int aFd);
// Read watcher for libevent. Only to be accessed on IO Thread.
MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
// Write watcher for libevent. Only to be accessed on IO Thread.
MessageLoopForIO::FileDescriptorWatcher mWriteWatcher;
// DBus structures
RawDBusConnection* mConnection;
DBusWatch* mWatch;
};
RawDBusConnection*
DBusWatcher::GetConnection()
{
return mConnection;
}
void DBusWatcher::StartWatching()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(mWatch);
int fd = dbus_watch_get_unix_fd(mWatch);
MessageLoopForIO* ioLoop = MessageLoopForIO::current();
unsigned int flags = dbus_watch_get_flags(mWatch);
if (flags & DBUS_WATCH_READABLE) {
ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_READ,
&mReadWatcher, this);
}
if (flags & DBUS_WATCH_WRITABLE) {
ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_WRITE,
&mWriteWatcher, this);
}
}
void DBusWatcher::StopWatching()
{
MOZ_ASSERT(!NS_IsMainThread());
unsigned int flags = dbus_watch_get_flags(mWatch);
if (flags & DBUS_WATCH_READABLE) {
mReadWatcher.StopWatchingFileDescriptor();
}
if (flags & DBUS_WATCH_WRITABLE) {
mWriteWatcher.StopWatchingFileDescriptor();
}
}
// DBus utility functions, used as function pointers in DBus setup
void
DBusWatcher::FreeFunction(void* aData)
{
delete static_cast<DBusWatcher*>(aData);
}
dbus_bool_t
DBusWatcher::AddWatchFunction(DBusWatch* aWatch, void* aData)
{
MOZ_ASSERT(!NS_IsMainThread());
RawDBusConnection* connection = static_cast<RawDBusConnection*>(aData);
DBusWatcher* dbusWatcher = new DBusWatcher(connection, aWatch);
dbus_watch_set_data(aWatch, dbusWatcher, DBusWatcher::FreeFunction);
if (dbus_watch_get_enabled(aWatch)) {
dbusWatcher->StartWatching();
}
return TRUE;
}
void
DBusWatcher::RemoveWatchFunction(DBusWatch* aWatch, void* aData)
{
MOZ_ASSERT(!NS_IsMainThread());
DBusWatcher* dbusWatcher =
static_cast<DBusWatcher*>(dbus_watch_get_data(aWatch));
dbusWatcher->StopWatching();
}
void
DBusWatcher::ToggleWatchFunction(DBusWatch* aWatch, void* aData)
{
MOZ_ASSERT(!NS_IsMainThread());
DBusWatcher* dbusWatcher =
static_cast<DBusWatcher*>(dbus_watch_get_data(aWatch));
if (dbus_watch_get_enabled(aWatch)) {
dbusWatcher->StartWatching();
} else {
dbusWatcher->StopWatching();
}
}
void
DBusWatcher::OnFileCanReadWithoutBlocking(int aFd)
{
MOZ_ASSERT(!NS_IsMainThread());
dbus_watch_handle(mWatch, DBUS_WATCH_READABLE);
DBusDispatchStatus dbusDispatchStatus;
do {
dbusDispatchStatus =
dbus_connection_dispatch(mConnection->GetConnection());
} while (dbusDispatchStatus == DBUS_DISPATCH_DATA_REMAINS);
}
void
DBusWatcher::OnFileCanWriteWithoutBlocking(int aFd)
{
MOZ_ASSERT(!NS_IsMainThread());
dbus_watch_handle(mWatch, DBUS_WATCH_WRITABLE);
}
class WatchDBusConnectionTask : public Task
{
public:
@ -232,15 +41,7 @@ public:
void Run()
{
MOZ_ASSERT(!NS_IsMainThread());
dbus_bool_t success =
dbus_connection_set_watch_functions(mConnection->GetConnection(),
DBusWatcher::AddWatchFunction,
DBusWatcher::RemoveWatchFunction,
DBusWatcher::ToggleWatchFunction,
mConnection, nullptr);
NS_ENSURE_TRUE_VOID(success == TRUE);
mConnection->Watch();
}
private:

View File

@ -23,13 +23,171 @@
/* TODO: Remove BlueZ constant */
#define BLUEZ_DBUS_BASE_IFC "org.bluez"
//
// Runnables
//
namespace mozilla {
namespace ipc {
//
// DBusWatcher
//
class DBusWatcher : public MessageLoopForIO::Watcher
{
public:
DBusWatcher(RawDBusConnection* aConnection, DBusWatch* aWatch)
: mConnection(aConnection),
mWatch(aWatch)
{
MOZ_ASSERT(mConnection);
MOZ_ASSERT(mWatch);
}
~DBusWatcher()
{ }
void StartWatching();
void StopWatching();
static void FreeFunction(void* aData);
static dbus_bool_t AddWatchFunction(DBusWatch* aWatch, void* aData);
static void RemoveWatchFunction(DBusWatch* aWatch, void* aData);
static void ToggleWatchFunction(DBusWatch* aWatch, void* aData);
RawDBusConnection* GetConnection();
private:
void OnFileCanReadWithoutBlocking(int aFd);
void OnFileCanWriteWithoutBlocking(int aFd);
// Read watcher for libevent. Only to be accessed on IO Thread.
MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
// Write watcher for libevent. Only to be accessed on IO Thread.
MessageLoopForIO::FileDescriptorWatcher mWriteWatcher;
// DBus structures
RawDBusConnection* mConnection;
DBusWatch* mWatch;
};
RawDBusConnection*
DBusWatcher::GetConnection()
{
return mConnection;
}
void DBusWatcher::StartWatching()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(mWatch);
int fd = dbus_watch_get_unix_fd(mWatch);
MessageLoopForIO* ioLoop = MessageLoopForIO::current();
unsigned int flags = dbus_watch_get_flags(mWatch);
if (flags & DBUS_WATCH_READABLE) {
ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_READ,
&mReadWatcher, this);
}
if (flags & DBUS_WATCH_WRITABLE) {
ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_WRITE,
&mWriteWatcher, this);
}
}
void DBusWatcher::StopWatching()
{
MOZ_ASSERT(!NS_IsMainThread());
unsigned int flags = dbus_watch_get_flags(mWatch);
if (flags & DBUS_WATCH_READABLE) {
mReadWatcher.StopWatchingFileDescriptor();
}
if (flags & DBUS_WATCH_WRITABLE) {
mWriteWatcher.StopWatchingFileDescriptor();
}
}
// DBus utility functions, used as function pointers in DBus setup
void
DBusWatcher::FreeFunction(void* aData)
{
delete static_cast<DBusWatcher*>(aData);
}
dbus_bool_t
DBusWatcher::AddWatchFunction(DBusWatch* aWatch, void* aData)
{
MOZ_ASSERT(!NS_IsMainThread());
RawDBusConnection* connection = static_cast<RawDBusConnection*>(aData);
DBusWatcher* dbusWatcher = new DBusWatcher(connection, aWatch);
dbus_watch_set_data(aWatch, dbusWatcher, DBusWatcher::FreeFunction);
if (dbus_watch_get_enabled(aWatch)) {
dbusWatcher->StartWatching();
}
return TRUE;
}
void
DBusWatcher::RemoveWatchFunction(DBusWatch* aWatch, void* aData)
{
MOZ_ASSERT(!NS_IsMainThread());
DBusWatcher* dbusWatcher =
static_cast<DBusWatcher*>(dbus_watch_get_data(aWatch));
dbusWatcher->StopWatching();
}
void
DBusWatcher::ToggleWatchFunction(DBusWatch* aWatch, void* aData)
{
MOZ_ASSERT(!NS_IsMainThread());
DBusWatcher* dbusWatcher =
static_cast<DBusWatcher*>(dbus_watch_get_data(aWatch));
if (dbus_watch_get_enabled(aWatch)) {
dbusWatcher->StartWatching();
} else {
dbusWatcher->StopWatching();
}
}
// I/O-loop callbacks
void
DBusWatcher::OnFileCanReadWithoutBlocking(int aFd)
{
MOZ_ASSERT(!NS_IsMainThread());
dbus_watch_handle(mWatch, DBUS_WATCH_READABLE);
DBusDispatchStatus dbusDispatchStatus;
do {
dbusDispatchStatus =
dbus_connection_dispatch(mConnection->GetConnection());
} while (dbusDispatchStatus == DBUS_DISPATCH_DATA_REMAINS);
}
void
DBusWatcher::OnFileCanWriteWithoutBlocking(int aFd)
{
MOZ_ASSERT(!NS_IsMainThread());
dbus_watch_handle(mWatch, DBUS_WATCH_WRITABLE);
}
//
// Notification
//
class Notification
{
public:
@ -103,6 +261,22 @@ nsresult RawDBusConnection::EstablishDBusConnection()
return NS_OK;
}
bool RawDBusConnection::Watch()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(MessageLoop::current());
dbus_bool_t success =
dbus_connection_set_watch_functions(mConnection,
DBusWatcher::AddWatchFunction,
DBusWatcher::RemoveWatchFunction,
DBusWatcher::ToggleWatchFunction,
this, nullptr);
NS_ENSURE_TRUE(success == TRUE, false);
return true;
}
void RawDBusConnection::ScopedDBusConnectionPtrTraits::release(DBusConnection* ptr)
{
if (ptr) {

View File

@ -31,6 +31,8 @@ public:
nsresult EstablishDBusConnection();
bool Watch();
DBusConnection* GetConnection()
{
return mConnection;

View File

@ -34,7 +34,6 @@ public class PanelGridView extends GridView
super(context, null, R.attr.panelGridViewStyle);
mAdapter = new PanelGridViewAdapter(context);
setAdapter(mAdapter);
setNumColumns(AUTO_FIT);
setOnItemClickListener(new PanelGridItemClickListener());
}

View File

@ -41,11 +41,11 @@ public class PanelListRow extends TwoLineRow {
int titleIndex = cursor.getColumnIndexOrThrow(HomeItems.TITLE);
final String title = cursor.getString(titleIndex);
setPrimaryText(title);
setTitle(title);
int urlIndex = cursor.getColumnIndexOrThrow(HomeItems.URL);
final String url = cursor.getString(urlIndex);
setSecondaryText(url);
setDescription(url);
int imageIndex = cursor.getColumnIndexOrThrow(HomeItems.IMAGE_URL);
final String imageUrl = cursor.getString(imageIndex);

View File

@ -21,12 +21,19 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;
import java.lang.ref.WeakReference;
public class TwoLinePageRow extends TwoLineRow
implements Tabs.OnTabsChangedListener {
private static final int NO_ICON = 0;
private final TextView mDescription;
private int mSwitchToTabIconId;
private int mPageTypeIconId;
private final FaviconView mFavicon;
private boolean mShowIcons;
@ -72,6 +79,10 @@ public class TwoLinePageRow extends TwoLineRow
mShowIcons = true;
mDescription = (TextView) findViewById(R.id.description);
mSwitchToTabIconId = NO_ICON;
mPageTypeIconId = NO_ICON;
mFavicon = (FaviconView) findViewById(R.id.icon);
mFaviconListener = new UpdateViewFaviconLoadedListener(mFavicon);
}
@ -104,6 +115,24 @@ public class TwoLinePageRow extends TwoLineRow
}
}
private void setSwitchToTabIcon(int iconId) {
if (mSwitchToTabIconId == iconId) {
return;
}
mSwitchToTabIconId = iconId;
mDescription.setCompoundDrawablesWithIntrinsicBounds(mSwitchToTabIconId, 0, mPageTypeIconId, 0);
}
private void setPageTypeIcon(int iconId) {
if (mPageTypeIconId == iconId) {
return;
}
mPageTypeIconId = iconId;
mDescription.setCompoundDrawablesWithIntrinsicBounds(mSwitchToTabIconId, 0, mPageTypeIconId, 0);
}
/**
* Stores the page URL, so that we can use it to replace "Switch to tab" if the open
* tab changes or is closed.
@ -122,11 +151,11 @@ public class TwoLinePageRow extends TwoLineRow
boolean isPrivate = Tabs.getInstance().getSelectedTab().isPrivate();
Tab tab = Tabs.getInstance().getFirstTabForUrl(mPageUrl, isPrivate);
if (!mShowIcons || tab == null) {
setSecondaryText(mPageUrl);
setSecondaryIcon(NO_ICON);
setDescription(mPageUrl);
setSwitchToTabIcon(NO_ICON);
} else {
setSecondaryText(R.string.switch_to_tab);
setSecondaryIcon(R.drawable.ic_url_bar_tab);
setDescription(R.string.switch_to_tab);
setSwitchToTabIcon(R.drawable.ic_url_bar_tab);
}
}
@ -162,20 +191,20 @@ public class TwoLinePageRow extends TwoLineRow
// The bookmark id will be 0 (null in database) when the url
// is not a bookmark.
if (bookmarkId == 0) {
setPrimaryIcon(NO_ICON);
setPageTypeIcon(NO_ICON);
} else if (display == Combined.DISPLAY_READER) {
setPrimaryIcon(R.drawable.ic_url_bar_reader);
setPageTypeIcon(R.drawable.ic_url_bar_reader);
} else {
setPrimaryIcon(R.drawable.ic_url_bar_star);
setPageTypeIcon(R.drawable.ic_url_bar_star);
}
} else {
setPrimaryIcon(NO_ICON);
setPageTypeIcon(NO_ICON);
}
}
// Use the URL instead of an empty title for consistency with the normal URL
// bar view - this is the equivalent of getDisplayTitle() in Tab.java
setPrimaryText(TextUtils.isEmpty(title) ? url : title);
setTitle(TextUtils.isEmpty(title) ? url : title);
// No point updating the below things if URL has not changed. Prevents evil Favicon flicker.
if (url.equals(mPageUrl)) {

View File

@ -18,13 +18,8 @@ import android.widget.TextView;
import java.lang.ref.WeakReference;
public abstract class TwoLineRow extends LinearLayout {
protected static final int NO_ICON = 0;
private final TextView mPrimaryText;
private int mPrimaryIconId;
private final TextView mSecondaryText;
private int mSecondaryIconId;
private final TextView mTitle;
private final TextView mDescription;
public TwoLineRow(Context context) {
this(context, null);
@ -35,42 +30,21 @@ public abstract class TwoLineRow extends LinearLayout {
setGravity(Gravity.CENTER_VERTICAL);
mSecondaryIconId = NO_ICON;
mPrimaryIconId = NO_ICON;
LayoutInflater.from(context).inflate(R.layout.two_line_row, this);
mPrimaryText = (TextView) findViewById(R.id.primary_text);
mSecondaryText = (TextView) findViewById(R.id.secondary_text);
mTitle = (TextView) findViewById(R.id.title);
mDescription = (TextView) findViewById(R.id.description);
}
protected void setPrimaryText(String text) {
mPrimaryText.setText(text);
protected void setTitle(String text) {
mTitle.setText(text);
}
protected void setSecondaryText(String text) {
mSecondaryText.setText(text);
protected void setDescription(String text) {
mDescription.setText(text);
}
protected void setSecondaryText(int stringId) {
mSecondaryText.setText(stringId);
}
protected void setPrimaryIcon(int iconId) {
if (mPrimaryIconId == iconId) {
return;
}
mPrimaryIconId = iconId;
mSecondaryText.setCompoundDrawablesWithIntrinsicBounds(mSecondaryIconId, 0, mPrimaryIconId, 0);
}
protected void setSecondaryIcon(int iconId) {
if (mSecondaryIconId == iconId) {
return;
}
mSecondaryIconId = iconId;
mSecondaryText.setCompoundDrawablesWithIntrinsicBounds(mSecondaryIconId, 0, mPrimaryIconId, 0);
protected void setDescription(int stringId) {
mDescription.setText(stringId);
}
public abstract void updateFromCursor(Cursor cursor);

View File

@ -68,13 +68,13 @@ public class PanelsPreferenceCategory extends CustomListCategory {
@Override
public void onPostExecute(List<PanelConfig> panelConfigs) {
mPanelConfigs = panelConfigs;
displayPanelConfig();
displayHomeConfig();
}
};
mLoadTask.execute();
}
private void displayPanelConfig() {
private void displayHomeConfig() {
for (PanelConfig panelConfig : mPanelConfigs) {
// Create and add the pref.
final PanelsPreference pref = new PanelsPreference(getContext(), PanelsPreferenceCategory.this);
@ -145,13 +145,13 @@ public class PanelsPreferenceCategory extends CustomListCategory {
* Update the local HomeConfig default state from mDefaultReference.
*/
private void updateConfigDefault() {
String mId = null;
String id = null;
if (mDefaultReference != null) {
mId = mDefaultReference.getKey();
id = mDefaultReference.getKey();
}
for (PanelConfig panelConfig : mPanelConfigs) {
if (TextUtils.equals(panelConfig.getId(), mId)) {
if (TextUtils.equals(panelConfig.getId(), id)) {
panelConfig.setIsDefault(true);
panelConfig.setIsDisabled(false);
} else {
@ -166,10 +166,10 @@ public class PanelsPreferenceCategory extends CustomListCategory {
// This could change the default, so update the local version of the config.
updateConfigDefault();
final String mId = pref.getKey();
final String id = pref.getKey();
PanelConfig toRemove = null;
for (PanelConfig panelConfig : mPanelConfigs) {
if (TextUtils.equals(panelConfig.getId(), mId)) {
if (TextUtils.equals(panelConfig.getId(), id)) {
toRemove = panelConfig;
break;
}
@ -190,9 +190,9 @@ public class PanelsPreferenceCategory extends CustomListCategory {
pref.setHidden(toHide);
ensureDefaultForHide(pref, toHide);
final String mId = pref.getKey();
final String id = pref.getKey();
for (PanelConfig panelConfig : mPanelConfigs) {
if (TextUtils.equals(panelConfig.getId(), mId)) {
if (TextUtils.equals(panelConfig.getId(), id)) {
panelConfig.setIsDisabled(toHide);
break;
}

View File

@ -18,14 +18,14 @@
android:orientation="vertical">
<org.mozilla.gecko.home.FadedTextView
android:id="@+id/primary_text"
style="@style/Widget.TwoLineRow.PrimaryText"
android:id="@+id/title"
style="@style/Widget.TwoLineRow.Title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
gecko:fadeWidth="30dp"/>
<TextView android:id="@+id/secondary_text"
style="@style/Widget.TwoLineRow.SecondaryText"
<TextView android:id="@+id/description"
style="@style/Widget.TwoLineRow.Description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawablePadding="5dp"

View File

@ -9,7 +9,7 @@
<item name="android:orientation">vertical</item>
</style>
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLineRow.PrimaryText">
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLineRow.Title">
<item name="android:paddingLeft">60dip</item>
<item name="android:drawablePadding">10dip</item>
<item name="android:drawableLeft">@drawable/bookmark_folder</item>

View File

@ -9,5 +9,6 @@
<dimen name="browser_toolbar_button_padding">16dp</dimen>
<dimen name="menu_popup_arrow_margin">8dip</dimen>
<dimen name="tabs_counter_size">26sp</dimen>
<dimen name="panel_grid_view_column_width">200dp</dimen>
</resources>

View File

@ -9,7 +9,7 @@
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="TextAppearance.Widget.TwoLineRow.PrimaryText" parent="TextAppearance.Medium">
<style name="TextAppearance.Widget.TwoLineRow.Title" parent="TextAppearance.Medium">
<item name="android:fontFamily">sans-serif-light</item>
</style>

View File

@ -103,5 +103,5 @@
<dimen name="icongrid_padding">16dp</dimen>
<!-- PanelGridView dimensions -->
<dimen name="panel_grid_view_column_width">180dp</dimen>
<dimen name="panel_grid_view_column_width">150dp</dimen>
</resources>

View File

@ -111,20 +111,20 @@
<style name="Widget.TwoLineRow" />
<style name="Widget.TwoLineRow.PrimaryText">
<item name="android:textAppearance">@style/TextAppearance.Widget.TwoLineRow.PrimaryText</item>
<style name="Widget.TwoLineRow.Title">
<item name="android:textAppearance">@style/TextAppearance.Widget.TwoLineRow.Title</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">none</item>
</style>
<style name="Widget.TwoLineRow.SecondaryText">
<item name="android:textAppearance">@style/TextAppearance.Widget.TwoLineRow.SecondaryText</item>
<style name="Widget.TwoLineRow.Description">
<item name="android:textAppearance">@style/TextAppearance.Widget.TwoLineRow.Description</item>
<item name="android:includeFontPadding">false</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">middle</item>
</style>
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLineRow.PrimaryText">
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLineRow.Title">
<item name="android:paddingLeft">10dip</item>
<item name="android:drawablePadding">10dip</item>
<item name="android:drawableLeft">@drawable/bookmark_folder</item>
@ -150,19 +150,20 @@
<item name="android:layout_height">fill_parent</item>
<item name="android:paddingTop">0dp</item>
<item name="android:stretchMode">columnWidth</item>
<item name="android:numColumns">auto_fit</item>
<item name="android:columnWidth">@dimen/panel_grid_view_column_width</item>
<item name="android:horizontalSpacing">2dp</item>
<item name="android:verticalSpacing">2dp</item>
</style>
<style name="Widget.PanelGridItemView">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
</style>
<style name="Widget.PanelGridItemImageView">
<item name="android:layout_height">@dimen/panel_grid_view_column_width</item>
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:scaleType">centerCrop</item>
<item name="android:adjustViewBounds">true</item>
<item name="android:background">@color/panel_grid_item_image_background</item>
@ -344,9 +345,9 @@
<style name="TextAppearance.Widget.TwoLineRow" />
<style name="TextAppearance.Widget.TwoLineRow.PrimaryText" parent="TextAppearance.Medium"/>
<style name="TextAppearance.Widget.TwoLineRow.Title" parent="TextAppearance.Medium"/>
<style name="TextAppearance.Widget.TwoLineRow.SecondaryText" parent="TextAppearance.Micro">
<style name="TextAppearance.Widget.TwoLineRow.Description" parent="TextAppearance.Micro">
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>

View File

@ -2,7 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-common/utils.js");
Cu.import("resource://gre/modules/osfile.jsm")
Cu.import("resource://gre/modules/osfile.jsm");
function run_test() {
initTestLogging();

View File

@ -17,11 +17,57 @@ Cu.import("resource://gre/modules/Timer.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/FxAccountsClient.jsm");
Cu.import("resource://gre/modules/FxAccountsCommon.js");
Cu.import("resource://gre/modules/FxAccountsUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "jwcrypto",
"resource://gre/modules/identity/jwcrypto.jsm");
"resource://gre/modules/identity/jwcrypto.jsm");
InternalMethods = function(mock) {
// All properties exposed by the public FxAccounts API.
let publicProperties = [
"getAccountsURI",
"getAssertion",
"getKeys",
"getSignedInUser",
"loadAndPoll",
"localtimeOffsetMsec",
"now",
"promiseAccountsForceSigninURI",
"resendVerificationEmail",
"setSignedInUser",
"signOut",
"version",
"whenVerified"
];
/**
* The public API's constructor.
*/
this.FxAccounts = function (mockInternal) {
let internal = new FxAccountsInternal();
let external = {};
// Copy all public properties to the 'external' object.
let prototype = FxAccountsInternal.prototype;
let options = {keys: publicProperties, bind: internal};
FxAccountsUtils.copyObjectProperties(prototype, external, options);
// Copy all of the mock's properties to the internal object.
if (mockInternal && !mockInternal.onlySetInternal) {
FxAccountsUtils.copyObjectProperties(mockInternal, internal);
}
if (mockInternal) {
// Exposes the internal object for testing only.
external.internal = internal;
}
return Object.freeze(external);
}
/**
* The internal API's constructor.
*/
function FxAccountsInternal() {
this.cert = null;
this.keyPair = null;
this.signedInUser = null;
@ -49,23 +95,23 @@ InternalMethods = function(mock) {
this.fxAccountsClient = new FxAccountsClient();
if (mock) { // Testing.
Object.keys(mock).forEach((prop) => {
log.debug("InternalMethods: mocking: " + prop);
this[prop] = mock[prop];
});
}
if (!this.signedInUserStorage) {
// Normal (i.e., non-testing) initialization.
// We don't reference |profileDir| in the top-level module scope
// as we may be imported before we know where it is.
this.signedInUserStorage = new JSONStorage({
filename: DEFAULT_STORAGE_FILENAME,
baseDir: OS.Constants.Path.profileDir,
});
}
// We don't reference |profileDir| in the top-level module scope
// as we may be imported before we know where it is.
this.signedInUserStorage = new JSONStorage({
filename: DEFAULT_STORAGE_FILENAME,
baseDir: OS.Constants.Path.profileDir,
});
}
InternalMethods.prototype = {
/**
* The internal API's prototype.
*/
FxAccountsInternal.prototype = {
/**
* The current data format's version number.
*/
version: DATA_FORMAT_VERSION,
/**
* Return the current time in milliseconds as an integer. Allows tests to
@ -102,6 +148,125 @@ InternalMethods.prototype = {
return this.fxAccountsClient.accountKeys(keyFetchToken);
},
// set() makes sure that polling is happening, if necessary.
// get() does not wait for verification, and returns an object even if
// unverified. The caller of get() must check .verified .
// The "fxaccounts:onverified" event will fire only when the verified
// state goes from false to true, so callers must register their observer
// and then call get(). In particular, it will not fire when the account
// was found to be verified in a previous boot: if our stored state says
// the account is verified, the event will never fire. So callers must do:
// register notification observer (go)
// userdata = get()
// if (userdata.verified()) {go()}
/**
* Get the user currently signed in to Firefox Accounts.
*
* @return Promise
* The promise resolves to the credentials object of the signed-in user:
* {
* email: The user's email address
* uid: The user's unique id
* sessionToken: Session for the FxA server
* kA: An encryption key from the FxA server
* kB: An encryption key derived from the user's FxA password
* verified: email verification status
* }
* or null if no user is signed in.
*/
getSignedInUser: function getSignedInUser() {
return this.getUserAccountData().then(data => {
if (!data) {
return null;
}
if (!this.isUserEmailVerified(data)) {
// If the email is not verified, start polling for verification,
// but return null right away. We don't want to return a promise
// that might not be fulfilled for a long time.
this.startVerifiedCheck(data);
}
return data;
});
},
/**
* Set the current user signed in to Firefox Accounts.
*
* @param credentials
* The credentials object obtained by logging in or creating
* an account on the FxA server:
* {
* email: The users email address
* uid: The user's unique id
* sessionToken: Session for the FxA server
* keyFetchToken: an unused keyFetchToken
* verified: true/false
* }
* @return Promise
* The promise resolves to null when the data is saved
* successfully and is rejected on error.
*/
setSignedInUser: function setSignedInUser(credentials) {
log.debug("setSignedInUser - aborting any existing flows");
this.abortExistingFlow();
let record = {version: this.version, accountData: credentials};
// Cache a clone of the credentials object.
this.signedInUser = JSON.parse(JSON.stringify(record));
// This promise waits for storage, but not for verification.
// We're telling the caller that this is durable now.
return this.signedInUserStorage.set(record).then(() => {
this.notifyObservers(ONLOGIN_NOTIFICATION);
if (!this.isUserEmailVerified(credentials)) {
this.startVerifiedCheck(credentials);
}
});
},
/**
* returns a promise that fires with the assertion. If there is no verified
* signed-in user, fires with null.
*/
getAssertion: function getAssertion(audience) {
log.debug("enter getAssertion()");
let mustBeValidUntil = this.now() + ASSERTION_LIFETIME;
return this.getUserAccountData().then(data => {
if (!data) {
// No signed-in user
return null;
}
if (!this.isUserEmailVerified(data)) {
// Signed-in user has not verified email
return null;
}
return this.getKeyPair(mustBeValidUntil).then(keyPair => {
return this.getCertificate(data, keyPair, mustBeValidUntil)
.then(cert => {
return this.getAssertionFromCert(data, keyPair, cert, audience);
});
});
});
},
/**
* Resend the verification email fot the currently signed-in user.
*
*/
resendVerificationEmail: function resendVerificationEmail() {
return this.getSignedInUser().then(data => {
// If the caller is asking for verification to be re-sent, and there is
// no signed-in user to begin with, this is probably best regarded as an
// error.
if (data) {
this.pollEmailStatus(data.sessionToken, "start");
return this.fxAccountsClient.resendVerificationEmail(data.sessionToken);
}
throw new Error("Cannot resend verification email; no signed-in user");
});
},
/*
* Reset state such that any previous flow is canceled.
*/
@ -179,14 +344,14 @@ InternalMethods.prototype = {
return Task.spawn(function* task() {
// Sign out if we don't have a key fetch token.
if (!keyFetchToken) {
yield internal.signOut();
yield this.signOut();
return null;
}
let myGenerationCount = internal.generationCount;
let myGenerationCount = this.generationCount;
let {kA, wrapKB} = yield internal.fetchKeys(keyFetchToken);
let {kA, wrapKB} = yield this.fetchKeys(keyFetchToken);
let data = yield internal.getUserAccountData();
let data = yield this.getUserAccountData();
// Sanity check that the user hasn't changed out from under us
if (data.keyFetchToken !== keyFetchToken) {
@ -208,16 +373,16 @@ InternalMethods.prototype = {
// Before writing any data, ensure that a new flow hasn't been
// started behind our backs.
if (internal.generationCount !== myGenerationCount) {
if (this.generationCount !== myGenerationCount) {
return null;
}
yield internal.setUserAccountData(data);
yield this.setUserAccountData(data);
// We are now ready for business. This should only be invoked once
// per setSignedInUser(), regardless of whether we've rebooted since
// setSignedInUser() was called.
internal.notifyObservers(ONVERIFIED_NOTIFICATION);
this.notifyObservers(ONVERIFIED_NOTIFICATION);
return data;
}.bind(this));
},
@ -227,8 +392,8 @@ InternalMethods.prototype = {
let payload = {};
let d = Promise.defer();
let options = {
localtimeOffsetMsec: internal.localtimeOffsetMsec,
now: internal.now()
localtimeOffsetMsec: this.localtimeOffsetMsec,
now: this.now()
};
// "audience" should look like "http://123done.org".
// The generated assertion will expire in two minutes.
@ -252,7 +417,7 @@ InternalMethods.prototype = {
return Promise.resolve(this.cert.cert);
}
// else get our cert signed
let willBeValidUntil = internal.now() + CERT_LIFETIME;
let willBeValidUntil = this.now() + CERT_LIFETIME;
return this.getCertificateSigned(data.sessionToken,
keyPair.serializedPublicKey,
CERT_LIFETIME)
@ -279,7 +444,7 @@ InternalMethods.prototype = {
return Promise.resolve(this.keyPair.keyPair);
}
// Otherwse, create a keypair and set validity limit.
let willBeValidUntil = internal.now() + KEY_LIFETIME;
let willBeValidUntil = this.now() + KEY_LIFETIME;
let d = Promise.defer();
jwcrypto.generateKeyPair("DS160", (err, kp) => {
if (err) {
@ -368,18 +533,6 @@ InternalMethods.prototype = {
return this.whenVerifiedPromise.promise;
},
/**
* Resend the verification email to the logged-in user.
*
* @return Promise
* fulfilled: json data returned from xhr call
* rejected: error
*/
resendVerificationEmail: function(data) {
this.pollEmailStatus(data.sessionToken, "start");
return this.fxAccountsClient.resendVerificationEmail(data.sessionToken);
},
notifyObservers: function(topic) {
log.debug("Notifying observers of " + topic);
Services.obs.notifyObservers(null, topic, null);
@ -445,194 +598,12 @@ InternalMethods.prototype = {
},
setUserAccountData: function(accountData) {
return this.signedInUserStorage.get().then((record) => {
return this.signedInUserStorage.get().then(record => {
record.accountData = accountData;
this.signedInUser = record;
return this.signedInUserStorage.set(record)
.then(() => accountData);
});
}
};
let internal = null;
/**
* FxAccounts delegates private methods to an instance of InternalMethods,
* which is not exported. The xpcshell tests need two overrides:
* 1) Access to the real internal.signedInUserStorage.
* 2) The ability to mock InternalMethods.
* If mockInternal is undefined, we are live.
* If mockInternal.onlySetInternal is present, we are executing the first
* case by binding internal to the FxAccounts instance.
* Otherwise if we have a mock instance, we are executing the second case.
*/
this.FxAccounts = function(mockInternal) {
let mocks = mockInternal;
if (mocks && mocks.onlySetInternal) {
mocks = null;
}
internal = new InternalMethods(mocks);
if (mockInternal) {
// Exposes the internal object for testing only.
this.internal = internal;
}
}
this.FxAccounts.prototype = Object.freeze({
version: DATA_FORMAT_VERSION,
now: function() {
if (this.internal) {
return this.internal.now();
}
return internal.now();
},
get localtimeOffsetMsec() {
if (this.internal) {
return this.internal.localtimeOffsetMsec;
}
return internal.localtimeOffsetMsec;
},
// set() makes sure that polling is happening, if necessary.
// get() does not wait for verification, and returns an object even if
// unverified. The caller of get() must check .verified .
// The "fxaccounts:onverified" event will fire only when the verified
// state goes from false to true, so callers must register their observer
// and then call get(). In particular, it will not fire when the account
// was found to be verified in a previous boot: if our stored state says
// the account is verified, the event will never fire. So callers must do:
// register notification observer (go)
// userdata = get()
// if (userdata.verified()) {go()}
/**
* Set the current user signed in to Firefox Accounts.
*
* @param credentials
* The credentials object obtained by logging in or creating
* an account on the FxA server:
* {
* email: The users email address
* uid: The user's unique id
* sessionToken: Session for the FxA server
* keyFetchToken: an unused keyFetchToken
* verified: true/false
* }
* @return Promise
* The promise resolves to null when the data is saved
* successfully and is rejected on error.
*/
setSignedInUser: function setSignedInUser(credentials) {
log.debug("setSignedInUser - aborting any existing flows");
internal.abortExistingFlow();
let record = {version: this.version, accountData: credentials};
// Cache a clone of the credentials object.
internal.signedInUser = JSON.parse(JSON.stringify(record));
// This promise waits for storage, but not for verification.
// We're telling the caller that this is durable now.
return internal.signedInUserStorage.set(record)
.then(() => {
internal.notifyObservers(ONLOGIN_NOTIFICATION);
if (!internal.isUserEmailVerified(credentials)) {
internal.startVerifiedCheck(credentials);
}
});
},
/**
* Get the user currently signed in to Firefox Accounts.
*
* @return Promise
* The promise resolves to the credentials object of the signed-in user:
* {
* email: The user's email address
* uid: The user's unique id
* sessionToken: Session for the FxA server
* kA: An encryption key from the FxA server
* kB: An encryption key derived from the user's FxA password
* verified: email verification status
* }
* or null if no user is signed in.
*/
getSignedInUser: function getSignedInUser() {
return internal.getUserAccountData()
.then((data) => {
if (!data) {
return null;
}
if (!internal.isUserEmailVerified(data)) {
// If the email is not verified, start polling for verification,
// but return null right away. We don't want to return a promise
// that might not be fulfilled for a long time.
internal.startVerifiedCheck(data);
}
return data;
});
},
/**
* Resend the verification email fot the currently signed-in user.
*
*/
resendVerificationEmail: function resendVerificationEmail() {
return this.getSignedInUser().then((data) => {
// If the caller is asking for verification to be re-sent, and there is
// no signed-in user to begin with, this is probably best regarded as an
// error.
if (data) {
return internal.resendVerificationEmail(data);
}
throw new Error("Cannot resend verification email; no signed-in user");
});
},
/**
* returns a promise that fires with the assertion. If there is no verified
* signed-in user, fires with null.
*/
getAssertion: function getAssertion(audience) {
log.debug("enter getAssertion()");
let mustBeValidUntil = internal.now() + ASSERTION_LIFETIME;
return internal.getUserAccountData()
.then((data) => {
if (!data) {
// No signed-in user
return null;
}
if (!internal.isUserEmailVerified(data)) {
// Signed-in user has not verified email
return null;
}
return internal.getKeyPair(mustBeValidUntil)
.then((keyPair) => {
return internal.getCertificate(data, keyPair, mustBeValidUntil)
.then((cert) => {
return internal.getAssertionFromCert(data, keyPair,
cert, audience)
});
});
});
},
getKeys: function() {
return internal.getKeys();
},
whenVerified: function(userData) {
return internal.whenVerified(userData);
},
/**
* Sign the current user out.
*
* @return Promise
* The promise is rejected if a storage error occurs.
*/
signOut: function signOut() {
return internal.signOut();
},
// Return the URI of the remote UI flows.
@ -661,8 +632,7 @@ this.FxAccounts.prototype = Object.freeze({
return url + newQueryPortion;
});
}
});
};
/**
* JSONStorage constructor that creates instances that may set/get
@ -697,8 +667,7 @@ XPCOMUtils.defineLazyGetter(this, "fxAccounts", function() {
// XXX Bug 947061 - We need a strategy for resuming email verification after
// browser restart
internal.loadAndPoll();
a.loadAndPoll();
return a;
});

View File

@ -0,0 +1,49 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = ["FxAccountsUtils"];
this.FxAccountsUtils = Object.freeze({
/**
* Copies properties from a given object to another object.
*
* @param from (object)
* The object we read property descriptors from.
* @param to (object)
* The object that we set property descriptors on.
* @param options (object) (optional)
* {keys: [...]}
* Lets the caller pass the names of all properties they want to be
* copied. Will copy all properties of the given source object by
* default.
* {bind: object}
* Lets the caller specify the object that will be used to .bind()
* all function properties we find to. Will bind to the given target
* object by default.
*/
copyObjectProperties: function (from, to, opts = {}) {
let keys = (opts && opts.keys) || Object.keys(from);
let thisArg = (opts && opts.bind) || to;
for (let prop of keys) {
let desc = Object.getOwnPropertyDescriptor(from, prop);
if (typeof(desc.value) == "function") {
desc.value = desc.value.bind(thisArg);
}
if (desc.get) {
desc.get = desc.get.bind(thisArg);
}
if (desc.set) {
desc.set = desc.set.bind(thisArg);
}
Object.defineProperty(to, prop, desc);
}
}
});

View File

@ -11,7 +11,8 @@ TEST_DIRS += ['tests']
EXTRA_JS_MODULES += [
'FxAccounts.jsm',
'FxAccountsClient.jsm',
'FxAccountsCommon.js'
'FxAccountsCommon.js',
'FxAccountsUtils.jsm'
]
# For now, we will only be using the FxA manager in B2G.

View File

@ -102,28 +102,23 @@ MockStorage.prototype = Object.freeze({
* mock the now() method, so that we can simulate the passing of
* time and verify that signatures expire correctly.
*/
let MockFxAccounts = function() {
this._getCertificateSigned_calls = [];
this._d_signCertificate = Promise.defer();
this._now_is = new Date();
let mockInternal = {
function MockFxAccounts() {
return new FxAccounts({
_getCertificateSigned_calls: [],
_d_signCertificate: Promise.defer(),
_now_is: new Date(),
signedInUserStorage: new MockStorage(),
now: () => {
now: function () {
return this._now_is;
},
getCertificateSigned: (sessionToken, serializedPublicKey) => {
_("mock getCerificateSigned\n");
getCertificateSigned: function (sessionToken, serializedPublicKey) {
_("mock getCertificateSigned\n");
this._getCertificateSigned_calls.push([sessionToken, serializedPublicKey]);
return this._d_signCertificate.promise;
},
fxAccountsClient: new MockFxAccountsClient()
};
FxAccounts.apply(this, [mockInternal]);
};
MockFxAccounts.prototype = {
__proto__: FxAccounts.prototype,
};
});
}
add_test(function test_non_https_remote_server_uri() {
Services.prefs.setCharPref(
@ -394,15 +389,15 @@ add_task(function test_getAssertion() {
// the test, we will update 'now', but leave 'start' where it is.
let now = Date.parse("Mon, 13 Jan 2014 21:45:06 GMT");
let start = now;
fxa._now_is = now;
fxa.internal._now_is = now;
let d = fxa.getAssertion("audience.example.com");
// At this point, a thread has been spawned to generate the keys.
_("-- back from fxa.getAssertion\n");
fxa._d_signCertificate.resolve("cert1");
fxa.internal._d_signCertificate.resolve("cert1");
let assertion = yield d;
do_check_eq(fxa._getCertificateSigned_calls.length, 1);
do_check_eq(fxa._getCertificateSigned_calls[0][0], "sessionToken");
do_check_eq(fxa.internal._getCertificateSigned_calls.length, 1);
do_check_eq(fxa.internal._getCertificateSigned_calls[0][0], "sessionToken");
do_check_neq(assertion, null);
_("ASSERTION: " + assertion + "\n");
let pieces = assertion.split("~");
@ -424,18 +419,18 @@ add_task(function test_getAssertion() {
do_check_eq(exp, now + TWO_MINUTES_MS);
// Reset for next call.
fxa._d_signCertificate = Promise.defer();
fxa.internal._d_signCertificate = Promise.defer();
// Getting a new assertion "soon" (i.e., w/o incrementing "now"), even for
// a new audience, should not provoke key generation or a signing request.
assertion = yield fxa.getAssertion("other.example.com");
// There were no additional calls - same number of getcert calls as before
do_check_eq(fxa._getCertificateSigned_calls.length, 1);
do_check_eq(fxa.internal._getCertificateSigned_calls.length, 1);
// Wait an hour; assertion expires, but not the certificate
now += ONE_HOUR_MS;
fxa._now_is = now;
fxa.internal._now_is = now;
// This won't block on anything - will make an assertion, but not get a
// new certificate.
@ -462,12 +457,12 @@ add_task(function test_getAssertion() {
// Now we wait even longer, and expect both assertion and cert to expire. So
// we will have to get a new keypair and cert.
now += ONE_DAY_MS;
fxa._now_is = now;
fxa.internal._now_is = now;
d = fxa.getAssertion("fourth.example.com");
fxa._d_signCertificate.resolve("cert2");
fxa.internal._d_signCertificate.resolve("cert2");
assertion = yield d;
do_check_eq(fxa._getCertificateSigned_calls.length, 2);
do_check_eq(fxa._getCertificateSigned_calls[1][0], "sessionToken");
do_check_eq(fxa.internal._getCertificateSigned_calls.length, 2);
do_check_eq(fxa.internal._getCertificateSigned_calls[1][0], "sessionToken");
pieces = assertion.split("~");
do_check_eq(pieces[0], "cert2");
p2 = pieces[1].split(".");

View File

@ -63,6 +63,8 @@ function AuthenticationError(message) {
}
this.BrowserIDManager = function BrowserIDManager() {
// NOTE: _fxaService and _tokenServerClient are replaced with mocks by
// the test suite.
this._fxaService = fxAccounts;
this._tokenServerClient = new TokenServerClient();
// will be a promise that resolves when we are ready to authenticate
@ -112,7 +114,7 @@ this.BrowserIDManager.prototype = {
this.whenReadyToAuthenticate = Promise.defer();
this._shouldHaveSyncKeyBundle = false;
return fxAccounts.getSignedInUser().then(accountData => {
return this._fxaService.getSignedInUser().then(accountData => {
if (!accountData) {
this._log.info("initializeWithCurrentIdentity has no user logged in");
this._account = null;
@ -124,7 +126,7 @@ this.BrowserIDManager.prototype = {
// this and the rest of initialization off in the background (ie, we
// don't return the promise)
this._log.info("Waiting for user to be verified.");
fxAccounts.whenVerified(accountData).then(accountData => {
this._fxaService.whenVerified(accountData).then(accountData => {
// We do the background keybundle fetch...
this._log.info("Starting fetch for key bundle.");
if (this.needsCustomization) {
@ -141,7 +143,7 @@ this.BrowserIDManager.prototype = {
Services.prefs.clearUserPref(PREF_SYNC_SHOW_CUSTOMIZATION);
} else {
// Log out if the user canceled the dialog.
return fxAccounts.signOut();
return this._fxaService.signOut();
}
}
}).then(() => {
@ -411,6 +413,7 @@ this.BrowserIDManager.prototype = {
let tokenServerURI = Svc.Prefs.get("tokenServerURI");
let log = this._log;
let client = this._tokenServerClient;
let fxa = this._fxaService;
// Both Jelly and FxAccounts give us kB as hex
let kBbytes = CommonUtils.hexToBytes(userData.kB);
@ -437,7 +440,7 @@ this.BrowserIDManager.prototype = {
function getAssertion() {
log.debug("Getting an assertion");
let audience = Services.io.newURI(tokenServerURI, null, null).prePath;
return fxAccounts.getAssertion(audience).then(null, err => {
return fxa.getAssertion(audience).then(null, err => {
if (err.code === 401) {
throw new AuthenticationError("Unable to get assertion for user");
} else {
@ -448,7 +451,7 @@ this.BrowserIDManager.prototype = {
// wait until the account email is verified and we know that
// getAssertion() will return a real assertion (not null).
return this._fxaService.whenVerified(userData)
return fxa.whenVerified(userData)
.then(() => getAssertion())
.then(assertion => getToken(tokenServerURI, assertion))
.then(token => {
@ -561,8 +564,9 @@ BrowserIDClusterManager.prototype = {
__proto__: ClusterManager.prototype,
_findCluster: function() {
let fxa = this.identity._fxaService; // will be mocked for tests.
let promiseClusterURL = function() {
return fxAccounts.getSignedInUser().then(userData => {
return fxa.getSignedInUser().then(userData => {
return this.identity._fetchTokenForUser(userData).then(token => {
let endpoint = token.endpoint;
// For Sync 1.5 storage endpoints, we use the base endpoint verbatim.

View File

@ -100,28 +100,12 @@ TabStore.prototype = {
return id == this.engine.service.clientsEngine.localID;
},
/**
* Return the recorded last used time of the provided tab, or
* 0 if none is present.
* The result will always be an integer value.
*/
tabLastUsed: function tabLastUsed(tab) {
// weaveLastUsed will only be set if the tab was ever selected (or
// opened after Sync was running).
let weaveLastUsed = tab.extData && tab.extData.weaveLastUsed;
if (!weaveLastUsed) {
return 0;
}
return parseInt(weaveLastUsed, 10) || 0;
},
getAllTabs: function getAllTabs(filter) {
let filteredUrls = new RegExp(Svc.Prefs.get("engine.tabs.filteredUrls"), "i");
let allTabs = [];
let currentState = JSON.parse(Svc.Session.getBrowserState());
let tabLastUsed = this.tabLastUsed;
currentState.windows.forEach(function (window) {
if (window.isPrivate) {
return;
@ -145,7 +129,7 @@ TabStore.prototype = {
title: entry.title || "",
urlHistory: [entry.url],
icon: tab.attributes && tab.attributes.image || "",
lastUsed: tabLastUsed(tab)
lastUsed: Math.floor((tab.lastAccessed || 0) / 1000)
});
});
});
@ -329,20 +313,10 @@ TabTracker.prototype = {
this._log.trace("onTab event: " + event.type);
this.modified = true;
// For pageshow events, only give a partial score bump (~.1)
let chance = .1;
// For regular Tab events, do a full score bump and remember when it changed
if (event.type != "pageshow") {
chance = 1;
// Store a timestamp in the tab to track when it was last used
Svc.Session.setTabValue(event.originalTarget, "weaveLastUsed",
Math.floor(Date.now() / 1000));
}
// Only increase the score by whole numbers, so use random for partial score
if (Math.random() < chance)
// For page shows, bump the score 10% of the time, emulating a partial
// score. We don't want to sync too frequently. For all other page
// events, always bump the score.
if (event.type != "pageshow" || Math.random() < .1)
this.score += SCORE_INCREMENT_SMALL;
},
}

View File

@ -11,6 +11,7 @@ Cu.import("resource://testing-common/services/sync/utils.js");
Cu.import("resource://services-common/hawk.js");
Cu.import("resource://gre/modules/FxAccounts.jsm");
Cu.import("resource://gre/modules/FxAccountsClient.jsm");
Cu.import("resource://gre/modules/FxAccountsCommon.js");
const SECOND_MS = 1000;
const MINUTE_MS = SECOND_MS * 60;
@ -33,22 +34,25 @@ MockFxAccountsClient.prototype = {
__proto__: FxAccountsClient.prototype
};
let MockFxAccounts = function() {
this._now_is = Date.now();
function MockFxAccounts() {
return new FxAccounts({
_now_is: Date.now(),
let mockInternal = {
now: () => {
now: function () {
return this._now_is;
},
fxAccountsClient: new MockFxAccountsClient()
};
getCertificate: function(data, keyPair, mustBeValidUntil) {
this.cert = {
validUntil: Date.now() + CERT_LIFETIME,
cert: "certificate",
};
return Promise.resolve(this.cert.cert);
},
FxAccounts.apply(this, [mockInternal]);
};
MockFxAccounts.prototype = {
__proto__: FxAccounts.prototype,
};
fxAccountsClient: new MockFxAccountsClient()
});
}
function run_test() {
initTestLogging("Trace");
@ -129,7 +133,7 @@ add_test(function test_resourceAuthenticatorSkew() {
do_check_eq(fxaClient.localtimeOffsetMsec, localtimeOffsetMsec);
let fxa = new MockFxAccounts();
fxa._now_is = now;
fxa.internal._now_is = now;
fxa.internal.fxAccountsClient = fxaClient;
// Picked up by the signed-in user module
@ -141,6 +145,10 @@ add_test(function test_resourceAuthenticatorSkew() {
// Mocks within mocks...
configureFxAccountIdentity(browseridManager, identityConfig);
// Ensure the new FxAccounts mock has a signed-in user.
fxa.internal.signedInUser = browseridManager._fxaService.internal.signedInUser;
browseridManager._fxaService = fxa;
do_check_eq(browseridManager._fxaService.internal.now(), now);
@ -186,10 +194,14 @@ add_test(function test_RESTResourceAuthenticatorSkew() {
let fxaClient = new MockFxAccountsClient();
fxaClient.hawk = hawkClient;
let fxa = new MockFxAccounts();
fxa._now_is = now;
fxa.internal._now_is = now;
fxa.internal.fxAccountsClient = fxaClient;
configureFxAccountIdentity(browseridManager, identityConfig);
// Ensure the new FxAccounts mock has a signed-in user.
fxa.internal.signedInUser = browseridManager._fxaService.internal.signedInUser;
browseridManager._fxaService = fxa;
do_check_eq(browseridManager._fxaService.internal.now(), now);

View File

@ -46,10 +46,8 @@ add_task(function test_locally_changed_keys() {
}],
attributes: {
image: "image"
},
extData: {
weaveLastUsed: 1
}}]}]};
}
}]}]};
delete Svc.Session;
Svc.Session = {
getBrowserState: function () JSON.stringify(myTabs)

View File

@ -54,10 +54,8 @@ add_test(function v4_upgrade() {
}],
attributes: {
image: "image"
},
extData: {
weaveLastUsed: 1
}}]}]};
}
}]}]};
delete Svc.Session;
Svc.Session = {
getBrowserState: function () JSON.stringify(myTabs)
@ -225,10 +223,8 @@ add_test(function v5_upgrade() {
}],
attributes: {
image: "image"
},
extData: {
weaveLastUsed: 1
}}]}]};
}
}]}]};
delete Svc.Session;
Svc.Session = {
getBrowserState: function () JSON.stringify(myTabs)

View File

@ -16,9 +16,6 @@ function fakeSessionSvc() {
}],
attributes: {
image: "image"
},
extData: {
weaveLastUsed: 1
}
});
}

View File

@ -6,25 +6,6 @@ Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services-common/utils.js");
function test_lastUsed() {
let store = new TabEngine(Service)._store;
_("Check extraction of last used times from tab objects.");
let expected = [
[0, {}],
[0, {extData: null}],
[0, {extData: {}}],
[0, {extData: {weaveLastUsed: null}}],
[123456789, {extData: {weaveLastUsed: "123456789"}}],
[123456789, {extData: {weaveLastUsed: 123456789}}],
[123456789, {extData: {weaveLastUsed: 123456789.12}}]
];
for each (let [ex, input] in expected) {
do_check_eq(ex, store.tabLastUsed(input));
}
}
function test_create() {
let store = new TabEngine(Service)._store;
@ -76,9 +57,7 @@ function fakeSessionSvc(url, numtabs) {
attributes: {
image: "image"
},
extData: {
weaveLastUsed: 1
}
lastAccessed: 1499
}]
}]
};
@ -136,7 +115,6 @@ function test_createRecord() {
}
function run_test() {
test_lastUsed();
test_create();
test_getAllTabs();
test_createRecord();

View File

@ -34,18 +34,6 @@ function fakeSvcWinMediator() {
return logs;
}
function fakeSvcSession() {
// actions on Session are captured in logs
let logs = [];
delete Svc.Session;
Svc.Session = {
setTabValue: function(target, prop, value) {
logs.push({target: target, prop: prop, value: value});
}
};
return logs;
}
function run_test() {
let engine = Service.engineManager.get("tabs");
@ -88,8 +76,6 @@ function run_test() {
}
_("Test tab listener");
logs = fakeSvcSession();
let idx = 0;
for each (let evttype in ["TabOpen", "TabClose", "TabSelect"]) {
// Pretend we just synced.
tracker.clearChangedIDs();
@ -100,11 +86,6 @@ function run_test() {
do_check_true(tracker.modified);
do_check_true(Utils.deepEquals(Object.keys(engine.getChangedIDs()),
[clientsEngine.localID]));
do_check_eq(logs.length, idx+1);
do_check_eq(logs[idx].target, evttype);
do_check_eq(logs[idx].prop, "weaveLastUsed");
do_check_true(typeof logs[idx].value == "number");
idx++;
}
// Pretend we just synced.
@ -114,5 +95,4 @@ function run_test() {
tracker.onTab({type: "pageshow", originalTarget: "pageshow"});
do_check_true(Utils.deepEquals(Object.keys(engine.getChangedIDs()),
[clientsEngine.localID]));
do_check_eq(logs.length, idx); // test that setTabValue isn't called
}

View File

@ -336,6 +336,24 @@ Type.prototype = {
return type;
},
/**
* Lazy variant of releaseWith.
* Attach a finalizer lazily to a type.
*
* @param {function} getFinalizer The function that
* returns finalizer lazily.
*/
releaseWithLazy: function releaseWithLazy(getFinalizer) {
let parent = this;
let type = this.withName("[auto " + this.name + ", (lazy)] ");
type.importFromC = function importFromC(value, operation) {
return ctypes.CDataFinalizer(
parent.importFromC(value, operation),
getFinalizer());
};
return type;
},
/**
* Return an alias to a type with a different name.
*/
@ -912,6 +930,7 @@ Library.prototype = Object.freeze({
for (let candidate of this._candidates) {
try {
library = ctypes.open(candidate);
break;
} catch (ex) {
LOG("Could not open library", candidate, ex);
}
@ -961,6 +980,33 @@ Library.prototype = Object.freeze({
});
},
/**
* Define a js-ctypes function lazily using ctypes method declare.
*
* @param {object} The object containing the function as a field.
* @param {string} The name of the field containing the function.
* @param {string} symbol The name of the function, as defined in the
* library.
* @param {ctypes.abi} abi The abi to use, or |null| for default.
* @param {ctypes.CType} returnType The type of values returned by the function.
* @param {...ctypes.CType} argTypes The type of arguments to the function.
*/
declareLazy: function(object, field, ...args) {
let lib = this;
Object.defineProperty(object, field, {
get: function() {
delete this[field];
let ffi = lib.library.declare(...args);
if (ffi) {
return this[field] = ffi;
}
return undefined;
},
configurable: true,
enumerable: true
});
},
toString: function() {
return "[Library " + this.name + "]";
}

View File

@ -39,34 +39,20 @@ let LOG = SharedAll.LOG.bind(SharedAll, "Unix", "allthreads");
let Const = SharedAll.Constants.libc;
// Open libc
let libc;
let libc_candidates = [ "libc.so",
"libSystem.B.dylib",
"a.out" ];
for (let i = 0; i < libc_candidates.length; ++i) {
try {
libc = ctypes.open(libc_candidates[i]);
break;
} catch (x) {
LOG("Could not open libc ", libc_candidates[i]);
}
}
if (!libc) {
// Note: If you change the string here, please adapt tests accordingly
throw new Error("Could not open system library: no libc");
}
let libc = new SharedAll.Library("libc",
"libc.so", "libSystem.B.dylib", "a.out");
exports.libc = libc;
// Define declareFFI
let declareFFI = SharedAll.declareFFI.bind(null, libc);
exports.declareFFI = declareFFI;
// Define Error
let strerror = libc.declare("strerror",
ctypes.default_abi,
/*return*/ ctypes.char.ptr,
/*errnum*/ ctypes.int);
// Define lazy binding
let LazyBindings = {};
libc.declareLazy(LazyBindings, "strerror",
"strerror", ctypes.default_abi,
/*return*/ ctypes.char.ptr,
/*errnum*/ ctypes.int);
/**
* A File-related error.
@ -100,7 +86,7 @@ OSError.prototype = Object.create(SharedAll.OSError.prototype);
OSError.prototype.toString = function toString() {
return "Unix error " + this.unixErrno +
" during operation " + this.operation +
" (" + strerror(this.unixErrno).readString() + ")";
" (" + LazyBindings.strerror(this.unixErrno).readString() + ")";
};
/**

View File

@ -221,8 +221,8 @@
// Declare libc functions as functions of |OS.Unix.File|
// Finalizer-related functions
SharedAll.declareLazy(SysFile, "_close", libc,
"close", ctypes.default_abi,
libc.declareLazy(SysFile, "_close",
"close", ctypes.default_abi,
/*return */ctypes.int,
/*fd*/ ctypes.int);
@ -231,8 +231,8 @@
return fd.dispose();
};
SharedAll.declareLazy(SysFile, "_close_dir", libc,
"closedir", ctypes.default_abi,
libc.declareLazy(SysFile, "_close_dir",
"closedir", ctypes.default_abi,
/*return */ctypes.int,
/*dirp*/ Type.DIR.in_ptr.implementation);
@ -244,14 +244,14 @@
{
// Symbol free() is special.
// We override the definition of free() on several platforms.
let default_lib = libc;
let default_lib = new SharedAll.Library("default_lib",
"a.out");
try {
// On platforms for which we override free(), nspr defines
// a special library name "a.out" that will resolve to the
// correct implementation free().
default_lib = ctypes.open("a.out");
SharedAll.declareLazy(SysFile, "free", default_lib,
default_lib.declareLazy(SysFile, "free",
"free", ctypes.default_abi,
/*return*/ ctypes.void_t,
/*ptr*/ ctypes.voidptr_t);
@ -260,7 +260,7 @@
// We don't have an a.out library or a.out doesn't contain free.
// Either way, use the ordinary libc free.
SharedAll.declareLazy(SysFile, "free", libc,
libc.declareLazy(SysFile, "free",
"free", ctypes.default_abi,
/*return*/ ctypes.void_t,
/*ptr*/ ctypes.voidptr_t);
@ -269,36 +269,42 @@
// Other functions
declareLazyFFI(SysFile, "access", libc, "access", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*mode*/ Type.int);
libc.declareLazyFFI(SysFile, "access",
"access", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*mode*/ Type.int);
declareLazyFFI(SysFile, "chdir", libc, "chdir", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path);
libc.declareLazyFFI(SysFile, "chdir",
"chdir", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path);
declareLazyFFI(SysFile, "chmod", libc, "chmod", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*mode*/ Type.mode_t);
libc.declareLazyFFI(SysFile, "chmod",
"chmod", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*mode*/ Type.mode_t);
declareLazyFFI(SysFile, "chown", libc, "chown", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*uid*/ Type.uid_t,
/*gid*/ Type.gid_t);
libc.declareLazyFFI(SysFile, "chown",
"chown", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*uid*/ Type.uid_t,
/*gid*/ Type.gid_t);
declareLazyFFI(SysFile, "copyfile", libc, "copyfile", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*source*/ Type.path,
/*dest*/ Type.path,
/*state*/ Type.void_t.in_ptr, // Ignored atm
/*flags*/ Type.uint32_t);
libc.declareLazyFFI(SysFile, "copyfile",
"copyfile", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*source*/ Type.path,
/*dest*/ Type.path,
/*state*/ Type.void_t.in_ptr, // Ignored atm
/*flags*/ Type.uint32_t);
declareLazyFFI(SysFile, "dup", libc, "dup", ctypes.default_abi,
/*return*/ Type.negativeone_or_fd,
/*fd*/ Type.fd);
libc.declareLazyFFI(SysFile, "dup",
"dup", ctypes.default_abi,
/*return*/ Type.negativeone_or_fd,
/*fd*/ Type.fd);
if ("OSFILE_SIZEOF_DIR" in Const) {
// On platforms for which |dirfd| is a macro
@ -308,127 +314,150 @@
};
} else {
// On platforms for which |dirfd| is a function
declareLazyFFI(SysFile, "dirfd", libc, "dirfd", ctypes.default_abi,
/*return*/ Type.negativeone_or_fd,
/*dir*/ Type.DIR.in_ptr);
libc.declareLazyFFI(SysFile, "dirfd",
"dirfd", ctypes.default_abi,
/*return*/ Type.negativeone_or_fd,
/*dir*/ Type.DIR.in_ptr);
}
declareLazyFFI(SysFile, "chdir", libc, "chdir", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path);
libc.declareLazyFFI(SysFile, "chdir",
"chdir", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path);
declareLazyFFI(SysFile, "fchdir", libc, "fchdir", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd);
libc.declareLazyFFI(SysFile, "fchdir",
"fchdir", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd);
declareLazyFFI(SysFile, "fchown", libc, "fchown", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd,
/*uid_t*/ Type.uid_t,
/*gid_t*/ Type.gid_t);
libc.declareLazyFFI(SysFile, "fchown",
"fchown", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd,
/*uid_t*/ Type.uid_t,
/*gid_t*/ Type.gid_t);
declareLazyFFI(SysFile, "fsync", libc, "fsync", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd);
libc.declareLazyFFI(SysFile, "fsync",
"fsync", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd);
declareLazyFFI(SysFile, "getcwd", libc, "getcwd", ctypes.default_abi,
/*return*/ Type.out_path,
/*buf*/ Type.out_path,
/*size*/ Type.size_t);
libc.declareLazyFFI(SysFile, "getcwd",
"getcwd", ctypes.default_abi,
/*return*/ Type.out_path,
/*buf*/ Type.out_path,
/*size*/ Type.size_t);
declareLazyFFI(SysFile, "getwd", libc, "getwd", ctypes.default_abi,
/*return*/ Type.out_path,
/*buf*/ Type.out_path);
libc.declareLazyFFI(SysFile, "getwd",
"getwd", ctypes.default_abi,
/*return*/ Type.out_path,
/*buf*/ Type.out_path);
// Two variants of |getwd| which allocate the memory
// dynamically.
// Linux/Android version
declareLazyFFI(SysFile, "get_current_dir_name", libc,
"get_current_dir_name", ctypes.default_abi,
/*return*/ Type.out_path.releaseWith(SysFile.free));
libc.declareLazyFFI(SysFile, "get_current_dir_name",
"get_current_dir_name", ctypes.default_abi,
/*return*/ Type.out_path.releaseWithLazy(() =>
SysFile.free
));
// MacOS/BSD version (will return NULL on Linux/Android)
declareLazyFFI(SysFile, "getwd_auto", libc,
"getwd", ctypes.default_abi,
/*return*/ Type.out_path.releaseWith(SysFile.free),
/*buf*/ Type.void_t.out_ptr);
libc.declareLazyFFI(SysFile, "getwd_auto",
"getwd", ctypes.default_abi,
/*return*/ Type.out_path.releaseWithLazy(() =>
SysFile.free
),
/*buf*/ Type.void_t.out_ptr);
declareLazyFFI(SysFile, "fdatasync", libc,
"fdatasync", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd); // Note: MacOS/BSD-specific
libc.declareLazyFFI(SysFile, "fdatasync",
"fdatasync", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd); // Note: MacOS/BSD-specific
declareLazyFFI(SysFile, "ftruncate", libc,
"ftruncate", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd,
/*length*/ Type.off_t);
libc.declareLazyFFI(SysFile, "ftruncate",
"ftruncate", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd,
/*length*/ Type.off_t);
declareLazyFFI(SysFile, "lchown", libc, "lchown", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*uid_t*/ Type.uid_t,
/*gid_t*/ Type.gid_t);
libc.declareLazyFFI(SysFile, "lchown",
"lchown", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*uid_t*/ Type.uid_t,
/*gid_t*/ Type.gid_t);
declareLazyFFI(SysFile, "link", libc, "link", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*source*/ Type.path,
/*dest*/ Type.path);
libc.declareLazyFFI(SysFile, "link",
"link", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*source*/ Type.path,
/*dest*/ Type.path);
declareLazyFFI(SysFile, "lseek", libc, "lseek", ctypes.default_abi,
/*return*/ Type.off_t,
/*fd*/ Type.fd,
/*offset*/ Type.off_t,
/*whence*/ Type.int);
libc.declareLazyFFI(SysFile, "lseek",
"lseek", ctypes.default_abi,
/*return*/ Type.off_t,
/*fd*/ Type.fd,
/*offset*/ Type.off_t,
/*whence*/ Type.int);
declareLazyFFI(SysFile, "mkdir", libc, "mkdir", ctypes.default_abi,
/*return*/ Type.int,
/*path*/ Type.path,
/*mode*/ Type.int);
libc.declareLazyFFI(SysFile, "mkdir",
"mkdir", ctypes.default_abi,
/*return*/ Type.int,
/*path*/ Type.path,
/*mode*/ Type.int);
declareLazyFFI(SysFile, "mkstemp", libc, "mkstemp", ctypes.default_abi,
/*return*/ Type.fd,
/*template*/Type.out_path);
libc.declareLazyFFI(SysFile, "mkstemp",
"mkstemp", ctypes.default_abi,
/*return*/ Type.fd,
/*template*/ Type.out_path);
declareLazyFFI(SysFile, "open", libc, "open", ctypes.default_abi,
/*return*/Type.negativeone_or_fd,
/*path*/ Type.path,
/*oflags*/Type.int,
/*mode*/ Type.int);
libc.declareLazyFFI(SysFile, "open",
"open", ctypes.default_abi,
/*return*/ Type.negativeone_or_fd,
/*path*/ Type.path,
/*oflags*/ Type.int,
/*mode*/ Type.int);
if (OS.Constants.Sys.Name == "NetBSD") {
declareLazyFFI(SysFile, "opendir", libc, "__opendir30", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "opendir",
"__opendir30", ctypes.default_abi,
/*return*/ Type.null_or_DIR_ptr,
/*path*/ Type.path);
} else {
declareLazyFFI(SysFile, "opendir", libc, "opendir", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "opendir",
"opendir", ctypes.default_abi,
/*return*/ Type.null_or_DIR_ptr,
/*path*/ Type.path);
}
declareLazyFFI(SysFile, "pread", libc, "pread", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "pread",
"pread", ctypes.default_abi,
/*return*/ Type.negativeone_or_ssize_t,
/*fd*/ Type.fd,
/*buf*/ Type.void_t.out_ptr,
/*nbytes*/ Type.size_t,
/*offset*/ Type.off_t);
declareLazyFFI(SysFile, "pwrite", libc, "pwrite", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "pwrite",
"pwrite", ctypes.default_abi,
/*return*/ Type.negativeone_or_ssize_t,
/*fd*/ Type.fd,
/*buf*/ Type.void_t.in_ptr,
/*nbytes*/ Type.size_t,
/*offset*/ Type.off_t);
declareLazyFFI(SysFile, "read", libc, "read", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "read",
"read", ctypes.default_abi,
/*return*/Type.negativeone_or_ssize_t,
/*fd*/ Type.fd,
/*buf*/ Type.void_t.out_ptr,
/*nbytes*/Type.size_t);
declareLazyFFI(SysFile, "posix_fadvise", libc, "posix_fadvise", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "posix_fadvise",
"posix_fadvise", ctypes.default_abi,
/*return*/ Type.int,
/*fd*/ Type.fd,
/*offset*/ Type.off_t,
@ -440,29 +469,35 @@
// Symbol name "readdir" still exists but is used for a
// deprecated function that does not match the
// constants of |Const|.
declareLazyFFI(SysFile, "readdir", libc, "readdir$INODE64", ctypes.default_abi,
/*return*/Type.null_or_dirent_ptr,
libc.declareLazyFFI(SysFile, "readdir",
"readdir$INODE64", ctypes.default_abi,
/*return*/ Type.null_or_dirent_ptr,
/*dir*/ Type.DIR.in_ptr); // For MacOS X
} else if (OS.Constants.Sys.Name == "NetBSD") {
declareLazyFFI(SysFile, "readdir", libc, "__readdir30", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "readdir",
"__readdir30", ctypes.default_abi,
/*return*/Type.null_or_dirent_ptr,
/*dir*/ Type.DIR.in_ptr); // Other Unices
} else {
declareLazyFFI(SysFile, "readdir", libc, "readdir", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "readdir",
"readdir", ctypes.default_abi,
/*return*/Type.null_or_dirent_ptr,
/*dir*/ Type.DIR.in_ptr); // Other Unices
}
declareLazyFFI(SysFile, "rename", libc, "rename", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "rename",
"rename", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*old*/ Type.path,
/*new*/ Type.path);
declareLazyFFI(SysFile, "rmdir", libc, "rmdir", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "rmdir",
"rmdir", ctypes.default_abi,
/*return*/ Type.int,
/*path*/ Type.path);
declareLazyFFI(SysFile, "splice", libc, "splice", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "splice",
"splice", ctypes.default_abi,
/*return*/ Type.long,
/*fd_in*/ Type.fd,
/*off_in*/ Type.off_t.in_ptr,
@ -471,21 +506,25 @@
/*len*/ Type.size_t,
/*flags*/ Type.unsigned_int); // Linux/Android-specific
declareLazyFFI(SysFile, "symlink", libc, "symlink", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "symlink",
"symlink", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*source*/ Type.path,
/*dest*/ Type.path);
declareLazyFFI(SysFile, "truncate", libc, "truncate", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "truncate",
"truncate", ctypes.default_abi,
/*return*/Type.negativeone_or_nothing,
/*path*/ Type.path,
/*length*/ Type.off_t);
declareLazyFFI(SysFile, "unlink", libc, "unlink", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "unlink",
"unlink", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path);
declareLazyFFI(SysFile, "write", libc, "write", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "write",
"write", ctypes.default_abi,
/*return*/ Type.negativeone_or_ssize_t,
/*fd*/ Type.fd,
/*buf*/ Type.void_t.in_ptr,
@ -497,17 +536,20 @@
// 32-bits and 64-bits versions of |stat|, |lstat|, |fstat|.
if (Const._DARWIN_FEATURE_64_BIT_INODE) {
// MacOS X 64-bits
declareLazyFFI(SysFile, "stat", libc, "stat$INODE64", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "stat",
"stat$INODE64", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*buf*/ Type.stat.out_ptr
);
declareLazyFFI(SysFile, "lstat", libc, "lstat$INODE64", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "lstat",
"lstat$INODE64", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*buf*/ Type.stat.out_ptr
);
declareLazyFFI(SysFile, "fstat", libc, "fstat$INODE64", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "fstat",
"fstat$INODE64", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.fd,
/*buf*/ Type.stat.out_ptr
@ -528,18 +570,20 @@
}
let Stat = {};
declareLazyFFI(Stat, "xstat", libc, xstat_name, ctypes.default_abi,
libc.declareLazyFFI(Stat, "xstat",
xstat_name, ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*_stat_ver*/ Type.int,
/*path*/ Type.path,
/*buf*/ Type.stat.out_ptr);
declareLazyFFI(Stat, "lxstat", libc, lxstat_name, ctypes.default_abi,
libc.declareLazyFFI(Stat, "lxstat",
lxstat_name, ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*_stat_ver*/ Type.int,
/*path*/ Type.path,
/*buf*/ Type.stat.out_ptr);
declareLazyFFI(Stat, "fxstat", libc,
fxstat_name, ctypes.default_abi,
libc.declareLazyFFI(Stat, "fxstat",
fxstat_name, ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*_stat_ver*/ Type.int,
/*fd*/ Type.fd,
@ -559,34 +603,40 @@
};
} else if (OS.Constants.Sys.Name == "NetBSD") {
// NetBSD 5.0 and newer
declareLazyFFI(SysFile, "stat", libc, "__stat50", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "stat",
"__stat50", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*buf*/ Type.stat.out_ptr
);
declareLazyFFI(SysFile, "lstat", libc, "__lstat50", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "lstat",
"__lstat50", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*buf*/ Type.stat.out_ptr
);
declareLazyFFI(SysFile, "fstat", libc, "__fstat50", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "fstat",
"__fstat50", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd,
/*buf*/ Type.stat.out_ptr
);
} else {
// Mac OS X 32-bits, other Unix
declareLazyFFI(SysFile, "stat", libc, "stat", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "stat",
"stat", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*buf*/ Type.stat.out_ptr
);
declareLazyFFI(SysFile, "lstat", libc, "lstat", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "lstat",
"lstat", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*buf*/ Type.stat.out_ptr
);
declareLazyFFI(SysFile, "fstat", libc, "fstat", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "fstat",
"fstat", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd,
/*buf*/ Type.stat.out_ptr
@ -597,7 +647,7 @@
// pipe cannot be directly defined as a C function.
let Pipe = {};
declareLazyFFI(Pipe, "_pipe", libc,
libc.declareLazyFFI(Pipe, "_pipe",
"pipe", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fds*/ new SharedAll.Type("two file descriptors",
@ -617,26 +667,30 @@
};
if (OS.Constants.Sys.Name == "NetBSD") {
declareLazyFFI(SysFile, "utimes", libc, "__utimes50", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "utimes",
"__utimes50", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*timeval[2]*/ Type.timevals.out_ptr
);
} else {
declareLazyFFI(SysFile, "utimes", libc, "utimes", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "utimes",
"utimes", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*timeval[2]*/ Type.timevals.out_ptr
);
}
if (OS.Constants.Sys.Name == "NetBSD") {
declareLazyFFI(SysFile, "futimes", libc, "__futimes50", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "futimes",
"__futimes50", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd,
/*timeval[2]*/ Type.timevals.out_ptr
);
} else {
declareLazyFFI(SysFile, "futimes", libc, "futimes", ctypes.default_abi,
libc.declareLazyFFI(SysFile, "futimes",
"futimes", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd,
/*timeval[2]*/ Type.timevals.out_ptr

View File

@ -39,14 +39,7 @@ let LOG = SharedAll.LOG.bind(SharedAll, "Win", "allthreads");
let Const = SharedAll.Constants.Win;
// Open libc
let libc;
try {
libc = ctypes.open("kernel32.dll");
} catch (ex) {
// Note: If you change the string here, please adapt consumers and
// tests accordingly
throw new Error("Could not open system library: " + ex.message);
}
let libc = new SharedAll.Library("libc", "kernel32.dll");
exports.libc = libc;
// Define declareFFI
@ -56,17 +49,16 @@ exports.declareFFI = declareFFI;
let Scope = {};
// Define Error
SharedAll.declareLazy(Scope, "FormatMessage", libc,
"FormatMessageW", ctypes.winapi_abi,
/*return*/ ctypes.uint32_t,
/*flags*/ ctypes.uint32_t,
/*source*/ ctypes.voidptr_t,
/*msgid*/ ctypes.uint32_t,
/*langid*/ ctypes.uint32_t,
/*buf*/ ctypes.jschar.ptr,
/*size*/ ctypes.uint32_t,
/*Arguments*/ctypes.voidptr_t
);
libc.declareLazy(Scope, "FormatMessage",
"FormatMessageW", ctypes.winapi_abi,
/*return*/ ctypes.uint32_t,
/*flags*/ ctypes.uint32_t,
/*source*/ ctypes.voidptr_t,
/*msgid*/ ctypes.uint32_t,
/*langid*/ ctypes.uint32_t,
/*buf*/ ctypes.jschar.ptr,
/*size*/ ctypes.uint32_t,
/*Arguments*/ctypes.voidptr_t);
/**
* A File-related error.

View File

@ -196,8 +196,8 @@
// Special case: these functions are used by the
// finalizer
SharedAll.declareLazy(SysFile, "_CloseHandle", libc,
"CloseHandle", ctypes.winapi_abi,
libc.declareLazy(SysFile, "_CloseHandle",
"CloseHandle", ctypes.winapi_abi,
/*return */ctypes.bool,
/*handle*/ ctypes.voidptr_t);
@ -209,8 +209,8 @@
}
};
SharedAll.declareLazy(SysFile, "_FindClose", libc,
"FindClose", ctypes.winapi_abi,
libc.declareLazy(SysFile, "_FindClose",
"FindClose", ctypes.winapi_abi,
/*return */ctypes.bool,
/*handle*/ ctypes.voidptr_t);
@ -224,20 +224,20 @@
// Declare libc functions as functions of |OS.Win.File|
declareLazyFFI(SysFile, "CopyFile", libc,
libc.declareLazyFFI(SysFile, "CopyFile",
"CopyFileW", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*sourcePath*/ Type.path,
/*destPath*/ Type.path,
/*bailIfExist*/Type.bool);
declareLazyFFI(SysFile, "CreateDirectory", libc,
libc.declareLazyFFI(SysFile, "CreateDirectory",
"CreateDirectoryW", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*name*/ Type.jschar.in_ptr,
/*security*/Type.SECURITY_ATTRIBUTES.in_ptr);
declareLazyFFI(SysFile, "CreateFile", libc,
libc.declareLazyFFI(SysFile, "CreateFile",
"CreateFileW", ctypes.winapi_abi,
/*return*/ Type.file_HANDLE,
/*name*/ Type.path,
@ -248,36 +248,36 @@
/*flags*/ Type.DWORD,
/*template*/Type.HANDLE);
declareLazyFFI(SysFile, "DeleteFile", libc,
libc.declareLazyFFI(SysFile, "DeleteFile",
"DeleteFileW", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*path*/ Type.path);
declareLazyFFI(SysFile, "FileTimeToSystemTime", libc,
libc.declareLazyFFI(SysFile, "FileTimeToSystemTime",
"FileTimeToSystemTime", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*filetime*/Type.FILETIME.in_ptr,
/*systime*/ Type.SystemTime.out_ptr);
declareLazyFFI(SysFile, "SystemTimeToFileTime", libc,
libc.declareLazyFFI(SysFile, "SystemTimeToFileTime",
"SystemTimeToFileTime", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*systime*/ Type.SystemTime.in_ptr,
/*filetime*/ Type.FILETIME.out_ptr);
declareLazyFFI(SysFile, "FindFirstFile", libc,
libc.declareLazyFFI(SysFile, "FindFirstFile",
"FindFirstFileW", ctypes.winapi_abi,
/*return*/ Type.find_HANDLE,
/*pattern*/Type.path,
/*data*/ Type.FindData.out_ptr);
declareLazyFFI(SysFile, "FindNextFile", libc,
libc.declareLazyFFI(SysFile, "FindNextFile",
"FindNextFileW", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*prev*/ Type.find_HANDLE,
/*data*/ Type.FindData.out_ptr);
declareLazyFFI(SysFile, "FormatMessage", libc,
libc.declareLazyFFI(SysFile, "FormatMessage",
"FormatMessageW", ctypes.winapi_abi,
/*return*/ Type.DWORD,
/*flags*/ Type.DWORD,
@ -289,20 +289,20 @@
/*Arguments*/Type.void_t.in_ptr
);
declareLazyFFI(SysFile, "GetCurrentDirectory", libc,
libc.declareLazyFFI(SysFile, "GetCurrentDirectory",
"GetCurrentDirectoryW", ctypes.winapi_abi,
/*return*/ Type.zero_or_DWORD,
/*length*/ Type.DWORD,
/*buf*/ Type.out_path
);
declareLazyFFI(SysFile, "GetFileInformationByHandle", libc,
libc.declareLazyFFI(SysFile, "GetFileInformationByHandle",
"GetFileInformationByHandle", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*handle*/ Type.HANDLE,
/*info*/ Type.FILE_INFORMATION.out_ptr);
declareLazyFFI(SysFile, "MoveFileEx", libc,
libc.declareLazyFFI(SysFile, "MoveFileEx",
"MoveFileExW", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*sourcePath*/ Type.path,
@ -310,7 +310,7 @@
/*flags*/ Type.DWORD
);
declareLazyFFI(SysFile, "ReadFile", libc,
libc.declareLazyFFI(SysFile, "ReadFile",
"ReadFile", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*file*/ Type.HANDLE,
@ -320,23 +320,23 @@
/*overlapped*/Type.void_t.inout_ptr // FIXME: Implement?
);
declareLazyFFI(SysFile, "RemoveDirectory", libc,
libc.declareLazyFFI(SysFile, "RemoveDirectory",
"RemoveDirectoryW", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*path*/ Type.path);
declareLazyFFI(SysFile, "SetCurrentDirectory", libc,
libc.declareLazyFFI(SysFile, "SetCurrentDirectory",
"SetCurrentDirectoryW", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*path*/ Type.path
);
declareLazyFFI(SysFile, "SetEndOfFile", libc,
libc.declareLazyFFI(SysFile, "SetEndOfFile",
"SetEndOfFile", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*file*/ Type.HANDLE);
declareLazyFFI(SysFile, "SetFilePointer", libc,
libc.declareLazyFFI(SysFile, "SetFilePointer",
"SetFilePointer", ctypes.winapi_abi,
/*return*/ Type.negative_or_DWORD,
/*file*/ Type.HANDLE,
@ -344,7 +344,7 @@
/*disthi*/ Type.long.in_ptr,
/*method*/ Type.DWORD);
declareLazyFFI(SysFile, "SetFileTime", libc,
libc.declareLazyFFI(SysFile, "SetFileTime",
"SetFileTime", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*file*/ Type.HANDLE,
@ -353,7 +353,7 @@
/*write*/ Type.FILETIME.in_ptr);
declareLazyFFI(SysFile, "WriteFile", libc,
libc.declareLazyFFI(SysFile, "WriteFile",
"WriteFile", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*file*/ Type.HANDLE,
@ -363,17 +363,17 @@
/*overlapped*/Type.void_t.inout_ptr // FIXME: Implement?
);
declareLazyFFI(SysFile, "FlushFileBuffers", libc,
libc.declareLazyFFI(SysFile, "FlushFileBuffers",
"FlushFileBuffers", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*file*/ Type.HANDLE);
declareLazyFFI(SysFile, "GetFileAttributes", libc,
libc.declareLazyFFI(SysFile, "GetFileAttributes",
"GetFileAttributesW", ctypes.winapi_abi,
/*return*/ Type.DWORD,
/*fileName*/ Type.path);
declareLazyFFI(SysFile, "SetFileAttributes", libc,
libc.declareLazyFFI(SysFile, "SetFileAttributes",
"SetFileAttributesW", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*fileName*/ Type.path,
@ -402,7 +402,7 @@
/*dacl*/ Type.PACL,
/*sacl*/ Type.PACL);
declareLazyFFI(SysFile, "LocalFree", libc,
libc.declareLazyFFI(SysFile, "LocalFree",
"LocalFree", ctypes.winapi_abi,
/*return*/ Type.HLOCAL,
/*mem*/ Type.HLOCAL);

View File

@ -8,7 +8,7 @@ let Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm", this);
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
Cu.import("resource://gre/modules/ThirdPartyCookieProbe.jsm", this);
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", this);
Cu.import("resource://gre/modules/Promise.jsm", this);
Cu.import("resource://gre/modules/TelemetryPing.jsm", this);
let TOPIC_ACCEPTED = "third-party-cookie-accepted";