Merge m-c to fx-team. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-01-28 15:04:51 -05:00
commit ebf78ade2e
107 changed files with 1189 additions and 472 deletions

View File

@ -1078,6 +1078,13 @@ pref("dom.mozSettings.allowForceReadOnly", false);
// RequestSync API is enabled by default on B2G.
pref("dom.requestSync.enabled", true);
// Enable hardware vsync compositor
// Only enable for kit kat and above devices
// kit kat == 19, L = 21, 20 is kit-kat for wearables
// 15 is for the ICS emulators which will fallback to software vsync
#if ANDROID_VERSION == 19 || ANDROID_VERSION == 21 || ANDROID_VERSION == 15
pref("gfx.vsync.hw-vsync.enabled", true);
pref("gfx.vsync.compositor", true);
#else
pref("gfx.vsync.hw-vsync.enabled", false);
pref("gfx.vsync.compositor", false);
#endif

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="d6a27295acb0a25926bf6290dd2532a7f9027864"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="d6a27295acb0a25926bf6290dd2532a7f9027864"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "ba613ae583a706131c45e885f65d428d4a541a81",
"git_revision": "782d371263911a526870263bffcb419b52c7c88a",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "4705c493adb5c766382b27e4fbff42f7447900e9",
"revision": "8c97eed028b3ad9580854e6c12f80e3046440e45",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="d6a27295acb0a25926bf6290dd2532a7f9027864"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ba613ae583a706131c45e885f65d428d4a541a81"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="782d371263911a526870263bffcb419b52c7c88a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -235,6 +235,11 @@ FeedConverter.prototype = {
getService(Ci.nsIIOService);
var chromeChannel;
// handling a redirect, hence forwarding the loadInfo from the old channel
// to the newchannel.
var oldChannel = this._request.QueryInterface(Ci.nsIChannel);
var loadInfo = oldChannel.loadInfo;
// If there was no automatic handler, or this was a podcast,
// photostream or some other kind of application, show the preview page
// if the parser returned a document.
@ -246,12 +251,12 @@ FeedConverter.prototype = {
// Now load the actual XUL document.
var aboutFeedsURI = ios.newURI("about:feeds", null, null);
chromeChannel = ios.newChannelFromURI(aboutFeedsURI, null);
chromeChannel = ios.newChannelFromURIWithLoadInfo(aboutFeedsURI, loadInfo);
chromeChannel.originalURI = result.uri;
chromeChannel.owner =
Services.scriptSecurityManager.getNoAppCodebasePrincipal(aboutFeedsURI);
} else {
chromeChannel = ios.newChannelFromURI(result.uri, null);
chromeChannel = ios.newChannelFromURIWithLoadInfo(result.uri, loadInfo);
}
chromeChannel.loadGroup = this._request.loadGroup;
@ -546,7 +551,12 @@ GenericProtocolHandler.prototype = {
newChannel: function GPH_newChannel(aUri) {
var inner = aUri.QueryInterface(Ci.nsINestedURI).innerURI;
var channel = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService).newChannelFromURI(inner, null);
getService(Ci.nsIIOService).newChannelFromURI2(inner,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
if (channel instanceof Components.interfaces.nsIHttpChannel)
// Set this so we know this is supposed to be a feed
channel.setRequestHeader("X-Moz-Is-Feed", "1", false);

View File

@ -1128,9 +1128,19 @@ FeedWriter.prototype = {
getInterface(Ci.nsIWebNavigation).
QueryInterface(Ci.nsIDocShell).currentDocumentChannel;
var nullPrincipal = Cc["@mozilla.org/nullprincipal;1"].
createInstance(Ci.nsIPrincipal);
var resolvedURI = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService).
newChannel("about:feeds", null, null).URI;
newChannel2("about:feeds",
null,
null,
null, // aLoadingNode
nullPrincipal,
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER).URI;
if (resolvedURI.equals(chan.URI))
return chan.originalURI;

View File

@ -4,5 +4,17 @@
"digest": "bb345b0e700ffab4d09436981f14b5de84da55a3f18a7f09ebc4364a4488acdeab8d46f447b12ac70f2da1444a68b8ce8b8675f0dae2ccf845e966d1df0f0869",
"algorithm": "sha512",
"filename": "mozmake.exe"
},
{
"size": 176,
"digest": "2809058907ac5eefdc394113d2e4fe76ba559ac61c2eca2f88e7a12a74bdf44a15d9039fa8aa229f7362a14b67d67395063f68147ae098beac5dfcc78aff98da",
"algorithm": "sha512",
"filename": "setup.sh"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}
]

View File

@ -896,13 +896,16 @@ Messages.Simple.prototype = Heritage.extend(Messages.BaseMessage.prototype,
let body = this.document.createElementNS(XHTML_NS, "span");
body.className = "message-body-wrapper message-body devtools-monospace";
let anchor, container = body;
let bodyInner = this.document.createElementNS(XHTML_NS, "span");
body.appendChild(bodyInner);
let anchor, container = bodyInner;
if (this._link || this._linkCallback) {
container = anchor = this.document.createElementNS(XHTML_NS, "a");
anchor.href = this._link || "#";
anchor.draggable = false;
this._addLinkCallback(anchor, this._linkCallback);
body.appendChild(anchor);
bodyInner.appendChild(anchor);
}
if (typeof this._message == "function") {

View File

@ -57,7 +57,9 @@ function consoleOpened(aHud) {
controller = top.document.commandDispatcher.getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
let selection = HUD.iframeWindow.getSelection() + "";
// Remove new lines since getSelection() includes one between message and line
// number, but the clipboard doesn't (see bug 1119503)
let selection = (HUD.iframeWindow.getSelection() + "").replace(/\r?\n|\r/g, " ");
isnot(selection.indexOf("bug587617"), -1,
"selection text includes 'bug587617'");
@ -80,7 +82,9 @@ function testContextMenuCopy() {
let copyItem = contextMenu.querySelector("*[command='cmd_copy']");
ok(copyItem, "the context menu on the output node has a \"Copy\" item");
let selection = HUD.iframeWindow.getSelection() + "";
// Remove new lines since getSelection() includes one between message and line
// number, but the clipboard doesn't (see bug 1119503)
let selection = (HUD.iframeWindow.getSelection() + "").replace(/\r?\n|\r/g, " ");
copyItem.doCommand();

View File

@ -69,7 +69,9 @@ function performTest(HUD, [result]) {
getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
let selectionText = HUD.iframeWindow.getSelection() + "";
// Remove new lines since getSelection() includes one between message and line
// number, but the clipboard doesn't (see bug 1119503)
let selectionText = (HUD.iframeWindow.getSelection() + "").replace(/\r?\n|\r/g, " ");
isnot(selectionText.indexOf("foobarBazBug613280"), -1,
"selection text includes 'foobarBazBug613280'");

View File

@ -117,7 +117,7 @@ a {
display: flex;
}
.message-body {
.message-body > * {
white-space: pre-wrap;
word-wrap: break-word;
}

View File

@ -753,7 +753,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
}
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
-moz-border-end: none;
-moz-border-end: none transparent;
}
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {

View File

@ -97,7 +97,8 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
// Do the first and potentially trial encoding as preformatted and raw.
uint32_t flags = aFlags | nsIDocumentEncoder::OutputPreformatted
| nsIDocumentEncoder::OutputRaw;
| nsIDocumentEncoder::OutputRaw
| nsIDocumentEncoder::OutputForPlainTextClipboardCopy;
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
NS_ASSERTION(domDoc, "Need a document");

View File

@ -1220,8 +1220,7 @@ nsDOMWindowUtils::SendKeyEvent(const nsAString& aType,
uint32_t locationFlag = (aAdditionalFlags &
(KEY_FLAG_LOCATION_STANDARD | KEY_FLAG_LOCATION_LEFT |
KEY_FLAG_LOCATION_RIGHT | KEY_FLAG_LOCATION_NUMPAD |
KEY_FLAG_LOCATION_MOBILE | KEY_FLAG_LOCATION_JOYSTICK));
KEY_FLAG_LOCATION_RIGHT | KEY_FLAG_LOCATION_NUMPAD));
switch (locationFlag) {
case KEY_FLAG_LOCATION_STANDARD:
event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD;
@ -1235,12 +1234,6 @@ nsDOMWindowUtils::SendKeyEvent(const nsAString& aType,
case KEY_FLAG_LOCATION_NUMPAD:
event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_NUMPAD;
break;
case KEY_FLAG_LOCATION_MOBILE:
event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_MOBILE;
break;
case KEY_FLAG_LOCATION_JOYSTICK:
event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_JOYSTICK;
break;
default:
if (locationFlag != 0) {
return NS_ERROR_INVALID_ARG;

View File

@ -227,6 +227,13 @@ interface nsIDocumentEncoder : nsISupports
*/
const unsigned long OutputDontRemoveLineEndingSpaces = (1 << 24);
/**
* Serialize in a way that is suitable for copying a plaintext version of the
* document to the clipboard. This can for example cause line endings to be
* injected at preformatted block element boundaries.
*/
const unsigned long OutputForPlainTextClipboardCopy = (1 << 25);
/**
* Initialize with a pointer to the document and the mime type.
* @param aDocument Document to encode.

View File

@ -91,6 +91,8 @@ nsPlainTextSerializer::nsPlainTextSerializer()
mPreFormatted = false;
mStartedOutput = false;
mPreformattedBlockBoundary = false;
// initialize the tag stack to zero:
// The stack only ever contains pointers to static atoms, so they don't
// need refcounting.
@ -167,6 +169,8 @@ nsPlainTextSerializer::Init(uint32_t aFlags, uint32_t aWrapColumn,
mLineBreakDue = false;
mFloatingLines = -1;
mPreformattedBlockBoundary = false;
if (mFlags & nsIDocumentEncoder::OutputFormatted) {
// Get some prefs that controls how we do formatted output
mStructs = Preferences::GetBool(PREF_STRUCTS, mStructs);
@ -437,6 +441,16 @@ nsPlainTextSerializer::DoOpenContainer(nsIAtom* aTag)
return NS_OK;
}
if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) {
if (mPreformattedBlockBoundary && DoOutput()) {
// Should always end a line, but get no more whitespace
if (mFloatingLines < 0)
mFloatingLines = 0;
mLineBreakDue = true;
}
mPreformattedBlockBoundary = false;
}
if (mFlags & nsIDocumentEncoder::OutputRaw) {
// Raw means raw. Don't even think about doing anything fancy
// here like indenting, adding line breaks or any other
@ -670,7 +684,7 @@ nsPlainTextSerializer::DoOpenContainer(nsIAtom* aTag)
// Else make sure we'll separate block level tags,
// even if we're about to leave, before doing any other formatting.
else if (nsContentUtils::IsHTMLBlock(aTag)) {
else if (IsElementBlock(mElement)) {
EnsureVerticalSpace(0);
}
@ -767,6 +781,14 @@ nsPlainTextSerializer::DoCloseContainer(nsIAtom* aTag)
return NS_OK;
}
if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) {
if (DoOutput() && IsInPre() && IsElementBlock(mElement)) {
// If we're closing a preformatted block element, output a line break
// when we find a new container.
mPreformattedBlockBoundary = true;
}
}
if (mFlags & nsIDocumentEncoder::OutputRaw) {
// Raw means raw. Don't even think about doing anything fancy
// here like indenting, adding line breaks or any other
@ -887,8 +909,7 @@ nsPlainTextSerializer::DoCloseContainer(nsIAtom* aTag)
else if (aTag == nsGkAtoms::q) {
Write(NS_LITERAL_STRING("\""));
}
else if (nsContentUtils::IsHTMLBlock(aTag)
&& aTag != nsGkAtoms::script) {
else if (IsElementBlock(mElement) && aTag != nsGkAtoms::script) {
// All other blocks get 1 vertical space after them
// in formatted mode, otherwise 0.
// This is hard. Sometimes 0 is a better number, but
@ -1037,6 +1058,8 @@ nsPlainTextSerializer::DoAddText(bool aIsLineBreak, const nsAString& aText)
nsresult
nsPlainTextSerializer::DoAddLeaf(nsIAtom* aTag)
{
mPreformattedBlockBoundary = false;
// If we don't want any output, just return
if (!DoOutput()) {
return NS_OK;
@ -1778,6 +1801,20 @@ nsPlainTextSerializer::IsElementPreformatted(Element* aElement)
return GetIdForContent(aElement) == nsGkAtoms::pre;
}
bool
nsPlainTextSerializer::IsElementBlock(Element* aElement)
{
nsRefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
nullptr);
if (styleContext) {
const nsStyleDisplay* displayStyle = styleContext->StyleDisplay();
return displayStyle->IsBlockOutsideStyle();
}
// Fall back to looking at the tag, in case there is no style information.
return nsContentUtils::IsHTMLBlock(GetIdForContent(aElement));
}
/**
* This method is required only to identify LI's inside OL.
* Returns TRUE if we are inside an OL tag and FALSE otherwise.

View File

@ -115,6 +115,7 @@ private:
bool ShouldReplaceContainerWithPlaceholder(nsIAtom* aTag);
bool IsElementPreformatted(mozilla::dom::Element* aElement);
bool IsElementBlock(mozilla::dom::Element* aElement);
private:
nsString mCurrentLine;
@ -171,6 +172,8 @@ private:
// Hence opening tags are guaranteed to start with appropriate line breaks.
bool mLineBreakDue;
bool mPreformattedBlockBoundary;
nsString mURL;
int32_t mHeaderStrategy; /* Header strategy (pref)
0 = no indention

View File

@ -137,6 +137,31 @@ TestPreElement()
return NS_OK;
}
nsresult
TestBlockElement()
{
nsString test;
test.AppendLiteral(
"<html>" NS_LINEBREAK
"<body>" NS_LINEBREAK
"<div>" NS_LINEBREAK
" first" NS_LINEBREAK
"</div>" NS_LINEBREAK
"<div>" NS_LINEBREAK
" second" NS_LINEBREAK
"</div>" NS_LINEBREAK
"</body>" NS_LINEBREAK "</html>");
ConvertBufToPlainText(test, 0);
if (!test.EqualsLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK)) {
fail("Wrong prettyprinted html to text serialization");
return NS_ERROR_FAILURE;
}
passed("prettyprinted HTML to text serialization test");
return NS_OK;
}
nsresult
TestPlainTextSerializer()
{
@ -163,6 +188,9 @@ TestPlainTextSerializer()
rv = TestPreElement();
NS_ENSURE_SUCCESS(rv, rv);
rv = TestBlockElement();
NS_ENSURE_SUCCESS(rv, rv);
// Add new tests here...
return NS_OK;
}

View File

@ -20,6 +20,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=116083
<div data-result="bar baz"><span style="white-space: pre-wrap">bar </span>baz</div>
<div data-result="bar baz"><span style="white-space: pre-line">bar </span>baz</div>
<div data-result="bar baz"><span style="white-space: -moz-pre-space">bar </span>baz</div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-wrap"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-wrap" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-line"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-line" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: -moz-pre-space"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: -moz-pre-space" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="&#10;foo bar&#10;">foo bar</div>
</div>
<script type="application/javascript">

View File

@ -200,10 +200,6 @@ function testSynthesizedKeyLocation()
event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
},
{ key: "VK_DOWN", isModifier: false,
event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
location: KeyboardEvent.DOM_KEY_LOCATION_JOYSTICK },
},
{ key: "5", isModifier: false,
event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
@ -212,14 +208,6 @@ function testSynthesizedKeyLocation()
event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
},
{ key: "5", isModifier: false,
event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
location: KeyboardEvent.DOM_KEY_LOCATION_MOBILE },
},
{ key: "VK_NUMPAD5", isModifier: false,
event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
location: KeyboardEvent.DOM_KEY_LOCATION_MOBILE },
},
{ key: "+", isModifier: false,
event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
@ -259,12 +247,8 @@ function testSynthesizedKeyLocation()
return "DOM_KEY_LOCATION_LEFT";
case KeyboardEvent.DOM_KEY_LOCATION_RIGHT:
return "DOM_KEY_LOCATION_RIGHT";
case KeyboardEvent.DOM_KEY_LOCATION_MOBILE:
return "DOM_KEY_LOCATION_MOBILE";
case KeyboardEvent.DOM_KEY_LOCATION_NUMPAD:
return "DOM_KEY_LOCATION_NUMPAD";
case KeyboardEvent.DOM_KEY_LOCATION_JOYSTICK:
return "DOM_KEY_LOCATION_JOYSTICK";
default:
return "Invalid value (" + aLocation + ")";
}

View File

@ -50,7 +50,7 @@ interface nsITranslationNodeList;
interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
[scriptable, uuid(04db2684-f9ed-4d70-827d-3d5b87825238)]
[scriptable, uuid(5ed850de-2b57-4555-ac48-93292e852eab)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -556,8 +556,6 @@ interface nsIDOMWindowUtils : nsISupports {
const unsigned long KEY_FLAG_LOCATION_LEFT = 0x0020;
const unsigned long KEY_FLAG_LOCATION_RIGHT = 0x0040;
const unsigned long KEY_FLAG_LOCATION_NUMPAD = 0x0080;
const unsigned long KEY_FLAG_LOCATION_MOBILE = 0x0100;
const unsigned long KEY_FLAG_LOCATION_JOYSTICK = 0x0200;
boolean sendKeyEvent(in AString aType,
in long aKeyCode,

View File

@ -250,8 +250,6 @@ interface nsIDOMKeyEvent : nsIDOMUIEvent
const unsigned long DOM_KEY_LOCATION_LEFT = 0x01;
const unsigned long DOM_KEY_LOCATION_RIGHT = 0x02;
const unsigned long DOM_KEY_LOCATION_NUMPAD = 0x03;
const unsigned long DOM_KEY_LOCATION_MOBILE = 0x04;
const unsigned long DOM_KEY_LOCATION_JOYSTICK = 0x05;
readonly attribute unsigned long location;
readonly attribute boolean repeat;

View File

@ -36,6 +36,9 @@
using namespace mozilla::layers;
using namespace mozilla::dom;
// Default timeout msecs until try to enter dormant state by heuristic.
static const int DEFAULT_HEURISTIC_DORMANT_TIMEOUT_MSECS = 60000;
namespace mozilla {
// Number of estimated seconds worth of data we need to have buffered
@ -123,27 +126,56 @@ void MediaDecoder::NotifyOwnerActivityChanged()
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
if (!mDecoderStateMachine ||
!mDecoderStateMachine->IsDormantNeeded() ||
mPlayState == PLAY_STATE_SHUTDOWN) {
return;
}
if (!mOwner) {
NS_WARNING("MediaDecoder without a decoder owner, can't update dormant");
return;
}
UpdateDormantState(false /* aDormantTimeout */, false /* aActivity */);
// Start dormant timer if necessary
StartDormantTimer();
}
void MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity)
{
MOZ_ASSERT(NS_IsMainThread());
GetReentrantMonitor().AssertCurrentThreadIn();
if (!mDecoderStateMachine ||
mPlayState == PLAY_STATE_SHUTDOWN ||
!mOwner->GetVideoFrameContainer() ||
!mDecoderStateMachine->IsDormantNeeded())
{
return;
}
bool prevDormant = mIsDormant;
mIsDormant = false;
if (!mOwner->IsActive() && mOwner->GetVideoFrameContainer()) {
if (!mOwner->IsActive()) {
mIsDormant = true;
}
#ifdef MOZ_WIDGET_GONK
if (mOwner->IsHidden() && mOwner->GetVideoFrameContainer()) {
if (mOwner->IsHidden()) {
mIsDormant = true;
}
#endif
// Try to enable dormant by idle heuristic, when the owner is hidden.
bool prevHeuristicDormant = mIsHeuristicDormant;
mIsHeuristicDormant = false;
if (mIsHeuristicDormantSupported && mOwner->IsHidden()) {
if (aDormantTimeout && !aActivity &&
(mPlayState == PLAY_STATE_PAUSED || mPlayState == PLAY_STATE_ENDED)) {
// Enable heuristic dormant
mIsHeuristicDormant = true;
} else if(prevHeuristicDormant && !aActivity) {
// Continue heuristic dormant
mIsHeuristicDormant = true;
}
if (mIsHeuristicDormant) {
mIsDormant = true;
}
}
if (prevDormant == mIsDormant) {
// No update to dormant state
@ -167,6 +199,47 @@ void MediaDecoder::NotifyOwnerActivityChanged()
}
}
void MediaDecoder::DormantTimerExpired(nsITimer* aTimer, void* aClosure)
{
MOZ_ASSERT(aClosure);
MediaDecoder* decoder = static_cast<MediaDecoder*>(aClosure);
ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor());
decoder->UpdateDormantState(true /* aDormantTimeout */,
false /* aActivity */);
}
void MediaDecoder::StartDormantTimer()
{
if (!mIsHeuristicDormantSupported) {
return;
}
if (mIsHeuristicDormant ||
mShuttingDown ||
!mOwner ||
!mOwner->IsHidden() ||
(mPlayState != PLAY_STATE_PAUSED &&
mPlayState != PLAY_STATE_ENDED))
{
return;
}
if (!mDormantTimer) {
mDormantTimer = do_CreateInstance("@mozilla.org/timer;1");
}
mDormantTimer->InitWithFuncCallback(&MediaDecoder::DormantTimerExpired,
this,
mHeuristicDormantTimeout,
nsITimer::TYPE_ONE_SHOT);
}
void MediaDecoder::CancelDormantTimer()
{
if (mDormantTimer) {
mDormantTimer->Cancel();
}
}
void MediaDecoder::Pause()
{
MOZ_ASSERT(NS_IsMainThread());
@ -472,7 +545,13 @@ MediaDecoder::MediaDecoder() :
mPausedForPlaybackRateNull(false),
mMinimizePreroll(false),
mMediaTracksConstructed(false),
mIsDormant(false)
mIsDormant(false),
mIsHeuristicDormantSupported(
Preferences::GetBool("media.decoder.heuristic.dormant.enabled", false)),
mHeuristicDormantTimeout(
Preferences::GetInt("media.decoder.heuristic.dormant.timeout",
DEFAULT_HEURISTIC_DORMANT_TIMEOUT_MSECS)),
mIsHeuristicDormant(false)
{
MOZ_COUNT_CTOR(MediaDecoder);
MOZ_ASSERT(NS_IsMainThread());
@ -521,6 +600,8 @@ void MediaDecoder::Shutdown()
mResource->Close();
}
CancelDormantTimer();
ChangeState(PLAY_STATE_SHUTDOWN);
mOwner = nullptr;
@ -622,6 +703,8 @@ nsresult MediaDecoder::Play()
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
UpdateDormantState(false /* aDormantTimeout */, true /* aActivity */);
NS_ASSERTION(mDecoderStateMachine != nullptr, "Should have state machine.");
if (mPausedForPlaybackRateNull) {
return NS_OK;
@ -644,6 +727,7 @@ nsresult MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType)
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
UpdateDormantState(false /* aDormantTimeout */, true /* aActivity */);
NS_ABORT_IF_FALSE(aTime >= 0.0, "Cannot seek to a negative value.");
@ -1192,6 +1276,10 @@ void MediaDecoder::ChangeState(PlayState aState)
ApplyStateToStateMachine(mPlayState);
CancelDormantTimer();
// Start dormant timer if necessary
StartDormantTimer();
GetReentrantMonitor().NotifyAll();
}

View File

@ -188,6 +188,7 @@ destroying the MediaDecoder object.
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsAutoPtr.h"
#include "nsITimer.h"
#include "MediaResource.h"
#include "mozilla/dom/AudioChannelBinding.h"
#include "mozilla/gfx/Rect.h"
@ -367,6 +368,8 @@ public:
// It is used to share scarece media resources in system.
virtual void NotifyOwnerActivityChanged();
void UpdateDormantState(bool aDormantTimeout, bool aActivity);
// Pause video playback.
virtual void Pause();
// Adjust the speed of the playback, optionally with pitch correction,
@ -1022,6 +1025,14 @@ protected:
virtual ~MediaDecoder();
void SetStateMachineParameters();
static void DormantTimerExpired(nsITimer *aTimer, void *aClosure);
// Start a timer for heuristic dormant.
void StartDormantTimer();
// Cancel a timer for heuristic dormant.
void CancelDormantTimer();
/******
* The following members should be accessed with the decoder lock held.
******/
@ -1219,6 +1230,18 @@ protected:
// True if MediaDecoder is in dormant state.
bool mIsDormant;
// True if heuristic dormant is supported.
const bool mIsHeuristicDormantSupported;
// Timeout ms of heuristic dormant timer.
const int mHeuristicDormantTimeout;
// True if MediaDecoder is in dormant by heuristic.
bool mIsHeuristicDormant;
// Timer to schedule updating dormant state.
nsCOMPtr<nsITimer> mDormantTimer;
};
} // namespace mozilla

View File

@ -21,8 +21,6 @@ interface KeyboardEvent : UIEvent
const unsigned long DOM_KEY_LOCATION_LEFT = 0x01;
const unsigned long DOM_KEY_LOCATION_RIGHT = 0x02;
const unsigned long DOM_KEY_LOCATION_NUMPAD = 0x03;
const unsigned long DOM_KEY_LOCATION_MOBILE = 0x04;
const unsigned long DOM_KEY_LOCATION_JOYSTICK = 0x05;
readonly attribute unsigned long location;
readonly attribute boolean repeat;

View File

@ -53,6 +53,7 @@ gfxHarfBuzzShaper::gfxHarfBuzzShaper(gfxFont *aFont)
mUseFontGlyphWidths(false),
mInitialized(false),
mVerticalInitialized(false),
mLoadedLocaGlyf(false),
mLocaLongOffsets(false)
{
}
@ -346,54 +347,13 @@ gfxHarfBuzzShaper::GetGlyphVOrigin(hb_codepoint_t aGlyph,
}
if (mVmtxTable) {
if (mLocaTable && mGlyfTable) {
// TrueType outlines: use glyph bbox + top sidebearing
uint32_t offset; // offset of glyph record in the 'glyf' table
uint32_t len;
const char* data = hb_blob_get_data(mLocaTable, &len);
if (mLocaLongOffsets) {
if ((aGlyph + 1) * sizeof(AutoSwap_PRUint32) > len) {
*aY = 0;
return;
}
const AutoSwap_PRUint32* offsets =
reinterpret_cast<const AutoSwap_PRUint32*>(data);
offset = offsets[aGlyph];
if (offset == offsets[aGlyph + 1]) {
// empty glyph
*aY = 0;
return;
}
} else {
if ((aGlyph + 1) * sizeof(AutoSwap_PRUint16) > len) {
*aY = 0;
return;
}
const AutoSwap_PRUint16* offsets =
reinterpret_cast<const AutoSwap_PRUint16*>(data);
offset = uint16_t(offsets[aGlyph]);
if (offset == uint16_t(offsets[aGlyph + 1])) {
// empty glyph
*aY = 0;
return;
}
offset *= 2;
}
struct Glyf { // we only need the bounding-box at the beginning
// of the glyph record, not the actual outline data
AutoSwap_PRInt16 numberOfContours;
AutoSwap_PRInt16 xMin;
AutoSwap_PRInt16 yMin;
AutoSwap_PRInt16 xMax;
AutoSwap_PRInt16 yMax;
};
data = hb_blob_get_data(mGlyfTable, &len);
if (offset + sizeof(Glyf) > len) {
bool emptyGlyf;
const Glyf *glyf = FindGlyf(aGlyph, &emptyGlyf);
if (glyf) {
if (emptyGlyf) {
*aY = 0;
return;
}
const Glyf* glyf = reinterpret_cast<const Glyf*>(data + offset);
if (aGlyph >= uint32_t(mNumLongVMetrics)) {
aGlyph = mNumLongVMetrics - 1;
@ -406,7 +366,8 @@ gfxHarfBuzzShaper::GetGlyphVOrigin(hb_codepoint_t aGlyph,
int16_t(glyf->yMax)));
return;
} else {
// XXX TODO: CFF outlines - need to get glyph extents.
// XXX TODO: not a truetype font; need to get glyph extents
// via some other API?
// For now, fall through to default code below.
}
}
@ -431,6 +392,112 @@ gfxHarfBuzzShaper::GetGlyphVOrigin(hb_codepoint_t aGlyph,
*aY = -FloatToFixed(GetFont()->GetAdjustedSize() / 2);
}
static hb_bool_t
HBGetGlyphExtents(hb_font_t *font, void *font_data,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents,
void *user_data)
{
const gfxHarfBuzzShaper::FontCallbackData *fcd =
static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
return fcd->mShaper->GetGlyphExtents(glyph, extents);
}
// Find the data for glyph ID |aGlyph| in the 'glyf' table, if present.
// Returns null if not found, otherwise pointer to the beginning of the
// glyph's data. Sets aEmptyGlyf true if there is no actual data;
// otherwise, it's guaranteed that we can read at least the bounding box.
const gfxHarfBuzzShaper::Glyf*
gfxHarfBuzzShaper::FindGlyf(hb_codepoint_t aGlyph, bool *aEmptyGlyf) const
{
if (!mLoadedLocaGlyf) {
mLoadedLocaGlyf = true; // only try this once; if it fails, this
// isn't a truetype font
gfxFontEntry *entry = mFont->GetFontEntry();
uint32_t len;
gfxFontEntry::AutoTable headTable(entry,
TRUETYPE_TAG('h','e','a','d'));
const HeadTable* head =
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable,
&len));
if (len < sizeof(HeadTable)) {
return nullptr;
}
mLocaLongOffsets = int16_t(head->indexToLocFormat) > 0;
mLocaTable = entry->GetFontTable(TRUETYPE_TAG('l','o','c','a'));
mGlyfTable = entry->GetFontTable(TRUETYPE_TAG('g','l','y','f'));
}
if (!mLocaTable || !mGlyfTable) {
// it's not a truetype font
return nullptr;
}
uint32_t offset; // offset of glyph record in the 'glyf' table
uint32_t len;
const char* data = hb_blob_get_data(mLocaTable, &len);
if (mLocaLongOffsets) {
if ((aGlyph + 1) * sizeof(AutoSwap_PRUint32) > len) {
return nullptr;
}
const AutoSwap_PRUint32* offsets =
reinterpret_cast<const AutoSwap_PRUint32*>(data);
offset = offsets[aGlyph];
*aEmptyGlyf = (offset == uint16_t(offsets[aGlyph + 1]));
} else {
if ((aGlyph + 1) * sizeof(AutoSwap_PRUint16) > len) {
return nullptr;
}
const AutoSwap_PRUint16* offsets =
reinterpret_cast<const AutoSwap_PRUint16*>(data);
offset = uint16_t(offsets[aGlyph]);
*aEmptyGlyf = (offset == uint16_t(offsets[aGlyph + 1]));
offset *= 2;
}
data = hb_blob_get_data(mGlyfTable, &len);
if (offset + sizeof(Glyf) > len) {
return nullptr;
}
return reinterpret_cast<const Glyf*>(data + offset);
}
hb_bool_t
gfxHarfBuzzShaper::GetGlyphExtents(hb_codepoint_t aGlyph,
hb_glyph_extents_t *aExtents) const
{
bool emptyGlyf;
const Glyf *glyf = FindGlyf(aGlyph, &emptyGlyf);
if (!glyf) {
// TODO: for non-truetype fonts, get extents some other way?
return false;
}
if (emptyGlyf) {
aExtents->x_bearing = 0;
aExtents->y_bearing = 0;
aExtents->width = 0;
aExtents->height = 0;
return true;
}
double f = mFont->FUnitsToDevUnitsFactor();
aExtents->x_bearing = FloatToFixed(int16_t(glyf->xMin) * f);
aExtents->width =
FloatToFixed((int16_t(glyf->xMax) - int16_t(glyf->xMin)) * f);
// Our y-coordinates are positive-downwards, whereas harfbuzz assumes
// positive-upwards; hence the apparently-reversed subtractions here.
aExtents->y_bearing =
FloatToFixed(int16_t(glyf->yMax) * f -
mFont->GetHorizontalMetrics().emAscent);
aExtents->height =
FloatToFixed((int16_t(glyf->yMin) - int16_t(glyf->yMax)) * f);
return true;
}
static hb_bool_t
HBGetContourPoint(hb_font_t *font, void *font_data,
unsigned int point_index, hb_codepoint_t glyph,
@ -1066,6 +1133,9 @@ gfxHarfBuzzShaper::Initialize()
hb_font_funcs_set_glyph_v_origin_func(sHBFontFuncs,
HBGetGlyphVOrigin,
nullptr, nullptr);
hb_font_funcs_set_glyph_extents_func(sHBFontFuncs,
HBGetGlyphExtents,
nullptr, nullptr);
hb_font_funcs_set_glyph_contour_point_func(sHBFontFuncs,
HBGetContourPoint,
nullptr, nullptr);
@ -1225,20 +1295,6 @@ gfxHarfBuzzShaper::InitializeVertical()
mVORGTable = nullptr;
}
}
} else if (mVmtxTable) {
// Otherwise, try to load loca and glyf tables so that we can read
// bounding boxes (needed to support vertical glyph origin).
uint32_t len;
gfxFontEntry::AutoTable headTable(entry,
TRUETYPE_TAG('h','e','a','d'));
const HeadTable* head =
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable,
&len));
if (len >= sizeof(HeadTable)) {
mLocaLongOffsets = int16_t(head->indexToLocFormat) > 0;
mLocaTable = entry->GetFontTable(TRUETYPE_TAG('l','o','c','a'));
mGlyfTable = entry->GetFontTable(TRUETYPE_TAG('g','l','y','f'));
}
}
return true;

View File

@ -73,6 +73,9 @@ public:
hb_position_t GetHKerning(uint16_t aFirstGlyph,
uint16_t aSecondGlyph) const;
hb_bool_t GetGlyphExtents(hb_codepoint_t aGlyph,
hb_glyph_extents_t *aExtents) const;
static hb_script_t
GetHBScriptUsedForShaping(int32_t aScript) {
// Decide what harfbuzz script code will be used for shaping
@ -107,6 +110,17 @@ protected:
bool InitializeVertical();
bool LoadHmtxTable();
struct Glyf { // we only need the bounding-box at the beginning
// of the glyph record, not the actual outline data
AutoSwap_PRInt16 numberOfContours;
AutoSwap_PRInt16 xMin;
AutoSwap_PRInt16 yMin;
AutoSwap_PRInt16 xMax;
AutoSwap_PRInt16 yMax;
};
const Glyf *FindGlyf(hb_codepoint_t aGlyph, bool *aEmptyGlyf) const;
// harfbuzz face object: we acquire a reference from the font entry
// on shaper creation, and release it in our destructor
hb_face_t *mHBFace;
@ -161,7 +175,10 @@ protected:
bool mInitialized;
bool mVerticalInitialized;
bool mLocaLongOffsets;
// these are set from the FindGlyf callback on first use of the glyf data
mutable bool mLoadedLocaGlyf;
mutable bool mLocaLongOffsets;
};
#endif /* GFX_HARFBUZZSHAPER_H */

View File

@ -9,6 +9,7 @@
#include <dbus/dbus-glib-lowlevel.h>
#include <mozilla/dom/battery/Constants.h>
#include "nsAutoRef.h"
#include <cmath>
/*
* Helper that manages the destruction of glib objects as soon as they leave
@ -428,14 +429,14 @@ UPowerClient::UpdateSavedInfo(GHashTable* aHashTable)
}
/*
* The battery level might be very close to 100% (like 99.xxxx%) without
* The battery level might be very close to 100% (like 99%) without
* increasing. It seems that upower sets the battery state as 'full' in that
* case so we should trust it and not even try to get the value.
*/
if (isFull) {
mLevel = 1.0;
} else {
mLevel = g_value_get_double(static_cast<const GValue*>(g_hash_table_lookup(aHashTable, "Percentage")))*0.01;
mLevel = round(g_value_get_double(static_cast<const GValue*>(g_hash_table_lookup(aHashTable, "Percentage"))))*0.01;
}
if (isFull) {

View File

@ -1,3 +1,6 @@
if (!this.hasOwnProperty("SIMD"))
quit();
setJitCompilerOption("baseline.warmup.trigger", 10);
setJitCompilerOption("ion.warmup.trigger", 30);

View File

@ -4,6 +4,9 @@
// as plain JS) as it should be. That gave rise to a difference in
// output.
if (!this.SharedArrayBuffer)
quit(0);
// Original test
g = (function(stdlib, n, heap) {

View File

@ -3735,6 +3735,10 @@ already_AddRefed<Layer>
nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) {
if (mOpacity == 0 && mFrame->GetContent() &&
!nsLayoutUtils::HasAnimations(mFrame->GetContent(), eCSSProperty_opacity)) {
return nullptr;
}
nsRefPtr<Layer> container = aManager->GetLayerBuilder()->
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
aContainerParameters, nullptr);

View File

@ -2921,10 +2921,22 @@ nsBlockFrame::AttributeChanged(int32_t aNameSpaceID,
}
static inline bool
IsNonAutoNonZeroHeight(const nsStyleCoord& aCoord)
IsNonAutoNonZeroBSize(const nsStyleCoord& aCoord)
{
if (aCoord.GetUnit() == eStyleUnit_Auto)
nsStyleUnit unit = aCoord.GetUnit();
if (unit == eStyleUnit_Auto ||
// The enumerated values were originally aimed at inline-size
// (or width, as it was before logicalization). For now, let them
// return false here, so we treat them like 'auto' pending a
// real implementation. (See bug 1126420.)
//
// FIXME (bug 567039, bug 527285)
// This isn't correct for the 'fill' value, which should more
// likely (but not necessarily, depending on the available space)
// be returning true.
unit == eStyleUnit_Enumerated) {
return false;
}
if (aCoord.IsCoordPercentCalcUnit()) {
// If we evaluate the length/percent/calc at a percentage basis of
// both nscoord_MAX and 0, and it's zero both ways, then it's a zero
@ -2951,13 +2963,13 @@ nsBlockFrame::IsSelfEmpty()
bool vertical = GetWritingMode().IsVertical();
if (vertical) {
if (IsNonAutoNonZeroHeight(position->mMinWidth) ||
IsNonAutoNonZeroHeight(position->mWidth)) {
if (IsNonAutoNonZeroBSize(position->mMinWidth) ||
IsNonAutoNonZeroBSize(position->mWidth)) {
return false;
}
} else {
if (IsNonAutoNonZeroHeight(position->mMinHeight) ||
IsNonAutoNonZeroHeight(position->mHeight)) {
if (IsNonAutoNonZeroBSize(position->mMinHeight) ||
IsNonAutoNonZeroBSize(position->mHeight)) {
return false;
}
}

View File

@ -1948,6 +1948,17 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
return;
const nsStyleDisplay* disp = StyleDisplay();
// We can stop right away if this is a zero-opacity stacking context and
// we're painting, and we're not animating opacity. Don't do this
// if we're going to compute plugin geometry, since opacity-0 plugins
// need to have display items built for them.
if (disp->mOpacity == 0.0 && aBuilder->IsForPainting() &&
!aBuilder->WillComputePluginGeometry() &&
!(disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) &&
!nsLayoutUtils::HasAnimations(mContent, eCSSProperty_opacity)) {
return;
}
if (disp->mWillChangeBitField != 0) {
aBuilder->AddToWillChangeBudget(this, GetSize());
}

View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
@font-face {
font-family: test;
/* Note that this font has no OpenType layout tables: */
src: url(../fonts/sil/GenR102.ttf);
}
body {
font-family: test;
}
.test {
font-size: 100px;
line-height: 2;
}
</style>
</head>
<body>
These examples should NOT look the same:
<div class=test>x&#x303;&#x302; x&#x302;&#x303;</div>
</body>

View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
@font-face {
font-family: test;
/* Note that this font has no OpenType layout tables: */
src: url(../fonts/sil/GenR102.ttf);
}
body {
font-family: test;
}
.test {
font-size: 100px;
line-height: 2;
}
</style>
</head>
<body>
These examples should NOT look the same:
<div class=test>x&#x302;&#x303; x&#x303;&#x302;</div>
</body>

View File

@ -163,6 +163,8 @@ fails-if(cocoaWidget||Android||B2G) HTTP(..) == arabic-fallback-2.html arabic-fa
fails-if(cocoaWidget||Android||B2G) HTTP(..) == arabic-fallback-3.html arabic-fallback-3-ref.html
fails-if(!cocoaWidget&&!Android&&!B2G) HTTP(..) != arabic-fallback-4.html arabic-fallback-4-notref.html
== arabic-marks-1.html arabic-marks-1-ref.html
# harfbuzz fallback mark stacking in the absence of GPOS:
HTTP(..) != fallback-mark-stacking-1.html fallback-mark-stacking-1-notref.html
== 726392-1.html 726392-1-ref.html
== 726392-2.html 726392-2-ref.html

View File

@ -115,26 +115,6 @@ public class GeckoEvent {
}
}
/**
* The DomKeyLocation enum encapsulates the DOM KeyboardEvent's constants.
* @see https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent#Key_location_constants
*/
@JNITarget
public enum DomKeyLocation {
DOM_KEY_LOCATION_STANDARD(0),
DOM_KEY_LOCATION_LEFT(1),
DOM_KEY_LOCATION_RIGHT(2),
DOM_KEY_LOCATION_NUMPAD(3),
DOM_KEY_LOCATION_MOBILE(4),
DOM_KEY_LOCATION_JOYSTICK(5);
public final int value;
private DomKeyLocation(int value) {
this.value = value;
}
}
// Encapsulation of common IME actions.
@JNITarget
public enum ImeAction {
@ -223,7 +203,6 @@ public class GeckoEvent {
private int mRangeLineColor;
private Location mLocation;
private Address mAddress;
private DomKeyLocation mDomKeyLocation;
private int mConnectionType;
private boolean mIsWifi;
@ -313,30 +292,6 @@ public class GeckoEvent {
mDOMPrintableKeyValue = k.getUnicodeChar(unmodifiedMetaState);
}
}
mDomKeyLocation = isJoystickButton(mKeyCode) ? DomKeyLocation.DOM_KEY_LOCATION_JOYSTICK
: DomKeyLocation.DOM_KEY_LOCATION_MOBILE;
}
/**
* This method tests if a key is one of the described in:
* https://bugzilla.mozilla.org/show_bug.cgi?id=756504#c0
* @param keyCode int with the key code (Android key constant from KeyEvent)
* @return true if the key is one of the listed above, false otherwise.
*/
private static boolean isJoystickButton(int keyCode) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_UP:
return true;
default:
if (Versions.feature12Plus) {
return KeyEvent.isGamepadButton(keyCode);
}
return GeckoEvent.isGamepadButton(keyCode);
}
}
/**

View File

@ -1319,6 +1319,7 @@ pref("network.http.spdy.ping-timeout", 8);
pref("network.http.spdy.send-buffer-size", 131072);
pref("network.http.spdy.allow-push", true);
pref("network.http.spdy.push-allowance", 131072);
pref("network.http.spdy.default-concurrent", 100);
// alt-svc allows separation of transport routing from
// the origin host without using a proxy.

View File

@ -50,6 +50,8 @@ public:
// scenarios.
const static uint32_t kInitialRwin = 256 * 1024 * 1024;
const static uint32_t kDefaultMaxConcurrent = 100;
// soft errors are errors that terminate a stream without terminating the
// connection. In general non-network errors are stream errors as well
// as network specific items like cancels.

View File

@ -89,7 +89,6 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t versio
, mGoAwayReason(NO_HTTP_ERROR)
, mGoAwayID(0)
, mOutgoingGoAwayID(0)
, mMaxConcurrent(kDefaultMaxConcurrent)
, mConcurrent(0)
, mServerPushedResources(0)
, mServerInitialStreamWindow(kDefaultRwin)
@ -119,7 +118,7 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t versio
mDecompressor.SetCompressor(&mCompressor);
mPushAllowance = gHttpHandler->SpdyPushAllowance();
mMaxConcurrent = gHttpHandler->DefaultSpdyConcurrent();
mSendingChunkSize = gHttpHandler->SpdySendingChunkSize();
SendHello();

View File

@ -135,7 +135,6 @@ public:
const static uint32_t kQueueTailRoom = 4096;
const static uint32_t kQueueReserved = 1024;
const static uint32_t kDefaultMaxConcurrent = 100;
const static uint32_t kMaxStreamID = 0x7800000;
// This is a sentinel for a deleted stream. It is not a valid

View File

@ -184,11 +184,10 @@ Http2Stream::ReadSegments(nsAHttpSegmentReader *reader,
// If the sending flow control window is open (!mBlockedOnRwin) then
// continue sending the request
if (!mBlockedOnRwin && mUpstreamState != GENERATING_HEADERS &&
if (!mBlockedOnRwin && mOpenGenerated &&
!mTxInlineFrameUsed && NS_SUCCEEDED(rv) && (!*countRead)) {
MOZ_ASSERT(!mQueued);
MOZ_ASSERT(mRequestHeadersDone);
MOZ_ASSERT(mOpenGenerated);
LOG3(("Http2Stream::ReadSegments %p 0x%X: Sending request data complete, "
"mUpstreamState=%x\n",this, mStreamID, mUpstreamState));
if (mSentFin) {
@ -1234,7 +1233,7 @@ Http2Stream::OnReadSegment(const char *buf,
if (mRequestHeadersDone && !mOpenGenerated) {
if (!mSession->TryToActivate(this)) {
LOG3(("Http2Stream::OnReadSegment %p cannot activate now. queued.\n", this));
return NS_OK;
return *countRead ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
}
if (NS_FAILED(rv = GenerateOpen())) {
return rv;

View File

@ -63,7 +63,6 @@ SpdySession31::SpdySession31(nsISocketTransport *aSocketTransport)
, mCleanShutdown(false)
, mDataPending(false)
, mGoAwayID(0)
, mMaxConcurrent(kDefaultMaxConcurrent)
, mConcurrent(0)
, mServerPushedResources(0)
, mServerInitialStreamWindow(kDefaultRwin)
@ -89,7 +88,7 @@ SpdySession31::SpdySession31(nsISocketTransport *aSocketTransport)
zlibInit();
mPushAllowance = gHttpHandler->SpdyPushAllowance();
mMaxConcurrent = gHttpHandler->DefaultSpdyConcurrent();
mSendingChunkSize = gHttpHandler->SpdySendingChunkSize();
GenerateSettings();

View File

@ -134,7 +134,6 @@ public:
const static uint32_t kQueueTailRoom = 4096;
const static uint32_t kQueueReserved = 1024;
const static uint32_t kDefaultMaxConcurrent = 100;
const static uint32_t kMaxStreamID = 0x7800000;
// This is a sentinel for a deleted stream. It is not a valid

View File

@ -160,7 +160,7 @@ SpdyStream31::ReadSegments(nsAHttpSegmentReader *reader,
// If the sending flow control window is open (!mBlockedOnRwin) then
// continue sending the request
if (!mBlockedOnRwin && mUpstreamState != GENERATING_SYN_STREAM &&
if (!mBlockedOnRwin && mSynFrameGenerated &&
!mTxInlineFrameUsed && NS_SUCCEEDED(rv) && (!*countRead)) {
LOG3(("SpdyStream31::ReadSegments %p 0x%X: Sending request data complete, "
"mUpstreamState=%x finondata=%d",this, mStreamID,
@ -1491,7 +1491,7 @@ SpdyStream31::OnReadSegment(const char *buf,
if (mRequestHeadersDone && !mSynFrameGenerated) {
if (!mSession->TryToActivate(this)) {
LOG3(("SpdyStream31::OnReadSegment %p cannot activate now. queued.\n", this));
return NS_OK;
return *countRead ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
}
if (NS_FAILED(rv = GenerateSynFrame())) {
return rv;

View File

@ -194,6 +194,7 @@ nsHttpHandler::nsHttpHandler()
, mSpdySendingChunkSize(ASpdySession::kSendingChunkSize)
, mSpdySendBufferSize(ASpdySession::kTCPSendBufferSize)
, mSpdyPushAllowance(32768)
, mDefaultSpdyConcurrent(ASpdySession::kDefaultMaxConcurrent)
, mSpdyPingThreshold(PR_SecondsToInterval(58))
, mSpdyPingTimeout(PR_SecondsToInterval(8))
, mConnectTimeout(90000)
@ -1287,6 +1288,14 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
}
}
if (PREF_CHANGED(HTTP_PREF("spdy.default-concurrent"))) {
rv = prefs->GetIntPref(HTTP_PREF("spdy.default-concurrent"), &val);
if (NS_SUCCEEDED(rv)) {
mDefaultSpdyConcurrent =
static_cast<uint32_t>(std::max<int32_t>(std::min<int32_t>(val, 9999), 1));
}
}
// The amount of seconds to wait for a spdy ping response before
// closing the session.
if (PREF_CHANGED(HTTP_PREF("spdy.send-buffer-size"))) {

View File

@ -105,6 +105,7 @@ public:
uint32_t SpdySendingChunkSize() { return mSpdySendingChunkSize; }
uint32_t SpdySendBufferSize() { return mSpdySendBufferSize; }
uint32_t SpdyPushAllowance() { return mSpdyPushAllowance; }
uint32_t DefaultSpdyConcurrent() { return mDefaultSpdyConcurrent; }
PRIntervalTime SpdyPingThreshold() { return mSpdyPingThreshold; }
PRIntervalTime SpdyPingTimeout() { return mSpdyPingTimeout; }
bool AllowPush() { return mAllowPush; }
@ -487,6 +488,7 @@ private:
uint32_t mSpdySendingChunkSize;
uint32_t mSpdySendBufferSize;
uint32_t mSpdyPushAllowance;
uint32_t mDefaultSpdyConcurrent;
PRIntervalTime mSpdyPingThreshold;
PRIntervalTime mSpdyPingTimeout;

View File

@ -15,6 +15,7 @@ function generateContent(size) {
var posts = [];
posts.push(generateContent(10));
posts.push(generateContent(250000));
posts.push(generateContent(128000));
// pre-calculated md5sums (in hex) of the above posts
var md5s = ['f1b708bba17f1ce948dc979f4d7092bc',
@ -277,11 +278,20 @@ var Http2ConcurrentListener = function() {};
Http2ConcurrentListener.prototype = new Http2CheckListener();
Http2ConcurrentListener.prototype.count = 0;
Http2ConcurrentListener.prototype.target = 0;
Http2ConcurrentListener.prototype.reset = 0;
Http2ConcurrentListener.prototype.recvdHdr = 0;
Http2ConcurrentListener.prototype.onStopRequest = function(request, ctx, status) {
this.count++;
do_check_true(this.isHttp2Connection);
if (this.recvdHdr > 0) {
do_check_eq(request.getResponseHeader("X-Recvd"), this.recvdHdr);
}
if (this.count == this.target) {
if (this.reset > 0) {
prefs.setIntPref("network.http.spdy.default-concurrent", this.reset);
}
run_next_test();
do_test_finished();
}
@ -290,6 +300,9 @@ Http2ConcurrentListener.prototype.onStopRequest = function(request, ctx, status)
function test_http2_concurrent() {
var concurrent_listener = new Http2ConcurrentListener();
concurrent_listener.target = 201;
concurrent_listener.reset = prefs.getIntPref("network.http.spdy.default-concurrent");
prefs.setIntPref("network.http.spdy.default-concurrent", 100);
for (var i = 0; i < concurrent_listener.target; i++) {
concurrent_channels[i] = makeChan("https://localhost:" + serverPort + "/750ms");
concurrent_channels[i].loadFlags = Ci.nsIRequest.LOAD_BYPASS_CACHE;
@ -297,6 +310,26 @@ function test_http2_concurrent() {
}
}
function test_http2_concurrent_post() {
var concurrent_listener = new Http2ConcurrentListener();
concurrent_listener.target = 8;
concurrent_listener.recvdHdr = posts[2].length;
concurrent_listener.reset = prefs.getIntPref("network.http.spdy.default-concurrent");
prefs.setIntPref("network.http.spdy.default-concurrent", 3);
for (var i = 0; i < concurrent_listener.target; i++) {
concurrent_channels[i] = makeChan("https://localhost:" + serverPort + "/750msPost");
concurrent_channels[i].loadFlags = Ci.nsIRequest.LOAD_BYPASS_CACHE;
var stream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
stream.data = posts[2];
var uchan = concurrent_channels[i].QueryInterface(Ci.nsIUploadChannel);
uchan.setUploadStream(stream, "text/plain", stream.available());
concurrent_channels[i].requestMethod = "POST";
concurrent_channels[i].asyncOpen(concurrent_listener, null);
}
}
// Test to make sure we get multiplexing right
function test_http2_multiplex() {
var chan1 = makeChan("https://localhost:" + serverPort + "/multiplex1");
@ -625,6 +658,7 @@ function test_complete() {
var tests = [ test_http2_post_big
, test_http2_basic
, test_http2_concurrent
, test_http2_concurrent_post
, test_http2_basic_unblocked_dep
, test_http2_nospdy
, test_http2_push1

View File

@ -103,7 +103,9 @@ Log(const char* aMessageType,
NS_DebugBreak(NS_DEBUG_WARNING, nullptr, msg.c_str(), nullptr, -1);
#endif
nsContentUtils::LogMessageToConsole(msg.c_str());
if (nsContentUtils::IsInitialized()) {
nsContentUtils::LogMessageToConsole(msg.c_str());
}
}
// Initialize sandbox logging if required.

View File

@ -305,7 +305,12 @@ RESTRequest.prototype = {
}
// Create and initialize HTTP channel.
let channel = Services.io.newChannelFromURI(this.uri, null, null)
let channel = Services.io.newChannelFromURI2(this.uri,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER)
.QueryInterface(Ci.nsIRequest)
.QueryInterface(Ci.nsIHttpChannel);
this.channel = channel;

View File

@ -180,7 +180,12 @@ AboutWeaveLog.prototype = {
newChannel: function(aURI) {
let dir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
let uri = Services.io.newFileURI(dir);
let channel = Services.io.newChannelFromURI(uri);
let channel = Services.io.newChannelFromURI2(uri,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
channel.originalURI = aURI;
// Ensure that the about page has the same privileges as a regular directory

View File

@ -146,7 +146,14 @@ AsyncResource.prototype = {
// to obtain a request channel.
//
_createRequest: function Res__createRequest(method) {
let channel = Services.io.newChannel(this.spec, null, null)
let channel = Services.io.newChannel2(this.spec,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER)
.QueryInterface(Ci.nsIRequest)
.QueryInterface(Ci.nsIHttpChannel);

View File

@ -7,6 +7,7 @@ Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/Services.jsm");
const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
const LOG_PREFIX_SUCCESS = "success-";
@ -81,11 +82,16 @@ add_test(function test_logOnSuccess_false() {
});
function readFile(file, callback) {
NetUtil.asyncFetch(file, function (inputStream, statusCode, request) {
NetUtil.asyncFetch2(file, function (inputStream, statusCode, request) {
let data = NetUtil.readInputStreamToString(inputStream,
inputStream.available());
callback(statusCode, data);
});
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
}
add_test(function test_logOnSuccess_true() {

View File

@ -552,12 +552,6 @@ function synthesizeKey(aKey, aEvent, aWindow)
case KeyboardEvent.DOM_KEY_LOCATION_NUMPAD:
flags |= utils.KEY_FLAG_LOCATION_NUMPAD;
break;
case KeyboardEvent.DOM_KEY_LOCATION_MOBILE:
flags |= utils.KEY_FLAG_LOCATION_MOBILE;
break;
case KeyboardEvent.DOM_KEY_LOCATION_JOYSTICK:
flags |= utils.KEY_FLAG_LOCATION_JOYSTICK;
break;
}
}

View File

@ -20,7 +20,14 @@ const STATE_ENABLED = 1;
const STATE_DISABLED = 2;
function GetFileAsText(file) {
let channel = Services.io.newChannel(file, null, null);
let channel = Services.io.newChannel2(file,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
let inputStream = channel.open();
if (channel instanceof Ci.nsIHttpChannel &&
channel.responseStatus != 200) {

View File

@ -586,12 +586,6 @@ function synthesizeKey(aKey, aEvent, aWindow)
case KeyboardEvent.DOM_KEY_LOCATION_NUMPAD:
flags |= utils.KEY_FLAG_LOCATION_NUMPAD;
break;
case KeyboardEvent.DOM_KEY_LOCATION_MOBILE:
flags |= utils.KEY_FLAG_LOCATION_MOBILE;
break;
case KeyboardEvent.DOM_KEY_LOCATION_JOYSTICK:
flags |= utils.KEY_FLAG_LOCATION_JOYSTICK;
break;
}
}

View File

@ -283,6 +283,29 @@ function handleRequest(req, res) {
return;
}
else if (u.pathname === "/750msPost") {
if (req.method != "POST") {
res.writeHead(405);
res.end('Unexpected method: ' + req.method);
return;
}
var accum = 0;
req.on('data', function receivePostData(chunk) {
accum += chunk.length;
});
req.on('end', function finishPost() {
res.setHeader('X-Recvd', accum);
var rl = new runlater();
rl.req = req;
rl.resp = res;
setTimeout(executeRunLater, 750, rl);
return;
});
return;
}
else if (u.pathname === "/h11required_stream") {
if (req.httpVersionMajor === 2) {
h11required_conn = req.stream.connection;

View File

@ -1,7 +1,20 @@
Version history
===============
### 3.0.0 (2014-08-XX) ###
### 3.1.0 (2014-12-11) ###
* Upgrade to the latest draft: [draft-ietf-httpbis-http2-16]
* This involves some state transition changes that are technically incompatible with draft-14. If you need to be assured to interop on -14, continue using 3.0.1
[draft-ietf-httpbis-http2-16]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-16
### 3.0.1 (2014-11-20) ###
* Bugfix release.
* Fixed #81 and #87
* Fixed a bug in flow control (without GitHub issue)
### 3.0.0 (2014-08-25) ###
* Re-join node-http2 and node-http2-protocol into one repository
* API Changes

View File

@ -1,7 +1,7 @@
node-http2
==========
An HTTP/2 ([draft-ietf-httpbis-http2-14](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14))
An HTTP/2 ([draft-ietf-httpbis-http2-16](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16))
client and server implementation for node.js.
![Travis CI status](https://travis-ci.org/molnarg/node-http2.svg?branch=master)
@ -116,12 +116,12 @@ point to understand the code.
### Test coverage ###
To generate a code coverage report, run `npm test --coverage` (which runs very slowly, be patient).
Code coverage summary as of version 3.0.0:
Code coverage summary as of version 3.0.1:
```
Statements : 91.85% ( 1747/1902 )
Branches : 81.61% ( 688/843 )
Functions : 90.95% ( 211/232 )
Lines : 91.92% ( 1741/1894 )
Statements : 92.09% ( 1759/1910 )
Branches : 82.56% ( 696/843 )
Functions : 91.38% ( 212/232 )
Lines : 92.17% ( 1753/1902 )
```
There's a hosted version of the detailed (line-by-line) coverage report
@ -151,12 +151,17 @@ $ HTTP2_LOG=info node ./example/client.js 'http://localhost:8080/server.js' >/de
Contributors
------------
The co-maintainer of the project is [Nick Hurley](https://github.com/todesschaf).
Code contributions are always welcome! People who contributed to node-http2 so far:
* Nick Hurley
* Mike Belshe
* Yoshihiro Iwanaga
* vsemogutor
* [Nick Hurley](https://github.com/todesschaf)
* [Mike Belshe](https://github.com/mbelshe)
* [Yoshihiro Iwanaga](https://github.com/iwanaga)
* [Igor Novikov](https://github.com/vsemogutor)
* [James Willcox](https://github.com/snorp)
* [David Björklund](https://github.com/kesla)
* [Patrick McManus](https://github.com/mcmanus)
Special thanks to Google for financing the development of this module as part of their [Summer of
Code program](https://developers.google.com/open-source/soc/) (project: [HTTP/2 prototype server

View File

@ -2,18 +2,17 @@ var fs = require('fs');
var path = require('path');
var http2 = require('..');
// Setting the global logger (optional)
http2.globalAgent = new http2.Agent({
log: require('../test/util').createLogger('client')
});
// We use self signed certs in the example code so we ignore cert errors
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
// Sending the request
// It would be `var request = http2.get(process.argv.pop());` if we wouldn't care about plain mode
var options = require('url').parse(process.argv.pop());
options.plain = Boolean(process.env.HTTP2_PLAIN);
var request = http2.request(options);
request.end();
var url = process.argv.pop();
var request = process.env.HTTP2_PLAIN ? http2.raw.get(url) : http2.get(url);
// Receiving the response
request.on('response', function(response) {

View File

@ -2,22 +2,12 @@ var fs = require('fs');
var path = require('path');
var http2 = require('..');
var options = process.env.HTTP2_PLAIN ? {
plain: true
} : {
key: fs.readFileSync(path.join(__dirname, '/localhost.key')),
cert: fs.readFileSync(path.join(__dirname, '/localhost.crt'))
};
// Passing bunyan logger (optional)
options.log = require('../test/util').createLogger('server');
// We cache one file to be able to do simple performance tests without waiting for the disk
var cachedFile = fs.readFileSync(path.join(__dirname, './server.js'));
var cachedUrl = '/server.js';
// Creating the server
var server = http2.createServer(options, function(request, response) {
// The callback to handle requests
function onRequest(request, response) {
var filename = path.join(__dirname, request.url);
// Serving server.js from cache. Useful for microbenchmarks.
@ -44,6 +34,22 @@ var server = http2.createServer(options, function(request, response) {
response.writeHead('404');
response.end();
}
});
}
// Creating a bunyan logger (optional)
var log = require('../test/util').createLogger('server');
// Creating the server in plain or TLS mode (TLS mode is the default)
var server;
if (process.env.HTTP2_PLAIN) {
server = http2.raw.createServer({
log: log
}, onRequest);
} else {
server = http2.createServer({
log: log,
key: fs.readFileSync(path.join(__dirname, '/localhost.key')),
cert: fs.readFileSync(path.join(__dirname, '/localhost.crt'))
}, onRequest);
}
server.listen(process.env.HTTP2_PORT || 8080);

View File

@ -121,7 +121,7 @@
//
// [1]: http://nodejs.org/api/https.html
// [2]: http://nodejs.org/api/http.html
// [3]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-8.1.3.2
// [3]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-8.1.2.4
// [expect-continue]: https://github.com/http2/http2-spec/issues/18
// [connect]: https://github.com/http2/http2-spec/issues/230
@ -246,7 +246,7 @@ function IncomingMessage(stream) {
}
IncomingMessage.prototype = Object.create(PassThrough.prototype, { constructor: { value: IncomingMessage } });
// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-8.1.3.1)
// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-8.1.2.3)
// * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
// of key-value pairs. This includes the target URI for the request, the status code for the
// response, as well as HTTP header fields.
@ -602,7 +602,7 @@ function IncomingRequest(stream) {
}
IncomingRequest.prototype = Object.create(IncomingMessage.prototype, { constructor: { value: IncomingRequest } });
// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-8.1.3.1)
// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-8.1.2.3)
// * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
// of key-value pairs. This includes the target URI for the request, the status code for the
// response, as well as HTTP header fields.
@ -753,7 +753,8 @@ function requestRaw(options, callback) {
if (typeof options === "string") {
options = url.parse(options);
}
if ((options.protocol && options.protocol !== "http:") || !options.plain) {
options.plain = true;
if (options.protocol && options.protocol !== "http:") {
throw new Error('This interface only supports http-schemed URLs');
}
return (options.agent || exports.globalAgent).request(options, callback);
@ -763,7 +764,8 @@ function requestTLS(options, callback) {
if (typeof options === "string") {
options = url.parse(options);
}
if ((options.protocol && options.protocol !== "https:") || options.plain) {
options.plain = false;
if (options.protocol && options.protocol !== "https:") {
throw new Error('This interface only supports https-schemed URLs');
}
return (options.agent || exports.globalAgent).request(options, callback);
@ -773,7 +775,8 @@ function getRaw(options, callback) {
if (typeof options === "string") {
options = url.parse(options);
}
if ((options.protocol && options.protocol !== "http:") || !options.plain) {
options.plain = true;
if (options.protocol && options.protocol !== "http:") {
throw new Error('This interface only supports http-schemed URLs');
}
return (options.agent || exports.globalAgent).get(options, callback);
@ -783,7 +786,8 @@ function getTLS(options, callback) {
if (typeof options === "string") {
options = url.parse(options);
}
if ((options.protocol && options.protocol !== "https:") || options.plain) {
options.plain = false;
if (options.protocol && options.protocol !== "https:") {
throw new Error('This interface only supports https-schemed URLs');
}
return (options.agent || exports.globalAgent).get(options, callback);
@ -863,7 +867,7 @@ Agent.prototype.request = function request(options, callback) {
request._start(endpoint.createStream(), options);
}
// * HTTP/2 over TLS negotiated using NPN or ALPN
// * HTTP/2 over TLS negotiated using NPN or ALPN, or fallback to HTTPS1
else {
var started = false;
options.ALPNProtocols = supportedProtocols;
@ -876,7 +880,7 @@ Agent.prototype.request = function request(options, callback) {
httpsRequest.on('socket', function(socket) {
var negotiatedProtocol = socket.alpnProtocol || socket.npnProtocol;
if (negotiatedProtocol != null) { // null in >=0.11.0, undefined in <0.11.0
negotiated()
negotiated();
} else {
socket.on('secureConnect', negotiated);
}
@ -894,11 +898,12 @@ Agent.prototype.request = function request(options, callback) {
endpoint.pipe(endpoint.socket).pipe(endpoint);
}
if (started) {
// ** In the meantime, an other connection was made to the same host...
if (endpoint) {
// *** and it turned out to be HTTP2 and the request was multiplexed on that one, so we should close this one
endpoint.close();
} else {
httpsRequest.abort();
}
// *** otherwise, the fallback to HTTPS1 is already done.
} else {
if (endpoint) {
self._log.info({ e: endpoint, server: options.host + ':' + options.port },
@ -1079,7 +1084,7 @@ function IncomingResponse(stream) {
}
IncomingResponse.prototype = Object.create(IncomingMessage.prototype, { constructor: { value: IncomingResponse } });
// [Response Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-8.1.3.2)
// [Response Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-8.1.2.4)
// * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
// of key-value pairs. This includes the target URI for the request, the status code for the
// response, as well as HTTP header fields.

View File

@ -1,4 +1,4 @@
// [node-http2][homepage] is an [HTTP/2 (draft 14)][http2] implementation for [node.js][node].
// [node-http2][homepage] is an [HTTP/2 (draft 16)][http2] implementation for [node.js][node].
//
// The core of the protocol is implemented in the protocol sub-directory. This directory provides
// two important features on top of the protocol:
@ -10,7 +10,7 @@
// (which is in turn very similar to the [HTTP module API][node-http]).
//
// [homepage]: https://github.com/molnarg/node-http2
// [http2]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-14
// [http2]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-16
// [node]: http://nodejs.org/
// [node-https]: http://nodejs.org/api/https.html
// [node-http]: http://nodejs.org/api/http.html

View File

@ -1123,10 +1123,10 @@ Compressor.prototype.compress = function compress(headers) {
// separate header fields, each with one or more cookie-pairs.
if (name == 'cookie') {
if (!(value instanceof Array)) {
value = [value]
value = [value];
}
value = Array.prototype.concat.apply([], value.map(function(cookie) {
return String(cookie).split(';').map(trim)
return String(cookie).split(';').map(trim);
}));
}
@ -1256,7 +1256,7 @@ Decompressor.prototype.decompress = function decompress(block) {
// into a single octet string using the two octet delimiter of 0x3B, 0x20 (the ASCII
// string "; ").
if (('cookie' in headers) && (headers['cookie'] instanceof Array)) {
headers['cookie'] = headers['cookie'].join('; ')
headers['cookie'] = headers['cookie'].join('; ');
}
return headers;
@ -1340,5 +1340,5 @@ function cut(buffer, size) {
}
function trim(string) {
return string.trim()
return string.trim();
}

View File

@ -19,7 +19,7 @@ exports.Flow = Flow;
// * **setInitialWindow(size)**: the initial flow control window size can be changed *any time*
// ([as described in the standard][1]) using this method
//
// [1]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.9.2
// [1]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.9.2
// API for child classes
// ---------------------
@ -81,7 +81,9 @@ Flow.prototype._receive = function _receive(frame, callback) {
// incoming frame is a WINDOW_UPDATE.
// [1]: http://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback_1
Flow.prototype._write = function _write(frame, encoding, callback) {
if (frame.flags.END_STREAM || (frame.type === 'RST_STREAM')) {
var sentToUs = (this._flowControlId === undefined) || (frame.stream === this._flowControlId);
if (sentToUs && (frame.flags.END_STREAM || (frame.type === 'RST_STREAM'))) {
this._ended = true;
}
@ -99,8 +101,7 @@ Flow.prototype._write = function _write(frame, encoding, callback) {
this._receive(frame, callback);
}
if ((frame.type === 'WINDOW_UPDATE') &&
((this._flowControlId === undefined) || (frame.stream === this._flowControlId))) {
if (sentToUs && (frame.type === 'WINDOW_UPDATE')) {
this._updateWindow(frame);
}
};

View File

@ -146,7 +146,7 @@ Deserializer.prototype._transform = function _transform(chunk, encoding, done) {
done();
};
// [Frame Header](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-4.1)
// [Frame Header](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-4.1)
// --------------------------------------------------------------
//
// HTTP/2.0 frames share a common base format consisting of a 9-byte header followed by 0 to 2^24 - 1
@ -269,7 +269,7 @@ Deserializer.commonHeader = function readCommonHeader(buffer, frame) {
// * `typeSpecificAttributes`: a register of frame specific frame object attributes (used by
// logging code and also serves as documentation for frame objects)
// [DATA Frames](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.1)
// [DATA Frames](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.1)
// ------------------------------------------------------------
//
// DATA frames (type=0x0) convey arbitrary, variable-length sequences of octets associated with a
@ -308,7 +308,7 @@ Deserializer.DATA = function readData(buffer, frame) {
}
};
// [HEADERS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.2)
// [HEADERS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.2)
// --------------------------------------------------------------
//
// The HEADERS frame (type=0x1) allows the sender to create a stream.
@ -390,7 +390,7 @@ Deserializer.HEADERS = function readHeadersPriority(buffer, frame) {
}
};
// [PRIORITY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.3)
// [PRIORITY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.3)
// -------------------------------------------------------
//
// The PRIORITY frame (type=0x2) specifies the sender-advised priority of a stream.
@ -435,7 +435,7 @@ Deserializer.PRIORITY = function readPriority(buffer, frame) {
frame.priorityWeight = buffer.readUInt8(4);
};
// [RST_STREAM](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.4)
// [RST_STREAM](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.4)
// -----------------------------------------------------------
//
// The RST_STREAM frame (type=0x3) allows for abnormal termination of a stream.
@ -473,7 +473,7 @@ Deserializer.RST_STREAM = function readRstStream(buffer, frame) {
}
};
// [SETTINGS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.5)
// [SETTINGS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.5)
// -------------------------------------------------------
//
// The SETTINGS frame (type=0x4) conveys configuration parameters that affect how endpoints
@ -580,7 +580,7 @@ definedSettings[4] = { name: 'SETTINGS_INITIAL_WINDOW_SIZE', flag: false };
// indicates the maximum size of a frame the receiver will allow.
definedSettings[5] = { name: 'SETTINGS_MAX_FRAME_SIZE', flag: false };
// [PUSH_PROMISE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.6)
// [PUSH_PROMISE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.6)
// ---------------------------------------------------------------
//
// The PUSH_PROMISE frame (type=0x5) is used to notify the peer endpoint in advance of streams the
@ -641,7 +641,7 @@ Deserializer.PUSH_PROMISE = function readPushPromise(buffer, frame) {
}
};
// [PING](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.7)
// [PING](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.7)
// -----------------------------------------------
//
// The PING frame (type=0x6) is a mechanism for measuring a minimal round-trip time from the
@ -671,7 +671,7 @@ Deserializer.PING = function readPing(buffer, frame) {
frame.data = buffer;
};
// [GOAWAY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.8)
// [GOAWAY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.8)
// ---------------------------------------------------
//
// The GOAWAY frame (type=0x7) informs the remote peer to stop creating streams on this connection.
@ -722,7 +722,7 @@ Deserializer.GOAWAY = function readGoaway(buffer, frame) {
}
};
// [WINDOW_UPDATE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.9)
// [WINDOW_UPDATE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.9)
// -----------------------------------------------------------------
//
// The WINDOW_UPDATE frame (type=0x8) is used to implement flow control.
@ -760,7 +760,7 @@ Deserializer.WINDOW_UPDATE = function readWindowUpdate(buffer, frame) {
}
};
// [CONTINUATION](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.10)
// [CONTINUATION](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.10)
// ------------------------------------------------------------
//
// The CONTINUATION frame (type=0x9) is used to continue a sequence of header block fragments.
@ -785,7 +785,7 @@ Deserializer.CONTINUATION = function readContinuation(buffer, frame) {
frame.data = buffer;
};
// [ALTSVC](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.11)
// [ALTSVC](http://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-04#section-4)
// ------------------------------------------------------------
//
// The ALTSVC frame (type=0xA) advertises the availability of an alternative service to the client.
@ -874,7 +874,7 @@ Deserializer.ALTSVC = function readAltSvc(buffer, frame) {
frame.origin = buffer.toString('ascii', 9 + pidLength + hostLength);
};
// [BLOCKED](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-6.12)
// BLOCKED
// ------------------------------------------------------------
//
// The BLOCKED frame (type=0xB) indicates that the sender is unable to send data
@ -894,7 +894,7 @@ Serializer.BLOCKED = function writeBlocked(frame, buffers) {
Deserializer.BLOCKED = function readBlocked(buffer, frame) {
};
// [Error Codes](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-7)
// [Error Codes](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-7)
// ------------------------------------------------------------
var errorCodes = [

View File

@ -1,4 +1,4 @@
// [node-http2-protocol][homepage] is an implementation of the [HTTP/2 (draft 14)][http2]
// [node-http2-protocol][homepage] is an implementation of the [HTTP/2 (draft 16)][http2]
// framing layer for [node.js][node].
//
// The main building blocks are [node.js streams][node-stream] that are connected through pipes.
@ -28,10 +28,10 @@
// between the binary and the JavaScript object representation of HTTP/2 frames
//
// [homepage]: https://github.com/molnarg/node-http2
// [http2]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-14
// [http2-connheader]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-3.5
// [http2-stream]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-5
// [http2-streamstate]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-5.1
// [http2]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-16
// [http2-connheader]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-3.5
// [http2-stream]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-5
// [http2-streamstate]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-5.1
// [node]: http://nodejs.org/
// [node-stream]: http://nodejs.org/api/stream.html
// [node-https]: http://nodejs.org/api/https.html

View File

@ -352,7 +352,7 @@ Stream.prototype._finishing = function _finishing() {
}
};
// [Stream States](http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-5.1)
// [Stream States](http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-5.1)
// ----------------
//
// +--------+
@ -464,7 +464,7 @@ Stream.prototype._transition = function transition(sending, frame) {
this._setState('HALF_CLOSED_REMOTE');
} else if (RST_STREAM) {
this._setState('CLOSED');
} else if (receiving && PRIORITY) {
} else if (PRIORITY) {
/* No state change */
} else {
connectionError = 'PROTOCOL_ERROR';
@ -483,7 +483,7 @@ Stream.prototype._transition = function transition(sending, frame) {
this._setState('CLOSED');
} else if (receiving && HEADERS) {
this._setState('HALF_CLOSED_LOCAL');
} else if (BLOCKED || (sending && PRIORITY)) {
} else if (BLOCKED || PRIORITY) {
/* No state change */
} else {
connectionError = 'PROTOCOL_ERROR';
@ -518,7 +518,7 @@ Stream.prototype._transition = function transition(sending, frame) {
case 'HALF_CLOSED_LOCAL':
if (RST_STREAM || (receiving && frame.flags.END_STREAM)) {
this._setState('CLOSED');
} else if (BLOCKED || ALTSVC ||receiving || (sending && (PRIORITY || WINDOW_UPDATE))) {
} else if (BLOCKED || ALTSVC || receiving || PRIORITY || (sending && WINDOW_UPDATE)) {
/* No state change */
} else {
connectionError = 'PROTOCOL_ERROR';
@ -538,7 +538,7 @@ Stream.prototype._transition = function transition(sending, frame) {
case 'HALF_CLOSED_REMOTE':
if (RST_STREAM || (sending && frame.flags.END_STREAM)) {
this._setState('CLOSED');
} else if (BLOCKED || ALTSVC ||sending || (receiving && (WINDOW_UPDATE || PRIORITY))) {
} else if (BLOCKED || ALTSVC || sending || PRIORITY || (receiving && WINDOW_UPDATE)) {
/* No state change */
} else {
connectionError = 'PROTOCOL_ERROR';
@ -566,9 +566,9 @@ Stream.prototype._transition = function transition(sending, frame) {
// causes a stream to become "reserved". If promised streams are not desired, a RST_STREAM
// can be used to close any of those streams.
case 'CLOSED':
if ((sending && RST_STREAM) ||
if (PRIORITY || (sending && RST_STREAM) ||
(receiving && this._closedByUs &&
(this._closedWithRst || WINDOW_UPDATE || PRIORITY || RST_STREAM || ALTSVC))) {
(this._closedWithRst || WINDOW_UPDATE || RST_STREAM || ALTSVC))) {
/* No state change */
} else {
streamError = 'STREAM_CLOSED';
@ -637,7 +637,7 @@ Stream.prototype._transition = function transition(sending, frame) {
this.emit('connectionError', connectionError);
} else {
this.reset(streamError);
this.emit('error', streamError)
this.emit('error', streamError);
}
}
}

View File

@ -1,6 +1,6 @@
{
"name": "http2",
"version": "3.0.0",
"version": "3.1.0",
"description": "An HTTP/2 client and server implementation",
"main": "lib/index.js",
"engines" : {
@ -14,7 +14,7 @@
"bunyan": "*"
},
"scripts": {
"test": "istanbul test _mocha -- --reporter spec --slow 200",
"test": "istanbul test _mocha -- --reporter spec --slow 500 --timeout 15000",
"doc": "docco lib/* --output doc --layout parallel --css doc/docco.css"
},
"repository": {
@ -36,7 +36,10 @@
"Nick Hurley",
"Mike Belshe",
"Yoshihiro Iwanaga",
"vsemogutor"
"Igor Novikov",
"James Willcox",
"David Björklund",
"Patrick McManus"
],
"license": "MIT",
"readmeFilename": "README.md"

View File

@ -406,21 +406,21 @@ describe('compressor.js', function() {
expect(table.encode(new Buffer(decoded)).toString('hex')).to.equal(encoded);
}
});
})
});
describe('method decode(buffer)', function() {
it('should return the Huffman decoded version of the input buffer', function() {
var table = HuffmanTable.huffmanTable;
for (var decoded in test_huffman_request) {
var encoded = test_huffman_request[decoded];
expect(table.decode(new Buffer(encoded, 'hex')).toString()).to.equal(decoded)
expect(table.decode(new Buffer(encoded, 'hex')).toString()).to.equal(decoded);
}
table = HuffmanTable.huffmanTable;
for (decoded in test_huffman_response) {
encoded = test_huffman_response[decoded];
expect(table.decode(new Buffer(encoded, 'hex')).toString()).to.equal(decoded)
expect(table.decode(new Buffer(encoded, 'hex')).toString()).to.equal(decoded);
}
});
})
});
});
describe('HeaderSetCompressor', function() {
@ -569,7 +569,7 @@ describe('compressor.js', function() {
var result = table.decode(table.encode(buffer));
expect(result).to.deep.equal(buffer);
}
})
})
});
});
});
});

View File

@ -131,7 +131,7 @@ describe('connection.js', function() {
client_stream.on('data', function(data) {
expect(data).to.deep.equal(response_data);
done();
})
});
});
});
describe('server push', function() {

View File

@ -254,7 +254,7 @@ describe('flow.js', function() {
// Start piping
flow1.pipe(flow2).pipe(flow1);
})
});
});
});
});

View File

@ -124,7 +124,7 @@ describe('http.js', function() {
var response = new http2.OutgoingResponse(stream);
response.writeHead(200);
response.writeHead(404)
response.writeHead(404);
});
});
describe('test scenario', function() {
@ -149,6 +149,66 @@ describe('http.js', function() {
});
});
});
describe('2 simple request in parallel', function() {
it('should work as expected', function(originalDone) {
var path = '/x';
var message = 'Hello world';
done = util.callNTimes(2, function() {
server.close();
originalDone();
});
var server = http2.createServer(options, function(request, response) {
expect(request.url).to.equal(path);
response.end(message);
});
server.listen(1234, function() {
http2.get('https://localhost:1234' + path, function(response) {
response.on('data', function(data) {
expect(data.toString()).to.equal(message);
done();
});
});
http2.get('https://localhost:1234' + path, function(response) {
response.on('data', function(data) {
expect(data.toString()).to.equal(message);
done();
});
});
});
});
});
describe('100 simple request in a series', function() {
it('should work as expected', function(done) {
var path = '/x';
var message = 'Hello world';
var server = http2.createServer(options, function(request, response) {
expect(request.url).to.equal(path);
response.end(message);
});
var n = 100;
server.listen(1242, function() {
doRequest();
function doRequest() {
http2.get('https://localhost:1242' + path, function(response) {
response.on('data', function(data) {
expect(data.toString()).to.equal(message);
if (n) {
n -= 1;
doRequest();
} else {
server.close();
done();
}
});
});
}
});
});
});
describe('request with payload', function() {
it('should work as expected', function(done) {
var path = '/x';
@ -240,7 +300,6 @@ describe('http.js', function() {
var message = 'Hello world';
var server = http2.raw.createServer({
plain: true,
log: util.serverLog
}, function(request, response) {
expect(request.url).to.equal(path);
@ -264,6 +323,30 @@ describe('http.js', function() {
});
});
});
describe('get over plain TCP', function() {
it('should work as expected', function(done) {
var path = '/x';
var message = 'Hello world';
var server = http2.raw.createServer({
log: util.serverLog
}, function(request, response) {
expect(request.url).to.equal(path);
response.end(message);
});
server.listen(1237, function() {
var request = http2.raw.get('http://localhost:1237/x', function(response) {
response.on('data', function(data) {
expect(data.toString()).to.equal(message);
server.close();
done();
});
});
request.end();
});
});
});
describe('request to an HTTPS/1 server', function() {
it('should fall back to HTTPS/1 successfully', function(done) {
var path = '/x';
@ -284,6 +367,36 @@ describe('http.js', function() {
});
});
});
describe('2 parallel request to an HTTPS/1 server', function() {
it('should fall back to HTTPS/1 successfully', function(originalDone) {
var path = '/x';
var message = 'Hello world';
done = util.callNTimes(2, function() {
server.close();
originalDone();
});
var server = https.createServer(options, function(request, response) {
expect(request.url).to.equal(path);
response.end(message);
});
server.listen(6789, function() {
http2.get('https://localhost:6789' + path, function(response) {
response.on('data', function(data) {
expect(data.toString()).to.equal(message);
done();
});
});
http2.get('https://localhost:6789' + path, function(response) {
response.on('data', function(data) {
expect(data.toString()).to.equal(message);
done();
});
});
});
});
});
describe('HTTPS/1 request to a HTTP/2 server', function() {
it('should fall back to HTTPS/1 successfully', function(done) {
var path = '/x';

View File

@ -112,7 +112,6 @@ var example_frames = [
var invalid_incoming_frames = {
IDLE: [
{ type: 'DATA', flags: {}, data: new Buffer(5) },
{ type: 'PRIORITY', flags: {}, priority: 1 },
{ type: 'WINDOW_UPDATE', flags: {}, settings: {} },
{ type: 'PUSH_PROMISE', flags: {}, headers: {} },
{ type: 'RST_STREAM', flags: {}, error: 'CANCEL' }
@ -125,7 +124,6 @@ var invalid_incoming_frames = {
],
RESERVED_REMOTE: [
{ type: 'DATA', flags: {}, data: new Buffer(5) },
{ type: 'PRIORITY', flags: {}, priority: 1 },
{ type: 'PUSH_PROMISE', flags: {}, headers: {} },
{ type: 'WINDOW_UPDATE', flags: {}, settings: {} }
],
@ -143,13 +141,11 @@ var invalid_incoming_frames = {
var invalid_outgoing_frames = {
IDLE: [
{ type: 'DATA', flags: {}, data: new Buffer(5) },
{ type: 'PRIORITY', flags: {}, priority: 1 },
{ type: 'WINDOW_UPDATE', flags: {}, settings: {} },
{ type: 'PUSH_PROMISE', flags: {}, headers: {} }
],
RESERVED_LOCAL: [
{ type: 'DATA', flags: {}, data: new Buffer(5) },
{ type: 'PRIORITY', flags: {}, priority: 1 },
{ type: 'PUSH_PROMISE', flags: {}, headers: {} },
{ type: 'WINDOW_UPDATE', flags: {}, settings: {} }
],
@ -169,7 +165,6 @@ var invalid_outgoing_frames = {
HALF_CLOSED_REMOTE: [
],
CLOSED: [
{ type: 'PRIORITY', flags: {}, priority: 1 },
{ type: 'WINDOW_UPDATE', flags: {}, settings: {} },
{ type: 'HEADERS', flags: {}, headers: {}, priority: undefined },
{ type: 'DATA', flags: {}, data: new Buffer(5) },
@ -188,7 +183,7 @@ describe('stream.js', function() {
stream.state = state;
stream.once('connectionError', function() { connectionErrorHappened = true; });
stream._transition(false, invalid_frame);
expect(connectionErrorHappened)
expect(connectionErrorHappened);
});
});
@ -197,7 +192,7 @@ describe('stream.js', function() {
stream.headers({});
stream.end();
stream.upstream.write({ type: 'HEADERS', headers:{}, flags: { END_STREAM: true }, count_change: util.noop });
example_frames.forEach(function(invalid_frame) {
example_frames.slice(1).forEach(function(invalid_frame) {
invalid_frame.count_change = util.noop;
expect(stream._transition.bind(stream, false, invalid_frame)).to.throw('Uncaught, unspecified "error" event.');
});

View File

@ -86,4 +86,4 @@ exports.shuffleBuffers = function shuffleBuffers(buffers) {
}
return output;
}
};

View File

@ -567,7 +567,7 @@ End of 5th\n\
SimpleTest.waitForClipboard(
function(aActual) {
mostRecentActual = aActual;
return aActual === aExpected;
return aActual.trim() === aExpected.trim();
},
function() {
synthesizeKey("A", {accelKey: true});

View File

@ -106,7 +106,7 @@
SimpleTest.waitForClipboard(
function(aActual) {
mostRecentActual = aActual;
return aActual === aExpected;
return aActual.trim() === aExpected.trim();
},
function() {
synthesizeKey("A", {accelKey: true});

View File

@ -106,7 +106,7 @@
let actual = SpecialPowers.getClipboardData("text/unicode");
actual = actual.replace(/\(pid \d+\)/g, "(pid NNN)");
if (actual === aExpected) {
if (actual.trim() === aExpected.trim()) {
SimpleTest.ok(true, "Clipboard has the expected contents");
aNext();
} else {

View File

@ -54,7 +54,7 @@
let actual = SpecialPowers.getClipboardData("text/unicode");
actual = actual.replace(/\(pid \d+\)/, "(pid NNN)");
if (actual === aExpected) {
if (actual.trim() === aExpected.trim()) {
SimpleTest.ok(true, "Clipboard has the expected contents");
aNext();
} else {

View File

@ -463,20 +463,27 @@ exports.fetch = function fetch(aURL, aOptions={ loadFromCache: true }) {
case "chrome":
case "resource":
try {
NetUtil.asyncFetch(url, function onFetch(aStream, aStatus, aRequest) {
if (!components.isSuccessCode(aStatus)) {
deferred.reject(new Error("Request failed with status code = "
+ aStatus
+ " after NetUtil.asyncFetch for url = "
+ url));
return;
}
NetUtil.asyncFetch2(
url,
function onFetch(aStream, aStatus, aRequest) {
if (!components.isSuccessCode(aStatus)) {
deferred.reject(new Error("Request failed with status code = "
+ aStatus
+ " after NetUtil.asyncFetch2 for url = "
+ url));
return;
}
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
contentType = aRequest.contentType;
deferred.resolve(source);
aStream.close();
});
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
contentType = aRequest.contentType;
deferred.resolve(source);
aStream.close();
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
} catch (ex) {
deferred.reject(ex);
}

View File

@ -199,14 +199,22 @@ SrcdirProvider.prototype = {
_readFile: function(filename) {
let deferred = promise.defer();
let file = new FileUtils.File(filename);
NetUtil.asyncFetch(file, (inputStream, status) => {
if (!Components.isSuccessCode(status)) {
deferred.reject(new Error("Couldn't load manifest: " + filename + "\n"));
return;
}
var data = NetUtil.readInputStreamToString(inputStream, inputStream.available());
deferred.resolve(data);
});
NetUtil.asyncFetch2(
file,
(inputStream, status) => {
if (!Components.isSuccessCode(status)) {
deferred.reject(new Error("Couldn't load manifest: " + filename + "\n"));
return;
}
var data = NetUtil.readInputStreamToString(inputStream, inputStream.available());
deferred.resolve(data);
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
return deferred.promise;
},

View File

@ -187,17 +187,24 @@ function uploadPackageBulk(client, webappsActor, packageFile, progressCallback)
});
request.on("bulk-send-ready", ({copyFrom}) => {
NetUtil.asyncFetch(packageFile, function(inputStream) {
let copying = copyFrom(inputStream);
copying.on("progress", (e, progress) => {
progressCallback(progress);
});
copying.then(() => {
console.log("Bulk upload done");
inputStream.close();
deferred.resolve(actor);
});
});
NetUtil.asyncFetch2(
packageFile,
function(inputStream) {
let copying = copyFrom(inputStream);
copying.on("progress", (e, progress) => {
progressCallback(progress);
});
copying.then(() => {
console.log("Bulk upload done");
inputStream.close();
deferred.resolve(actor);
});
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
});
}

View File

@ -86,7 +86,14 @@ function webappActorRequest(request, onResponse) {
function downloadURL(url, file) {
let channel = Services.io.newChannel(url, null, null);
let channel = Services.io.newChannel2(url,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
let istream = channel.open();
let bstream = Cc["@mozilla.org/binaryinputstream;1"]
.createInstance(Ci.nsIBinaryInputStream);

View File

@ -156,7 +156,14 @@ exports.items = [
try {
let io = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
let channel = io.newChannel(data, null, null);
let channel = io.newChannel2(data,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_IMAGE);
let input = channel.open();
let imgTools = Cc["@mozilla.org/image/tools;1"]
.getService(Ci.imgITools);

View File

@ -667,20 +667,27 @@ function fetch(aURL, aOptions={ loadFromCache: true, window: null,
case "chrome":
case "resource":
try {
NetUtil.asyncFetch(url, function onFetch(aStream, aStatus, aRequest) {
if (!components.isSuccessCode(aStatus)) {
deferred.reject(new Error("Request failed with status code = "
+ aStatus
+ " after NetUtil.asyncFetch for url = "
+ url));
return;
}
NetUtil.asyncFetch2(
url,
function onFetch(aStream, aStatus, aRequest) {
if (!components.isSuccessCode(aStatus)) {
deferred.reject(new Error("Request failed with status code = "
+ aStatus
+ " after NetUtil.asyncFetch2 for url = "
+ url));
return;
}
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
contentType = aRequest.contentType;
deferred.resolve(source);
aStream.close();
});
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
contentType = aRequest.contentType;
deferred.resolve(source);
aStream.close();
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_STYLESHEET);
} catch (ex) {
deferred.reject(ex);
}
@ -689,12 +696,26 @@ function fetch(aURL, aOptions={ loadFromCache: true, window: null,
default:
let channel;
try {
channel = Services.io.newChannel(url, null, null);
channel = Services.io.newChannel2(url,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_STYLESHEET);
} catch (e if e.name == "NS_ERROR_UNKNOWN_PROTOCOL") {
// On Windows xpcshell tests, c:/foo/bar can pass as a valid URL, but
// newChannel won't be able to handle it.
url = "file:///" + url;
channel = Services.io.newChannel(url, null, null);
channel = Services.io.newChannel2(url,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_STYLESHEET);
}
let chunks = [];
let streamListener = {

View File

@ -1086,20 +1086,27 @@ function fetch(aURL, aOptions={ loadFromCache: true, window: null,
case "chrome":
case "resource":
try {
NetUtil.asyncFetch(url, function onFetch(aStream, aStatus, aRequest) {
if (!components.isSuccessCode(aStatus)) {
deferred.reject(new Error("Request failed with status code = "
+ aStatus
+ " after NetUtil.asyncFetch for url = "
+ url));
return;
}
NetUtil.asyncFetch2(
url,
function onFetch(aStream, aStatus, aRequest) {
if (!components.isSuccessCode(aStatus)) {
deferred.reject(new Error("Request failed with status code = "
+ aStatus
+ " after NetUtil.asyncFetch2 for url = "
+ url));
return;
}
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
contentType = aRequest.contentType;
deferred.resolve(source);
aStream.close();
});
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
contentType = aRequest.contentType;
deferred.resolve(source);
aStream.close();
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_STYLESHEET);
} catch (ex) {
deferred.reject(ex);
}
@ -1108,12 +1115,26 @@ function fetch(aURL, aOptions={ loadFromCache: true, window: null,
default:
let channel;
try {
channel = Services.io.newChannel(url, null, null);
channel = Services.io.newChannel2(url,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_STYLESHEET);
} catch (e if e.name == "NS_ERROR_UNKNOWN_PROTOCOL") {
// On Windows xpcshell tests, c:/foo/bar can pass as a valid URL, but
// newChannel won't be able to handle it.
url = "file:///" + url;
channel = Services.io.newChannel(url, null, null);
channel = Services.io.newChannel2(url,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_STYLESHEET);
}
let chunks = [];
let streamListener = {

View File

@ -7,6 +7,7 @@ let { DebuggerClient } =
Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
let { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
let Pipe = CC("@mozilla.org/pipe;1", "nsIPipe", "init");
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
@ -61,11 +62,18 @@ TestBulkActor.prototype = {
type: type,
length: really_long().length
}).then(({copyFrom}) => {
NetUtil.asyncFetch(getTestTempFile("bulk-input"), input => {
copyFrom(input).then(() => {
input.close();
});
});
NetUtil.asyncFetch2(
getTestTempFile("bulk-input"),
input => {
copyFrom(input).then(() => {
input.close();
});
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
});
},
@ -160,12 +168,19 @@ let test_bulk_request_cs = Task.async(function*(transportFactory, actorType, rep
// Send bulk data to server
request.on("bulk-send-ready", ({copyFrom}) => {
NetUtil.asyncFetch(getTestTempFile("bulk-input"), input => {
copyFrom(input).then(() => {
input.close();
bulkCopyDeferred.resolve();
});
});
NetUtil.asyncFetch2(
getTestTempFile("bulk-input"),
input => {
copyFrom(input).then(() => {
input.close();
bulkCopyDeferred.resolve();
});
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
});
// Set up reply handling for this type
@ -242,13 +257,20 @@ function verify_files() {
// Ensure output file contents actually match
let compareDeferred = promise.defer();
NetUtil.asyncFetch(getTestTempFile("bulk-output"), input => {
let outputData = NetUtil.readInputStreamToString(input, reallyLong.length);
// Avoid do_check_eq here so we don't log the contents
do_check_true(outputData === reallyLong);
input.close();
compareDeferred.resolve();
});
NetUtil.asyncFetch2(
getTestTempFile("bulk-output"),
input => {
let outputData = NetUtil.readInputStreamToString(input, reallyLong.length);
// Avoid do_check_eq here so we don't log the contents
do_check_true(outputData === reallyLong);
input.close();
compareDeferred.resolve();
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
return compareDeferred.promise.then(cleanup_files);
}

View File

@ -40,11 +40,18 @@ let test_transport = Task.async(function*(transportFactory) {
// Sending from client to server
function write_data({copyFrom}) {
NetUtil.asyncFetch(getTestTempFile("bulk-input"), function(input, status) {
copyFrom(input).then(() => {
input.close();
});
});
NetUtil.asyncFetch2(
getTestTempFile("bulk-input"),
function(input, status) {
copyFrom(input).then(() => {
input.close();
});
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
}
// Receiving on server from client
@ -148,13 +155,20 @@ function verify() {
// Ensure output file contents actually match
let compareDeferred = promise.defer();
NetUtil.asyncFetch(getTestTempFile("bulk-output"), input => {
let outputData = NetUtil.readInputStreamToString(input, reallyLong.length);
// Avoid do_check_eq here so we don't log the contents
do_check_true(outputData === reallyLong);
input.close();
compareDeferred.resolve();
});
NetUtil.asyncFetch2(
getTestTempFile("bulk-output"),
input => {
let outputData = NetUtil.readInputStreamToString(input, reallyLong.length);
// Avoid do_check_eq here so we don't log the contents
do_check_true(outputData === reallyLong);
input.close();
compareDeferred.resolve();
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
return compareDeferred.promise.then(cleanup_files);
}

View File

@ -5,6 +5,7 @@ let { DebuggerServer } =
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
let { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
function run_test() {
initTestDebuggerServer();
@ -40,11 +41,18 @@ let test_bulk_transfer_transport = Task.async(function*(transportFactory) {
// Sending from client to server
function write_data({copyFrom}) {
NetUtil.asyncFetch(getTestTempFile("bulk-input"), function(input, status) {
copyFrom(input).then(() => {
input.close();
});
});
NetUtil.asyncFetch2(
getTestTempFile("bulk-input"),
function(input, status) {
copyFrom(input).then(() => {
input.close();
});
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
}
// Receiving on server from client
@ -119,13 +127,20 @@ function verify() {
// Ensure output file contents actually match
let compareDeferred = promise.defer();
NetUtil.asyncFetch(getTestTempFile("bulk-output"), input => {
let outputData = NetUtil.readInputStreamToString(input, reallyLong.length);
// Avoid do_check_eq here so we don't log the contents
do_check_true(outputData === reallyLong);
input.close();
compareDeferred.resolve();
});
NetUtil.asyncFetch2(
getTestTempFile("bulk-output"),
input => {
let outputData = NetUtil.readInputStreamToString(input, reallyLong.length);
// Avoid do_check_eq here so we don't log the contents
do_check_true(outputData === reallyLong);
input.close();
compareDeferred.resolve();
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
return compareDeferred.promise.then(cleanup_files);
}

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