Add JXR support to the browser

Can be enabled/disabled at runtime by toggling the 'media.jxr.enabled'
pref (disabled by default).

Two additional prefs are provided for testing purposes:
'media.jxr.autoaccept', and 'media.jxr.advertised_mime_type'
See comments in all.js for information on what these do.

This commit includes the MS OpenTech implementation of the decoder on
the browser side with some fixes applied; see the development in Pale
Moon GitGub issue #105 or my comments in the source code for more
information.
This commit is contained in:
rhinoduck
2017-02-08 07:08:08 +01:00
committed by roytam1
parent a34855657d
commit 7b7ccd5dce
13 changed files with 3224 additions and 0 deletions
+192
View File
@@ -1146,10 +1146,30 @@ nsresult imgLoader::Init()
{
InitCache();
#ifdef MOZ_JXR
nsAdoptingCString advertisedJxrMimeType = Preferences::GetCString(
"media.jxr.advertised_mime_type");
if (!advertisedJxrMimeType) {
mLastJxrMimeType = "";
} else {
advertisedJxrMimeType.Trim(" \t\n\v\f\r");
mLastJxrMimeType = advertisedJxrMimeType;
}
if (Preferences::GetBool("media.jxr.autoaccept", false)) {
UpdateJXRAcceptHeader(Preferences::GetBool("media.jxr.enabled", false));
}
Preferences::AddWeakObserver(this, "media.jxr.enabled");
Preferences::AddWeakObserver(this, "media.jxr.advertised_mime_type");
Preferences::AddWeakObserver(this, "media.jxr.autoaccept");
#endif
ReadAcceptHeaderPref();
Preferences::AddWeakObserver(this, "image.http.accept");
return NS_OK;
}
@@ -1168,6 +1188,20 @@ imgLoader::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aD
if (!NS_strcmp(aData, MOZ_UTF16("image.http.accept"))) {
ReadAcceptHeaderPref();
}
#ifdef MOZ_JXR
else if (!NS_strcmp(aData, MOZ_UTF16("media.jxr.enabled"))) {
if (Preferences::GetBool("media.jxr.autoaccept", false)) {
UpdateJXRAcceptHeader(Preferences::GetBool("media.jxr.enabled",
false));
}
} else if (!NS_strcmp(aData, MOZ_UTF16("media.jxr.advertised_mime_type"))) {
if (Preferences::GetBool("media.jxr.enabled", false) &&
Preferences::GetBool("media.jxr.autoaccept", false)) {
UpdateJXRAcceptHeader(false);
UpdateJXRAcceptHeader(true);
}
}
#endif
} else if (strcmp(aTopic, "memory-pressure") == 0) {
MinimizeCaches();
@@ -2397,6 +2431,164 @@ nsresult imgLoader::GetMimeTypeFromContent(const char* aContents, uint32_t aLeng
return NS_OK;
}
#ifdef MOZ_JXR
// In the Accept header passed in by the 'start' and 'end' pointers, finds a
// portion containing the first occurrence of the MIME type and retuns it as
// a pair of pointers in the subStart and subEnd out parameters. The returned
// span will also contain any paramters (HTTP term) the MIME type might have
// and a delimiter and surrounding whitespace so that it can directly be used
// to cut the MIME type information from the header field. In case of no match,
// *subEnd will be NULL.
void imgLoader::FindMIMETypeInAcceptHeader(const char* mimeType, char* start,
char* end, char** subStart, char** subEnd)
{
MOZ_ASSERT(mimeType);
MOZ_ASSERT(start);
MOZ_ASSERT(end);
MOZ_ASSERT(subStart);
MOZ_ASSERT(subEnd);
size_t mimeTypeLen = strlen(mimeType);
bool isEscaped = false;
bool inQuoted = false;
*subStart = NULL;
*subEnd = NULL;
for (char* current = start; current < end; ) {
// Only examine the header at points of interest.
if (current == start || *current++ == ',') {
*subStart = current;
while (current != end && isspace(*current)) {
++current;
}
if (size_t(end - current) < mimeTypeLen) {
break;
}
if (!strncmp(current, mimeType, mimeTypeLen)) {
current += mimeTypeLen;
while (current != end && isspace(*current)) {
++current;
}
// Also include parameters in the result if there are any present.
if (current != end && *current == ';') {
do {
if (*current == ',') {
if (!inQuoted) {
break;
}
} else if (*current == '"') {
if (!isEscaped) {
inQuoted = !inQuoted;
}
}
if (isEscaped) {
isEscaped = false;
} else if (*current == '\\') {
isEscaped = true;
}
} while (++current != end);
}
if (current != end && *current != ',') {
// These are not the droids you are looking for.
++current;
continue;
}
*subEnd = current;
// Also include the comma delimiter and surrounding whitespace to avoid
// accumulating it over time.
if (*subEnd != end) {
++*subEnd;
while (*subEnd != end && isspace(**subEnd)) {
++*subEnd;
}
} else if (*subStart != start) {
--*subStart;
while (*subStart != start && isspace(**subStart)) {
--*subStart;
}
}
break;
} // if strncmp
++current;
} // if start or comma
} // for
}
// Adds/removes the JPEG XR MIME type to/from the "image.http.accept" pref.
void imgLoader::UpdateJXRAcceptHeader(bool enabled)
{
nsAdoptingCString accept = Preferences::GetCString("image.http.accept");
if (!accept) {
return;
}
char* start = accept.BeginWriting();
char* end = accept.EndWriting();
char* subStart = NULL;
char* subEnd = NULL;
nsAdoptingCString jxrMimeType = Preferences::GetCString(
"media.jxr.advertised_mime_type");
if (enabled) { // Adding the MIME type.
if (!jxrMimeType) {
return;
}
jxrMimeType.Trim(" \t\n\v\f\r");
if (jxrMimeType.IsEmpty()) {
return;
}
mLastJxrMimeType = jxrMimeType;
FindMIMETypeInAcceptHeader(jxrMimeType.get(), start, end,
&subStart, &subEnd);
if (subEnd) {
// MIME type already present.
return;
}
// Try inserting after the WebP MIME type to have a canonical header if
// possible. If this fails, the JPEG XR MIME type will be "aggressively"
// inserted at the beginning.
FindMIMETypeInAcceptHeader("image/webp", start, end, &subStart, &subEnd);
if (subEnd) {
if (subEnd == end) {
accept.Insert(NS_LITERAL_CSTRING(",") + jxrMimeType, subEnd - start);
} else {
accept.Insert(jxrMimeType + NS_LITERAL_CSTRING(","), subEnd - start);
}
} else {
subStart = start;
while (subStart != end && isspace(*subStart)) {
++subStart;
}
if (subStart == end) {
accept.Insert(jxrMimeType, 0);
} else {
accept.Insert(jxrMimeType + NS_LITERAL_CSTRING(","), 0);
}
}
} else { // Removing the MIME type.
if (mLastJxrMimeType.IsEmpty()) {
return;
}
FindMIMETypeInAcceptHeader(mLastJxrMimeType.get(), start, end,
&subStart, &subEnd);
if (!subEnd) {
return;
}
accept.Cut(subStart - start, subEnd - subStart);
}
Preferences::SetCString("image.http.accept", accept);
}
#endif // MOZ_JXR
/**
* proxy stream listener class used to handle multipart/x-mixed-replace
*/