398 lines
16 KiB
Diff
398 lines
16 KiB
Diff
|
From d135e3b3c48811c577e1632a41c5c50bc55c035c Mon Sep 17 00:00:00 2001
|
||
|
From: Ehsan Akhgari <ehsan@mozilla.com>
|
||
|
Date: Tue, 20 Oct 2015 11:40:12 +0200
|
||
|
Subject: [PATCH] Bug 1210302 - Add a NS_ParseRequestContentType API; ba=al,
|
||
|
r=mcmanus, r=sicking, a=al
|
||
|
|
||
|
--HG--
|
||
|
extra : amend_source : d93021b626709b03f6499029dc3d1813cccba386
|
||
|
---
|
||
|
docshell/base/nsDocShell.cpp | 2 +-
|
||
|
dom/base/Navigator.cpp | 4 +--
|
||
|
dom/base/nsContentUtils.cpp | 2 +-
|
||
|
dom/html/nsHTMLDocument.cpp | 2 +-
|
||
|
dom/manifest/ManifestProcessor.jsm | 6 ++--
|
||
|
netwerk/base/moz.build | 1 +
|
||
|
netwerk/base/nsINetUtil_ESR_38.idl | 14 +++++++++
|
||
|
netwerk/base/nsIOService.cpp | 12 ++++++++
|
||
|
netwerk/base/nsIOService.h | 3 ++
|
||
|
netwerk/base/nsNetUtil.h | 21 +++++++++++++
|
||
|
netwerk/base/nsURLHelper.cpp | 60 +++++++++++++++++++++++++++++++++++---
|
||
|
netwerk/base/nsURLHelper.h | 32 +++++++++++++++-----
|
||
|
12 files changed, 139 insertions(+), 20 deletions(-)
|
||
|
create mode 100644 netwerk/base/nsINetUtil_ESR_38.idl
|
||
|
|
||
|
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
|
||
|
index bcc205c..4fc7c34 100644
|
||
|
--- a/docshell/base/nsDocShell.cpp
|
||
|
+++ b/docshell/base/nsDocShell.cpp
|
||
|
@@ -13519,7 +13519,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
||
|
anchor->GetType(typeHint);
|
||
|
NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
|
||
|
nsAutoCString type, dummy;
|
||
|
- NS_ParseContentType(utf8Hint, type, dummy);
|
||
|
+ NS_ParseRequestContentType(utf8Hint, type, dummy);
|
||
|
CopyUTF8toUTF16(type, typeHint);
|
||
|
}
|
||
|
|
||
|
diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
|
||
|
index f4ea502..7288420 100644
|
||
|
--- a/dom/base/Navigator.cpp
|
||
|
+++ b/dom/base/Navigator.cpp
|
||
|
@@ -1221,9 +1221,9 @@ Navigator::SendBeacon(const nsAString& aUrl,
|
||
|
rv = secMan->CheckSameOriginURI(documentURI, uri, false);
|
||
|
bool crossOrigin = NS_FAILED(rv);
|
||
|
nsAutoCString contentType, parsedCharset;
|
||
|
- rv = NS_ParseContentType(mimeType, contentType, parsedCharset);
|
||
|
+ rv = NS_ParseRequestContentType(mimeType, contentType, parsedCharset);
|
||
|
if (crossOrigin &&
|
||
|
- contentType.Length() > 0 &&
|
||
|
+ mimeType.Length() > 0 &&
|
||
|
!contentType.Equals(APPLICATION_WWW_FORM_URLENCODED) &&
|
||
|
!contentType.Equals(MULTIPART_FORM_DATA) &&
|
||
|
!contentType.Equals(TEXT_PLAIN)) {
|
||
|
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
|
||
|
index 5e8dbd6..686f7bf 100644
|
||
|
--- a/dom/base/nsContentUtils.cpp
|
||
|
+++ b/dom/base/nsContentUtils.cpp
|
||
|
@@ -7001,7 +7001,7 @@ nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
|
||
|
nsAutoCString contentType;
|
||
|
nsAutoCString unused;
|
||
|
|
||
|
- nsresult rv = NS_ParseContentType(aHeaderValue, contentType, unused);
|
||
|
+ nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
|
||
|
if (NS_FAILED(rv)) {
|
||
|
return false;
|
||
|
}
|
||
|
diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
|
||
|
index 7481109..d195792 100644
|
||
|
--- a/dom/html/nsHTMLDocument.cpp
|
||
|
+++ b/dom/html/nsHTMLDocument.cpp
|
||
|
@@ -1422,7 +1422,7 @@ nsHTMLDocument::Open(JSContext* cx,
|
||
|
nsAutoString type;
|
||
|
nsContentUtils::ASCIIToLower(aType, type);
|
||
|
nsAutoCString actualType, dummy;
|
||
|
- NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
|
||
|
+ NS_ParseRequestContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
|
||
|
if (!actualType.EqualsLiteral("text/html") &&
|
||
|
!type.EqualsLiteral("replace")) {
|
||
|
contentType.AssignLiteral("text/plain");
|
||
|
diff --git a/dom/manifest/ManifestProcessor.jsm b/dom/manifest/ManifestProcessor.jsm
|
||
|
index b6df920..f16881a 100644
|
||
|
--- a/dom/manifest/ManifestProcessor.jsm
|
||
|
+++ b/dom/manifest/ManifestProcessor.jsm
|
||
|
@@ -31,7 +31,7 @@ const imports = {};
|
||
|
Cu.import('resource://gre/modules/Services.jsm', imports);
|
||
|
Cu.importGlobalProperties(['URL']);
|
||
|
const securityManager = imports.Services.scriptSecurityManager;
|
||
|
-const netutil = Cc['@mozilla.org/network/util;1'].getService(Ci.nsINetUtil);
|
||
|
+const netutil = Cc['@mozilla.org/network/util;1'].getService(Ci.nsINetUtil_ESR_38);
|
||
|
const defaultDisplayMode = 'browser';
|
||
|
const displayModes = new Set([
|
||
|
'fullscreen',
|
||
|
@@ -258,7 +258,7 @@ this.ManifestProcessor.prototype.process = function({
|
||
|
};
|
||
|
let value = extractValue(obj),
|
||
|
isParsable = (typeof value === 'string' && value.length > 0);
|
||
|
- value = (isParsable) ? netutil.parseContentType(value.trim(), charset, hadCharset) : undefined;
|
||
|
+ value = (isParsable) ? netutil.parseRequestContentType(value.trim(), charset, hadCharset) : undefined;
|
||
|
return (value === '') ? undefined : value;
|
||
|
}
|
||
|
|
||
|
@@ -354,4 +354,4 @@ this.ManifestProcessor.prototype.process = function({
|
||
|
};
|
||
|
processedManifest.scope = processScopeMember(manifest, manifestURL, docURL, processedManifest.start_url);
|
||
|
return processedManifest;
|
||
|
-};
|
||
|
\ No newline at end of file
|
||
|
+};
|
||
|
diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build
|
||
|
index 877365b..deedf76 100644
|
||
|
--- a/netwerk/base/moz.build
|
||
|
+++ b/netwerk/base/moz.build
|
||
|
@@ -59,6 +59,7 @@ XPIDL_SOURCES += [
|
||
|
'nsINestedURI.idl',
|
||
|
'nsINetAddr.idl',
|
||
|
'nsINetUtil.idl',
|
||
|
+ 'nsINetUtil_ESR_38.idl',
|
||
|
'nsINetworkInterceptController.idl',
|
||
|
'nsINetworkLinkService.idl',
|
||
|
'nsINetworkPredictor.idl',
|
||
|
diff --git a/netwerk/base/nsINetUtil_ESR_38.idl b/netwerk/base/nsINetUtil_ESR_38.idl
|
||
|
new file mode 100644
|
||
|
index 0000000..7ef40e9
|
||
|
--- /dev/null
|
||
|
+++ b/netwerk/base/nsINetUtil_ESR_38.idl
|
||
|
@@ -0,0 +1,14 @@
|
||
|
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||
|
+/* This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||
|
+
|
||
|
+#include "nsISupports.idl"
|
||
|
+
|
||
|
+[scriptable, uuid(e82f2b9d-8bac-48bb-ade7-26a7cd4fb894)]
|
||
|
+interface nsINetUtil_ESR_38 : nsISupports
|
||
|
+{
|
||
|
+ AUTF8String parseRequestContentType(in AUTF8String aTypeHeader,
|
||
|
+ out AUTF8String aCharset,
|
||
|
+ out boolean aHadCharset);
|
||
|
+};
|
||
|
diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp
|
||
|
index 83db86f..9a17e8b 100644
|
||
|
--- a/netwerk/base/nsIOService.cpp
|
||
|
+++ b/netwerk/base/nsIOService.cpp
|
||
|
@@ -321,6 +321,7 @@ NS_IMPL_ISUPPORTS(nsIOService,
|
||
|
nsIIOService,
|
||
|
nsIIOService2,
|
||
|
nsINetUtil,
|
||
|
+ nsINetUtil_ESR_38,
|
||
|
nsISpeculativeConnect,
|
||
|
nsIObserver,
|
||
|
nsISupportsWeakReference)
|
||
|
@@ -1280,6 +1281,17 @@ nsIOService::Observe(nsISupports *subject,
|
||
|
|
||
|
// nsINetUtil interface
|
||
|
NS_IMETHODIMP
|
||
|
+nsIOService::ParseRequestContentType(const nsACString &aTypeHeader,
|
||
|
+ nsACString &aCharset,
|
||
|
+ bool *aHadCharset,
|
||
|
+ nsACString &aContentType)
|
||
|
+{
|
||
|
+ net_ParseRequestContentType(aTypeHeader, aContentType, aCharset, aHadCharset);
|
||
|
+ return NS_OK;
|
||
|
+}
|
||
|
+
|
||
|
+// nsINetUtil interface
|
||
|
+NS_IMETHODIMP
|
||
|
nsIOService::ParseContentType(const nsACString &aTypeHeader,
|
||
|
nsACString &aCharset,
|
||
|
bool *aHadCharset,
|
||
|
diff --git a/netwerk/base/nsIOService.h b/netwerk/base/nsIOService.h
|
||
|
index acd501c..b125709 100644
|
||
|
--- a/netwerk/base/nsIOService.h
|
||
|
+++ b/netwerk/base/nsIOService.h
|
||
|
@@ -14,6 +14,7 @@
|
||
|
#include "nsIObserver.h"
|
||
|
#include "nsWeakReference.h"
|
||
|
#include "nsINetUtil.h"
|
||
|
+#include "nsINetUtil_ESR_38.h"
|
||
|
#include "nsIChannelEventSink.h"
|
||
|
#include "nsCategoryCache.h"
|
||
|
#include "nsISpeculativeConnect.h"
|
||
|
@@ -47,6 +48,7 @@ namespace net {
|
||
|
class nsIOService final : public nsIIOService2
|
||
|
, public nsIObserver
|
||
|
, public nsINetUtil
|
||
|
+ , public nsINetUtil_ESR_38
|
||
|
, public nsISpeculativeConnect
|
||
|
, public nsSupportsWeakReference
|
||
|
{
|
||
|
@@ -56,6 +58,7 @@ public:
|
||
|
NS_DECL_NSIIOSERVICE2
|
||
|
NS_DECL_NSIOBSERVER
|
||
|
NS_DECL_NSINETUTIL
|
||
|
+ NS_DECL_NSINETUTIL_ESR_38
|
||
|
NS_DECL_NSISPECULATIVECONNECT
|
||
|
|
||
|
// Gets the singleton instance of the IO Service, creating it as needed
|
||
|
diff --git a/netwerk/base/nsNetUtil.h b/netwerk/base/nsNetUtil.h
|
||
|
index ec69716..df8874c 100644
|
||
|
--- a/netwerk/base/nsNetUtil.h
|
||
|
+++ b/netwerk/base/nsNetUtil.h
|
||
|
@@ -56,6 +56,7 @@
|
||
|
#include "nsISyncStreamListener.h"
|
||
|
#include "nsInterfaceRequestorAgg.h"
|
||
|
#include "nsINetUtil.h"
|
||
|
+#include "nsINetUtil_ESR_38.h"
|
||
|
#include "nsIURIWithPrincipal.h"
|
||
|
#include "nsIAuthPrompt.h"
|
||
|
#include "nsIAuthPrompt2.h"
|
||
|
@@ -1228,6 +1229,26 @@ NS_GetReferrerFromChannel(nsIChannel *channel,
|
||
|
}
|
||
|
|
||
|
inline nsresult
|
||
|
+NS_ParseRequestContentType(const nsACString &rawContentType,
|
||
|
+ nsCString &contentType,
|
||
|
+ nsCString &contentCharset)
|
||
|
+{
|
||
|
+ // contentCharset is left untouched if not present in rawContentType
|
||
|
+ nsresult rv;
|
||
|
+ nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
|
||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||
|
+ nsCOMPtr<nsINetUtil_ESR_38> utilESR38 = do_QueryInterface(util, &rv);
|
||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||
|
+ nsCString charset;
|
||
|
+ bool hadCharset;
|
||
|
+ rv = utilESR38->ParseRequestContentType(rawContentType, charset, &hadCharset,
|
||
|
+ contentType);
|
||
|
+ if (NS_SUCCEEDED(rv) && hadCharset)
|
||
|
+ contentCharset = charset;
|
||
|
+ return rv;
|
||
|
+}
|
||
|
+
|
||
|
+inline nsresult
|
||
|
NS_ParseContentType(const nsACString &rawContentType,
|
||
|
nsCString &contentType,
|
||
|
nsCString &contentCharset)
|
||
|
diff --git a/netwerk/base/nsURLHelper.cpp b/netwerk/base/nsURLHelper.cpp
|
||
|
index 10ea849..cdb2120 100644
|
||
|
--- a/netwerk/base/nsURLHelper.cpp
|
||
|
+++ b/netwerk/base/nsURLHelper.cpp
|
||
|
@@ -803,7 +803,8 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
|
||
|
int32_t aOffset,
|
||
|
bool *aHadCharset,
|
||
|
int32_t *aCharsetStart,
|
||
|
- int32_t *aCharsetEnd)
|
||
|
+ int32_t *aCharsetEnd,
|
||
|
+ bool aStrict)
|
||
|
{
|
||
|
const nsCString& flatStr = PromiseFlatCString(aMediaTypeStr);
|
||
|
const char* start = flatStr.get();
|
||
|
@@ -820,6 +821,8 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
|
||
|
int32_t charsetParamStart = 0;
|
||
|
int32_t charsetParamEnd = 0;
|
||
|
|
||
|
+ uint32_t consumed = typeEnd - type;
|
||
|
+
|
||
|
// Iterate over parameters
|
||
|
bool typeHasCharset = false;
|
||
|
uint32_t paramStart = flatStr.FindChar(';', typeEnd - start);
|
||
|
@@ -843,6 +846,7 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
|
||
|
charsetParamEnd = curParamEnd;
|
||
|
}
|
||
|
|
||
|
+ consumed = curParamEnd;
|
||
|
curParamStart = curParamEnd + 1;
|
||
|
} while (curParamStart < flatStr.Length());
|
||
|
}
|
||
|
@@ -872,8 +876,10 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
|
||
|
// some servers give junk after the charset parameter, which may
|
||
|
// include a comma, so this check makes us a bit more tolerant.
|
||
|
|
||
|
- if (type != typeEnd && strncmp(type, "*/*", typeEnd - type) != 0 &&
|
||
|
- memchr(type, '/', typeEnd - type) != nullptr) {
|
||
|
+ if (type != typeEnd &&
|
||
|
+ memchr(type, '/', typeEnd - type) != nullptr &&
|
||
|
+ (aStrict ? (net_FindCharNotInSet(start + consumed, end, HTTP_LWS) == end) :
|
||
|
+ (strncmp(type, "*/*", typeEnd - type) != 0))) {
|
||
|
// Common case here is that aContentType is empty
|
||
|
bool eq = !aContentType.IsEmpty() &&
|
||
|
aContentType.Equals(Substring(type, typeEnd),
|
||
|
@@ -980,13 +986,59 @@ net_ParseContentType(const nsACString &aHeaderStr,
|
||
|
net_ParseMediaType(Substring(flatStr, curTypeStart,
|
||
|
curTypeEnd - curTypeStart),
|
||
|
aContentType, aContentCharset, curTypeStart,
|
||
|
- aHadCharset, aCharsetStart, aCharsetEnd);
|
||
|
+ aHadCharset, aCharsetStart, aCharsetEnd, false);
|
||
|
|
||
|
// And let's move on to the next media-type
|
||
|
curTypeStart = curTypeEnd + 1;
|
||
|
} while (curTypeStart < flatStr.Length());
|
||
|
}
|
||
|
|
||
|
+void
|
||
|
+net_ParseRequestContentType(const nsACString &aHeaderStr,
|
||
|
+ nsACString &aContentType,
|
||
|
+ nsACString &aContentCharset,
|
||
|
+ bool *aHadCharset)
|
||
|
+{
|
||
|
+ //
|
||
|
+ // Augmented BNF (from RFC 7231 section 3.1.1.1):
|
||
|
+ //
|
||
|
+ // media-type = type "/" subtype *( OWS ";" OWS parameter )
|
||
|
+ // type = token
|
||
|
+ // subtype = token
|
||
|
+ // parameter = token "=" ( token / quoted-string )
|
||
|
+ //
|
||
|
+ // Examples:
|
||
|
+ //
|
||
|
+ // text/html
|
||
|
+ // text/html; charset=ISO-8859-1
|
||
|
+ // text/html; charset="ISO-8859-1"
|
||
|
+ // application/octet-stream
|
||
|
+ //
|
||
|
+
|
||
|
+ aContentType.Truncate();
|
||
|
+ aContentCharset.Truncate();
|
||
|
+ *aHadCharset = false;
|
||
|
+ const nsCString& flatStr = PromiseFlatCString(aHeaderStr);
|
||
|
+
|
||
|
+ // At this point curTypeEnd points to the spot where the media-type
|
||
|
+ // starting at curTypeEnd ends. Time to parse that!
|
||
|
+ nsAutoCString contentType, contentCharset;
|
||
|
+ bool hadCharset = false;
|
||
|
+ int32_t dummy1, dummy2;
|
||
|
+ uint32_t typeEnd = net_FindMediaDelimiter(flatStr, 0, ',');
|
||
|
+ if (typeEnd != flatStr.Length()) {
|
||
|
+ // We have some stuff left at the end, so this is not a valid
|
||
|
+ // request Content-Type header.
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ net_ParseMediaType(flatStr, contentType, contentCharset, 0,
|
||
|
+ &hadCharset, &dummy1, &dummy2, true);
|
||
|
+
|
||
|
+ aContentType = contentType;
|
||
|
+ aContentCharset = contentCharset;
|
||
|
+ *aHadCharset = hadCharset;
|
||
|
+}
|
||
|
+
|
||
|
bool
|
||
|
net_IsValidHostName(const nsCSubstring &host)
|
||
|
{
|
||
|
diff --git a/netwerk/base/nsURLHelper.h b/netwerk/base/nsURLHelper.h
|
||
|
index 816a3c5..21e17be 100644
|
||
|
--- a/netwerk/base/nsURLHelper.h
|
||
|
+++ b/netwerk/base/nsURLHelper.h
|
||
|
@@ -172,11 +172,27 @@ char * net_RFindCharNotInSet(const char *str, const char *end, const char *set);
|
||
|
* specified), aHadCharset is set to false. Otherwise, it's set to
|
||
|
* true. Note that aContentCharset can be empty even if aHadCharset
|
||
|
* is true.
|
||
|
+ *
|
||
|
+ * This parsing is suitable for HTTP request. Use net_ParseContentType
|
||
|
+ * for parsing this header in HTTP responses.
|
||
|
+ */
|
||
|
+void net_ParseRequestContentType(const nsACString &aHeaderStr,
|
||
|
+ nsACString &aContentType,
|
||
|
+ nsACString &aContentCharset,
|
||
|
+ bool* aHadCharset);
|
||
|
+
|
||
|
+/**
|
||
|
+ * Parses a content-type header and returns the content type and
|
||
|
+ * charset (if any). aCharset is not modified if no charset is
|
||
|
+ * specified in anywhere in aHeaderStr. In that case (no charset
|
||
|
+ * specified), aHadCharset is set to false. Otherwise, it's set to
|
||
|
+ * true. Note that aContentCharset can be empty even if aHadCharset
|
||
|
+ * is true.
|
||
|
*/
|
||
|
void net_ParseContentType(const nsACString &aHeaderStr,
|
||
|
- nsACString &aContentType,
|
||
|
- nsACString &aContentCharset,
|
||
|
- bool* aHadCharset);
|
||
|
+ nsACString &aContentType,
|
||
|
+ nsACString &aContentCharset,
|
||
|
+ bool* aHadCharset);
|
||
|
/**
|
||
|
* As above, but also returns the start and end indexes for the charset
|
||
|
* parameter in aHeaderStr. These are indices for the entire parameter, NOT
|
||
|
@@ -187,11 +203,11 @@ void net_ParseContentType(const nsACString &aHeaderStr,
|
||
|
* *aCharsetStart is nonnegative; this corresponds to charset="".
|
||
|
*/
|
||
|
void net_ParseContentType(const nsACString &aHeaderStr,
|
||
|
- nsACString &aContentType,
|
||
|
- nsACString &aContentCharset,
|
||
|
- bool *aHadCharset,
|
||
|
- int32_t *aCharsetStart,
|
||
|
- int32_t *aCharsetEnd);
|
||
|
+ nsACString &aContentType,
|
||
|
+ nsACString &aContentCharset,
|
||
|
+ bool *aHadCharset,
|
||
|
+ int32_t *aCharsetStart,
|
||
|
+ int32_t *aCharsetEnd);
|
||
|
|
||
|
/* inline versions */
|
||
|
|
||
|
--
|
||
|
2.5.0
|
||
|
|