Merge the last PGO-green inbound changeset to m-c.

This commit is contained in:
Ryan VanderMeulen 2012-11-08 19:52:11 -05:00
commit be3c66b5a5
184 changed files with 3421 additions and 930 deletions

View File

@ -9,7 +9,12 @@
<?xml-stylesheet href="chrome://browser/content/downloads/downloads.css"?>
<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css"?>
<!DOCTYPE overlay SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
<!DOCTYPE overlay [
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
%browserDTD;
<!ENTITY % downloadsDTD SYSTEM "chrome://browser/locale/downloads/downloads.dtd" >
%downloadsDTD;
]>
<overlay xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
@ -23,7 +28,7 @@
toolbar handling code could remove it from the document. -->
<toolbarbutton id="downloads-indicator"
class="toolbarbutton-1 chromeclass-toolbar-additional"
tooltiptext="&indicator.tooltiptext;"
tooltiptext="&downloads.tooltip;"
collapsed="true"
oncommand="DownloadsIndicatorView.onCommand(event);"
ondrop="DownloadsIndicatorView.onDrop(event);"

View File

@ -14,6 +14,7 @@ include $(DEPTH)/config/autoconf.mk
# browser_526613.js is disabled because of frequent failures (bug 534489)
# browser_589246.js is disabled for leaking browser windows (bug 752467)
# browser_580512.js is disabled for leaking browser windows (bug 752467)
# browser_586068-reload.js is disabled due to generally being broken (bug 809123, 797263)
MOCHITEST_BROWSER_FILES = \
head.js \
@ -88,7 +89,6 @@ MOCHITEST_BROWSER_FILES = \
browser_586068-browser_state_interrupted.js \
browser_586068-cascade.js \
browser_586068-multi_window.js \
browser_586068-reload.js \
browser_586068-select.js \
browser_586068-window_state.js \
browser_586068-window_state_override.js \

View File

@ -2,11 +2,6 @@
- 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/. -->
<!-- LOCALIZATION NOTE (indicator.tooltiptext):
Tooltip for the indicator that displays the progress of ongoing downloads.
-->
<!ENTITY indicator.tooltiptext "Downloads">
<!-- LOCALIZATION NOTE (downloads.title):
Used by screen readers to describe the Downloads Panel.
-->

View File

@ -160,37 +160,53 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
/*** Status and progress indicator ***/
#downloads-indicator {
width: 35px;
}
#downloads-indicator-anchor {
min-width: 18px;
min-height: 18px;
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
position: relative;
}
toolbar[iconsize="small"] #downloads-indicator-anchor {
min-width: 16px;
min-height: 16px;
}
toolbar[iconsize="large"] #downloads-indicator-anchor {
min-width: 24px;
min-height: 24px;
}
/*** Main indicator icon ***/
#downloads-indicator-icon {
toolbar[iconsize="small"] #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
0, 16, 16, 0) center no-repeat;
}
toolbar[iconsize="large"] #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 24, 24, 0) center no-repeat;
}
#downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/downloads/download-glow.png"),
16, 32, 32, 16) center no-repeat;
}
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
toolbar[iconsize="small"] #downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
0, 16, 16, 0) center no-repeat;
background-size: 12px;
}
toolbar[iconsize="large"] #downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 24, 24, 0) center no-repeat;
background-size: 24px;
}
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/downloads/download-glow.png"),
16, 32, 32, 16);

View File

@ -157,10 +157,6 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
/*** Status and progress indicator ***/
#downloads-indicator {
width: 35px;
}
#downloads-indicator-anchor {
min-width: 20px;
min-height: 20px;

View File

@ -159,13 +159,7 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
/*** Status and progress indicator ***/
#downloads-indicator {
width: 35px;
}
#downloads-indicator-anchor {
min-width: 18px;
min-height: 18px;
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
@ -177,6 +171,8 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
#downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 108, 18, 90) center no-repeat;
min-width: 18px;
min-height: 18px;
}
#downloads-indicator-icon:-moz-lwtheme-brighttext {

View File

@ -243,8 +243,17 @@ case "$target" in
android_platform_tools="$android_sdk"/tools # SDK Tools < r8
fi
ANDROID_SDK="${android_sdk}"
if test -e "${android_sdk}/../../extras/android/compatibility/v4/android-support-v4.jar" ; then
ANDROID_COMPAT_LIB="${android_sdk}/../../extras/android/compatibility/v4/android-support-v4.jar"
else
ANDROID_COMPAT_LIB="${android_sdk}/../../extras/android/support/v4/android-support-v4.jar";
fi
ANDROID_PLATFORM_TOOLS="${android_platform_tools}"
AC_SUBST(ANDROID_SDK)
AC_SUBST(ANDROID_COMPAT_LIB)
if ! test -e $ANDROID_COMPAT_LIB ; then
AC_MSG_ERROR([You must download the andrioid compatibility library when targeting Android. (found $ANDROID_COMPAT_LIB)])
fi
AC_SUBST(ANDROID_PLATFORM_TOOLS)
;;
esac

View File

@ -93,7 +93,7 @@ classes.dex: $(_JAVA_HARNESS)
classes.dex: $(_JAVA_TESTS)
$(NSINSTALL) -D classes
$(JAVAC) $(JAVAC_FLAGS) -d classes $(JAVAFILES) $(_JAVA_HARNESS) $(addprefix $(DEPTH)/mobile/android/base/tests/,$(_JAVA_TESTS))
$(DX) --dex --output=$@ classes $(ROBOTIUM_PATH)
$(DX) --dex --output=$@ classes $(ROBOTIUM_PATH) $(ANDROID_COMPT_LIB)
robocop.ap_: AndroidManifest.xml $(TESTPATH)/assets/*
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -A $(TESTPATH)/assets -F $@ -J ./

View File

@ -4,12 +4,13 @@
package com.mozilla.SUTAgentAndroid.service;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.util.Timer;
import java.io.IOException;
import java.net.InetAddress;
import com.mozilla.SUTAgentAndroid.SUTAgentAndroid;
import com.mozilla.SUTAgentAndroid.R;
@ -39,6 +40,7 @@ public class ASMozStub extends android.app.Service {
RunDataThread runDataThrd = null;
Thread monitor = null;
Timer timer = null;
boolean doZeroConfig = false;
@SuppressWarnings("unchecked")
private static final Class<?>[] mSetForegroundSignature = new Class[] {
@ -178,14 +180,24 @@ public class ASMozStub extends android.app.Service {
runDataThrd.start();
doToast(String.format("Data channel port %d ...", DATA_PORT));
startZeroConf();
DoCommand tmpdc = new DoCommand(getApplication());
File dir = getFilesDir();
File iniFile = new File(dir, "SUTAgent.ini");
String sIniFile = iniFile.getAbsolutePath();
String zeroconf = tmpdc.GetIniData("General", "ZeroConfig", sIniFile);
if (zeroconf != "" && Integer.parseInt(zeroconf) == 1) {
this.doZeroConfig = true;
}
if (this.doZeroConfig) {
startZeroConf();
}
Notification notification = new Notification();
startForegroundCompat(R.string.foreground_service_started, notification);
}
catch (Exception e) {
doToast(e.toString());
// Toast.makeText(getApplication().getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
}
return;
@ -195,7 +207,9 @@ public class ASMozStub extends android.app.Service {
{
super.onDestroy();
stopZeroConf();
if (this.doZeroConfig) {
stopZeroConf();
}
if (runCmdThrd.isAlive())
{

View File

@ -8,11 +8,14 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
@ -46,6 +49,8 @@ import android.os.Environment;
public class WatcherService extends Service
{
private final String prgVersion = "Watcher Version 1.15";
String sErrorPrefix = "##Installer Error## ";
String currentDir = "/";
String sPingTarget = "";
@ -53,6 +58,7 @@ public class WatcherService extends Service
long lPeriod = 300000;
int nMaxStrikes = 0; // maximum number of tries before we consider network unreachable (0 means don't check)
boolean bStartSUTAgent = true;
boolean bStartedTimer = false;
Process pProc;
Context myContext = null;
@ -217,9 +223,13 @@ public class WatcherService extends Service
}
else if (sCmd.equalsIgnoreCase("start"))
{
doToast("WatcherService started");
myTimer = new Timer();
myTimer.scheduleAtFixedRate(new MyTime(), lDelay, lPeriod);
if (!this.bStartedTimer) {
doToast("WatcherService started");
myTimer = new Timer();
Date startSchedule = new Date(System.currentTimeMillis() + lDelay);
myTimer.schedule(new MyTime(), startSchedule, lPeriod);
this.bStartedTimer = true;
}
}
else
{
@ -230,15 +240,33 @@ public class WatcherService extends Service
doToast("WatcherService created");
}
public void writeVersion() {
PrintWriter pw = null;
String appPath = getApplicationContext().getFilesDir().getAbsolutePath();
String versionPath = appPath + "/version.txt";
Log.i("Watcher", "writing version string to: " + versionPath);
try {
pw = new PrintWriter(new FileWriter(versionPath, true));
pw.println(this.prgVersion);
} catch (IOException ioe) {
Log.e("Watcher", "Exception writing version: " + this.prgVersion + " to file: " + versionPath);
} finally {
if (pw != null) {
pw.close();
}
}
}
@Override
public void onStart(Intent intent, int startId) {
writeVersion();
handleCommand(intent);
return;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
writeVersion();
handleCommand(intent);
return START_STICKY;
}

View File

@ -23,7 +23,7 @@ endif
# For Android, this defaults to $(ANDROID_SDK)/android.jar
ifndef JAVA_BOOTCLASSPATH
JAVA_BOOTCLASSPATH = $(ANDROID_SDK)/android.jar
JAVA_BOOTCLASSPATH = $(ANDROID_SDK)/android.jar:$(ANDROID_COMPAT_LIB)
endif
# For Android, we default to 1.5

View File

@ -42,7 +42,7 @@ nsReferencedElement.h \
nsTreeSanitizer.h \
nsXMLNameSpaceMap.h \
nsIXFormsUtilityService.h \
nsBlobProtocolHandler.h \
nsHostObjectProtocolHandler.h \
$(NULL)
EXPORTS_NAMESPACES = mozilla/dom mozilla

View File

@ -1,51 +0,0 @@
/* 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/. */
#ifndef nsBlobProtocolHandler_h
#define nsBlobProtocolHandler_h
#include "nsIProtocolHandler.h"
#include "nsIURI.h"
#include "nsCOMPtr.h"
#define BLOBURI_SCHEME "blob"
class nsIDOMBlob;
class nsIPrincipal;
class nsIInputStream;
inline bool IsBlobURI(nsIURI* aUri)
{
bool isBlob;
return NS_SUCCEEDED(aUri->SchemeIs(BLOBURI_SCHEME, &isBlob)) && isBlob;
}
extern nsresult
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream);
class nsBlobProtocolHandler : public nsIProtocolHandler
{
public:
NS_DECL_ISUPPORTS
// nsIProtocolHandler methods:
NS_DECL_NSIPROTOCOLHANDLER
// nsBlobProtocolHandler methods:
nsBlobProtocolHandler() {}
virtual ~nsBlobProtocolHandler() {}
// Methods for managing uri->file mapping
static void AddFileDataEntry(nsACString& aUri,
nsIDOMBlob* aFile,
nsIPrincipal* aPrincipal);
static void RemoveFileDataEntry(nsACString& aUri);
static nsIPrincipal* GetFileDataEntryPrincipal(nsACString& aUri);
};
#define NS_BLOBPROTOCOLHANDLER_CID \
{ 0xb43964aa, 0xa078, 0x44b2, \
{ 0xb0, 0x6b, 0xfd, 0x4d, 0x1b, 0x17, 0x2e, 0x66 } }
#endif /* nsBlobProtocolHandler_h */

View File

@ -0,0 +1,81 @@
/* 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/. */
#ifndef nsHostObjectProtocolHandler_h
#define nsHostObjectProtocolHandler_h
#include "nsIProtocolHandler.h"
#include "nsIURI.h"
#include "nsCOMPtr.h"
#define BLOBURI_SCHEME "blob"
#define MEDIASTREAMURI_SCHEME "mediastream"
class nsIDOMBlob;
class nsIDOMMediaStream;
class nsIPrincipal;
class nsIInputStream;
class nsHostObjectProtocolHandler : public nsIProtocolHandler
{
public:
NS_DECL_ISUPPORTS
// nsIProtocolHandler methods, except for GetScheme which is only defined
// in subclasses.
NS_IMETHOD GetDefaultPort(int32_t *aDefaultPort);
NS_IMETHOD GetProtocolFlags(uint32_t *aProtocolFlags);
NS_IMETHOD NewURI(const nsACString & aSpec, const char * aOriginCharset, nsIURI *aBaseURI, nsIURI * *_retval);
NS_IMETHOD NewChannel(nsIURI *aURI, nsIChannel * *_retval);
NS_IMETHOD AllowPort(int32_t port, const char * scheme, bool *_retval);
// Methods for managing uri->object mapping
// AddDataEntry creates the URI with the given scheme and returns it in aUri
static nsresult AddDataEntry(const nsACString& aScheme,
nsISupports* aObject,
nsIPrincipal* aPrincipal,
nsACString& aUri);
static void RemoveDataEntry(const nsACString& aUri);
static nsIPrincipal* GetDataEntryPrincipal(const nsACString& aUri);
};
class nsBlobProtocolHandler : public nsHostObjectProtocolHandler
{
public:
NS_IMETHOD GetScheme(nsACString &result);
};
class nsMediaStreamProtocolHandler : public nsHostObjectProtocolHandler
{
public:
NS_IMETHOD GetScheme(nsACString &result);
};
inline bool IsBlobURI(nsIURI* aUri)
{
bool isBlob;
return NS_SUCCEEDED(aUri->SchemeIs(BLOBURI_SCHEME, &isBlob)) && isBlob;
}
inline bool IsMediaStreamURI(nsIURI* aUri)
{
bool isStream;
return NS_SUCCEEDED(aUri->SchemeIs(MEDIASTREAMURI_SCHEME, &isStream)) && isStream;
}
extern nsresult
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream);
extern nsresult
NS_GetStreamForMediaStreamURI(nsIURI* aURI, nsIDOMMediaStream** aStream);
#define NS_BLOBPROTOCOLHANDLER_CID \
{ 0xb43964aa, 0xa078, 0x44b2, \
{ 0xb0, 0x6b, 0xfd, 0x4d, 0x1b, 0x17, 0x2e, 0x66 } }
#define NS_MEDIASTREAMPROTOCOLHANDLER_CID \
{ 0x27d1fa24, 0x2b73, 0x4db3, \
{ 0xab, 0x48, 0xb9, 0x83, 0x83, 0x40, 0xe0, 0x81 } }
#endif /* nsHostObjectProtocolHandler_h */

View File

@ -79,8 +79,8 @@ class Element;
} // namespace mozilla
#define NS_IDOCUMENT_IID \
{ 0x0e1324c9, 0xc997, 0x447e, \
{ 0xbc, 0xd9, 0xa6, 0x57, 0x80, 0x29, 0x91, 0xe4 } }
{ 0x20d19edb, 0xa74c, 0x4ce4, \
{ 0xb2, 0x7c, 0x5b, 0xdd, 0x6f, 0xbd, 0x2b, 0x66 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -1557,13 +1557,13 @@ public:
virtual nsISupports* GetCurrentContentSink() = 0;
/**
* Register/Unregister a filedata uri as being "owned" by this document.
* Register/Unregister a hostobject uri as being "owned" by this document.
* I.e. that its lifetime is connected with this document. When the document
* goes away it should "kill" the uri by calling
* nsBlobProtocolHandler::RemoveFileDataEntry
* nsHostObjectProtocolHandler::RemoveDataEntry
*/
virtual void RegisterFileDataUri(const nsACString& aUri) = 0;
virtual void UnregisterFileDataUri(const nsACString& aUri) = 0;
virtual void RegisterHostObjectUri(const nsACString& aUri) = 0;
virtual void UnregisterHostObjectUri(const nsACString& aUri) = 0;
virtual void SetScrollToRef(nsIURI *aDocumentURI) = 0;
virtual void ScrollToRef() = 0;

View File

@ -127,8 +127,8 @@ CPPSRCS = \
nsXMLNameSpaceMap.cpp \
FragmentOrElement.cpp \
Link.cpp \
nsBlobProtocolHandler.cpp \
nsBlobURI.cpp \
nsHostObjectProtocolHandler.cpp \
nsHostObjectURI.cpp \
nsFrameMessageManager.cpp \
nsInProcessTabChildGlobal.cpp \
ThirdPartyUtil.cpp \

View File

@ -1,217 +0,0 @@
/* 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 "nsBlobProtocolHandler.h"
#include "nsBlobURI.h"
#include "nsError.h"
#include "nsClassHashtable.h"
#include "nsNetUtil.h"
#include "nsIPrincipal.h"
#include "nsIDOMFile.h"
// -----------------------------------------------------------------------
// Hash table
struct FileDataInfo
{
nsCOMPtr<nsIDOMBlob> mFile;
nsCOMPtr<nsIPrincipal> mPrincipal;
};
static nsClassHashtable<nsCStringHashKey, FileDataInfo>* gFileDataTable;
void
nsBlobProtocolHandler::AddFileDataEntry(nsACString& aUri,
nsIDOMBlob* aFile,
nsIPrincipal* aPrincipal)
{
if (!gFileDataTable) {
gFileDataTable = new nsClassHashtable<nsCStringHashKey, FileDataInfo>;
gFileDataTable->Init();
}
FileDataInfo* info = new FileDataInfo;
info->mFile = aFile;
info->mPrincipal = aPrincipal;
gFileDataTable->Put(aUri, info);
}
void
nsBlobProtocolHandler::RemoveFileDataEntry(nsACString& aUri)
{
if (gFileDataTable) {
gFileDataTable->Remove(aUri);
if (gFileDataTable->Count() == 0) {
delete gFileDataTable;
gFileDataTable = nullptr;
}
}
}
nsIPrincipal*
nsBlobProtocolHandler::GetFileDataEntryPrincipal(nsACString& aUri)
{
if (!gFileDataTable) {
return nullptr;
}
FileDataInfo* res;
gFileDataTable->Get(aUri, &res);
if (!res) {
return nullptr;
}
return res->mPrincipal;
}
static FileDataInfo*
GetFileDataInfo(const nsACString& aUri)
{
NS_ASSERTION(StringBeginsWith(aUri,
NS_LITERAL_CSTRING(BLOBURI_SCHEME ":")),
"Bad URI");
if (!gFileDataTable) {
return nullptr;
}
FileDataInfo* res;
gFileDataTable->Get(aUri, &res);
return res;
}
// -----------------------------------------------------------------------
// Protocol handler
NS_IMPL_ISUPPORTS1(nsBlobProtocolHandler, nsIProtocolHandler)
NS_IMETHODIMP
nsBlobProtocolHandler::GetScheme(nsACString &result)
{
result.AssignLiteral(BLOBURI_SCHEME);
return NS_OK;
}
NS_IMETHODIMP
nsBlobProtocolHandler::GetDefaultPort(int32_t *result)
{
*result = -1;
return NS_OK;
}
NS_IMETHODIMP
nsBlobProtocolHandler::GetProtocolFlags(uint32_t *result)
{
*result = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_SUBSUMERS |
URI_IS_LOCAL_RESOURCE | URI_NON_PERSISTABLE;
return NS_OK;
}
NS_IMETHODIMP
nsBlobProtocolHandler::NewURI(const nsACString& aSpec,
const char *aCharset,
nsIURI *aBaseURI,
nsIURI **aResult)
{
*aResult = nullptr;
nsresult rv;
FileDataInfo* info =
GetFileDataInfo(aSpec);
nsRefPtr<nsBlobURI> uri =
new nsBlobURI(info ? info->mPrincipal.get() : nullptr);
rv = uri->SetSpec(aSpec);
NS_ENSURE_SUCCESS(rv, rv);
NS_TryToSetImmutable(uri);
uri.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsBlobProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
{
*result = nullptr;
nsCString spec;
uri->GetSpec(spec);
FileDataInfo* info =
GetFileDataInfo(spec);
if (!info) {
return NS_ERROR_DOM_BAD_URI;
}
#ifdef DEBUG
{
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(uri);
nsCOMPtr<nsIPrincipal> principal;
uriPrinc->GetPrincipal(getter_AddRefs(principal));
NS_ASSERTION(info->mPrincipal == principal, "Wrong principal!");
}
#endif
nsCOMPtr<nsIInputStream> stream;
nsresult rv = info->mFile->GetInternalStream(getter_AddRefs(stream));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIChannel> channel;
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
uri,
stream);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal);
nsAutoString type;
rv = info->mFile->GetType(type);
NS_ENSURE_SUCCESS(rv, rv);
uint64_t size;
rv = info->mFile->GetSize(&size);
NS_ENSURE_SUCCESS(rv, rv);
channel->SetOwner(owner);
channel->SetOriginalURI(uri);
channel->SetContentType(NS_ConvertUTF16toUTF8(type));
channel->SetContentLength(size);
channel.forget(result);
return NS_OK;
}
NS_IMETHODIMP
nsBlobProtocolHandler::AllowPort(int32_t port, const char *scheme,
bool *_retval)
{
// don't override anything.
*_retval = false;
return NS_OK;
}
nsresult
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
{
NS_ASSERTION(IsBlobURI(aURI), "Only call this with blob URIs");
*aStream = nullptr;
nsCString spec;
aURI->GetSpec(spec);
FileDataInfo* info =
GetFileDataInfo(spec);
if (!info) {
return NS_ERROR_DOM_BAD_URI;
}
return info->mFile->GetInternalStream(aStream);
}

View File

@ -27,7 +27,7 @@
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsIUUIDGenerator.h"
#include "nsBlobProtocolHandler.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsStringStream.h"
#include "nsJSUtils.h"
#include "nsPrintfCString.h"
@ -284,26 +284,15 @@ nsDOMFileBase::GetInternalUrl(nsIPrincipal* aPrincipal, nsAString& aURL)
{
NS_ENSURE_STATE(aPrincipal);
nsresult rv;
nsCOMPtr<nsIUUIDGenerator> uuidgen =
do_GetService("@mozilla.org/uuid-generator;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsID id;
rv = uuidgen->GenerateUUIDInPlace(&id);
NS_ENSURE_SUCCESS(rv, rv);
char chars[NSID_LENGTH];
id.ToProvidedString(chars);
nsCString url = NS_LITERAL_CSTRING(BLOBURI_SCHEME ":") +
Substring(chars + 1, chars + NSID_LENGTH - 2);
nsBlobProtocolHandler::AddFileDataEntry(url, this,
aPrincipal);
nsCString url;
nsresult rv = nsBlobProtocolHandler::AddDataEntry(
NS_LITERAL_CSTRING(BLOBURI_SCHEME),
static_cast<nsIDOMBlob*>(this), aPrincipal, url);
if (NS_FAILED(rv)) {
return rv;
}
CopyASCIItoUTF16(url, aURL);
return NS_OK;
}
@ -859,6 +848,6 @@ nsDOMFileInternalUrlHolder::~nsDOMFileInternalUrlHolder() {
if (!mUrl.IsEmpty()) {
nsAutoCString narrowUrl;
CopyUTF16toUTF8(mUrl, narrowUrl);
nsBlobProtocolHandler::RemoveFileDataEntry(narrowUrl);
nsBlobProtocolHandler::RemoveDataEntry(narrowUrl);
}
}

View File

@ -38,7 +38,7 @@
#include "nsCycleCollectionParticipant.h"
#include "nsLayoutStatics.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsBlobProtocolHandler.h"
#include "nsHostObjectProtocolHandler.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/EncodingUtils.h"
#include "xpcpublic.h"

View File

@ -107,7 +107,7 @@
#include "nsIDOMHTMLFormElement.h"
#include "nsIRequest.h"
#include "nsILink.h"
#include "nsBlobProtocolHandler.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsCharsetAlias.h"
#include "nsCharsetSource.h"
@ -1445,8 +1445,8 @@ nsDocument::~nsDocument()
mPendingTitleChangeEvent.Revoke();
for (uint32_t i = 0; i < mFileDataUris.Length(); ++i) {
nsBlobProtocolHandler::RemoveFileDataEntry(mFileDataUris[i]);
for (uint32_t i = 0; i < mHostObjectURIs.Length(); ++i) {
nsHostObjectProtocolHandler::RemoveDataEntry(mHostObjectURIs[i]);
}
// We don't want to leave residual locks on images. Make sure we're in an
@ -7595,15 +7595,15 @@ nsDocument::GetCurrentContentSink()
}
void
nsDocument::RegisterFileDataUri(const nsACString& aUri)
nsDocument::RegisterHostObjectUri(const nsACString& aUri)
{
mFileDataUris.AppendElement(aUri);
mHostObjectURIs.AppendElement(aUri);
}
void
nsDocument::UnregisterFileDataUri(const nsACString& aUri)
nsDocument::UnregisterHostObjectUri(const nsACString& aUri)
{
mFileDataUris.RemoveElement(aUri);
mHostObjectURIs.RemoveElement(aUri);
}
void

View File

@ -839,7 +839,7 @@ public:
virtual NS_HIDDEN_(void)
EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData);
nsTArray<nsCString> mFileDataUris;
nsTArray<nsCString> mHostObjectURIs;
// Returns our (lazily-initialized) animation controller.
// If HasAnimationController is true, this is guaranteed to return non-null.
@ -891,8 +891,8 @@ public:
virtual nsEventStates GetDocumentState();
virtual void RegisterFileDataUri(const nsACString& aUri);
virtual void UnregisterFileDataUri(const nsACString& aUri);
virtual void RegisterHostObjectUri(const nsACString& aUri);
virtual void UnregisterHostObjectUri(const nsACString& aUri);
// Only BlockOnload should call this!
void AsyncBlockOnload();

View File

@ -0,0 +1,264 @@
/* 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 "nsHostObjectProtocolHandler.h"
#include "nsHostObjectURI.h"
#include "nsError.h"
#include "nsClassHashtable.h"
#include "nsNetUtil.h"
#include "nsIPrincipal.h"
#include "nsIDOMFile.h"
#include "nsIDOMMediaStream.h"
// -----------------------------------------------------------------------
// Hash table
struct DataInfo
{
// mObject must be an nsIDOMBlob or an nsIDOMMediaStream
nsCOMPtr<nsISupports> mObject;
nsCOMPtr<nsIPrincipal> mPrincipal;
};
static nsClassHashtable<nsCStringHashKey, DataInfo>* gDataTable;
nsresult
nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme,
nsISupports* aObject,
nsIPrincipal* aPrincipal,
nsACString& aUri)
{
nsresult rv;
nsCOMPtr<nsIUUIDGenerator> uuidgen =
do_GetService("@mozilla.org/uuid-generator;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsID id;
rv = uuidgen->GenerateUUIDInPlace(&id);
NS_ENSURE_SUCCESS(rv, rv);
char chars[NSID_LENGTH];
id.ToProvidedString(chars);
aUri += aScheme;
aUri += NS_LITERAL_CSTRING(":");
aUri += Substring(chars + 1, chars + NSID_LENGTH - 2);
if (!gDataTable) {
gDataTable = new nsClassHashtable<nsCStringHashKey, DataInfo>;
gDataTable->Init();
}
DataInfo* info = new DataInfo;
info->mObject = aObject;
info->mPrincipal = aPrincipal;
gDataTable->Put(aUri, info);
return NS_OK;
}
void
nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri)
{
if (gDataTable) {
gDataTable->Remove(aUri);
if (gDataTable->Count() == 0) {
delete gDataTable;
gDataTable = nullptr;
}
}
}
nsIPrincipal*
nsHostObjectProtocolHandler::GetDataEntryPrincipal(const nsACString& aUri)
{
if (!gDataTable) {
return nullptr;
}
DataInfo* res;
gDataTable->Get(aUri, &res);
if (!res) {
return nullptr;
}
return res->mPrincipal;
}
static DataInfo*
GetDataInfo(const nsACString& aUri)
{
if (!gDataTable) {
return nullptr;
}
DataInfo* res;
gDataTable->Get(aUri, &res);
return res;
}
static nsISupports*
GetDataObject(nsIURI* aURI)
{
nsCString spec;
aURI->GetSpec(spec);
DataInfo* info = GetDataInfo(spec);
return info ? info->mObject : nullptr;
}
// -----------------------------------------------------------------------
// Protocol handler
NS_IMPL_ISUPPORTS1(nsHostObjectProtocolHandler, nsIProtocolHandler)
NS_IMETHODIMP
nsHostObjectProtocolHandler::GetDefaultPort(int32_t *result)
{
*result = -1;
return NS_OK;
}
NS_IMETHODIMP
nsHostObjectProtocolHandler::GetProtocolFlags(uint32_t *result)
{
*result = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_SUBSUMERS |
URI_IS_LOCAL_RESOURCE | URI_NON_PERSISTABLE;
return NS_OK;
}
NS_IMETHODIMP
nsHostObjectProtocolHandler::NewURI(const nsACString& aSpec,
const char *aCharset,
nsIURI *aBaseURI,
nsIURI **aResult)
{
*aResult = nullptr;
nsresult rv;
DataInfo* info = GetDataInfo(aSpec);
nsRefPtr<nsHostObjectURI> uri =
new nsHostObjectURI(info ? info->mPrincipal.get() : nullptr);
rv = uri->SetSpec(aSpec);
NS_ENSURE_SUCCESS(rv, rv);
NS_TryToSetImmutable(uri);
uri.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
{
*result = nullptr;
nsCString spec;
uri->GetSpec(spec);
DataInfo* info = GetDataInfo(spec);
if (!info) {
return NS_ERROR_DOM_BAD_URI;
}
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(info->mObject);
if (!blob) {
return NS_ERROR_DOM_BAD_URI;
}
#ifdef DEBUG
{
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(uri);
nsCOMPtr<nsIPrincipal> principal;
uriPrinc->GetPrincipal(getter_AddRefs(principal));
NS_ASSERTION(info->mPrincipal == principal, "Wrong principal!");
}
#endif
nsCOMPtr<nsIInputStream> stream;
nsresult rv = blob->GetInternalStream(getter_AddRefs(stream));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIChannel> channel;
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
uri,
stream);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal);
nsAutoString type;
rv = blob->GetType(type);
NS_ENSURE_SUCCESS(rv, rv);
uint64_t size;
rv = blob->GetSize(&size);
NS_ENSURE_SUCCESS(rv, rv);
channel->SetOwner(owner);
channel->SetOriginalURI(uri);
channel->SetContentType(NS_ConvertUTF16toUTF8(type));
channel->SetContentLength(size);
channel.forget(result);
return NS_OK;
}
NS_IMETHODIMP
nsHostObjectProtocolHandler::AllowPort(int32_t port, const char *scheme,
bool *_retval)
{
// don't override anything.
*_retval = false;
return NS_OK;
}
NS_IMETHODIMP
nsBlobProtocolHandler::GetScheme(nsACString &result)
{
result.AssignLiteral(BLOBURI_SCHEME);
return NS_OK;
}
NS_IMETHODIMP
nsMediaStreamProtocolHandler::GetScheme(nsACString &result)
{
result.AssignLiteral(MEDIASTREAMURI_SCHEME);
return NS_OK;
}
nsresult
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
{
NS_ASSERTION(IsBlobURI(aURI), "Only call this with blob URIs");
*aStream = nullptr;
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(GetDataObject(aURI));
if (!blob) {
return NS_ERROR_DOM_BAD_URI;
}
return blob->GetInternalStream(aStream);
}
nsresult
NS_GetStreamForMediaStreamURI(nsIURI* aURI, nsIDOMMediaStream** aStream)
{
NS_ASSERTION(IsMediaStreamURI(aURI), "Only call this with mediastream URIs");
*aStream = nullptr;
nsCOMPtr<nsIDOMMediaStream> stream = do_QueryInterface(GetDataObject(aURI));
if (!stream) {
return NS_ERROR_DOM_BAD_URI;
}
*aStream = stream;
NS_ADDREF(*aStream);
return NS_OK;
}

View File

@ -2,24 +2,24 @@
* 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 "nsBlobURI.h"
#include "nsHostObjectURI.h"
#include "nsAutoPtr.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsIProgrammingLanguage.h"
static NS_DEFINE_CID(kBLOBURICID, NS_BLOBURI_CID);
static NS_DEFINE_CID(kHOSTOBJECTURICID, NS_HOSTOBJECTURI_CID);
static NS_DEFINE_CID(kThisSimpleURIImplementationCID,
NS_THIS_SIMPLEURI_IMPLEMENTATION_CID);
NS_IMPL_ADDREF_INHERITED(nsBlobURI, nsSimpleURI)
NS_IMPL_RELEASE_INHERITED(nsBlobURI, nsSimpleURI)
NS_IMPL_ADDREF_INHERITED(nsHostObjectURI, nsSimpleURI)
NS_IMPL_RELEASE_INHERITED(nsHostObjectURI, nsSimpleURI)
NS_INTERFACE_MAP_BEGIN(nsBlobURI)
NS_INTERFACE_MAP_BEGIN(nsHostObjectURI)
NS_INTERFACE_MAP_ENTRY(nsIURIWithPrincipal)
if (aIID.Equals(kBLOBURICID))
if (aIID.Equals(kHOSTOBJECTURICID))
foundInterface = static_cast<nsIURI*>(this);
else if (aIID.Equals(kThisSimpleURIImplementationCID)) {
// Need to return explicitly here, because if we just set foundInterface
@ -34,7 +34,7 @@ NS_INTERFACE_MAP_END_INHERITING(nsSimpleURI)
// nsIURIWithPrincipal methods:
NS_IMETHODIMP
nsBlobURI::GetPrincipal(nsIPrincipal** aPrincipal)
nsHostObjectURI::GetPrincipal(nsIPrincipal** aPrincipal)
{
NS_IF_ADDREF(*aPrincipal = mPrincipal);
@ -42,7 +42,7 @@ nsBlobURI::GetPrincipal(nsIPrincipal** aPrincipal)
}
NS_IMETHODIMP
nsBlobURI::GetPrincipalUri(nsIURI** aUri)
nsHostObjectURI::GetPrincipalUri(nsIURI** aUri)
{
if (mPrincipal) {
mPrincipal->GetURI(aUri);
@ -57,7 +57,7 @@ nsBlobURI::GetPrincipalUri(nsIURI** aUri)
// nsISerializable methods:
NS_IMETHODIMP
nsBlobURI::Read(nsIObjectInputStream* aStream)
nsHostObjectURI::Read(nsIObjectInputStream* aStream)
{
nsresult rv = nsSimpleURI::Read(aStream);
NS_ENSURE_SUCCESS(rv, rv);
@ -66,7 +66,7 @@ nsBlobURI::Read(nsIObjectInputStream* aStream)
}
NS_IMETHODIMP
nsBlobURI::Write(nsIObjectOutputStream* aStream)
nsHostObjectURI::Write(nsIObjectOutputStream* aStream)
{
nsresult rv = nsSimpleURI::Write(aStream);
NS_ENSURE_SUCCESS(rv, rv);
@ -78,8 +78,8 @@ nsBlobURI::Write(nsIObjectOutputStream* aStream)
// nsIURI methods:
nsresult
nsBlobURI::CloneInternal(nsSimpleURI::RefHandlingEnum aRefHandlingMode,
nsIURI** aClone)
nsHostObjectURI::CloneInternal(nsSimpleURI::RefHandlingEnum aRefHandlingMode,
nsIURI** aClone)
{
nsCOMPtr<nsIURI> simpleClone;
nsresult rv =
@ -87,56 +87,56 @@ nsBlobURI::CloneInternal(nsSimpleURI::RefHandlingEnum aRefHandlingMode,
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
nsRefPtr<nsBlobURI> uriCheck;
rv = simpleClone->QueryInterface(kBLOBURICID, getter_AddRefs(uriCheck));
nsRefPtr<nsHostObjectURI> uriCheck;
rv = simpleClone->QueryInterface(kHOSTOBJECTURICID, getter_AddRefs(uriCheck));
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) && uriCheck,
"Unexpected!");
#endif
nsBlobURI* blobURI = static_cast<nsBlobURI*>(simpleClone.get());
nsHostObjectURI* u = static_cast<nsHostObjectURI*>(simpleClone.get());
blobURI->mPrincipal = mPrincipal;
u->mPrincipal = mPrincipal;
simpleClone.forget(aClone);
return NS_OK;
}
/* virtual */ nsresult
nsBlobURI::EqualsInternal(nsIURI* aOther,
nsSimpleURI::RefHandlingEnum aRefHandlingMode,
bool* aResult)
nsHostObjectURI::EqualsInternal(nsIURI* aOther,
nsSimpleURI::RefHandlingEnum aRefHandlingMode,
bool* aResult)
{
if (!aOther) {
*aResult = false;
return NS_OK;
}
nsRefPtr<nsBlobURI> otherBlobUri;
aOther->QueryInterface(kBLOBURICID, getter_AddRefs(otherBlobUri));
if (!otherBlobUri) {
nsRefPtr<nsHostObjectURI> otherUri;
aOther->QueryInterface(kHOSTOBJECTURICID, getter_AddRefs(otherUri));
if (!otherUri) {
*aResult = false;
return NS_OK;
}
// Compare the member data that our base class knows about.
if (!nsSimpleURI::EqualsInternal(otherBlobUri, aRefHandlingMode)) {
if (!nsSimpleURI::EqualsInternal(otherUri, aRefHandlingMode)) {
*aResult = false;
return NS_OK;
}
}
// Compare the piece of additional member data that we add to base class.
if (mPrincipal && otherBlobUri->mPrincipal) {
if (mPrincipal && otherUri->mPrincipal) {
// Both of us have mPrincipals. Compare them.
return mPrincipal->Equals(otherBlobUri->mPrincipal, aResult);
return mPrincipal->Equals(otherUri->mPrincipal, aResult);
}
// else, at least one of us lacks a principal; only equal if *both* lack it.
*aResult = (!mPrincipal && !otherBlobUri->mPrincipal);
*aResult = (!mPrincipal && !otherUri->mPrincipal);
return NS_OK;
}
// nsIClassInfo methods:
NS_IMETHODIMP
nsBlobURI::GetInterfaces(uint32_t *count, nsIID * **array)
nsHostObjectURI::GetInterfaces(uint32_t *count, nsIID * **array)
{
*count = 0;
*array = nullptr;
@ -144,14 +144,14 @@ nsBlobURI::GetInterfaces(uint32_t *count, nsIID * **array)
}
NS_IMETHODIMP
nsBlobURI::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
nsHostObjectURI::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
{
*_retval = nullptr;
return NS_OK;
}
NS_IMETHODIMP
nsBlobURI::GetContractID(char * *aContractID)
nsHostObjectURI::GetContractID(char * *aContractID)
{
// Make sure to modify any subclasses as needed if this ever
// changes.
@ -160,14 +160,14 @@ nsBlobURI::GetContractID(char * *aContractID)
}
NS_IMETHODIMP
nsBlobURI::GetClassDescription(char * *aClassDescription)
nsHostObjectURI::GetClassDescription(char * *aClassDescription)
{
*aClassDescription = nullptr;
return NS_OK;
}
NS_IMETHODIMP
nsBlobURI::GetClassID(nsCID * *aClassID)
nsHostObjectURI::GetClassID(nsCID * *aClassID)
{
// Make sure to modify any subclasses as needed if this ever
// changes to not call the virtual GetClassIDNoAlloc.
@ -178,22 +178,22 @@ nsBlobURI::GetClassID(nsCID * *aClassID)
}
NS_IMETHODIMP
nsBlobURI::GetImplementationLanguage(uint32_t *aImplementationLanguage)
nsHostObjectURI::GetImplementationLanguage(uint32_t *aImplementationLanguage)
{
*aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
return NS_OK;
}
NS_IMETHODIMP
nsBlobURI::GetFlags(uint32_t *aFlags)
nsHostObjectURI::GetFlags(uint32_t *aFlags)
{
*aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
return NS_OK;
}
NS_IMETHODIMP
nsBlobURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
nsHostObjectURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
{
*aClassIDNoAlloc = kBLOBURICID;
*aClassIDNoAlloc = kHOSTOBJECTURICID;
return NS_OK;
}

View File

@ -2,8 +2,8 @@
* 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/. */
#ifndef nsBlobURI_h
#define nsBlobURI_h
#ifndef nsHostObjectURI_h
#define nsHostObjectURI_h
#include "nsCOMPtr.h"
#include "nsIClassInfo.h"
@ -12,17 +12,21 @@
#include "nsIURIWithPrincipal.h"
#include "nsSimpleURI.h"
class nsBlobURI : public nsSimpleURI,
public nsIURIWithPrincipal
/**
* These URIs refer to host objects: Blobs, with scheme "blob", and
* MediaStreams, with scheme "mediastream".
*/
class nsHostObjectURI : public nsSimpleURI,
public nsIURIWithPrincipal
{
public:
nsBlobURI(nsIPrincipal* aPrincipal) :
nsHostObjectURI(nsIPrincipal* aPrincipal) :
nsSimpleURI(), mPrincipal(aPrincipal)
{}
virtual ~nsBlobURI() {}
virtual ~nsHostObjectURI() {}
// For use only from deserialization
nsBlobURI() : nsSimpleURI() {}
nsHostObjectURI() : nsSimpleURI() {}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIURIWITHPRINCIPAL
@ -36,15 +40,15 @@ public:
RefHandlingEnum aRefHandlingMode,
bool* aResult);
// Override StartClone to hand back a nsBlobURI
// Override StartClone to hand back a nsHostObjectURI
virtual nsSimpleURI* StartClone(RefHandlingEnum /* unused */)
{ return new nsBlobURI(); }
{ return new nsHostObjectURI(); }
nsCOMPtr<nsIPrincipal> mPrincipal;
};
#define NS_BLOBURI_CID \
#define NS_HOSTOBJECTURI_CID \
{ 0xf5475c51, 0x59a7, 0x4757, \
{ 0xb3, 0xd9, 0xe2, 0x11, 0xa9, 0x41, 0x08, 0x72 } }
#endif /* nsBlobURI_h */
#endif /* nsHostObjectURI_h */

View File

@ -429,9 +429,9 @@ protected:
void SetPlayedOrSeeked(bool aValue);
/**
* Initialize the media element for playback of mSrcAttrStream
* Initialize the media element for playback of aStream
*/
void SetupSrcMediaStreamPlayback();
void SetupSrcMediaStreamPlayback(nsDOMMediaStream* aStream);
/**
* Stop playback on mSrcStream.
*/

View File

@ -64,6 +64,7 @@
#include "MediaStreamGraph.h"
#include "nsDOMMediaStream.h"
#include "nsIScriptError.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsCSSParser.h"
#include "nsIMediaList.h"
@ -758,7 +759,7 @@ void nsHTMLMediaElement::SelectResource()
// If we have a 'src' attribute, use that exclusively.
nsAutoString src;
if (mSrcAttrStream) {
SetupSrcMediaStreamPlayback();
SetupSrcMediaStreamPlayback(mSrcAttrStream);
} else if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
nsCOMPtr<nsIURI> uri;
nsresult rv = NewURIFromString(src, getter_AddRefs(uri));
@ -766,6 +767,7 @@ void nsHTMLMediaElement::SelectResource()
LOG(PR_LOG_DEBUG, ("%p Trying load from src=%s", this, NS_ConvertUTF16toUTF8(src).get()));
NS_ASSERTION(!mIsLoadingFromSourceChildren,
"Should think we're not loading from source children by default");
mLoadingSrc = uri;
if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
// preload:none media, suspend the load here before we make any
@ -1035,7 +1037,7 @@ nsresult nsHTMLMediaElement::LoadResource()
mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
nsHTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc);
if (other) {
if (other && other->mDecoder) {
// Clone it.
nsresult rv = InitializeDecoderAsClone(other->mDecoder);
// Get the mimetype from the element we clone, since we will not get it via
@ -1062,6 +1064,21 @@ nsresult nsHTMLMediaElement::LoadResource()
return NS_ERROR_FAILURE;
}
if (IsMediaStreamURI(mLoadingSrc)) {
nsCOMPtr<nsIDOMMediaStream> stream;
rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, getter_AddRefs(stream));
if (NS_FAILED(rv)) {
nsCString specUTF8;
mLoadingSrc->GetSpec(specUTF8);
NS_ConvertUTF8toUTF16 spec(specUTF8);
const PRUnichar* params[] = { spec.get() };
ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
return rv;
}
SetupSrcMediaStreamPlayback(static_cast<nsDOMMediaStream*>(stream.get()));
return NS_OK;
}
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
// check for a Content Security Policy to pass down to the channel
@ -2765,11 +2782,11 @@ private:
bool mDidHaveCurrentData;
};
void nsHTMLMediaElement::SetupSrcMediaStreamPlayback()
void nsHTMLMediaElement::SetupSrcMediaStreamPlayback(nsDOMMediaStream* aStream)
{
NS_ASSERTION(!mSrcStream && !mSrcStreamListener, "Should have been ended already");
mSrcStream = mSrcAttrStream;
mSrcStream = aStream;
// XXX if we ever support capturing the output of a media element which is
// playing a stream, we'll need to add a CombineWithPrincipal call here.
mSrcStreamListener = new StreamListener(this);

View File

@ -28,7 +28,7 @@
#include "nsIAsyncVerifyRedirectCallback.h"
#include "mozilla/Util.h" // for DebugOnly
#include "nsContentUtils.h"
#include "nsBlobProtocolHandler.h"
#include "nsHostObjectProtocolHandler.h"
#ifdef PR_LOGGING
PRLogModuleInfo* gMediaResourceLog;

View File

@ -138,6 +138,7 @@ ifneq ($(OS_ARCH), WINNT)
MOCHITEST_FILES += \
test_streams_element_capture.html \
test_streams_element_capture_reset.html \
test_streams_element_capture_createObjectURL.html \
test_timeupdate_small_files.html \
$(NULL)
else

View File

@ -0,0 +1,62 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test that a MediaStream captured from one element plays back in another</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
var manager = new MediaTestManager;
function checkDrawImage(vout) {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.drawImage(vout, 0, 0);
var imgData = ctx.getImageData(0, 0, 1, 1);
is(imgData.data[3], 255, "Check video frame pixel has been drawn");
}
function startTest(test, token) {
manager.started(token);
var v = document.createElement('video');
var vout = document.createElement('video');
vout.token = token;
v.src = test.name;
var stream = v.mozCaptureStreamUntilEnded();
is(stream.currentTime, 0, test.name + " stream initial currentTime");
vout.src = URL.createObjectURL(stream);
var checkEnded = function(test, vout, stream) { return function() {
is(stream.currentTime, vout.currentTime, test.name + " stream final currentTime");
if (test.duration) {
ok(Math.abs(vout.currentTime - test.duration) < 0.1,
test.name + " current time at end: " + vout.currentTime + " should be: " + test.duration);
}
is(vout.readyState, vout.HAVE_CURRENT_DATA, test.name + " checking readyState");
ok(vout.ended, test.name + " checking playback has ended");
if (test.type.match(/^video/)) {
checkDrawImage(vout);
}
vout.parentNode.removeChild(vout);
URL.revokeObjectURL(vout.src);
manager.finished(vout.token);
}}(test, vout, stream);
vout.addEventListener("ended", checkEnded, false);
document.body.appendChild(vout);
v.play();
vout.play();
}
manager.runTests([getPlayableVideo(gSmallTests)], startTest);
</script>
</pre>
</body>
</html>

View File

@ -17,6 +17,7 @@
#include "PannerNode.h"
#include "AudioListener.h"
#include "DynamicsCompressorNode.h"
#include "BiquadFilterNode.h"
namespace mozilla {
namespace dom {
@ -124,6 +125,14 @@ AudioContext::CreateDynamicsCompressor()
return compressorNode.forget();
}
already_AddRefed<BiquadFilterNode>
AudioContext::CreateBiquadFilter()
{
nsRefPtr<BiquadFilterNode> filterNode =
new BiquadFilterNode(this);
return filterNode.forget();
}
AudioListener*
AudioContext::Listener()
{

View File

@ -27,6 +27,7 @@ class AudioBuffer;
class AudioBufferSourceNode;
class AudioDestinationNode;
class AudioListener;
class BiquadFilterNode;
class DelayNode;
class DynamicsCompressorNode;
class GainNode;
@ -80,6 +81,9 @@ public:
already_AddRefed<DynamicsCompressorNode>
CreateDynamicsCompressor();
already_AddRefed<BiquadFilterNode>
CreateBiquadFilter();
private:
nsCOMPtr<nsIDOMWindow> mWindow;
nsRefPtr<AudioDestinationNode> mDestination;

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "BiquadFilterNode.h"
#include "mozilla/dom/BiquadFilterNodeBinding.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(BiquadFilterNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BiquadFilterNode, AudioNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFrequency)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mQ)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGain)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BiquadFilterNode, AudioNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->mFrequency, AudioParam, "frequency value")
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->mQ, AudioParam, "Q value")
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->mGain, AudioParam, "gain value")
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BiquadFilterNode)
NS_INTERFACE_MAP_END_INHERITING(AudioNode)
NS_IMPL_ADDREF_INHERITED(BiquadFilterNode, AudioNode)
NS_IMPL_RELEASE_INHERITED(BiquadFilterNode, AudioNode)
static float
Nyquist(AudioContext* aContext)
{
// TODO: Replace the hardcoded 44100 here with AudioContext::SampleRate()
// when we implement that.
return 0.5f * 44100;
}
BiquadFilterNode::BiquadFilterNode(AudioContext* aContext)
: AudioNode(aContext)
, mType(BiquadTypeEnum::LOWPASS)
, mFrequency(new AudioParam(aContext, 350.f, 10.f, Nyquist(aContext)))
, mQ(new AudioParam(aContext, 1.f, 0.0001f, 1000.f))
, mGain(new AudioParam(aContext, 0.f, -40.f, 40.f))
{
}
JSObject*
BiquadFilterNode::WrapObject(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap)
{
return BiquadFilterNodeBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
}
}

View File

@ -0,0 +1,92 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef BiquadFilterNode_h_
#define BiquadFilterNode_h_
#include "AudioNode.h"
#include "AudioParam.h"
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
namespace mozilla {
namespace dom {
class AudioContext;
MOZ_BEGIN_ENUM_CLASS(BiquadTypeEnum, uint16_t)
LOWPASS = 0,
HIGHPASS = 1,
BANDPASS = 2,
LOWSHELF = 3,
HIGHSHELF = 4,
PEAKING = 5,
NOTCH = 6,
ALLPASS = 7,
Max = 7
MOZ_END_ENUM_CLASS(BiquadTypeEnum)
class BiquadFilterNode : public AudioNode
{
public:
explicit BiquadFilterNode(AudioContext* aContext);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BiquadFilterNode, AudioNode)
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap);
virtual uint32_t MaxNumberOfInputs() const MOZ_FINAL MOZ_OVERRIDE
{
return 1;
}
virtual uint32_t MaxNumberOfOutputs() const MOZ_FINAL MOZ_OVERRIDE
{
return 1;
}
uint16_t Type() const
{
return static_cast<uint16_t> (mType);
}
void SetType(uint16_t aType, ErrorResult& aRv)
{
BiquadTypeEnum type = static_cast<BiquadTypeEnum> (aType);
if (type > BiquadTypeEnum::Max) {
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
} else {
mType = type;
}
}
AudioParam* Frequency() const
{
return mFrequency;
}
AudioParam* Q() const
{
return mQ;
}
AudioParam* Gain() const
{
return mGain;
}
private:
BiquadTypeEnum mType;
nsRefPtr<AudioParam> mFrequency;
nsRefPtr<AudioParam> mQ;
nsRefPtr<AudioParam> mGain;
};
}
}
#endif

View File

@ -23,6 +23,7 @@ CPPSRCS := \
AudioNode.cpp \
AudioParam.cpp \
AudioSourceNode.cpp \
BiquadFilterNode.cpp \
DelayNode.cpp \
DynamicsCompressorNode.cpp \
EnableWebAudioCheck.cpp \
@ -39,6 +40,7 @@ EXPORTS_mozilla/dom := \
AudioNode.h \
AudioParam.h \
AudioSourceNode.h \
BiquadFilterNode.h \
DelayNode.h \
DynamicsCompressorNode.h \
GainNode.h \

View File

@ -11,11 +11,13 @@ relativesrcdir := @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
MOCHITEST_FILES := \
webaudio.js \
test_bug808374.html \
test_AudioBuffer.html \
test_AudioContext.html \
test_AudioListener.html \
test_badConnect.html \
test_biquadFilterNode.html \
test_delayNode.html \
test_dynamicsCompressorNode.html \
test_gainNode.html \

View File

@ -7,20 +7,9 @@
</head>
<body>
<pre id="test">
<script src="webaudio.js" type="text/javascript"></script>
<script class="testbody" type="text/javascript">
function expectException(func, exceptionCode) {
var threw = false;
try {
func();
} catch (ex) {
threw = true;
ok(ex instanceof DOMException, "Expect a DOM exception");
ok(ex.code, exceptionCode, "Expect the correct exception code");
}
ok(threw, "The exception was thrown");
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.setBoolPref("media.webaudio.enabled", true);

View File

@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test BiquadFilterNode</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script src="webaudio.js" type="text/javascript"></script>
<script class="testbody" type="text/javascript">
function near(a, b, msg) {
ok(Math.abs(a - b) < 1e-3, msg);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
var context = new mozAudioContext();
var buffer = context.createBuffer(1, 2048, 44100);
for (var i = 0; i < 2048; ++i) {
buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / 44100);
}
var destination = context.destination;
var source = context.createBufferSource();
var filter = context.createBiquadFilter();
source.buffer = buffer;
source.connect(filter);
filter.connect(destination);
// Verify default values
is(filter.type, 0, "Correct default value for type");
near(filter.frequency.minValue, 10, "Correct min value for filter frequency");
near(filter.frequency.maxValue, 22050, "Correct max value for filter frequency");
near(filter.frequency.defaultValue, 350, "Correct default value for filter frequency");
near(filter.Q.minValue, 0.001, "Correct min value for filter Q");
near(filter.Q.maxValue, 1000, "Correct max value for filter Q");
near(filter.Q.defaultValue, 1, "Correct default value for filter Q");
near(filter.gain.minValue, -40, "Correct min value for filter gain");
near(filter.gain.maxValue, 40, "Correct max value for filter gain");
near(filter.gain.defaultValue, 0, "Correct default value for filter gain");
// Make sure that we can set all of the valid type values
for (var i = 0; i <= 7; ++i) {
filter.type = i;
}
expectException(function() {
filter.type = 8;
}, DOMException.INDEX_SIZE_ERR);
source.start(0);
SimpleTest.executeSoon(function() {
source.stop(0);
source.disconnect();
filter.disconnect();
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
});
});
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,14 @@
// Helpers for Web Audio tests
function expectException(func, exceptionCode) {
var threw = false;
try {
func();
} catch (ex) {
threw = true;
ok(ex instanceof DOMException, "Expect a DOM exception");
ok(ex.code, exceptionCode, "Expect the correct exception code");
}
ok(threw, "The exception was thrown");
}

View File

@ -84,6 +84,7 @@ EXPORTS_mozilla/dom = \
DOMRequest.h \
StructuredCloneTags.h \
ScreenOrientation.h \
URL.h \
$(NULL)
CPPSRCS = \
@ -115,6 +116,7 @@ CPPSRCS = \
DOMError.cpp \
DOMRequest.cpp \
Navigator.cpp \
URL.cpp \
$(NULL)
include $(topsrcdir)/dom/dom-config.mk

101
dom/base/URL.cpp Normal file
View File

@ -0,0 +1,101 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "URL.h"
#include "nsGlobalWindow.h"
#include "nsIDOMFile.h"
#include "nsIDOMMediaStream.h"
#include "nsIDocument.h"
#include "nsIPrincipal.h"
#include "nsContentUtils.h"
#include "nsHostObjectProtocolHandler.h"
namespace mozilla {
namespace dom {
void
URL::CreateObjectURL(nsISupports* aGlobal, nsIDOMBlob* aBlob,
const objectURLOptions& aOptions,
nsAString& aResult,
ErrorResult& aError)
{
CreateObjectURLInternal(aGlobal, aBlob, NS_LITERAL_CSTRING(BLOBURI_SCHEME),
aOptions, aResult, aError);
}
void
URL::CreateObjectURL(nsISupports* aGlobal, nsIDOMMediaStream* aStream,
const mozilla::dom::objectURLOptions& aOptions,
nsAString& aResult,
ErrorResult& aError)
{
CreateObjectURLInternal(aGlobal, aStream, NS_LITERAL_CSTRING(MEDIASTREAMURI_SCHEME),
aOptions, aResult, aError);
}
void
URL::CreateObjectURLInternal(nsISupports* aGlobal, nsISupports* aObject,
const nsACString& aScheme,
const mozilla::dom::objectURLOptions& aOptions,
nsAString& aResult,
ErrorResult& aError)
{
nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal);
nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
NS_PRECONDITION(!window || window->IsInnerWindow(),
"Should be inner window");
if (!window || !window->GetExtantDoc()) {
aError.Throw(NS_ERROR_INVALID_POINTER);
return;
}
nsIDocument* doc = window->GetExtantDoc();
nsCString url;
nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(aScheme, aObject,
doc->NodePrincipal(), url);
if (NS_FAILED(rv)) {
aError.Throw(rv);
return;
}
doc->RegisterHostObjectUri(url);
CopyASCIItoUTF16(url, aResult);
}
void
URL::RevokeObjectURL(nsISupports* aGlobal, const nsAString& aURL)
{
nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal);
nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
NS_PRECONDITION(!window || window->IsInnerWindow(),
"Should be inner window");
if (!window)
return;
NS_LossyConvertUTF16toASCII asciiurl(aURL);
nsIPrincipal* winPrincipal = window->GetPrincipal();
if (!winPrincipal) {
return;
}
nsIPrincipal* principal =
nsHostObjectProtocolHandler::GetDataEntryPrincipal(asciiurl);
bool subsumes;
if (principal && winPrincipal &&
NS_SUCCEEDED(winPrincipal->Subsumes(principal, &subsumes)) &&
subsumes) {
if (window->GetExtantDoc()) {
window->GetExtantDoc()->UnregisterHostObjectUri(asciiurl);
}
nsHostObjectProtocolHandler::RemoveDataEntry(asciiurl);
}
}
}
}

42
dom/base/URL.h Normal file
View File

@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef URL_h___
#define URL_h___
#include "nscore.h"
#include "mozilla/dom/URLBinding.h"
class nsIDOMBlob;
class nsIDOMMediaStream;
namespace mozilla {
namespace dom {
class URL MOZ_FINAL
{
public:
// WebIDL methods
static void CreateObjectURL(nsISupports* aGlobal, nsIDOMBlob* aBlob,
const objectURLOptions& aOptions,
nsAString& aResult,
ErrorResult& aError);
static void CreateObjectURL(nsISupports* aGlobal, nsIDOMMediaStream* aStream,
const mozilla::dom::objectURLOptions& aOptions,
nsAString& aResult,
mozilla::ErrorResult& aError);
static void RevokeObjectURL(nsISupports* aGlobal, const nsAString& aURL);
private:
static void CreateObjectURLInternal(nsISupports* aGlobal, nsISupports* aObject,
const nsACString& aScheme,
const mozilla::dom::objectURLOptions& aOptions,
nsAString& aResult,
mozilla::ErrorResult& aError);
};
}
}
#endif /* URL_h___ */

View File

@ -1434,8 +1434,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(ArchiveRequest, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozURLProperty, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH,
DEFAULT_SCRIPTABLE_FLAGS |
@ -4008,10 +4006,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMRequest)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozURLProperty, nsIDOMMozURLProperty)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozURLProperty)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
DOM_CLASSINFO_WINDOW_MAP_ENTRIES(nsGlobalWindow::HasIndexedDBSupport())
DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow)
@ -6683,6 +6677,14 @@ ConstructorEnabled(const nsGlobalNameStruct *aStruct, nsGlobalWindow *aWin)
}
}
// Don't expose ArchiveReader unless user has explicitly enabled it
if (aStruct->mDOMClassInfoID == eDOMClassInfo_ArchiveReader_id ||
aStruct->mDOMClassInfoID == eDOMClassInfo_ArchiveRequest_id) {
if (!dom::file::ArchiveReader::PrefEnabled()) {
return false;
}
}
return true;
}

View File

@ -366,7 +366,6 @@ DOMCI_CLASS(File)
DOMCI_CLASS(FileReader)
DOMCI_CLASS(ArchiveReader)
DOMCI_CLASS(ArchiveRequest)
DOMCI_CLASS(MozURLProperty)
// DOM modal content window class, almost identical to Window
DOMCI_CLASS(ModalContentWindow)

View File

@ -148,7 +148,6 @@
#include "nsAutoPtr.h"
#include "nsContentUtils.h"
#include "nsCSSProps.h"
#include "nsBlobProtocolHandler.h"
#include "nsIDOMFile.h"
#include "nsIDOMFileList.h"
#include "nsIURIFixup.h"
@ -422,85 +421,6 @@ static const char sPopStatePrefStr[] = "browser.history.allowPopState";
#define NETWORK_UPLOAD_EVENT_NAME NS_LITERAL_STRING("moznetworkupload")
#define NETWORK_DOWNLOAD_EVENT_NAME NS_LITERAL_STRING("moznetworkdownload")
/**
* An object implementing the window.URL property.
*/
class nsDOMMozURLProperty MOZ_FINAL : public nsIDOMMozURLProperty
{
public:
nsDOMMozURLProperty(nsGlobalWindow* aWindow)
: mWindow(aWindow)
{
}
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMMOZURLPROPERTY
void ClearWindowReference() {
mWindow = nullptr;
}
private:
nsGlobalWindow* mWindow;
};
DOMCI_DATA(MozURLProperty, nsDOMMozURLProperty)
NS_IMPL_ADDREF(nsDOMMozURLProperty)
NS_IMPL_RELEASE(nsDOMMozURLProperty)
NS_INTERFACE_MAP_BEGIN(nsDOMMozURLProperty)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozURLProperty)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozURLProperty)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozURLProperty)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsDOMMozURLProperty::CreateObjectURL(nsIDOMBlob* aBlob, nsAString& aURL)
{
NS_PRECONDITION(!mWindow || mWindow->IsInnerWindow(),
"Should be inner window");
NS_ENSURE_STATE(mWindow && mWindow->mDoc);
NS_ENSURE_ARG_POINTER(aBlob);
nsIDocument* doc = mWindow->mDoc;
nsresult rv = aBlob->GetInternalUrl(doc->NodePrincipal(), aURL);
NS_ENSURE_SUCCESS(rv, rv);
doc->RegisterFileDataUri(NS_LossyConvertUTF16toASCII(aURL));
return NS_OK;
}
NS_IMETHODIMP
nsDOMMozURLProperty::RevokeObjectURL(const nsAString& aURL)
{
NS_PRECONDITION(!mWindow || mWindow->IsInnerWindow(),
"Should be inner window");
NS_ENSURE_STATE(mWindow);
NS_LossyConvertUTF16toASCII asciiurl(aURL);
nsIPrincipal* winPrincipal = mWindow->GetPrincipal();
if (!winPrincipal) {
return NS_OK;
}
nsIPrincipal* principal =
nsBlobProtocolHandler::GetFileDataEntryPrincipal(asciiurl);
bool subsumes;
if (principal && winPrincipal &&
NS_SUCCEEDED(winPrincipal->Subsumes(principal, &subsumes)) &&
subsumes) {
if (mWindow->mDoc) {
mWindow->mDoc->UnregisterFileDataUri(asciiurl);
}
nsBlobProtocolHandler::RemoveFileDataEntry(asciiurl);
}
return NS_OK;
}
/**
* An indirect observer object that means we don't have to implement nsIObserver
* on nsGlobalWindow, where any script could see it.
@ -533,6 +453,14 @@ private:
NS_IMPL_ISUPPORTS2(nsGlobalWindowObserver, nsIObserver, nsIInterfaceRequestor)
nsTimeout::nsTimeout()
: mCleared(false),
mRunning(false),
mIsInterval(false),
mPublicId(0),
mInterval(0),
mFiringDepth(0),
mNestingLevel(0),
mPopupState(openAllowed)
{
#ifdef DEBUG_jst
{
@ -542,8 +470,6 @@ nsTimeout::nsTimeout()
}
#endif
memset(this, 0, sizeof(*this));
MOZ_COUNT_CTOR(nsTimeout);
}
@ -723,9 +649,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
// Initialize the PRCList (this).
PR_INIT_CLIST(this);
// Initialize timeout storage
PR_INIT_CLIST(&mTimeouts);
if (aOuterWindow) {
// |this| is an inner window, add this inner window to the outer
// window list of inners.
@ -928,10 +851,6 @@ nsGlobalWindow::~nsGlobalWindow()
nsCycleCollector_DEBUG_wasFreed(static_cast<nsIScriptGlobalObject*>(this));
#endif
if (mURLProperty) {
mURLProperty->ClearWindowReference();
}
nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
if (ac)
ac->RemoveWindowAsListener(this);
@ -1319,9 +1238,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
nsEventListenerManager)
for (nsTimeout* timeout = tmp->FirstTimeout();
tmp->IsTimeout(timeout);
timeout = timeout->Next()) {
for (nsTimeout* timeout = tmp->mTimeouts.getFirst();
timeout;
timeout = timeout->getNext()) {
cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(nsTimeout));
}
@ -1426,9 +1345,9 @@ nsGlobalWindow::IsBlackForCC()
void
nsGlobalWindow::UnmarkGrayTimers()
{
for (nsTimeout* timeout = FirstTimeout();
timeout && IsTimeout(timeout);
timeout = timeout->Next()) {
for (nsTimeout* timeout = mTimeouts.getFirst();
timeout;
timeout = timeout->getNext()) {
if (timeout->mScriptHandler) {
JSObject* o = timeout->mScriptHandler->GetScriptObject();
xpc_UnmarkGrayObject(o);
@ -2318,8 +2237,7 @@ nsGlobalWindow::DetachFromDocShell()
// (mJSObject) so that it can be retrieved later (until it is
// finalized by the JS GC).
NS_ASSERTION(PR_CLIST_IS_EMPTY(&mTimeouts),
"Uh, outer window holds timeouts!");
NS_ASSERTION(mTimeouts.isEmpty(), "Uh, outer window holds timeouts!");
// Call FreeInnerObjects on all inner windows, not just the current
// one, since some could be held by WindowStateHolder objects that
@ -9906,7 +9824,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
// timeout events fire "early", so we need to test the timer as well
// as the deadline.
last_expired_timeout = nullptr;
for (timeout = FirstTimeout(); IsTimeout(timeout); timeout = timeout->Next()) {
for (timeout = mTimeouts.getFirst(); timeout; timeout = timeout->getNext()) {
if (((timeout == aTimeout) || (timeout->mWhen <= deadline)) &&
(timeout->mFiringDepth == 0)) {
// Mark any timeouts that are on the list to be fired with the
@ -9940,7 +9858,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
// list for any timeouts inserted as a result of running a timeout.
dummy_timeout.mFiringDepth = firingDepth;
dummy_timeout.mWhen = now;
PR_INSERT_AFTER(&dummy_timeout, last_expired_timeout);
last_expired_timeout->setNext(&dummy_timeout);
// Don't let ClearWindowTimeouts throw away our stack-allocated
// dummy timeout.
@ -9954,10 +9872,10 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
Telemetry::AutoCounter<Telemetry::DOM_TIMERS_FIRED_PER_NATIVE_TIMEOUT> timeoutsRan;
for (timeout = FirstTimeout();
for (timeout = mTimeouts.getFirst();
timeout != &dummy_timeout && !IsFrozen();
timeout = nextTimeout) {
nextTimeout = timeout->Next();
nextTimeout = timeout->getNext();
if (timeout->mFiringDepth != firingDepth) {
// We skip the timeout since it's on the list to run at another
@ -10021,9 +9939,9 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
// Running a timeout can cause another timeout to be deleted, so
// we need to reset the pointer to the following timeout.
nextTimeout = timeout->Next();
nextTimeout = timeout->getNext();
PR_REMOVE_LINK(timeout);
timeout->remove();
if (needsReinsertion) {
// Insert interval timeout onto list sorted in deadline order.
@ -10036,7 +9954,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
}
// Take the dummy timeout off the head of the list
PR_REMOVE_LINK(&dummy_timeout);
dummy_timeout.remove();
mTimeoutInsertionPoint = last_insertion_point;
}
@ -10074,9 +9992,7 @@ nsGlobalWindow::ClearTimeoutOrInterval(int32_t aTimerID)
uint32_t public_id = (uint32_t)aTimerID;
nsTimeout *timeout;
for (timeout = FirstTimeout();
IsTimeout(timeout);
timeout = timeout->Next()) {
for (timeout = mTimeouts.getFirst(); timeout; timeout = timeout->getNext()) {
if (timeout->mPublicId == public_id) {
if (timeout->mRunning) {
/* We're running from inside the timeout. Mark this
@ -10086,7 +10002,7 @@ nsGlobalWindow::ClearTimeoutOrInterval(int32_t aTimerID)
}
else {
/* Delete the timeout from the pending timeout list */
PR_REMOVE_LINK(timeout);
timeout->remove();
if (timeout->mTimer) {
timeout->mTimer->Cancel();
@ -10121,13 +10037,13 @@ nsresult nsGlobalWindow::ResetTimersForNonBackgroundWindow()
// start at the timer after mTimeoutInsertionPoint, if there is one.
// Otherwise, start at the beginning of the list.
for (nsTimeout *timeout = mTimeoutInsertionPoint ?
mTimeoutInsertionPoint->Next() : FirstTimeout();
IsTimeout(timeout); ) {
mTimeoutInsertionPoint->getNext() : mTimeouts.getFirst();
timeout; ) {
// It's important that this check be <= so that we guarantee that
// taking NS_MAX with |now| won't make a quantity equal to
// timeout->mWhen below.
if (timeout->mWhen <= now) {
timeout = timeout->Next();
timeout = timeout->getNext();
continue;
}
@ -10164,14 +10080,14 @@ nsresult nsGlobalWindow::ResetTimersForNonBackgroundWindow()
// Get the pointer to the next timeout now, before we move the
// current timeout in the list.
nsTimeout* nextTimeout = timeout->Next();
nsTimeout* nextTimeout = timeout->getNext();
// It is safe to remove and re-insert because mWhen is now
// strictly smaller than it used to be, so we know we'll insert
// |timeout| before nextTimeout.
NS_ASSERTION(!IsTimeout(nextTimeout) ||
NS_ASSERTION(!nextTimeout ||
timeout->mWhen < nextTimeout->mWhen, "How did that happen?");
PR_REMOVE_LINK(timeout);
timeout->remove();
// InsertTimeoutIntoList will addref |timeout| and reset
// mFiringDepth. Make sure to undo that after calling it.
uint32_t firingDepth = timeout->mFiringDepth;
@ -10188,7 +10104,7 @@ nsresult nsGlobalWindow::ResetTimersForNonBackgroundWindow()
timeout = nextTimeout;
} else {
timeout = timeout->Next();
timeout = timeout->getNext();
}
}
@ -10200,7 +10116,7 @@ nsGlobalWindow::ClearAllTimeouts()
{
nsTimeout *timeout, *nextTimeout;
for (timeout = FirstTimeout(); IsTimeout(timeout); timeout = nextTimeout) {
for (timeout = mTimeouts.getFirst(); timeout; timeout = nextTimeout) {
/* If RunTimeout() is higher up on the stack for this
window, e.g. as a result of document.write from a timeout,
then we need to reset the list insertion point for
@ -10209,7 +10125,7 @@ nsGlobalWindow::ClearAllTimeouts()
if (mRunningTimeout == timeout)
mTimeoutInsertionPoint = nullptr;
nextTimeout = timeout->Next();
nextTimeout = timeout->getNext();
if (timeout->mTimer) {
timeout->mTimer->Cancel();
@ -10229,7 +10145,7 @@ nsGlobalWindow::ClearAllTimeouts()
}
// Clear out our list
PR_INIT_CLIST(&mTimeouts);
mTimeouts.clear();
}
void
@ -10242,19 +10158,23 @@ nsGlobalWindow::InsertTimeoutIntoList(nsTimeout *aTimeout)
// mTimeoutInsertionPoint, though. This optimizes for the common case of
// insertion at the end.
nsTimeout* prevSibling;
for (prevSibling = LastTimeout();
IsTimeout(prevSibling) && prevSibling != mTimeoutInsertionPoint &&
for (prevSibling = mTimeouts.getLast();
prevSibling && prevSibling != mTimeoutInsertionPoint &&
// This condition needs to match the one in SetTimeoutOrInterval that
// determines whether to set mWhen or mTimeRemaining.
((IsFrozen() || mTimeoutsSuspendDepth) ?
prevSibling->mTimeRemaining > aTimeout->mTimeRemaining :
prevSibling->mWhen > aTimeout->mWhen);
prevSibling = prevSibling->Prev()) {
prevSibling = prevSibling->getPrevious()) {
/* Do nothing; just searching */
}
// Now link in aTimeout after prevSibling.
PR_INSERT_AFTER(aTimeout, prevSibling);
if (prevSibling) {
prevSibling->setNext(aTimeout);
} else {
mTimeouts.insertFront(aTimeout);
}
aTimeout->mFiringDepth = 0;
@ -10546,7 +10466,7 @@ nsGlobalWindow::SuspendTimeouts(uint32_t aIncrease,
mozilla::dom::workers::SuspendWorkersForWindow(cx, this);
TimeStamp now = TimeStamp::Now();
for (nsTimeout *t = FirstTimeout(); IsTimeout(t); t = t->Next()) {
for (nsTimeout *t = mTimeouts.getFirst(); t; t = t->getNext()) {
// Set mTimeRemaining to be the time remaining for this timer.
if (t->mWhen > now)
t->mTimeRemaining = t->mWhen - now;
@ -10634,7 +10554,7 @@ nsGlobalWindow::ResumeTimeouts(bool aThawChildren)
bool _seenDummyTimeout = false;
#endif
for (nsTimeout *t = FirstTimeout(); IsTimeout(t); t = t->Next()) {
for (nsTimeout *t = mTimeouts.getFirst(); t; t = t->getNext()) {
// There's a chance we're being called with RunTimeout on the stack in which
// case we have a dummy timeout in the list that *must not* be resumed. It
// can be identified by a null mWindow.
@ -10770,20 +10690,6 @@ nsGlobalWindow::DisableDeviceSensor(uint32_t aType)
}
}
NS_IMETHODIMP
nsGlobalWindow::GetURL(nsIDOMMozURLProperty** aURL)
{
FORWARD_TO_INNER(GetURL, (aURL), NS_ERROR_UNEXPECTED);
if (!mURLProperty) {
mURLProperty = new nsDOMMozURLProperty(this);
}
NS_ADDREF(*aURL = mURLProperty);
return NS_OK;
}
void
nsGlobalWindow::EnableTimeChangeNotifications()
{

View File

@ -59,6 +59,7 @@
#include "nsIContent.h"
#include "nsIIDBFactory.h"
#include "nsFrameMessageManager.h"
#include "mozilla/LinkedList.h"
#include "mozilla/TimeStamp.h"
#include "nsIDOMTouchEvent.h"
#include "nsIInlineEventHandlers.h"
@ -111,7 +112,6 @@ class PostMessageEvent;
class nsRunnable;
class nsDOMEventTargetHelper;
class nsDOMOfflineResourceList;
class nsDOMMozURLProperty;
class nsDOMWindowUtils;
class nsIIdleService;
@ -124,6 +124,7 @@ class nsWindowSizes;
namespace mozilla {
namespace dom {
class Navigator;
class URL;
} // namespace dom
} // namespace mozilla
@ -138,7 +139,7 @@ NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
* timeout. Holds a strong reference to an nsIScriptTimeoutHandler, which
* abstracts the language specific cruft.
*/
struct nsTimeout : PRCList
struct nsTimeout : mozilla::LinkedListElement<nsTimeout>
{
nsTimeout();
~nsTimeout();
@ -148,16 +149,6 @@ struct nsTimeout : PRCList
nsrefcnt Release();
nsrefcnt AddRef();
nsTimeout* Next() {
// Note: might not actually return an nsTimeout. Use IsTimeout to check.
return static_cast<nsTimeout*>(PR_NEXT_LINK(this));
}
nsTimeout* Prev() {
// Note: might not actually return an nsTimeout. Use IsTimeout to check.
return static_cast<nsTimeout*>(PR_PREV_LINK(this));
}
nsresult InitTimer(nsTimerCallbackFunc aFunc, uint64_t delay) {
return mTimer->InitWithFuncCallback(aFunc, this, delay,
nsITimer::TYPE_ONE_SHOT);
@ -282,8 +273,6 @@ class nsGlobalWindow : public nsPIDOMWindow,
#endif // MOZ_B2G
{
public:
friend class nsDOMMozURLProperty;
typedef mozilla::TimeStamp TimeStamp;
typedef mozilla::TimeDuration TimeDuration;
typedef mozilla::dom::Navigator Navigator;
@ -886,20 +875,6 @@ protected:
bool IsInModalState();
nsTimeout* FirstTimeout() {
// Note: might not actually return an nsTimeout. Use IsTimeout to check.
return static_cast<nsTimeout*>(PR_LIST_HEAD(&mTimeouts));
}
nsTimeout* LastTimeout() {
// Note: might not actually return an nsTimeout. Use IsTimeout to check.
return static_cast<nsTimeout*>(PR_LIST_TAIL(&mTimeouts));
}
bool IsTimeout(PRCList* aList) {
return aList != &mTimeouts;
}
// Convenience functions for the many methods that need to scale
// from device to CSS pixels or vice versa. Note: if a presentation
// context is not available, they will assume a 1:1 ratio.
@ -1067,7 +1042,7 @@ protected:
// non-null. In that case, the dummy timeout pointed to by
// mTimeoutInsertionPoint may have a later mWhen than some of the timeouts
// that come after it.
PRCList mTimeouts;
mozilla::LinkedList<nsTimeout> mTimeouts;
// If mTimeoutInsertionPoint is non-null, insertions should happen after it.
// This is a dummy timeout at the moment; if that ever changes, the logic in
// ResetTimersForNonBackgroundWindow needs to change.
@ -1128,8 +1103,6 @@ protected:
// destroying this window).
bool mDialogsPermanentlyDisabled;
nsRefPtr<nsDOMMozURLProperty> mURLProperty;
nsTHashtable<nsPtrHashKey<nsDOMEventTargetHelper> > mEventTargetObjects;
nsTArray<uint32_t> mEnabledSensors;

View File

@ -108,31 +108,6 @@ nsLocation::GetDocShell()
return docshell;
}
// Try to get the the document corresponding to the given JSScript.
static already_AddRefed<nsIDocument>
GetScriptDocument(JSContext *cx, JSScript *script)
{
if (!cx || !script)
return nullptr;
JSObject* scope = JS_GetGlobalFromScript(script);
if (!scope)
return nullptr;
JSAutoCompartment ac(cx, scope);
nsCOMPtr<nsIDOMWindow> window =
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, scope));
if (!window)
return nullptr;
// If it's a window, get its document.
nsCOMPtr<nsIDOMDocument> domDoc;
window->GetDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
return doc.forget();
}
nsresult
nsLocation::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
{
@ -166,13 +141,12 @@ nsLocation::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
// current URI as the referrer. If they don't match, use the principal's
// URI.
JSScript* script = nullptr;
nsCOMPtr<nsIDocument> doc;
nsCOMPtr<nsIURI> docOriginalURI, docCurrentURI, principalURI;
// NB: A false return value from JS_DescribeScriptedCaller means no caller
// was found. It does not signal that an exception was thrown.
if (JS_DescribeScriptedCaller(cx, &script, nullptr)) {
doc = GetScriptDocument(cx, script);
nsCOMPtr<nsPIDOMWindow> entryPoint =
do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
if (entryPoint) {
doc = entryPoint->GetDoc();
}
if (doc) {
docOriginalURI = doc->GetOriginalURI();

View File

@ -48,8 +48,8 @@ class nsIArray;
class nsPIWindowRoot;
#define NS_PIDOMWINDOW_IID \
{ 0x54fd92bd, 0xda33, 0x4451, \
{ 0x8f, 0xb5, 0x11, 0x20, 0x5c, 0x03, 0xce, 0xaa } }
{ 0x7b18e421, 0x2179, 0x4e24, \
{ 0x96, 0x58, 0x26, 0x75, 0xa4, 0x37, 0xf3, 0x8f } }
class nsPIDOMWindow : public nsIDOMWindowInternal
{

View File

@ -114,6 +114,10 @@ DOMInterfaces = {
'concrete': False,
},
'BiquadFilterNode': {
'resultNotAddRefed': [ 'frequency', 'q', 'gain' ],
},
'Blob': [
{
'headerFile': 'nsIDOMFile.h',
@ -365,6 +369,10 @@ DOMInterfaces = {
'implicitJSContext': [ 'encode' ],
},
'URL' : {
'concrete': False,
},
'WebGLActiveInfo': {
'nativeType': 'mozilla::WebGLActiveInfo',
'headerFile': 'WebGLContext.h',

View File

@ -1095,7 +1095,9 @@ class MethodDefiner(PropertyDefiner):
"flags": "JSPROP_ENUMERATE",
"pref": None })
if not descriptor.interface.parent and not static and descriptor.nativeOwnership == 'nsisupports':
if (not descriptor.interface.parent and not static and
descriptor.nativeOwnership == 'nsisupports' and
descriptor.interface.hasInterfacePrototypeObject()):
self.chrome.append({"name": 'QueryInterface',
"methodInfo": False,
"length": 1,
@ -5634,50 +5636,53 @@ class CGDescriptor(CGThing):
assert not descriptor.concrete or descriptor.interface.hasInterfacePrototypeObject()
cgThings = []
if descriptor.interface.hasInterfacePrototypeObject():
# These are set to true if at least one non-static
# method/getter/setter exist on the interface.
(hasMethod, hasGetter, hasLenientGetter,
hasSetter, hasLenientSetter) = False, False, False, False, False
for m in descriptor.interface.members:
if (m.isMethod() and
(not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
if m.isStatic():
cgThings.append(CGStaticMethod(descriptor, m))
# These are set to true if at least one non-static
# method/getter/setter exist on the interface.
(hasMethod, hasGetter, hasLenientGetter,
hasSetter, hasLenientSetter) = False, False, False, False, False
for m in descriptor.interface.members:
if (m.isMethod() and
(not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
if m.isStatic():
assert descriptor.interface.hasInterfaceObject
cgThings.append(CGStaticMethod(descriptor, m))
elif descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGSpecializedMethod(descriptor, m))
cgThings.append(CGMemberJITInfo(descriptor, m))
hasMethod = True
elif m.isAttr():
if m.isStatic():
assert descriptor.interface.hasInterfaceObject
cgThings.append(CGStaticGetter(descriptor, m))
elif descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGSpecializedGetter(descriptor, m))
if m.hasLenientThis():
hasLenientGetter = True
else:
cgThings.append(CGSpecializedMethod(descriptor, m))
cgThings.append(CGMemberJITInfo(descriptor, m))
hasMethod = True
elif m.isAttr():
hasGetter = True
if not m.readonly:
if m.isStatic():
cgThings.append(CGStaticGetter(descriptor, m))
else:
cgThings.append(CGSpecializedGetter(descriptor, m))
assert descriptor.interface.hasInterfaceObject
cgThings.append(CGStaticSetter(descriptor, m))
elif descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGSpecializedSetter(descriptor, m))
if m.hasLenientThis():
hasLenientGetter = True
hasLenientSetter = True
else:
hasGetter = True
if not m.readonly:
if m.isStatic():
cgThings.append(CGStaticSetter(descriptor, m))
else:
cgThings.append(CGSpecializedSetter(descriptor, m))
if m.hasLenientThis():
hasLenientSetter = True
else:
hasSetter = True
elif m.getExtendedAttribute("PutForwards"):
cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
hasSetter = True
if not m.isStatic():
cgThings.append(CGMemberJITInfo(descriptor, m))
if hasMethod: cgThings.append(CGGenericMethod(descriptor))
if hasGetter: cgThings.append(CGGenericGetter(descriptor))
if hasLenientGetter: cgThings.append(CGGenericGetter(descriptor,
lenientThis=True))
if hasSetter: cgThings.append(CGGenericSetter(descriptor))
if hasLenientSetter: cgThings.append(CGGenericSetter(descriptor,
lenientThis=True))
hasSetter = True
elif m.getExtendedAttribute("PutForwards"):
cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
hasSetter = True
if (not m.isStatic() and
descriptor.interface.hasInterfacePrototypeObject()):
cgThings.append(CGMemberJITInfo(descriptor, m))
if hasMethod: cgThings.append(CGGenericMethod(descriptor))
if hasGetter: cgThings.append(CGGenericGetter(descriptor))
if hasLenientGetter: cgThings.append(CGGenericGetter(descriptor,
lenientThis=True))
if hasSetter: cgThings.append(CGGenericSetter(descriptor))
if hasLenientSetter: cgThings.append(CGGenericSetter(descriptor,
lenientThis=True))
if descriptor.concrete:
if descriptor.nativeOwnership == 'owned' or descriptor.nativeOwnership == 'refcounted':
@ -5805,9 +5810,10 @@ class CGNamespacedEnum(CGThing):
class CGDictionary(CGThing):
def __init__(self, dictionary, descriptorProvider):
self.dictionary = dictionary;
self.dictionary = dictionary
self.descriptorProvider = descriptorProvider
self.workers = descriptorProvider.workers
self.needToInitIds = not self.workers and len(dictionary.members) > 0
if all(CGDictionary(d, descriptorProvider).generatable for
d in CGDictionary.getDictionaryDependencies(dictionary)):
self.generatable = True
@ -5869,7 +5875,7 @@ class CGDictionary(CGThing):
" ${selfName}(const ${selfName}&) MOZ_DELETE;\n" +
# NOTE: jsids are per-runtime, so don't use them in workers
(" static bool InitIds(JSContext* cx);\n"
" static bool initedIds;\n" if not self.workers else "") +
" static bool initedIds;\n" if self.needToInitIds else "") +
"\n".join(" static jsid " +
self.makeIdName(m.identifier.name) + ";" for
m in d.members) + "\n"
@ -5934,7 +5940,7 @@ class CGDictionary(CGThing):
" initedIds = true;\n"
" return true;\n"
"}\n"
"\n" if not self.workers else "") +
"\n" if self.needToInitIds else "") +
"bool\n"
"${selfName}::Init(JSContext* cx, const JS::Value& val)\n"
"{\n"
@ -5944,10 +5950,10 @@ class CGDictionary(CGThing):
# NOTE: jsids are per-runtime, so don't use them in workers
(" if (cx && !initedIds && !InitIds(cx)) {\n"
" return false;\n"
" }\n" if not self.workers else "") +
"${initParent}"
" JSBool found;\n"
" JS::Value temp;\n"
" }\n" if self.needToInitIds else "") +
"${initParent}" +
(" JSBool found;\n"
" JS::Value temp;\n" if len(memberInits) > 0 else "") +
" bool isNull = val.isNullOrUndefined();\n"
" if (!isNull && !val.isObject()) {\n"
" return ThrowErrorMessage(cx, MSG_NOT_OBJECT);\n"
@ -5963,7 +5969,7 @@ class CGDictionary(CGThing):
# NOTE: jsids are per-runtime, so don't use them in workers
(" if (!initedIds && !InitIds(cx)) {\n"
" return false;\n"
" }\n" if not self.workers else "") +
" }\n" if self.needToInitIds else "") +
"${toObjectParent}"
"${ensureObject}"
"\n"

View File

@ -16,6 +16,8 @@
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "mozilla/Preferences.h"
USING_FILE_NAMESPACE
ArchiveReader::ArchiveReader()
@ -33,6 +35,12 @@ ArchiveReader::~ArchiveReader()
nsLayoutStatics::Release();
}
bool
ArchiveReader::PrefEnabled()
{
return Preferences::GetBool("dom.archivereader.enabled", true);
}
NS_IMETHODIMP
ArchiveReader::Initialize(nsISupports* aOwner,
JSContext* aCx,
@ -42,6 +50,10 @@ ArchiveReader::Initialize(nsISupports* aOwner,
{
NS_ENSURE_TRUE(aArgc == 1 || aArgc == 2, NS_ERROR_INVALID_ARG);
if (!PrefEnabled()) {
return NS_ERROR_UNEXPECTED;
}
// We expect to get a Blob object
if (!aArgv[0].isObject()) {
return NS_ERROR_INVALID_ARG; // We're not interested

View File

@ -48,6 +48,8 @@ public:
nsresult GetInputStream(nsIInputStream** aInputStream);
nsresult GetSize(uint64_t* aSize);
static bool PrefEnabled();
public: // for the ArchiveRequest:
nsresult RegisterRequest(ArchiveRequest* aRequest);

View File

@ -13,11 +13,14 @@ var fileStorages = [
var utils = SpecialPowers.getDOMWindowUtils(window);
var archiveReaderEnabled = false;
var testGenerator = testSteps();
function runTest()
{
allowUnlimitedQuota();
enableArchiveReader();
SimpleTest.waitForExplicitFinish();
testGenerator.next();
@ -26,6 +29,7 @@ function runTest()
function finishTest()
{
resetUnlimitedQuota();
resetArchiveReader();
SimpleTest.executeSoon(function() {
testGenerator.close();
@ -98,6 +102,17 @@ function resetUnlimitedQuota(url)
removePermission("indexedDB-unlimited", url);
}
function enableArchiveReader()
{
archiveReaderEnabled = SpecialPowers.getBoolPref("dom.archivereader.enabled");
SpecialPowers.setBoolPref("dom.archivereader.enabled", true);
}
function resetArchiveReader()
{
SpecialPowers.setBoolPref("dom.archivereader.enabled", archiveReaderEnabled);
}
function getFileHandle(fileStorageKey, name)
{
var requestService = SpecialPowers.getDOMRequestService();

View File

@ -8,14 +8,8 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display">
<input id="fileList" type="file"></input>
</p>
<script type="text/javascript;version=1.7">
<script type="text/javascript;version=1.7">
function createZipFileWithData(fileData) {
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
@ -58,7 +52,7 @@
function markTestDone() {
++handleFinished;
if (isFinished()) {
SimpleTest.finish();
finishTest();
}
}
function isFinished() {
@ -251,11 +245,17 @@
ok(false, "ArchiveReader.getFiles() should not return an 'error'");
markTestDone();
}
yield;
}
SimpleTest.waitForExplicitFinish();
testSteps();
</script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();">
<p id="display">
<input id="fileList" type="file"></input>
</p>
</body>
</html>

View File

@ -4,6 +4,7 @@
*/
var testGenerator = testSteps();
var archiveReaderEnabled = false;
// The test js is shared between xpcshell (which has no SpecialPowers object)
// and content mochitests (where the |Components| object is accessible only as
@ -68,6 +69,8 @@ if (!window.runTest) {
allowUnlimitedQuota();
}
enableArchiveReader();
clearAllDatabases(function () { testGenerator.next(); });
}
}
@ -75,6 +78,7 @@ if (!window.runTest) {
function finishTest()
{
resetUnlimitedQuota();
resetArchiveReader();
SimpleTest.executeSoon(function() {
testGenerator.close();
@ -163,12 +167,12 @@ function compareKeys(k1, k2) {
if (!(k2 instanceof Array) ||
k1.length != k2.length)
return false;
for (let i = 0; i < k1.length; ++i) {
if (!compareKeys(k1[i], k2[i]))
return false;
}
return true;
}
@ -211,6 +215,17 @@ function resetUnlimitedQuota(url)
removePermission("indexedDB-unlimited", url);
}
function enableArchiveReader()
{
archiveReaderEnabled = SpecialPowers.getBoolPref("dom.archivereader.enabled");
SpecialPowers.setBoolPref("dom.archivereader.enabled", true);
}
function resetArchiveReader()
{
SpecialPowers.setBoolPref("dom.archivereader.enabled", archiveReaderEnabled);
}
function gc()
{
SpecialPowers.forceGC();

View File

@ -16,13 +16,6 @@ interface nsIPrompt;
interface nsISelection;
interface nsIVariant;
[scriptable, uuid(8fc58f56-f769-4368-a098-edd08550cf1a)]
interface nsIDOMMozURLProperty : nsISupports
{
DOMString createObjectURL(in nsIDOMBlob blob);
void revokeObjectURL(in DOMString URL);
};
/**
* The nsIDOMWindow interface is the primary interface for a DOM
* window object. It represents a single window object that may
@ -32,7 +25,7 @@ interface nsIDOMMozURLProperty : nsISupports
* @see <http://www.whatwg.org/html/#window>
*/
[scriptable, uuid(1534ecd7-e298-420e-9063-e6c2d1243d49)]
[scriptable, uuid(b9c71e0b-7f81-419a-8253-91f4c8893c4f)]
interface nsIDOMWindow : nsISupports
{
// the current browsing context
@ -461,11 +454,6 @@ interface nsIDOMWindow : nsISupports
*/
readonly attribute long long mozAnimationStartTime;
/**
* @see <http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking>
*/
readonly attribute nsIDOMMozURLProperty URL;
/**
* HTML5 event attributes that only apply to windows and <body>/<frameset>
*/
@ -525,5 +513,5 @@ interface nsIWindowCrypto : nsISupports
* Empty interface for compatibility with older versions.
* @deprecated Use nsIDOMWindow instead
*/
[scriptable, uuid(8da641ab-906a-456e-97f2-b77df4ca2d95)]
[scriptable, uuid(a5cd0946-bac1-4606-9aaa-9e68dd0a3279)]
interface nsIDOMWindowInternal : nsIDOMWindow {};

View File

@ -130,6 +130,11 @@ MOCHITEST_FILES = \
test_bug755320.html \
test_bug777628.html \
test_bug665548.html \
test_bug809290.html \
file_bug809290_b1.html \
file_bug809290_b2.html \
file_bug809290_c.html \
file_empty.html \
$(NULL)
ifneq (Linux,$(OS_ARCH))

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<script>
function innerLoad() {
var win = document.getElementById('ifr').contentWindow;
win.location = "file_bug809290_c.html";
}
</script>
</head>
<body>
<iframe id="ifr" src="file_empty.html">
</body>
</html>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<script>
function eventHandlerLoad() {
var win = document.getElementById('ifr').contentWindow;
win.location = "file_bug809290_c.html";
}
</script>
</head>
<body onload="eventHandlerLoad();">
<iframe id="ifr" src="file_empty.html">
</body>
</html>

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<script>
window.parent.parent.notifyReferrer(document.referrer);
</script>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,2 @@
<!DOCTYPE html>
<html><head></head><body></body></html>

View File

@ -56,8 +56,15 @@ function iframeLoaded(identifier) {
is(iframeCw.getInnerIframeReferrer(), iframeCw.location, 'inner iframe referrer');
// Now do the test again, this time with a popup.
popup = window.open('file_bug593174_1.html');
popup.onload = iframeLoaded('popup/outer');
//
// NB: in this situation, we're actually getting called in an event handler from
// the iframe, meaning that it serves as the script entry point. But that's a detail,
// and we want to pretend like this window is doing the call. So let's use setTimeout
// to forget about the iframe.
window.setTimeout(function() {
popup = window.open('file_bug593174_1.html');
popup.onload = iframeLoaded('popup/outer');
}, 0);
}
else if (loadCount == 4) {
history.replaceState('', '', Math.random());

View File

@ -0,0 +1,48 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=809290
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 809290</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=809290">Mozilla Bug 809290</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 809290 **/
SimpleTest.waitForExplicitFinish();
var gNotifyCount = 0;
function notifyReferrer(referrer) {
++gNotifyCount;
if (gNotifyCount == 1) {
is(referrer, window.location.href, "Referrer should be the script entry point (this script)");
document.getElementById('ifr').setAttribute('src', 'file_bug809290_b2.html');
} else {
is(gNotifyCount, 2);
is(referrer, window.location.href.replace(/test_bug.*/, 'file_bug809290_b2.html'),
"Referrer should be the script entry point (iframe)");
SimpleTest.finish();
}
}
function go() {
var ifr = document.getElementById('ifr');
ifr.onload = null;
ifr.contentWindow.innerLoad();
}
</script>
</pre>
<iframe id="ifr" src="file_bug809290_b1.html" onload="go();"></iframe>
</body>
</html>

View File

@ -207,8 +207,6 @@ var interfaceNamesInGlobalScope =
"SVGAltGlyphElement",
"Screen",
"FileReader",
"ArchiveReader",
"ArchiveRequest",
"SVGSwitchElement",
"SVGPolylineElement",
"SVGPathSegLinetoAbs",
@ -342,7 +340,7 @@ var interfaceNamesInGlobalScope =
"HTMLSelectElement",
"MessageEvent",
"SVGFEImageElement",
"MozURLProperty",
"URL",
"DeviceStorage",
"SVGFEOffsetElement",
"DOMImplementation",

View File

@ -31,6 +31,8 @@ interface mozAudioContext {
[Creator]
DelayNode createDelay(optional float maxDelayTime = 1);
[Creator]
BiquadFilterNode createBiquadFilter();
[Creator]
PannerNode createPanner();
[Creator]

View File

@ -0,0 +1,37 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origin of this IDL file is
* https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface BiquadFilterNode : AudioNode {
// Filter type.
const unsigned short LOWPASS = 0;
const unsigned short HIGHPASS = 1;
const unsigned short BANDPASS = 2;
const unsigned short LOWSHELF = 3;
const unsigned short HIGHSHELF = 4;
const unsigned short PEAKING = 5;
const unsigned short NOTCH = 6;
const unsigned short ALLPASS = 7;
[SetterThrows]
attribute unsigned short type;
readonly attribute AudioParam frequency; // in Hertz
readonly attribute AudioParam Q; // Quality factor
readonly attribute AudioParam gain; // in Decibels
// void getFrequencyResponse(Float32Array frequencyHz,
// Float32Array magResponse,
// Float32Array phaseResponse);
};

27
dom/webidl/URL.webidl Normal file
View File

@ -0,0 +1,27 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origins of this IDL file are
* http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking
* http://dev.w3.org/2011/webrtc/editor/getusermedia.html#url
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
interface MediaStream;
interface URL {
[Throws]
static DOMString? createObjectURL(Blob blob, optional objectURLOptions options);
[Throws]
static DOMString? createObjectURL(MediaStream stream, optional objectURLOptions options);
static void revokeObjectURL(DOMString url);
};
dictionary objectURLOptions
{
/* boolean autoRevoke = true; */ /* not supported yet */
};

View File

@ -17,6 +17,7 @@ webidl_files = \
AudioNode.webidl \
AudioParam.webidl \
AudioSourceNode.webidl \
BiquadFilterNode.webidl \
Blob.webidl \
CanvasRenderingContext2D.webidl \
ClientRectList.webidl \
@ -52,6 +53,7 @@ webidl_files = \
SVGTransformList.webidl \
TextDecoder.webidl \
TextEncoder.webidl \
URL.webidl \
WebSocket.webidl \
XMLHttpRequest.webidl \
XMLHttpRequestEventTarget.webidl \

View File

@ -992,6 +992,10 @@ LayerManagerOGL::Render()
// Allow widget to render a custom background.
mWidget->DrawWindowUnderlay(this, rect);
// Reset some state that might of been clobbered by the underlay.
mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
LOCAL_GL_ONE, LOCAL_GL_ONE);
// Render our layers.
RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO,
nsIntPoint(0, 0));

View File

@ -501,8 +501,7 @@ nsresult nsExtensibleStringBundle::GetSimpleEnumeration(nsISimpleEnumerator ** a
#define MAX_CACHED_BUNDLES 16
struct bundleCacheEntry_t {
PRCList list;
struct bundleCacheEntry_t : public LinkedListElement<bundleCacheEntry_t> {
nsCStringKey *mHashKey;
// do not use a nsCOMPtr - this is a struct not a class!
nsIStringBundle* mBundle;
@ -516,7 +515,6 @@ nsStringBundleService::nsStringBundleService() :
printf("\n++ nsStringBundleService::nsStringBundleService ++\n");
#endif
PR_INIT_CLIST(&mBundleCache);
PL_InitArenaPool(&mCacheEntryPool, "srEntries",
sizeof(bundleCacheEntry_t)*MAX_CACHED_BUNDLES,
sizeof(bundleCacheEntry_t));
@ -582,16 +580,10 @@ nsStringBundleService::flushBundleCache()
// release all bundles in the cache
mBundleMap.Reset();
PRCList *current = PR_LIST_HEAD(&mBundleCache);
while (current != &mBundleCache) {
bundleCacheEntry_t *cacheEntry = (bundleCacheEntry_t*)current;
while (!mBundleCache.isEmpty()) {
bundleCacheEntry_t *cacheEntry = mBundleCache.popFirst();
recycleEntry(cacheEntry);
PRCList *oldItem = current;
current = PR_NEXT_LINK(current);
// will be freed in PL_FreeArenaPool
PR_REMOVE_LINK(oldItem);
}
PL_FreeArenaPool(&mCacheEntryPool);
}
@ -616,7 +608,7 @@ nsStringBundleService::getStringBundle(const char *aURLSpec,
// cache hit!
// remove it from the list, it will later be reinserted
// at the head of the list
PR_REMOVE_LINK((PRCList*)cacheEntry);
cacheEntry->remove();
} else {
@ -633,8 +625,7 @@ nsStringBundleService::getStringBundle(const char *aURLSpec,
// at this point the cacheEntry should exist in the hashtable,
// but is not in the LRU cache.
// put the cache entry at the front of the list
PR_INSERT_LINK((PRCList *)cacheEntry, &mBundleCache);
mBundleCache.insertFront(cacheEntry);
// finally, return the value
*aResult = cacheEntry->mBundle;
@ -654,12 +645,12 @@ nsStringBundleService::insertIntoCache(nsIStringBundle* aBundle,
void *cacheEntryArena;
PL_ARENA_ALLOCATE(cacheEntryArena, &mCacheEntryPool, sizeof(bundleCacheEntry_t));
cacheEntry = (bundleCacheEntry_t*)cacheEntryArena;
cacheEntry = new (cacheEntryArena) bundleCacheEntry_t();
} else {
// cache is full
// take the last entry in the list, and recycle it.
cacheEntry = (bundleCacheEntry_t*)PR_LIST_TAIL(&mBundleCache);
cacheEntry = mBundleCache.getLast();
// remove it from the hash table and linked list
NS_ASSERTION(mBundleMap.Exists(cacheEntry->mHashKey),
@ -670,7 +661,7 @@ nsStringBundleService::insertIntoCache(nsIStringBundle* aBundle,
aHashKey->GetString()).get());
#endif
mBundleMap.Remove(cacheEntry->mHashKey);
PR_REMOVE_LINK((PRCList*)cacheEntry);
cacheEntry->remove();
// free up excess memory
recycleEntry(cacheEntry);

View File

@ -6,7 +6,6 @@
#ifndef nsStringBundleService_h__
#define nsStringBundleService_h__
#include "prclist.h"
#include "plarena.h"
#include "nsCOMPtr.h"
@ -18,6 +17,8 @@
#include "nsIErrorService.h"
#include "nsIStringBundleOverride.h"
#include "mozilla/LinkedList.h"
struct bundleCacheEntry_t;
class nsStringBundleService : public nsIStringBundleService,
@ -48,7 +49,7 @@ private:
static void recycleEntry(bundleCacheEntry_t*);
nsHashtable mBundleMap;
PRCList mBundleCache;
mozilla::LinkedList<bundleCacheEntry_t> mBundleCache;
PLArenaPool mCacheEntryPool;
nsCOMPtr<nsIErrorService> mErrorService;

View File

@ -243,8 +243,17 @@ case "$target" in
android_platform_tools="$android_sdk"/tools # SDK Tools < r8
fi
ANDROID_SDK="${android_sdk}"
if test -e "${android_sdk}/../../extras/android/compatibility/v4/android-support-v4.jar" ; then
ANDROID_COMPAT_LIB="${android_sdk}/../../extras/android/compatibility/v4/android-support-v4.jar"
else
ANDROID_COMPAT_LIB="${android_sdk}/../../extras/android/support/v4/android-support-v4.jar";
fi
ANDROID_PLATFORM_TOOLS="${android_platform_tools}"
AC_SUBST(ANDROID_SDK)
AC_SUBST(ANDROID_COMPAT_LIB)
if ! test -e $ANDROID_COMPAT_LIB ; then
AC_MSG_ERROR([You must download the andrioid compatibility library when targeting Android. (found $ANDROID_COMPAT_LIB)])
fi
AC_SUBST(ANDROID_PLATFORM_TOOLS)
;;
esac

View File

@ -1701,9 +1701,9 @@ ion::InvalidateAll(FreeOp *fop, JSCompartment *c)
CancelOffThreadIonCompile(c, NULL);
FinishAllOffThreadCompilations(c->ionCompartment());
for (IonActivationIterator iter(fop->runtime()); iter.more(); ++iter) {
if (iter.activation()->compartment() == c) {
IonContext ictx(NULL, c, NULL);
AutoFlushCache afc ("InvalidateAll", c->ionCompartment());
IonSpew(IonSpew_Invalidate, "Invalidating all frames for GC");
InvalidateActivation(fop, iter.top(), true);
@ -1875,10 +1875,8 @@ AutoFlushCache::AutoFlushCache(const char *nonce, IonCompartment *comp)
name_(nonce),
used_(false)
{
if (comp == NULL) {
if (CurrentIonContext() != NULL)
comp = GetIonContext()->compartment->ionCompartment();
}
if (CurrentIonContext() != NULL)
comp = GetIonContext()->compartment->ionCompartment();
// If a compartment isn't available, then be a nop, nobody will ever see this flusher
if (comp) {
if (comp->flusher())

View File

@ -471,7 +471,6 @@ struct GetNativePropertyStub
// TODO: ensure stack is aligned?
DebugOnly<uint32> initialStack = masm.framePushed();
masm.checkStackAlignment();
Label success, exception;

View File

@ -230,6 +230,8 @@ ion::CheckLogging()
EnableChannel(IonSpew_Safepoints);
if (ContainsFlag(env, "pools"))
EnableChannel(IonSpew_Pools);
if (ContainsFlag(env, "cacheflush"))
EnableChannel(IonSpew_CacheFlush);
if (ContainsFlag(env, "logs"))
EnableIonDebugLogging();
if (ContainsFlag(env, "all"))

View File

@ -958,9 +958,20 @@ MMul::analyzeEdgeCasesBackward()
canBeNegativeZero_ = NeedNegativeZeroCheck(this);
}
bool
MMul::updateForReplacement(MDefinition *ins)
void
MMul::analyzeTruncateBackward()
{
if (!isPossibleTruncated())
setPossibleTruncated(js::ion::EdgeCaseAnalysis::AllUsesTruncate(this));
}
bool
MMul::updateForReplacement(MDefinition *ins_)
{
JS_ASSERT(ins_->isMul());
MMul *ins = ins_->toMul();
if (isPossibleTruncated())
setPossibleTruncated(ins->isPossibleTruncated());
return true;
}

View File

@ -2498,11 +2498,24 @@ class MSub : public MBinaryArithInstruction
class MMul : public MBinaryArithInstruction
{
// Annotation the result could be a negative zero
// and we need to guard this during execution.
bool canBeNegativeZero_;
// Annotation the result of this Mul is only used in int32 domain
// and we could possible truncate the result.
bool possibleTruncate_;
// Annotation the Mul can truncate. This is only set after range analysis,
// because the result could be in the imprecise double range.
// In that case the truncated result isn't correct.
bool implicitTruncate_;
MMul(MDefinition *left, MDefinition *right, MIRType type)
: MBinaryArithInstruction(left, right),
canBeNegativeZero_(true)
canBeNegativeZero_(true),
possibleTruncate_(false),
implicitTruncate_(false)
{
if (type != MIRType_Value)
specialization_ = type;
@ -2521,13 +2534,14 @@ class MMul : public MBinaryArithInstruction
MDefinition *foldsTo(bool useValueNumbers);
void analyzeEdgeCasesForward();
void analyzeEdgeCasesBackward();
void analyzeTruncateBackward();
double getIdentity() {
return 1;
}
bool canOverflow() {
return !range()->isFinite();
return !implicitTruncate_ && !range()->isFinite();
}
bool canBeNegativeZero() {
@ -2546,8 +2560,18 @@ class MMul : public MBinaryArithInstruction
return false;
Range *left = getOperand(0)->range();
Range *right = getOperand(1)->range();
if (isPossibleTruncated())
implicitTruncate_ = !Range::precisionLossMul(left, right);
return range()->update(Range::mul(left, right));
}
bool isPossibleTruncated() const {
return possibleTruncate_;
}
void setPossibleTruncated(bool truncate) {
possibleTruncate_ = truncate;
}
};
class MDiv : public MBinaryArithInstruction

View File

@ -417,6 +417,24 @@ Range::shr(const Range *lhs, int32 c)
return ret;
}
bool
Range::precisionLossMul(const Range *lhs, const Range *rhs)
{
int64_t loss = 1LL<<53; // result must be lower than 2^53
int64_t a = (int64_t)lhs->lower_ * (int64_t)rhs->lower_;
int64_t b = (int64_t)lhs->lower_ * (int64_t)rhs->upper_;
int64_t c = (int64_t)lhs->upper_ * (int64_t)rhs->lower_;
int64_t d = (int64_t)lhs->upper_ * (int64_t)rhs->upper_;
int64_t lower = Min( Min(a, b), Min(c, d) );
int64_t upper = Max( Max(a, b), Max(c, d) );
if (lower < 0)
lower = -lower;
if (upper < 0)
upper = -upper;
return lower > loss || upper > loss;
}
bool
Range::update(const Range *other)
{

View File

@ -126,6 +126,8 @@ class Range {
static Range shl(const Range *lhs, int32 c);
static Range shr(const Range *lhs, int32 c);
static bool precisionLossMul(const Range *lhs, const Range *rhs);
inline void makeLowerInfinite() {
lower_infinite_ = true;
lower_ = JSVAL_INT_MIN;

View File

@ -72,7 +72,6 @@ struct EnterJITStack
IonCode *
IonCompartment::generateEnterJIT(JSContext *cx)
{
AutoFlushCache afc("GenerateEnterJIT", cx->compartment->ionCompartment());
const Register reg_code = r0;
const Register reg_argc = r1;
@ -85,6 +84,7 @@ IonCompartment::generateEnterJIT(JSContext *cx)
JS_ASSERT(OsrFrameReg == reg_frame);
MacroAssembler masm(cx);
AutoFlushCache afc("GenerateEnterJIT", cx->compartment->ionCompartment());
Assembler *aasm = &masm;
// Save non-volatile registers. These must be saved by the trampoline,

View File

@ -0,0 +1,19 @@
function test1(x) {
return (x*((2<<23)-1))|0
}
function test2(x) {
return (x*((2<<22)-1))|0
}
function test3(x) {
return (x*((2<<21)-1))|0
}
function test4(x) {
var b = x + x + 3
return (b*b) | 0
}
//MAX_INT
var x = 0x7ffffffe;
assertEq(test1(x), 2113929216);
assertEq(test2(x), 2130706434);
assertEq(test3(x), 2139095042);
assertEq(test4(x), 0);

View File

@ -0,0 +1,3 @@
var obj = new Proxy(Object.create(null), {});
assertEq(typeof obj, 'object');
assertEq(obj != null, true);

View File

@ -3156,9 +3156,12 @@ proxy(JSContext *cx, unsigned argc, jsval *vp)
RootedObject proto(cx);
if (!JSObject::getProto(cx, target, &proto))
return false;
JSObject *parent = NULL;
if (proto)
parent = proto->getParent();
RootedObject fun(cx, target->isCallable() ? target : (JSObject *) NULL);
JSObject *proxy = NewProxyObject(cx, &ScriptedDirectProxyHandler::singleton,
ObjectValue(*target), proto, proto->getParent(),
ObjectValue(*target), proto, parent,
fun, fun);
if (!proxy)
return false;

View File

@ -944,8 +944,7 @@ SourceCompressorThread::internalCompress()
// Try to keep the maximum memory usage down by only allocating half the
// size of the string, first.
size_t firstSize = nbytes / 2;
ss->data.compressed = static_cast<unsigned char *>(js_malloc(firstSize));
if (!ss->data.compressed)
if (!ss->adjustDataSize(firstSize))
return false;
Compressor comp(reinterpret_cast<const unsigned char *>(tok->chars), nbytes);
if (!comp.init())
@ -964,13 +963,8 @@ SourceCompressorThread::internalCompress()
// The compressed output is greater than half the size of the
// original string. Reallocate to the full size.
void *newmem = js_realloc(ss->data.compressed, nbytes);
if (!newmem) {
js_free(ss->data.compressed);
ss->data.compressed = NULL;
if (!ss->adjustDataSize(nbytes))
return false;
}
ss->data.compressed = static_cast<unsigned char *>(newmem);
comp.setOutput(ss->data.compressed, nbytes);
break;
}
@ -988,22 +982,12 @@ SourceCompressorThread::internalCompress()
}
#endif
if (compressedLength == 0) {
// Note ss->data.source might be NULL.
jschar *buf = static_cast<jschar *>(js_realloc(ss->data.source, nbytes));
if (!buf) {
if (ss->data.source) {
js_free(ss->data.source);
ss->data.source = NULL;
}
if (!ss->adjustDataSize(nbytes))
return false;
}
ss->data.source = buf;
PodCopy(ss->data.source, tok->chars, ss->length());
} else {
// Shrink the buffer to the size of the compressed data. Shouldn't fail.
void *newmem = js_realloc(ss->data.compressed, compressedLength);
JS_ASSERT(newmem);
ss->data.compressed = static_cast<unsigned char *>(newmem);
JS_ALWAYS_TRUE(ss->adjustDataSize(compressedLength));
}
ss->compressedLength_ = compressedLength;
return true;
@ -1085,6 +1069,29 @@ SourceCompressorThread::abort(SourceCompressionToken *userTok)
}
#endif /* JS_THREADSAFE */
static const unsigned char emptySource[] = "";
/* Adjust the amount of memory this script source uses for source data,
reallocating if needed. */
bool
ScriptSource::adjustDataSize(size_t nbytes)
{
// Allocating 0 bytes has undefined behavior, so special-case it.
if (nbytes == 0) {
if (data.compressed != emptySource)
js_free(data.compressed);
data.compressed = const_cast<unsigned char *>(emptySource);
return true;
}
// |data.compressed| can be NULL.
void *buf = js_realloc(data.compressed, nbytes);
if (!buf && data.compressed != emptySource)
js_free(data.compressed);
data.compressed = static_cast<unsigned char *>(buf);
return !!data.compressed;
}
void
JSScript::setScriptSource(ScriptSource *ss)
{
@ -1210,8 +1217,7 @@ ScriptSource::setSourceCopy(JSContext *cx, StableCharPtr src, uint32_t length,
} else
#endif
{
data.source = cx->runtime->pod_malloc<jschar>(length);
if (!data.source)
if (!adjustDataSize(sizeof(jschar) * length))
return false;
PodCopy(data.source, src.get(), length_);
}
@ -1257,7 +1263,7 @@ void
ScriptSource::destroy(JSRuntime *rt)
{
JS_ASSERT(ready());
js_free(data.compressed);
adjustDataSize(0);
js_free(sourceMap_);
#ifdef DEBUG
ready_ = false;
@ -1270,9 +1276,9 @@ ScriptSource::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf)
{
JS_ASSERT(ready());
// data is a union, but both members are pointers to allocated memory or
// NULL, so just using compressed will work.
return mallocSizeOf(this) + mallocSizeOf(data.compressed);
// |data| is a union, but both members are pointers to allocated memory,
// |emptySource|, or NULL, so just using |data.compressed| will work.
return mallocSizeOf(this) + ((data.compressed != emptySource) ? mallocSizeOf(data.compressed) : 0);
}
template<XDRMode mode>
@ -1305,8 +1311,7 @@ ScriptSource::performXDR(XDRState<mode> *xdr)
size_t byteLen = compressedLength ? compressedLength : (length * sizeof(jschar));
if (mode == XDR_DECODE) {
data.compressed = static_cast<unsigned char *>(xdr->cx()->malloc_(byteLen));
if (!data.compressed)
if (!adjustDataSize(byteLen))
return false;
}
if (!xdr->codeBytes(data.compressed, byteLen)) {

View File

@ -990,9 +990,14 @@ struct ScriptSource
friend class SourceCompressorThread;
private:
union {
// When the script source is ready, compressedLength_ != 0 implies
// compressed holds the compressed data; otherwise, source holds the
// uncompressed source.
// Before setSourceCopy or setSource are successfully called, this union
// has a NULL pointer. When the script source is ready,
// compressedLength_ != 0 implies compressed holds the compressed data;
// otherwise, source holds the uncompressed source. There is a special
// pointer |emptySource| for source code for length 0.
//
// The only function allowed to malloc, realloc, or free the pointers in
// this union is adjustDataSize(). Don't do it elsewhere.
jschar *source;
unsigned char *compressed;
} data;
@ -1068,6 +1073,7 @@ struct ScriptSource
size_t computedSizeOfData() const {
return compressed() ? compressedLength_ : sizeof(jschar) * length_;
}
bool adjustDataSize(size_t nbytes);
};
class ScriptSourceHolder

View File

@ -87,6 +87,7 @@ MOCHITEST_FILES = chrome_wrappers_helper.html \
test_bug800864.html \
test_bug802557.html \
file_bug802557.html \
test_bug809547.html \
$(NULL)
ifneq ($(OS_TARGET),Android)

View File

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=809547
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 809547</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body onload="go()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=809547">Mozilla Bug 809547</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 809547 **/
SimpleTest.waitForExplicitFinish();
var gObj = {};
function go() {
window.location.expando = gObj;
is(window.location.expando, gObj, "Expando appears");
SimpleTest.executeSoon(finish);
}
function finish() {
SpecialPowers.forceGC();
SpecialPowers.forceCC();
SpecialPowers.forceGC();
SpecialPowers.forceCC();
is(window.location.expando, gObj, "Expando preserved");
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

View File

@ -80,8 +80,8 @@
#include "ArchiveReader.h"
#include "nsFormData.h"
#include "nsBlobProtocolHandler.h"
#include "nsBlobURI.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsHostObjectURI.h"
#include "nsGlobalWindowCommands.h"
#include "nsIControllerCommandTable.h"
#include "nsJSProtocolHandler.h"
@ -278,7 +278,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDOMFileReader, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(ArchiveReader)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormData)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBlobProtocolHandler)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBlobURI)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMediaStreamProtocolHandler)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHostObjectURI)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMParser)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDOMStorageManager,
nsDOMStorageManager::GetInstance)
@ -773,7 +774,8 @@ NS_DEFINE_NAMED_CID(NS_FILEREADER_CID);
NS_DEFINE_NAMED_CID(NS_ARCHIVEREADER_CID);
NS_DEFINE_NAMED_CID(NS_FORMDATA_CID);
NS_DEFINE_NAMED_CID(NS_BLOBPROTOCOLHANDLER_CID);
NS_DEFINE_NAMED_CID(NS_BLOBURI_CID);
NS_DEFINE_NAMED_CID(NS_MEDIASTREAMPROTOCOLHANDLER_CID);
NS_DEFINE_NAMED_CID(NS_HOSTOBJECTURI_CID);
NS_DEFINE_NAMED_CID(NS_XMLHTTPREQUEST_CID);
NS_DEFINE_NAMED_CID(NS_EVENTSOURCE_CID);
NS_DEFINE_NAMED_CID(NS_DOMACTIVITY_CID);
@ -1058,7 +1060,8 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_ARCHIVEREADER_CID, false, NULL, ArchiveReaderConstructor },
{ &kNS_FORMDATA_CID, false, NULL, nsFormDataConstructor },
{ &kNS_BLOBPROTOCOLHANDLER_CID, false, NULL, nsBlobProtocolHandlerConstructor },
{ &kNS_BLOBURI_CID, false, NULL, nsBlobURIConstructor },
{ &kNS_MEDIASTREAMPROTOCOLHANDLER_CID, false, NULL, nsMediaStreamProtocolHandlerConstructor },
{ &kNS_HOSTOBJECTURI_CID, false, NULL, nsHostObjectURIConstructor },
{ &kNS_XMLHTTPREQUEST_CID, false, NULL, nsXMLHttpRequestConstructor },
{ &kNS_EVENTSOURCE_CID, false, NULL, nsEventSourceConstructor },
{ &kNS_DOMACTIVITY_CID, false, NULL, ActivityConstructor },
@ -1206,6 +1209,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ NS_ARCHIVEREADER_CONTRACTID, &kNS_ARCHIVEREADER_CID },
{ NS_FORMDATA_CONTRACTID, &kNS_FORMDATA_CID },
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX BLOBURI_SCHEME, &kNS_BLOBPROTOCOLHANDLER_CID },
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASTREAMURI_SCHEME, &kNS_MEDIASTREAMPROTOCOLHANDLER_CID },
{ NS_XMLHTTPREQUEST_CONTRACTID, &kNS_XMLHTTPREQUEST_CID },
{ NS_EVENTSOURCE_CONTRACTID, &kNS_EVENTSOURCE_CID },
{ NS_DOMACTIVITY_CONTRACTID, &kNS_DOMACTIVITY_CID },

View File

@ -3058,9 +3058,13 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// constrained height to turn into an unconstrained one.
aState.mY = startingY;
aState.mPrevBottomMargin = incomingMargin;
PushLines(aState, aLine.prev());
NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
*aKeepReflowGoing = false;
if (ShouldAvoidBreakInside(aState.mReflowState)) {
aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
} else {
PushLines(aState, aLine.prev());
NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
}
return NS_OK;
}
@ -3120,9 +3124,13 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
if (NS_INLINE_IS_BREAK_BEFORE(frameReflowStatus)) {
// None of the child block fits.
PushLines(aState, aLine.prev());
*aKeepReflowGoing = false;
NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
if (ShouldAvoidBreakInside(aState.mReflowState)) {
aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
} else {
PushLines(aState, aLine.prev());
NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
}
}
else {
// Note: line-break-after a block is a nop
@ -3141,6 +3149,11 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
collapsedBottomMargin,
aLine->mBounds, overflowAreas,
frameReflowStatus);
if (!NS_FRAME_IS_FULLY_COMPLETE(frameReflowStatus) &&
ShouldAvoidBreakInside(aState.mReflowState)) {
*aKeepReflowGoing = false;
}
if (aLine->SetCarriedOutBottomMargin(collapsedBottomMargin)) {
line_iterator nextLine = aLine;
++nextLine;
@ -3281,16 +3294,14 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
brc.GetCarriedOutBottomMargin(), collapsedBottomMargin.get(),
aState.mPrevBottomMargin);
#endif
}
else {
// None of the block fits. Determine the correct reflow status.
if (aLine == mLines.front() && !GetPrevInFlow()) {
// If it's our very first line then we need to be pushed to
// our parents next-in-flow. Therefore, return break-before
// status for our reflow status.
} else {
if ((aLine == mLines.front() && !GetPrevInFlow()) ||
ShouldAvoidBreakInside(aState.mReflowState)) {
// If it's our very first line *or* we're not at the top of the page
// and we have page-break-inside:avoid, then we need to be pushed to
// our parent's next-in-flow.
aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
}
else {
} else {
// Push the line that didn't fit and any lines that follow it
// to our next-in-flow.
PushLines(aState, aLine.prev());
@ -3399,12 +3410,10 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
void
nsBlockFrame::PushTruncatedLine(nsBlockReflowState& aState,
line_iterator aLine,
bool& aKeepReflowGoing)
bool* aKeepReflowGoing)
{
line_iterator prevLine = aLine;
--prevLine;
PushLines(aState, prevLine);
aKeepReflowGoing = false;
PushLines(aState, aLine.prev());
*aKeepReflowGoing = false;
NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
}
@ -3625,8 +3634,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// it to the next page/column where its contents can fit not
// next to a float.
lineReflowStatus = LINE_REFLOW_TRUNCATED;
// Push the line that didn't fit
PushTruncatedLine(aState, aLine, *aKeepReflowGoing);
PushTruncatedLine(aState, aLine, aKeepReflowGoing);
}
}
@ -4191,21 +4199,25 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
newY = aState.mY + dy;
}
// See if the line fit. If it doesn't we need to push it. Our first
// line will always fit.
if (!NS_FRAME_IS_FULLY_COMPLETE(aState.mReflowStatus) &&
ShouldAvoidBreakInside(aState.mReflowState)) {
aLine->AppendFloats(aState.mCurrentLineFloats);
aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
return true;
}
// See if the line fit (our first line always does).
if (mLines.front() != aLine &&
newY > aState.mBottomEdge &&
aState.mBottomEdge != NS_UNCONSTRAINEDSIZE) {
// Push this line and all of its children and anything else that
// follows to our next-in-flow
NS_ASSERTION((aState.mCurrentLine == aLine), "oops");
PushLines(aState, aLine.prev());
// Stop reflow and whack the reflow status if reflow hasn't
// already been stopped.
if (*aKeepReflowGoing) {
NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
*aKeepReflowGoing = false;
NS_ASSERTION(aState.mCurrentLine == aLine, "oops");
if (ShouldAvoidBreakInside(aState.mReflowState)) {
// All our content doesn't fit, start on the next page.
aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
} else {
// Push aLine and all of its children and anything else that
// follows to our next-in-flow.
PushTruncatedLine(aState, aLine, aKeepReflowGoing);
}
return true;
}
@ -5755,11 +5767,15 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
aReflowStatus, aState);
} while (NS_SUCCEEDED(rv) && clearanceFrame);
// An incomplete reflow status means we should split the float
// if the height is constrained (bug 145305).
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
(NS_UNCONSTRAINEDSIZE == aAdjustedAvailableSpace.height))
if (!NS_FRAME_IS_FULLY_COMPLETE(aReflowStatus) &&
ShouldAvoidBreakInside(floatRS)) {
aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
} else if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
(NS_UNCONSTRAINEDSIZE == aAdjustedAvailableSpace.height)) {
// An incomplete reflow status means we should split the float
// if the height is constrained (bug 145305).
aReflowStatus = NS_FRAME_COMPLETE;
}
if (aReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW) {
aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;

View File

@ -631,11 +631,14 @@ protected:
nsIFrame* aFrame,
bool& aMadeNewFrame);
// Push aLine, which cannot be placed on this page/column but should
// fit on a future one. Set aKeepReflowGoing to false.
/**
* Push aLine (and any after it), since it cannot be placed on this
* page/column. Set aKeepReflowGoing to false and set
* flag aState.mReflowStatus as incomplete.
*/
void PushTruncatedLine(nsBlockReflowState& aState,
line_iterator aLine,
bool& aKeepReflowGoing);
bool* aKeepReflowGoing);
nsresult SplitLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,

View File

@ -760,15 +760,28 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
// (This code is only for DISABLE_FLOAT_BREAKING_IN_COLUMNS .)
//
// Likewise, if none of the float fit, and it needs to be pushed in
// its entirety to the next page (NS_FRAME_IS_TRUNCATED), we need to
// do the same.
// its entirety to the next page (NS_FRAME_IS_TRUNCATED or
// NS_INLINE_IS_BREAK_BEFORE), we need to do the same.
if ((mContentArea.height != NS_UNCONSTRAINEDSIZE &&
adjustedAvailableSpace.height == NS_UNCONSTRAINEDSIZE &&
!mustPlaceFloat &&
aFloat->GetSize().height + floatMargin.TopBottom() >
mContentArea.YMost() - floatY) ||
NS_FRAME_IS_TRUNCATED(reflowStatus)) {
NS_FRAME_IS_TRUNCATED(reflowStatus) ||
NS_INLINE_IS_BREAK_BEFORE(reflowStatus)) {
PushFloatPastBreak(aFloat);
return false;
}
// We can't use aFloat->ShouldAvoidBreakInside(mReflowState) here since
// its mIsTopOfPage may be true even though the float isn't at the
// top when floatY > 0.
if (!mustPlaceFloat && (!mReflowState.mFlags.mIsTopOfPage || floatY > 0) &&
NS_STYLE_PAGE_BREAK_AVOID == aFloat->GetStyleDisplay()->mBreakInside &&
(!NS_FRAME_IS_FULLY_COMPLETE(reflowStatus) ||
aFloat->GetSize().height + floatMargin.TopBottom() >
mContentArea.YMost() - floatY) &&
!aFloat->GetPrevInFlow()) {
PushFloatPastBreak(aFloat);
return false;
}

View File

@ -2876,11 +2876,10 @@ nsFrame::SelectByTypeAtPoint(nsPresContext* aPresContext,
if (!offsets.content)
return NS_ERROR_FAILURE;
nsIFrame* theFrame;
int32_t offset;
const nsFrameSelection* frameSelection =
PresContext()->GetPresShell()->ConstFrameSelection();
theFrame = frameSelection->
nsIFrame* theFrame = frameSelection->
GetFrameForNodeOffset(offsets.content, offsets.offset,
nsFrameSelection::HINT(offsets.associateWithNext),
&offset);
@ -2888,8 +2887,8 @@ nsFrame::SelectByTypeAtPoint(nsPresContext* aPresContext,
return NS_ERROR_FAILURE;
nsFrame* frame = static_cast<nsFrame*>(theFrame);
return frame->PeekBackwardAndForward(aBeginAmountType, aEndAmountType,
offsets.offset, aPresContext,
return frame->PeekBackwardAndForward(aBeginAmountType, aEndAmountType,
offset, aPresContext,
aBeginAmountType != eSelectWord,
aSelectFlags);
}

View File

@ -408,6 +408,15 @@ public:
virtual const void* GetStyleDataExternal(nsStyleStructID aSID) const;
/**
* @return true if we should avoid a page/column break in this frame.
*/
bool ShouldAvoidBreakInside(const nsHTMLReflowState& aReflowState) const {
return !aReflowState.mFlags.mIsTopOfPage &&
NS_STYLE_PAGE_BREAK_AVOID == GetStyleDisplay()->mBreakInside &&
!GetPrevInFlow();
}
#ifdef DEBUG
/**
* Tracing method that writes a method enter/exit routine to the

View File

@ -1,4 +1,4 @@
<html>
<html class="reftest-wait">
<head>
</head>
<body style="direction: rtl;">
@ -13,6 +13,7 @@ var a=document.getElementById('a');
a.style.outline = '1px solid transparent';
document.body.offsetHeight;
a.style.outline = '';
document.documentElement.removeAttribute('class');
}
setTimeout(doe, 500);
</script>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head>
<title>CSS 2.1 Test Suite: dynamic changes to 'counter-increment'</title>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
@ -21,11 +21,13 @@
s.setAttribute("class", "increment");
s.appendChild(document.createTextNode("new-"));
t.insertBefore(s, t.childNodes.item(1));
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", run, false);
</script>
</head>
<body onload="setTimeout('run()', 0)">
<body>
<div id="test"><span class="increment"></span><span class="increment"></span><span class="increment"></span></div>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head>
<title>CSS 2.1 Test Suite: dynamic changes to 'counter-increment'</title>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
@ -18,11 +18,13 @@
function run() {
var t = document.getElementById("test");
t.removeChild(t.childNodes.item(1));
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", run, false);
</script>
</head>
<body onload="setTimeout('run()', 0)">
<body>
<div id="test"><span class="increment"></span><span class="increment">FAIL-</span><span class="increment"></span><span class="increment"></span></div>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head>
<title>CSS 2.1 Test Suite: dynamic changes to 'counter-increment'</title>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
@ -20,11 +20,13 @@
document.getElementById("one").removeAttribute("class");
document.getElementById("two").setAttribute("class", "increment");
document.getElementById("three").setAttribute("style", "counter-increment: c");
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", run, false);
</script>
</head>
<body onload="setTimeout('run()', 0)">
<body>
<div id="test"><span id="one" class="increment"></span><span><span class="reset"><span class="increment"></span><span id="two" class="increment"></span></span></span><span id="three" class="use"></span><span class="increment"></span></div>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head>
<title>CSS 2.1 Test Suite: dynamic changes to 'counter-increment'</title>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
@ -18,11 +18,13 @@
function run() {
var t = document.getElementById("test");
t.removeChild(t.childNodes.item(1));
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", run, false);
</script>
</head>
<body onload="setTimeout('run()', 0)">
<body>
<div id="test"><span class="increment"></span><span class="reset"></span><span class="increment"></span><span class="increment"></span></div>

View File

@ -0,0 +1,48 @@
<html class="reftest-wait">
<head>
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
<meta name="flags" content="paged">
<meta charset="utf-8">
<title>Balancing Overflow, page-break-inside:avoid</title>
<style>
/* Sets of heights that trigger crash:
100px/50px/51+px
100px/30px/74+px
Get only an assert unless you set ".d { position: absolute; }".
Trigger hang (separate issue, absolute not needed):
10px/10px/9999px
10px/10px/999999px --> "bad height" notreached
*/
/* Note: The -moz-column-gap and the backgrounds
are just added here for easier visualization */
#colset { width: 200px;
padding: 2px;
-moz-column-count: 3;
-moz-column-gap: 2px; }
#a { height: 100px; background: lightblue;}
#b { height: 50px; background: lightblue;}
#c { height: 51px; background: orange;}
</style>
<script>
function boom() {
document.getElementById('colset').offsetHeight;
document.getElementById('a').style.height = 'auto';
document.documentElement.className = ''
}
</script>
</head>
<!-- Removing whitespace in body for simpler frame trees -->
<body onload="boom()"
><div id="colset"
><div
><div id="a"></div
><div id="b"
><div id="c"></div
><div id="d"></div
></div
></div
></div
></body>
</html>

View File

@ -0,0 +1,49 @@
<html class="reftest-wait">
<head>
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
<meta name="flags" content="paged">
<meta charset="utf-8">
<title>Balancing Overflow, page-break-inside:avoid</title>
<style>
/* Sets of heights that trigger crash:
100px/50px/51+px
100px/30px/74+px
Get only an assert unless you set ".d { position: absolute; }".
Trigger hang (separate issue, absolute not needed):
10px/10px/9999px
10px/10px/999999px --> "bad height" notreached
*/
/* Note: The -moz-column-gap and the backgrounds
are just added here for easier visualization */
#colset { width: 200px;
padding: 2px;
-moz-column-count: 3;
-moz-column-gap: 2px; }
#a { height: 100px; background: lightblue;}
#b { height: 50px; background: lightblue;}
#c { height: 51px; background: orange;}
div {page-break-inside:avoid; }
</style>
<script>
function boom() {
document.getElementById('colset').offsetHeight;
document.getElementById('a').style.height = 'auto';
document.documentElement.className = ''
}
</script>
</head>
<!-- Removing whitespace in body for simpler frame trees -->
<body onload="boom()"
><div id="colset"
><div
><div id="a"></div
><div id="b"
><div id="c"></div
><div id="d"></div
></div
></div
></div
></body>
</html>

View File

@ -1,3 +1,5 @@
# For more pagination tests, see layout/reftests/w3c-css/submitted/css21/pagination/
# and layout/reftests/w3c-css/submitted/multicol3/
# Pagination tests
== abspos-breaking-000.xhtml abspos-breaking-000.ref.xhtml
== abspos-breaking-001.xhtml abspos-breaking-000.ref.xhtml
@ -57,3 +59,4 @@ fails == float-continuations-000.html float-continuations-000.ref.html
# == table-caption-splitaftercaption-9.html blank.html # bug 672654
# == table-caption-splitaftercaption-10.html blank.html # bug 672654
# == table-caption-splitaftercaption-11.html blank.html # bug 672654
== column-balancing-break-inside-avoid-2.html column-balancing-break-inside-avoid-2-ref.html

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