mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 05:15:45 +00:00
merge m-c to fx-team
This commit is contained in:
commit
c4dc91996b
@ -1170,8 +1170,7 @@ nsXULTreeGridCellAccessible::GetAttributesInternal(nsIPersistentProperties *aAtt
|
||||
if (!grandParent)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIAccessibleTable> tableAccessible =
|
||||
do_QueryInterface(static_cast<nsIAccessible*>(grandParent));
|
||||
nsCOMPtr<nsIAccessibleTable> tableAccessible = do_QueryObject(grandParent);
|
||||
|
||||
// XXX - temp fix for crash bug 516047
|
||||
if (!tableAccessible)
|
||||
|
@ -798,12 +798,6 @@ pref("accessibility.blockautorefresh", false);
|
||||
// Whether history is enabled or not.
|
||||
pref("places.history.enabled", true);
|
||||
|
||||
// The percentage of system memory that the Places database can use. Out of the
|
||||
// allowed cache size it will at most use the size of the database file.
|
||||
// Changes to this value are effective after an application restart.
|
||||
// Acceptable values are between 0 and 50.
|
||||
pref("places.database.cache_to_memory_percentage", 6);
|
||||
|
||||
// the (maximum) number of the recent visits to sample
|
||||
// when calculating frecency
|
||||
pref("places.frecency.numVisits", 10);
|
||||
|
@ -2213,8 +2213,12 @@ var gLastOpenDirectory = {
|
||||
return this._lastDir;
|
||||
},
|
||||
set path(val) {
|
||||
if (!val || !val.exists() || !val.isDirectory())
|
||||
try {
|
||||
if (!val || !val.isDirectory())
|
||||
return;
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
this._lastDir = val.clone();
|
||||
|
||||
// Don't save the last open directory pref inside the Private Browsing mode
|
||||
@ -2239,8 +2243,11 @@ function BrowserOpenFileWindow()
|
||||
fp.displayDirectory = gLastOpenDirectory.path;
|
||||
|
||||
if (fp.show() == nsIFilePicker.returnOK) {
|
||||
if (fp.file && fp.file.exists())
|
||||
gLastOpenDirectory.path = fp.file.parent.QueryInterface(Ci.nsILocalFile);
|
||||
try {
|
||||
if (fp.file)
|
||||
gLastOpenDirectory.path = fp.file.parent.QueryInterface(Ci.nsILocalFile);
|
||||
} catch(e) {
|
||||
}
|
||||
openTopWin(fp.fileURL.spec);
|
||||
}
|
||||
} catch (ex) {
|
||||
@ -7331,7 +7338,8 @@ var FeedHandler = {
|
||||
* a page is loaded or the user switches tabs to a page that has feeds.
|
||||
*/
|
||||
updateFeeds: function() {
|
||||
clearTimeout(this._updateFeedTimeout);
|
||||
if (this._updateFeedTimeout)
|
||||
clearTimeout(this._updateFeedTimeout);
|
||||
|
||||
var feeds = gBrowser.selectedBrowser.feeds;
|
||||
var haveFeeds = feeds && feeds.length > 0;
|
||||
|
@ -75,8 +75,11 @@ function deleteLocalstore() {
|
||||
var directoryService = Components.classes[nsIDirectoryServiceContractID]
|
||||
.getService(nsIProperties);
|
||||
var localstoreFile = directoryService.get("LStoreS", Components.interfaces.nsIFile);
|
||||
if (localstoreFile.exists())
|
||||
try {
|
||||
localstoreFile.remove(false);
|
||||
} catch(e) {
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
function disableAddons() {
|
||||
|
@ -16,12 +16,6 @@
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
.tab-close-button[selected="true"] {
|
||||
/* Make this button focusable so clicking on it will not focus the tab while
|
||||
it's getting closed */
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
.tab-label[pinned] {
|
||||
width: 0;
|
||||
margin-left: 0 !important;
|
||||
|
@ -4002,7 +4002,6 @@
|
||||
role="presentation"/>
|
||||
<xul:toolbarbutton anonid="close-button"
|
||||
xbl:inherits="fadein,pinned,selected"
|
||||
tabindex="-1"
|
||||
clickthrough="never"
|
||||
class="tab-close-button"/>
|
||||
</xul:hbox>
|
||||
@ -4040,25 +4039,14 @@
|
||||
<handler event="dragstart" phase="capturing">
|
||||
this.style.MozUserFocus = '';
|
||||
</handler>
|
||||
<handler event="mousedown" button="0" phase="capturing">
|
||||
<handler event="mousedown">
|
||||
<![CDATA[
|
||||
if (this.mOverCloseButton) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
else if (this.selected) {
|
||||
if (this.selected) {
|
||||
this.style.MozUserFocus = 'ignore';
|
||||
this.clientTop; // just using this to flush style updates
|
||||
}
|
||||
]]>
|
||||
</handler>
|
||||
<handler event="mousedown" button="1">
|
||||
this.style.MozUserFocus = 'ignore';
|
||||
this.clientTop;
|
||||
</handler>
|
||||
<handler event="mousedown" button="2">
|
||||
this.style.MozUserFocus = 'ignore';
|
||||
this.clientTop;
|
||||
</handler>
|
||||
<handler event="mouseup">
|
||||
this.style.MozUserFocus = '';
|
||||
</handler>
|
||||
|
@ -344,9 +344,11 @@ nsWindowsShellService::IsDefaultBrowserVista(PRBool* aIsDefaultBrowser)
|
||||
(void**)&pAAR);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
BOOL res;
|
||||
hr = pAAR->QueryAppIsDefaultAll(AL_EFFECTIVE,
|
||||
APP_REG_NAME,
|
||||
aIsDefaultBrowser);
|
||||
&res);
|
||||
*aIsDefaultBrowser = res;
|
||||
|
||||
pAAR->Release();
|
||||
return PR_TRUE;
|
||||
|
@ -1868,10 +1868,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
|
||||
.tab-close-button:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
/* Tab scrollbox arrow, tabstrip new tab and all-tabs buttons */
|
||||
|
||||
@media all and (-moz-touch-enabled) {
|
||||
|
@ -336,6 +336,7 @@ user_pref("browser.console.showInPanel", true);
|
||||
user_pref("browser.dom.window.dump.enabled", true);
|
||||
user_pref("browser.firstrun.show.localepicker", false);
|
||||
user_pref("browser.firstrun.show.uidiscovery", false);
|
||||
user_pref("browser.ui.layout.tablet", 0); // force tablet UI off
|
||||
user_pref("dom.allow_scripts_to_close_windows", true);
|
||||
user_pref("dom.disable_open_during_load", false);
|
||||
user_pref("dom.max_script_run_time", 0); // no slow script dialogs
|
||||
|
@ -3,6 +3,7 @@
|
||||
package="com.mozilla.watcher"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS"></uses-permission>
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name">
|
||||
<activity android:name=".WatcherMain"
|
||||
android:label="@string/app_name">
|
||||
|
@ -58,6 +58,7 @@ import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
@ -65,9 +66,12 @@ import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Debug;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.widget.Toast;
|
||||
@ -134,11 +138,26 @@ public class WatcherService extends Service
|
||||
|
||||
this.sPingTarget = GetIniData("watcher", "PingTarget", sIniFile, "www.mozilla.org");
|
||||
sHold = GetIniData("watcher", "delay", sIniFile, "60000");
|
||||
this.lDelay = Long.parseLong(sHold.trim());
|
||||
this.lDelay = Long.parseLong(sHold.trim());
|
||||
sHold = GetIniData("watcher", "period", sIniFile,"300000");
|
||||
this.lPeriod = Long.parseLong(sHold.trim());
|
||||
this.lPeriod = Long.parseLong(sHold.trim());
|
||||
sHold = GetIniData("watcher", "strikes", sIniFile,"3");
|
||||
this.nMaxStrikes = Integer.parseInt(sHold.trim());
|
||||
this.nMaxStrikes = Integer.parseInt(sHold.trim());
|
||||
|
||||
sHold = GetIniData("watcher", "stayon", sIniFile,"0");
|
||||
int nStayOn = Integer.parseInt(sHold.trim());
|
||||
|
||||
try {
|
||||
if (nStayOn != 0) {
|
||||
if (!Settings.System.putInt(getContentResolver(), Settings.System.STAY_ON_WHILE_PLUGGED_IN, BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB)) {
|
||||
doToast("Screen couldn't be set to Always On [stay on while plugged in]");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
String sExcept = e.getMessage();
|
||||
doToast("Screen couldn't be set to Always On [exception " + sExcept + "]");
|
||||
}
|
||||
|
||||
doToast("WatcherService created");
|
||||
}
|
||||
|
68
config/makefiles/target_export.mk
Normal file
68
config/makefiles/target_export.mk
Normal file
@ -0,0 +1,68 @@
|
||||
# -*- makefile -*-
|
||||
# vim:set ts=8 sw=8 sts=8 noet:
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chase Phillips <chase@mozilla.org>
|
||||
# Benjamin Smedberg <benjamin@smedbergs.us>
|
||||
# Jeff Walden <jwalden+code@mit.edu>
|
||||
# Joey Armstrong <joey@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
PARALLEL_DIRS_export = $(addsuffix _export,$(PARALLEL_DIRS))
|
||||
|
||||
.PHONY: export $(PARALLEL_DIRS_export)
|
||||
|
||||
###############
|
||||
## TIER targets
|
||||
###############
|
||||
export_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
@$(MAKE_TIER_SUBMAKEFILES)
|
||||
$(foreach dir,$(tier_$*_dirs),$(call SUBMAKE,export,$(dir)))
|
||||
|
||||
#################
|
||||
## Common targets
|
||||
#################
|
||||
ifdef PARALLEL_DIRS
|
||||
export:: $(PARALLEL_DIRS_export)
|
||||
|
||||
$(PARALLEL_DIRS_export): %_export: %/Makefile
|
||||
+@$(call SUBMAKE,export,$*)
|
||||
endif
|
||||
|
||||
export:: $(SUBMAKEFILES) $(MAKE_DIRS) $(if $(XPIDLSRCS),$(IDL_DIR))
|
||||
$(LOOP_OVER_DIRS)
|
||||
$(LOOP_OVER_TOOL_DIRS)
|
141
config/makefiles/target_libs.mk
Normal file
141
config/makefiles/target_libs.mk
Normal file
@ -0,0 +1,141 @@
|
||||
# -*- makefile -*-
|
||||
# vim:set ts=8 sw=8 sts=8 noet:
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chase Phillips <chase@mozilla.org>
|
||||
# Benjamin Smedberg <benjamin@smedbergs.us>
|
||||
# Jeff Walden <jwalden+code@mit.edu>
|
||||
# Joey Armstrong <joey@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
PARALLEL_DIRS_libs = $(addsuffix _libs,$(PARALLEL_DIRS))
|
||||
|
||||
.PHONY: libs $(PARALLEL_DIRS_libs)
|
||||
|
||||
###############
|
||||
## TIER targets
|
||||
###############
|
||||
libs_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
@$(MAKE_TIER_SUBMAKEFILES)
|
||||
$(foreach dir,$(tier_$*_dirs),$(call SUBMAKE,libs,$(dir)))
|
||||
|
||||
#################
|
||||
## Common targets
|
||||
#################
|
||||
ifdef PARALLEL_DIRS
|
||||
libs:: $(PARALLEL_DIRS_libs)
|
||||
|
||||
$(PARALLEL_DIRS_libs): %_libs: %/Makefile
|
||||
+@$(call SUBMAKE,libs,$*)
|
||||
endif
|
||||
|
||||
|
||||
####################
|
||||
##
|
||||
####################
|
||||
ifdef EXPORT_LIBRARY
|
||||
ifeq ($(EXPORT_LIBRARY),1)
|
||||
ifdef IS_COMPONENT
|
||||
EXPORT_LIBRARY = $(DEPTH)/staticlib/components
|
||||
else
|
||||
EXPORT_LIBRARY = $(DEPTH)/staticlib
|
||||
endif
|
||||
else
|
||||
# If EXPORT_LIBRARY has a value, we'll be installing there. We also need to cleanup there
|
||||
GARBAGE += $(foreach lib,$(LIBRARY),$(EXPORT_LIBRARY)/$(lib))
|
||||
endif
|
||||
endif # EXPORT_LIBRARY
|
||||
|
||||
libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
|
||||
ifndef NO_DIST_INSTALL
|
||||
ifdef LIBRARY
|
||||
ifdef EXPORT_LIBRARY # Stage libs that will be linked into a static build
|
||||
$(INSTALL) $(IFLAGS1) $(LIBRARY) $(EXPORT_LIBRARY)
|
||||
endif # EXPORT_LIBRARY
|
||||
ifdef DIST_INSTALL
|
||||
ifdef IS_COMPONENT
|
||||
$(error Shipping static component libs makes no sense.)
|
||||
else
|
||||
$(INSTALL) $(IFLAGS1) $(LIBRARY) $(DIST)/lib
|
||||
endif
|
||||
endif # DIST_INSTALL
|
||||
endif # LIBRARY
|
||||
ifdef SHARED_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
|
||||
$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
|
||||
ifndef NO_COMPONENTS_MANIFEST
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
|
||||
endif
|
||||
else # ! IS_COMPONENT
|
||||
ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
|
||||
ifndef NO_INSTALL_IMPORT_LIBRARY
|
||||
$(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(DIST)/lib
|
||||
endif
|
||||
else
|
||||
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DIST)/lib
|
||||
endif
|
||||
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)
|
||||
endif # IS_COMPONENT
|
||||
endif # SHARED_LIBRARY
|
||||
ifdef PROGRAM
|
||||
$(INSTALL) $(IFLAGS2) $(PROGRAM) $(FINAL_TARGET)
|
||||
endif
|
||||
ifdef SIMPLE_PROGRAMS
|
||||
$(INSTALL) $(IFLAGS2) $(SIMPLE_PROGRAMS) $(FINAL_TARGET)
|
||||
endif
|
||||
ifdef HOST_PROGRAM
|
||||
$(INSTALL) $(IFLAGS2) $(HOST_PROGRAM) $(DIST)/host/bin
|
||||
endif
|
||||
ifdef HOST_SIMPLE_PROGRAMS
|
||||
$(INSTALL) $(IFLAGS2) $(HOST_SIMPLE_PROGRAMS) $(DIST)/host/bin
|
||||
endif
|
||||
ifdef HOST_LIBRARY
|
||||
$(INSTALL) $(IFLAGS1) $(HOST_LIBRARY) $(DIST)/host/lib
|
||||
endif
|
||||
ifdef JAVA_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
$(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)/components
|
||||
else
|
||||
$(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)
|
||||
endif
|
||||
endif # JAVA_LIBRARY
|
||||
endif # !NO_DIST_INSTALL
|
||||
$(LOOP_OVER_DIRS)
|
||||
|
||||
# EOF
|
72
config/makefiles/target_tools.mk
Normal file
72
config/makefiles/target_tools.mk
Normal file
@ -0,0 +1,72 @@
|
||||
# -*- makefile -*-
|
||||
# vim:set ts=8 sw=8 sts=8 noet:
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chase Phillips <chase@mozilla.org>
|
||||
# Benjamin Smedberg <benjamin@smedbergs.us>
|
||||
# Jeff Walden <jwalden+code@mit.edu>
|
||||
# Joey Armstrong <joey@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
PARALLEL_DIRS_tools = $(addsuffix _tools,$(PARALLEL_DIRS))
|
||||
|
||||
.PHONY: tools $(PARALLEL_DIRS_tools)
|
||||
|
||||
###############
|
||||
## TIER targets
|
||||
###############
|
||||
tools_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
@$(MAKE_TIER_SUBMAKEFILES)
|
||||
$(foreach dir,$(tier_$*_dirs),$(call SUBMAKE,tools,$(dir)))
|
||||
|
||||
#################
|
||||
## Common targets
|
||||
#################
|
||||
ifdef PARALLEL_DIRS
|
||||
tools:: $(PARALLEL_DIRS_tools)
|
||||
|
||||
$(PARALLEL_DIRS_tools): %_tools: %/Makefile
|
||||
+@$(call SUBMAKE,tools,$*)
|
||||
endif
|
||||
|
||||
tools:: $(SUBMAKEFILES) $(MAKE_DIRS)
|
||||
$(LOOP_OVER_DIRS)
|
||||
ifneq (,$(strip $(TOOL_DIRS)))
|
||||
$(foreach dir,$(TOOL_DIRS),$(call SUBMAKE,libs,$(dir)))
|
||||
endif
|
||||
|
||||
# EOF
|
130
config/rules.mk
130
config/rules.mk
@ -1,3 +1,4 @@
|
||||
# -*- makefile -*-
|
||||
# vim:set ts=8 sw=8 sts=8 noet:
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
@ -24,6 +25,7 @@
|
||||
# Chase Phillips <chase@mozilla.org>
|
||||
# Benjamin Smedberg <benjamin@smedbergs.us>
|
||||
# Jeff Walden <jwalden+code@mit.edu>
|
||||
# Joey Armstrong <joey@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -489,15 +491,6 @@ LOOP_OVER_TOOL_DIRS = \
|
||||
$(foreach dir,$(TOOL_DIRS),$(call SUBMAKE,$@,$(dir)))
|
||||
endif
|
||||
|
||||
ifdef PARALLEL_DIRS
|
||||
# create a bunch of fake targets for order-only processing
|
||||
PARALLEL_DIRS_export = $(addsuffix _export,$(PARALLEL_DIRS))
|
||||
PARALLEL_DIRS_libs = $(addsuffix _libs,$(PARALLEL_DIRS))
|
||||
PARALLEL_DIRS_tools = $(addsuffix _tools,$(PARALLEL_DIRS))
|
||||
|
||||
.PHONY: $(PARALLEL_DIRS_export) $(PARALLEL_DIRS_libs) $(PARALLEL_DIRS_tools)
|
||||
endif
|
||||
|
||||
#
|
||||
# Now we can differentiate between objects used to build a library, and
|
||||
# objects used to build an executable in the same directory.
|
||||
@ -736,21 +729,6 @@ endif
|
||||
|
||||
MAKE_TIER_SUBMAKEFILES = +$(if $(tier_$*_dirs),$(MAKE) $(addsuffix /Makefile,$(tier_$*_dirs)))
|
||||
|
||||
export_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
@$(MAKE_TIER_SUBMAKEFILES)
|
||||
$(foreach dir,$(tier_$*_dirs),$(call SUBMAKE,export,$(dir)))
|
||||
|
||||
libs_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
@$(MAKE_TIER_SUBMAKEFILES)
|
||||
$(foreach dir,$(tier_$*_dirs),$(call SUBMAKE,libs,$(dir)))
|
||||
|
||||
tools_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
@$(MAKE_TIER_SUBMAKEFILES)
|
||||
$(foreach dir,$(tier_$*_dirs),$(call SUBMAKE,tools,$(dir)))
|
||||
|
||||
$(foreach tier,$(TIERS),tier_$(tier))::
|
||||
@$(ECHO) "$@: $($@_staticdirs) $($@_dirs)"
|
||||
$(foreach dir,$($@_staticdirs),$(call SUBMAKE,,$(dir)))
|
||||
@ -774,29 +752,8 @@ ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS))
|
||||
$(LOOP_OVER_TOOL_DIRS)
|
||||
endif
|
||||
|
||||
ifdef PARALLEL_DIRS
|
||||
export:: $(PARALLEL_DIRS_export)
|
||||
|
||||
$(PARALLEL_DIRS_export): %_export: %/Makefile
|
||||
+@$(call SUBMAKE,export,$*)
|
||||
endif
|
||||
|
||||
export:: $(SUBMAKEFILES) $(MAKE_DIRS) $(if $(XPIDLSRCS),$(IDL_DIR))
|
||||
$(LOOP_OVER_DIRS)
|
||||
$(LOOP_OVER_TOOL_DIRS)
|
||||
|
||||
ifdef PARALLEL_DIRS
|
||||
tools:: $(PARALLEL_DIRS_tools)
|
||||
|
||||
$(PARALLEL_DIRS_tools): %_tools: %/Makefile
|
||||
+@$(call SUBMAKE,tools,$*)
|
||||
endif
|
||||
|
||||
tools:: $(SUBMAKEFILES) $(MAKE_DIRS)
|
||||
$(LOOP_OVER_DIRS)
|
||||
ifneq (,$(strip $(TOOL_DIRS)))
|
||||
$(foreach dir,$(TOOL_DIRS),$(call SUBMAKE,libs,$(dir)))
|
||||
endif
|
||||
include $(topsrcdir)/config/makefiles/target_export.mk
|
||||
include $(topsrcdir)/config/makefiles/target_tools.mk
|
||||
|
||||
#
|
||||
# Rule to create list of libraries for final link
|
||||
@ -826,86 +783,9 @@ DSO_LDOPTS_DEPS = $(call DO_EXPAND_LIBS,$(EXTRA_DSO_LIBS) $(filter %.$(LIB_SUFFI
|
||||
GLOBAL_DEPS += Makefile Makefile.in $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk
|
||||
|
||||
##############################################
|
||||
ifdef PARALLEL_DIRS
|
||||
libs:: $(PARALLEL_DIRS_libs)
|
||||
|
||||
$(PARALLEL_DIRS_libs): %_libs: %/Makefile
|
||||
+@$(call SUBMAKE,libs,$*)
|
||||
endif
|
||||
|
||||
ifdef EXPORT_LIBRARY
|
||||
ifeq ($(EXPORT_LIBRARY),1)
|
||||
ifdef IS_COMPONENT
|
||||
EXPORT_LIBRARY = $(DEPTH)/staticlib/components
|
||||
else
|
||||
EXPORT_LIBRARY = $(DEPTH)/staticlib
|
||||
endif
|
||||
else
|
||||
# If EXPORT_LIBRARY has a value, we'll be installing there. We also need to cleanup there
|
||||
GARBAGE += $(foreach lib,$(LIBRARY),$(EXPORT_LIBRARY)/$(lib))
|
||||
endif
|
||||
endif # EXPORT_LIBRARY
|
||||
|
||||
libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
|
||||
ifndef NO_DIST_INSTALL
|
||||
ifdef LIBRARY
|
||||
ifdef EXPORT_LIBRARY # Stage libs that will be linked into a static build
|
||||
$(INSTALL) $(IFLAGS1) $(LIBRARY) $(EXPORT_LIBRARY)
|
||||
endif # EXPORT_LIBRARY
|
||||
ifdef DIST_INSTALL
|
||||
ifdef IS_COMPONENT
|
||||
$(error Shipping static component libs makes no sense.)
|
||||
else
|
||||
$(INSTALL) $(IFLAGS1) $(LIBRARY) $(DIST)/lib
|
||||
endif
|
||||
endif # DIST_INSTALL
|
||||
endif # LIBRARY
|
||||
ifdef SHARED_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
|
||||
$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
|
||||
ifndef NO_COMPONENTS_MANIFEST
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
|
||||
endif
|
||||
else # ! IS_COMPONENT
|
||||
ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
|
||||
ifndef NO_INSTALL_IMPORT_LIBRARY
|
||||
$(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(DIST)/lib
|
||||
endif
|
||||
else
|
||||
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DIST)/lib
|
||||
endif
|
||||
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)
|
||||
endif # IS_COMPONENT
|
||||
endif # SHARED_LIBRARY
|
||||
ifdef PROGRAM
|
||||
$(INSTALL) $(IFLAGS2) $(PROGRAM) $(FINAL_TARGET)
|
||||
endif
|
||||
ifdef SIMPLE_PROGRAMS
|
||||
$(INSTALL) $(IFLAGS2) $(SIMPLE_PROGRAMS) $(FINAL_TARGET)
|
||||
endif
|
||||
ifdef HOST_PROGRAM
|
||||
$(INSTALL) $(IFLAGS2) $(HOST_PROGRAM) $(DIST)/host/bin
|
||||
endif
|
||||
ifdef HOST_SIMPLE_PROGRAMS
|
||||
$(INSTALL) $(IFLAGS2) $(HOST_SIMPLE_PROGRAMS) $(DIST)/host/bin
|
||||
endif
|
||||
ifdef HOST_LIBRARY
|
||||
$(INSTALL) $(IFLAGS1) $(HOST_LIBRARY) $(DIST)/host/lib
|
||||
endif
|
||||
ifdef JAVA_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
$(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)/components
|
||||
else
|
||||
$(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)
|
||||
endif
|
||||
endif # JAVA_LIBRARY
|
||||
endif # !NO_DIST_INSTALL
|
||||
$(LOOP_OVER_DIRS)
|
||||
include $(topsrcdir)/config/makefiles/target_libs.mk
|
||||
|
||||
##############################################
|
||||
|
||||
ifndef NO_PROFILE_GUIDED_OPTIMIZE
|
||||
ifdef MOZ_PROFILE_USE
|
||||
ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_)
|
||||
|
@ -1662,13 +1662,6 @@ public:
|
||||
const nsAString& aClasses,
|
||||
nsIDOMNodeList** aReturn);
|
||||
|
||||
/**
|
||||
* Returns the widget for this document if there is one. Looks at all ancestor
|
||||
* documents to try to find a widget, so for example this can still find a
|
||||
* widget for documents in display:none frames that have no presentation.
|
||||
*/
|
||||
static nsIWidget *WidgetForDocument(nsIDocument *aDoc);
|
||||
|
||||
/**
|
||||
* Returns a layer manager to use for the given document. Basically we
|
||||
* look up the document hierarchy for the first document which has
|
||||
|
@ -51,7 +51,7 @@ interface nsIDOMClientRect;
|
||||
/**
|
||||
* This interface represents a content node that loads objects.
|
||||
*/
|
||||
[scriptable, uuid(6D8914C7-0E22-4452-8962-11B69BBE84D7)]
|
||||
[scriptable, uuid(107e8048-d00f-4711-bd21-97184ccae0b1)]
|
||||
interface nsIObjectLoadingContent : nsISupports
|
||||
{
|
||||
const unsigned long TYPE_LOADING = 0;
|
||||
@ -86,6 +86,24 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
*/
|
||||
[noscript] readonly attribute nsNPAPIPluginInstancePtr pluginInstance;
|
||||
|
||||
/**
|
||||
* Makes sure that a frame for this object exists, and that the plugin is
|
||||
* instantiated. This method does nothing if the type is not #TYPE_PLUGIN.
|
||||
* There is no guarantee that there will be a frame after this method is
|
||||
* called; for example, the node may have a display:none style. If plugin
|
||||
* instantiation is possible, it will be done synchronously by this method,
|
||||
* and the plugin instance will be returned. A success return value does not
|
||||
* necessarily mean that the instance is nonnull.
|
||||
*
|
||||
* This is a noscript method because it is internal and will go away once
|
||||
* plugin loading moves to content.
|
||||
*
|
||||
* @note If there is an error instantiating the plugin, this method will
|
||||
* trigger fallback to replacement content, and the type will change (and
|
||||
* this method will return a failure code)
|
||||
*/
|
||||
[noscript] nsNPAPIPluginInstancePtr ensureInstantiation();
|
||||
|
||||
/**
|
||||
* Tells the content about an associated object frame.
|
||||
* This can be called multiple times for different frames.
|
||||
@ -95,8 +113,6 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
*/
|
||||
[noscript] void hasNewFrame(in nsIObjectFrame aFrame);
|
||||
|
||||
[noscript] void disconnectFrame();
|
||||
|
||||
/**
|
||||
* If this object is in going to be printed, this method
|
||||
* returns the nsIObjectFrame object which should be used when
|
||||
@ -109,8 +125,4 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
in AString pluginDumpID,
|
||||
in AString browserDumpID,
|
||||
in boolean submittedCrashReport);
|
||||
|
||||
[noscript] void stopPluginInstance();
|
||||
|
||||
[noscript] void startPluginInstance();
|
||||
};
|
||||
|
@ -5517,8 +5517,9 @@ nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
|
||||
}
|
||||
}
|
||||
|
||||
nsIWidget *
|
||||
nsContentUtils::WidgetForDocument(nsIDocument *aDoc)
|
||||
static already_AddRefed<LayerManager>
|
||||
LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
|
||||
bool* aAllowRetaining)
|
||||
{
|
||||
nsIDocument* doc = aDoc;
|
||||
nsIDocument* displayDoc = doc->GetDisplayDocument();
|
||||
@ -5553,7 +5554,15 @@ nsContentUtils::WidgetForDocument(nsIDocument *aDoc)
|
||||
if (rootView) {
|
||||
nsIView* displayRoot = nsIViewManager::GetDisplayRootFor(rootView);
|
||||
if (displayRoot) {
|
||||
return displayRoot->GetNearestWidget(nsnull);
|
||||
nsIWidget* widget = displayRoot->GetNearestWidget(nsnull);
|
||||
if (widget) {
|
||||
nsRefPtr<LayerManager> manager =
|
||||
widget->
|
||||
GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT :
|
||||
nsIWidget::LAYER_MANAGER_CURRENT,
|
||||
aAllowRetaining);
|
||||
return manager.forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5562,22 +5571,6 @@ nsContentUtils::WidgetForDocument(nsIDocument *aDoc)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static already_AddRefed<LayerManager>
|
||||
LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
|
||||
bool* aAllowRetaining)
|
||||
{
|
||||
nsIWidget *widget = nsContentUtils::WidgetForDocument(aDoc);
|
||||
if (widget) {
|
||||
nsRefPtr<LayerManager> manager =
|
||||
widget->GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT :
|
||||
nsIWidget::LAYER_MANAGER_CURRENT,
|
||||
aAllowRetaining);
|
||||
return manager.forget();
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
already_AddRefed<LayerManager>
|
||||
nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
|
||||
{
|
||||
|
@ -173,7 +173,6 @@
|
||||
#include "nsIDOMPageTransitionEvent.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
#ifdef MOZ_MEDIA
|
||||
#include "nsHTMLMediaElement.h"
|
||||
#endif // MOZ_MEDIA
|
||||
@ -2740,8 +2739,7 @@ nsDocument::GetActiveElement(nsIDOMElement **aElement)
|
||||
}
|
||||
|
||||
// No focused element anywhere in this document. Try to get the BODY.
|
||||
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc =
|
||||
do_QueryInterface(static_cast<nsIDocument*>(this));
|
||||
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryObject(this);
|
||||
if (htmlDoc) {
|
||||
nsCOMPtr<nsIDOMHTMLElement> bodyElement;
|
||||
htmlDoc->GetBody(getter_AddRefs(bodyElement));
|
||||
@ -3748,11 +3746,6 @@ NotifyActivityChanged(nsIContent *aContent, void *aUnused)
|
||||
mediaElem->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
#endif
|
||||
nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aContent));
|
||||
if (objectLoadingContent) {
|
||||
nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
|
||||
olc->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -457,8 +457,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
// messageManager is wrapped in TabChildGlobal.
|
||||
nsCOMPtr<nsISupports> defaultThisValue;
|
||||
if (mChrome) {
|
||||
defaultThisValue =
|
||||
do_QueryInterface(static_cast<nsIContentFrameMessageManager*>(this));
|
||||
defaultThisValue = do_QueryObject(this);
|
||||
} else {
|
||||
defaultThisValue = aTarget;
|
||||
}
|
||||
|
@ -4874,8 +4874,7 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (hasMutationListeners) {
|
||||
nsCOMPtr<nsIDOMEventTarget> node =
|
||||
do_QueryInterface(static_cast<nsIContent *>(this));
|
||||
nsCOMPtr<nsIDOMEventTarget> node = do_QueryObject(this);
|
||||
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_ATTRMODIFIED);
|
||||
|
||||
mutation.mRelatedNode = attrNode;
|
||||
|
@ -66,7 +66,6 @@
|
||||
#include "jsobj.h"
|
||||
#include "jsgc.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
@ -576,20 +575,15 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
|
||||
}
|
||||
}
|
||||
|
||||
if (wasRegistered && oldDoc != newDoc) {
|
||||
#ifdef MOZ_MEDIA
|
||||
if (wasRegistered && oldDoc != newDoc) {
|
||||
nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aNode));
|
||||
if (domMediaElem) {
|
||||
nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aNode);
|
||||
mediaElem->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
#endif
|
||||
nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aNode));
|
||||
if (objectLoadingContent) {
|
||||
nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
|
||||
olc->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// nsImageLoadingContent needs to know when its document changes
|
||||
if (oldDoc != newDoc) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,15 +53,11 @@
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
#include "nsIThreadInternal.h"
|
||||
|
||||
class nsAsyncInstantiateEvent;
|
||||
class nsStopPluginRunnable;
|
||||
class AutoNotifier;
|
||||
class AutoFallback;
|
||||
class AutoSetInstantiatingToFalse;
|
||||
class nsObjectFrame;
|
||||
|
||||
enum PluginSupportState {
|
||||
ePluginUnsupported, // The plugin is not supported (e.g. not installed)
|
||||
@ -100,8 +96,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
friend class AutoNotifier;
|
||||
friend class AutoFallback;
|
||||
friend class AutoSetInstantiatingToFalse;
|
||||
friend class nsStopPluginRunnable;
|
||||
friend class nsAsyncInstantiateEvent;
|
||||
|
||||
public:
|
||||
// This enum's values must be the same as the constants on
|
||||
@ -144,16 +138,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
{
|
||||
mNetworkCreated = aNetworkCreated;
|
||||
}
|
||||
|
||||
// Both "InstantiatePluginInstance" methods can flush layout.
|
||||
nsresult InstantiatePluginInstance(nsIChannel* aChannel,
|
||||
nsIStreamListener** aStreamListener);
|
||||
nsresult InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI);
|
||||
|
||||
void NotifyOwnerDocumentActivityChanged();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Load the object from the given URI.
|
||||
* @param aURI The URI to load.
|
||||
@ -241,14 +226,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
nsCycleCollectionTraversalCallback &cb);
|
||||
|
||||
void CreateStaticClone(nsObjectLoadingContent* aDest) const;
|
||||
|
||||
static void DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop);
|
||||
|
||||
private:
|
||||
|
||||
void TryNotifyContentObjectWrapper();
|
||||
void NotifyContentObjectWrapper();
|
||||
|
||||
/**
|
||||
* Check whether the given request represents a successful load.
|
||||
*/
|
||||
@ -327,7 +305,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
eFlushLayout,
|
||||
eDontFlush
|
||||
};
|
||||
nsObjectFrame* GetExistingFrame(FlushType aFlushType);
|
||||
nsIObjectFrame* GetExistingFrame(FlushType aFlushType);
|
||||
|
||||
/**
|
||||
* Handle being blocked by a content policy. aStatus is the nsresult
|
||||
@ -337,6 +315,22 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
void HandleBeingBlockedByContentPolicy(nsresult aStatus,
|
||||
PRInt16 aRetval);
|
||||
|
||||
/**
|
||||
* Checks if we have a frame that's ready for instantiation, and
|
||||
* if so, calls Instantiate(). Note that this can cause the frame
|
||||
* to be deleted while we're instantiating the plugin.
|
||||
*/
|
||||
nsresult TryInstantiate(const nsACString& aMIMEType, nsIURI* aURI);
|
||||
|
||||
/**
|
||||
* Instantiates the plugin. This differs from
|
||||
* GetFrame()->Instantiate() in that it ensures that the URI will
|
||||
* be non-null, and that a MIME type will be passed. Note that
|
||||
* this can cause the frame to be deleted while we're
|
||||
* instantiating the plugin.
|
||||
*/
|
||||
nsresult Instantiate(nsIObjectFrame* aFrame, const nsACString& aMIMEType, nsIURI* aURI);
|
||||
|
||||
/**
|
||||
* Get the plugin support state for the given content node and MIME type.
|
||||
* This is used for purposes of determining whether to fire PluginNotFound
|
||||
@ -420,7 +414,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
|
||||
nsWeakFrame mPrintFrame;
|
||||
|
||||
nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
|
||||
friend class nsAsyncInstantiateEvent;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -3969,6 +3969,7 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
||||
|
||||
compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
|
||||
SH_WEBGL_SPEC,
|
||||
gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT,
|
||||
&resources);
|
||||
|
||||
nsPromiseFlatCString src(shader->Source());
|
||||
|
@ -339,7 +339,9 @@ public:
|
||||
// nsICanvasRenderingContextInternal
|
||||
NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas);
|
||||
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
|
||||
void Initialize(nsIDocShell *shell, PRInt32 width, PRInt32 height);
|
||||
NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height);
|
||||
PRBool EnsureSurface();
|
||||
NS_IMETHOD Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter);
|
||||
NS_IMETHOD GetInputStream(const char* aMimeType,
|
||||
const PRUnichar* aEncoderOptions,
|
||||
@ -380,7 +382,7 @@ public:
|
||||
{
|
||||
public:
|
||||
PathAutoSaveRestore(nsCanvasRenderingContext2D* aCtx) :
|
||||
mContext(aCtx->mThebes)
|
||||
mContext(aCtx->mThebes)
|
||||
{
|
||||
if (aCtx->mHasPath) {
|
||||
mPath = mContext->CopyPath();
|
||||
@ -460,12 +462,16 @@ protected:
|
||||
return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
|
||||
}
|
||||
|
||||
// Initialize the Thebes rendering context
|
||||
void CreateThebes();
|
||||
|
||||
// If mCanvasElement is not provided, then a docshell is
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
|
||||
// our drawing surfaces, contexts, and layers
|
||||
nsRefPtr<gfxContext> mThebes;
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
PRPackedBool mSurfaceCreated;
|
||||
|
||||
PRUint32 mSaveCount;
|
||||
|
||||
@ -527,6 +533,11 @@ protected:
|
||||
*/
|
||||
PRBool NeedToUseIntermediateSurface()
|
||||
{
|
||||
if (!mThebes) {
|
||||
// Haven't created a surface yet, default is OVER.
|
||||
return OperatorAffectsUncoveredAreas(gfxContext::OPERATOR_OVER);
|
||||
}
|
||||
|
||||
// certain operators always need an intermediate surface, except
|
||||
// with quartz since quartz does compositing differently than cairo
|
||||
return OperatorAffectsUncoveredAreas(mThebes->CurrentOperator());
|
||||
@ -541,6 +552,11 @@ protected:
|
||||
*/
|
||||
void ClearSurfaceForUnboundedSource()
|
||||
{
|
||||
if (!mThebes) {
|
||||
// Haven't created a surface yet, default is OVER.
|
||||
return;
|
||||
}
|
||||
|
||||
gfxContext::GraphicsOperator current = mThebes->CurrentOperator();
|
||||
if (current != gfxContext::OPERATOR_SOURCE)
|
||||
return;
|
||||
@ -597,8 +613,7 @@ protected:
|
||||
* Gets the pres shell from either the canvas element or the doc shell
|
||||
*/
|
||||
nsIPresShell *GetPresShell() {
|
||||
nsCOMPtr<nsIContent> content =
|
||||
do_QueryInterface(static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
|
||||
nsCOMPtr<nsIContent> content = do_QueryObject(mCanvasElement);
|
||||
if (content) {
|
||||
nsIDocument* ownerDoc = content->GetOwnerDoc();
|
||||
return ownerDoc ? ownerDoc->GetShell() : nsnull;
|
||||
@ -965,6 +980,10 @@ nsCanvasRenderingContext2D::ApplyStyle(Style aWhichStyle,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EnsureSurface()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if not using global alpha, don't optimize with dirty bit
|
||||
if (aUseGlobalAlpha)
|
||||
mDirtyStyle[aWhichStyle] = PR_FALSE;
|
||||
@ -1059,70 +1078,13 @@ nsCanvasRenderingContext2D::RedrawUser(const gfxRect& r)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
{
|
||||
nsRefPtr<gfxASurface> surface;
|
||||
|
||||
// Check that the dimensions are sane
|
||||
gfxIntSize size(width, height);
|
||||
if (gfxASurface::CheckSurfaceSize(size, 0xffff)) {
|
||||
// Zero sized surfaces have problems, so just use a 1 by 1.
|
||||
if (height == 0 || width == 0) {
|
||||
mZero = PR_TRUE;
|
||||
height = 1;
|
||||
width = 1;
|
||||
} else {
|
||||
mZero = PR_FALSE;
|
||||
}
|
||||
|
||||
gfxASurface::gfxImageFormat format = GetImageFormat();
|
||||
|
||||
if (!PR_GetEnv("MOZ_CANVAS_IMAGE_SURFACE")) {
|
||||
nsCOMPtr<nsIContent> content =
|
||||
do_QueryInterface(static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
|
||||
nsIDocument* ownerDoc = nsnull;
|
||||
if (content)
|
||||
ownerDoc = content->GetOwnerDoc();
|
||||
nsRefPtr<LayerManager> layerManager = nsnull;
|
||||
|
||||
if (ownerDoc)
|
||||
layerManager =
|
||||
nsContentUtils::PersistentLayerManagerForDocument(ownerDoc);
|
||||
|
||||
if (layerManager) {
|
||||
surface = layerManager->CreateOptimalSurface(gfxIntSize(width, height), format);
|
||||
} else {
|
||||
surface = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(width, height), gfxASurface::ContentFromFormat(format));
|
||||
}
|
||||
}
|
||||
|
||||
if (!surface || surface->CairoStatus()) {
|
||||
// If we couldn't create a surface of the type we want, fall back
|
||||
// to an image surface. This lets us handle surface sizes that
|
||||
// the underlying cairo backend might not handle.
|
||||
surface = new gfxImageSurface(gfxIntSize(width, height), format);
|
||||
if (!surface || surface->CairoStatus()) {
|
||||
surface = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (surface) {
|
||||
if (gCanvasMemoryReporter == nsnull) {
|
||||
gCanvasMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasMemory);
|
||||
NS_RegisterMemoryReporter(gCanvasMemoryReporter);
|
||||
}
|
||||
|
||||
gCanvasMemoryUsed += width * height * 4;
|
||||
JSContext* context = nsContentUtils::GetCurrentJSContext();
|
||||
if (context) {
|
||||
JS_updateMallocCounter(context, width * height * 4);
|
||||
}
|
||||
}
|
||||
|
||||
return InitializeWithSurface(NULL, surface, width, height);
|
||||
Initialize(NULL, width, height);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height) {
|
||||
void
|
||||
nsCanvasRenderingContext2D::Initialize(nsIDocShell *docShell, PRInt32 width, PRInt32 height)
|
||||
{
|
||||
Reset();
|
||||
|
||||
NS_ASSERTION(!docShell ^ !mCanvasElement, "Cannot set both docshell and canvas element");
|
||||
@ -1131,19 +1093,9 @@ nsCanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *docShell, gfxASur
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
mSurface = surface;
|
||||
mThebes = surface ? new gfxContext(mSurface) : nsnull;
|
||||
mResetLayer = PR_TRUE;
|
||||
|
||||
/* Create dummy surfaces here */
|
||||
if (mSurface == nsnull || mSurface->CairoStatus() != 0 ||
|
||||
mThebes == nsnull || mThebes->HasError())
|
||||
{
|
||||
mSurface = new gfxImageSurface(gfxIntSize(1,1), gfxASurface::ImageFormatARGB32);
|
||||
mThebes = new gfxContext(mSurface);
|
||||
} else {
|
||||
mValid = PR_TRUE;
|
||||
}
|
||||
mValid = PR_TRUE;
|
||||
mSurfaceCreated = PR_FALSE;
|
||||
|
||||
// set up the initial canvas defaults
|
||||
mStyleStack.Clear();
|
||||
@ -1157,6 +1109,19 @@ nsCanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *docShell, gfxASur
|
||||
state->colorStyles[STYLE_SHADOW] = NS_RGBA(0,0,0,0);
|
||||
DirtyAllStyles();
|
||||
|
||||
// always force a redraw, because if the surface dimensions were reset
|
||||
// then the surface became cleared, and we need to redraw everything.
|
||||
Redraw();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
nsCanvasRenderingContext2D::CreateThebes()
|
||||
{
|
||||
mThebes = new gfxContext(mSurface);
|
||||
mSurfaceCreated = PR_TRUE;
|
||||
|
||||
mThebes->SetOperator(gfxContext::OPERATOR_CLEAR);
|
||||
mThebes->NewPath();
|
||||
mThebes->Rectangle(gfxRect(0, 0, mWidth, mHeight));
|
||||
@ -1167,17 +1132,105 @@ nsCanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *docShell, gfxASur
|
||||
mThebes->SetMiterLimit(10.0);
|
||||
mThebes->SetLineCap(gfxContext::LINE_CAP_BUTT);
|
||||
mThebes->SetLineJoin(gfxContext::LINE_JOIN_MITER);
|
||||
mThebes->SetFillRule(gfxContext::FILL_RULE_WINDING);
|
||||
|
||||
mThebes->NewPath();
|
||||
}
|
||||
|
||||
// always force a redraw, because if the surface dimensions were reset
|
||||
// then the surface became cleared, and we need to redraw everything.
|
||||
Redraw();
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *docShell,
|
||||
gfxASurface *surface,
|
||||
PRInt32 width,
|
||||
PRInt32 height)
|
||||
{
|
||||
Initialize(docShell, width, height);
|
||||
|
||||
mSurface = surface;
|
||||
CreateThebes();
|
||||
return mValid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsCanvasRenderingContext2D::EnsureSurface()
|
||||
{
|
||||
if (!mValid) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (mSurface && mThebes && mSurfaceCreated) {
|
||||
if (mSurface->CairoStatus()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxASurface> surface;
|
||||
|
||||
// Check that the dimensions are sane
|
||||
if (gfxASurface::CheckSurfaceSize(gfxIntSize(mWidth, mHeight), 0xffff)) {
|
||||
// Zero sized surfaces have problems, so just use a 1 by 1.
|
||||
if (mHeight == 0 || mWidth == 0) {
|
||||
mZero = PR_TRUE;
|
||||
mHeight = 1;
|
||||
mWidth = 1;
|
||||
} else {
|
||||
mZero = PR_FALSE;
|
||||
}
|
||||
|
||||
gfxASurface::gfxImageFormat format = GetImageFormat();
|
||||
|
||||
if (!PR_GetEnv("MOZ_CANVAS_IMAGE_SURFACE")) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryObject(mCanvasElement);
|
||||
nsIDocument* ownerDoc = nsnull;
|
||||
if (content)
|
||||
ownerDoc = content->GetOwnerDoc();
|
||||
nsRefPtr<LayerManager> layerManager = nsnull;
|
||||
|
||||
if (ownerDoc)
|
||||
layerManager =
|
||||
nsContentUtils::PersistentLayerManagerForDocument(ownerDoc);
|
||||
|
||||
if (layerManager) {
|
||||
surface = layerManager->CreateOptimalSurface(gfxIntSize(mWidth, mHeight), format);
|
||||
} else {
|
||||
surface = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(mWidth, mHeight), gfxASurface::ContentFromFormat(format));
|
||||
}
|
||||
}
|
||||
|
||||
if (!surface || surface->CairoStatus()) {
|
||||
// If we couldn't create a surface of the type we want, fall back
|
||||
// to an image surface. This lets us handle surface sizes that
|
||||
// the underlying cairo backend might not handle.
|
||||
surface = new gfxImageSurface(gfxIntSize(mWidth, mHeight), format);
|
||||
if (!surface || surface->CairoStatus()) {
|
||||
surface = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (surface) {
|
||||
if (gCanvasMemoryReporter == nsnull) {
|
||||
gCanvasMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasMemory);
|
||||
NS_RegisterMemoryReporter(gCanvasMemoryReporter);
|
||||
}
|
||||
|
||||
gCanvasMemoryUsed += mWidth * mHeight * 4;
|
||||
JSContext* context = nsContentUtils::GetCurrentJSContext();
|
||||
if (context) {
|
||||
JS_updateMallocCounter(context, mWidth * mHeight * 4);
|
||||
}
|
||||
} else {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
mSurface = surface;
|
||||
CreateThebes();
|
||||
|
||||
if (mSurface->CairoStatus()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetIsOpaque(PRBool isOpaque)
|
||||
{
|
||||
@ -1219,9 +1272,7 @@ nsCanvasRenderingContext2D::Render(gfxContext *ctx, gfxPattern::GraphicsFilter a
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!mValid || !mSurface ||
|
||||
mSurface->CairoStatus() ||
|
||||
mThebes->HasError())
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface);
|
||||
@ -1250,9 +1301,7 @@ nsCanvasRenderingContext2D::GetInputStream(const char *aMimeType,
|
||||
const PRUnichar *aEncoderOptions,
|
||||
nsIInputStream **aStream)
|
||||
{
|
||||
if (!mValid || !mSurface ||
|
||||
mSurface->CairoStatus() ||
|
||||
mThebes->HasError())
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
@ -1337,6 +1386,9 @@ nsCanvasRenderingContext2D::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Save()
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
ContextState state = CurrentState();
|
||||
mStyleStack.AppendElement(state);
|
||||
mThebes->Save();
|
||||
@ -1347,6 +1399,9 @@ nsCanvasRenderingContext2D::Save()
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Restore()
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mSaveCount == 0)
|
||||
return NS_OK;
|
||||
|
||||
@ -1367,6 +1422,9 @@ nsCanvasRenderingContext2D::Restore()
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Scale(float x, float y)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(x,y))
|
||||
return NS_OK;
|
||||
|
||||
@ -1377,6 +1435,9 @@ nsCanvasRenderingContext2D::Scale(float x, float y)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Rotate(float angle)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(angle))
|
||||
return NS_OK;
|
||||
|
||||
@ -1387,6 +1448,9 @@ nsCanvasRenderingContext2D::Rotate(float angle)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Translate(float x, float y)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(x,y))
|
||||
return NS_OK;
|
||||
|
||||
@ -1397,6 +1461,9 @@ nsCanvasRenderingContext2D::Translate(float x, float y)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Transform(float m11, float m12, float m21, float m22, float dx, float dy)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(m11,m12,m21,m22,dx,dy))
|
||||
return NS_OK;
|
||||
|
||||
@ -1409,6 +1476,9 @@ nsCanvasRenderingContext2D::Transform(float m11, float m12, float m21, float m22
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetTransform(float m11, float m12, float m21, float m22, float dx, float dy)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(m11,m12,m21,m22,dx,dy))
|
||||
return NS_OK;
|
||||
|
||||
@ -1424,6 +1494,9 @@ nsCanvasRenderingContext2D::SetMozCurrentTransform(JSContext* cx,
|
||||
{
|
||||
nsresult rv;
|
||||
gfxMatrix newCTM;
|
||||
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!JSValToMatrix(cx, matrix, &newCTM, &rv)) {
|
||||
return rv;
|
||||
@ -1438,6 +1511,9 @@ NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetMozCurrentTransform(JSContext* cx,
|
||||
jsval* matrix)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return MatrixToJSVal(mThebes->CurrentMatrix(), cx, matrix);
|
||||
}
|
||||
|
||||
@ -1447,6 +1523,9 @@ nsCanvasRenderingContext2D::SetMozCurrentTransformInverse(JSContext* cx,
|
||||
{
|
||||
nsresult rv;
|
||||
gfxMatrix newCTMInverse;
|
||||
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!JSValToMatrix(cx, matrix, &newCTMInverse, &rv)) {
|
||||
return rv;
|
||||
@ -1648,6 +1727,9 @@ NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetMozFillRule(const nsAString& aString)
|
||||
{
|
||||
gfxContext::FillRule rule;
|
||||
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (aString.EqualsLiteral("evenodd"))
|
||||
rule = gfxContext::FILL_RULE_EVEN_ODD;
|
||||
@ -1664,6 +1746,9 @@ nsCanvasRenderingContext2D::SetMozFillRule(const nsAString& aString)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetMozFillRule(nsAString& aString)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
switch (mThebes->CurrentFillRule()) {
|
||||
case gfxContext::FILL_RULE_WINDING:
|
||||
aString.AssignLiteral("nonzero"); break;
|
||||
@ -1888,6 +1973,9 @@ nsCanvasRenderingContext2D::ShadowInitialize(const gfxRect& extents, gfxAlphaBox
|
||||
void
|
||||
nsCanvasRenderingContext2D::ShadowFinalize(gfxAlphaBoxBlur& blur)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return;
|
||||
|
||||
ApplyStyle(STYLE_SHADOW);
|
||||
// canvas matrix was already applied, don't apply it twice, but do
|
||||
// apply the shadow offset
|
||||
@ -1902,6 +1990,9 @@ nsCanvasRenderingContext2D::ShadowFinalize(gfxAlphaBoxBlur& blur)
|
||||
nsresult
|
||||
nsCanvasRenderingContext2D::DrawPath(Style style, gfxRect *dirtyRect)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRBool doUseIntermediateSurface = PR_FALSE;
|
||||
|
||||
if (mSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
|
||||
@ -2029,6 +2120,9 @@ nsCanvasRenderingContext2D::DrawPath(Style style, gfxRect *dirtyRect)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::ClearRect(float x, float y, float w, float h)
|
||||
{
|
||||
if (!mSurfaceCreated)
|
||||
return NS_OK;
|
||||
|
||||
if (!FloatValidate(x,y,w,h))
|
||||
return NS_OK;
|
||||
|
||||
@ -2046,6 +2140,9 @@ nsCanvasRenderingContext2D::ClearRect(float x, float y, float w, float h)
|
||||
nsresult
|
||||
nsCanvasRenderingContext2D::DrawRect(const gfxRect& rect, Style style)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(rect.X(), rect.Y(), rect.Width(), rect.Height()))
|
||||
return NS_OK;
|
||||
|
||||
@ -2084,6 +2181,9 @@ nsCanvasRenderingContext2D::StrokeRect(float x, float y, float w, float h)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::BeginPath()
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mHasPath = PR_FALSE;
|
||||
mThebes->NewPath();
|
||||
return NS_OK;
|
||||
@ -2092,6 +2192,9 @@ nsCanvasRenderingContext2D::BeginPath()
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::ClosePath()
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mThebes->ClosePath();
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2119,6 +2222,9 @@ nsCanvasRenderingContext2D::Stroke()
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Clip()
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mThebes->Clip();
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2126,6 +2232,9 @@ nsCanvasRenderingContext2D::Clip()
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::MoveTo(float x, float y)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(x,y))
|
||||
return NS_OK;
|
||||
|
||||
@ -2137,6 +2246,9 @@ nsCanvasRenderingContext2D::MoveTo(float x, float y)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::LineTo(float x, float y)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(x,y))
|
||||
return NS_OK;
|
||||
|
||||
@ -2148,6 +2260,9 @@ nsCanvasRenderingContext2D::LineTo(float x, float y)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::QuadraticCurveTo(float cpx, float cpy, float x, float y)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(cpx,cpy,x,y))
|
||||
return NS_OK;
|
||||
|
||||
@ -2168,6 +2283,9 @@ nsCanvasRenderingContext2D::BezierCurveTo(float cp1x, float cp1y,
|
||||
float cp2x, float cp2y,
|
||||
float x, float y)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(cp1x,cp1y,cp2x,cp2y,x,y))
|
||||
return NS_OK;
|
||||
|
||||
@ -2182,6 +2300,9 @@ nsCanvasRenderingContext2D::BezierCurveTo(float cp1x, float cp1y,
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::ArcTo(float x1, float y1, float x2, float y2, float radius)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(x1,y1,x2,y2,radius))
|
||||
return NS_OK;
|
||||
|
||||
@ -2241,6 +2362,9 @@ nsCanvasRenderingContext2D::ArcTo(float x1, float y1, float x2, float y2, float
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Arc(float x, float y, float r, float startAngle, float endAngle, PRBool ccw)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(x,y,r,startAngle,endAngle))
|
||||
return NS_OK;
|
||||
|
||||
@ -2260,6 +2384,9 @@ nsCanvasRenderingContext2D::Arc(float x, float y, float r, float startAngle, flo
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Rect(float x, float y, float w, float h)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(x,y,w,h))
|
||||
return NS_OK;
|
||||
|
||||
@ -2772,7 +2899,13 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
|
||||
|
||||
GetAppUnitsValues(&processor.mAppUnitsPerDevPixel, NULL);
|
||||
processor.mPt = gfxPoint(aX, aY);
|
||||
processor.mThebes = mThebes;
|
||||
nsRefPtr<nsRenderingContext> ctx;
|
||||
if (mThebes) {
|
||||
processor.mThebes = mThebes;
|
||||
} else {
|
||||
ctx = presShell->GetReferenceRenderingContext();
|
||||
processor.mThebes = ctx->ThebesContext();
|
||||
}
|
||||
processor.mOp = aOp;
|
||||
processor.mBoundingBox = gfxRect(0, 0, 0, 0);
|
||||
processor.mDoMeasureBoundingBox = doDrawShadow || !mIsEntireFrameInvalid;
|
||||
@ -2806,6 +2939,11 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
|
||||
if (aOp==TEXT_DRAW_OPERATION_MEASURE)
|
||||
return NS_OK;
|
||||
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
processor.mThebes = mThebes;
|
||||
|
||||
// offset pt.x based on text align
|
||||
gfxFloat anchorX;
|
||||
|
||||
@ -3026,6 +3164,9 @@ nsCanvasRenderingContext2D::MakeTextRun(const PRUnichar* aText,
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetLineWidth(float width)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(width) || width <= 0.0)
|
||||
return NS_OK;
|
||||
|
||||
@ -3036,6 +3177,9 @@ nsCanvasRenderingContext2D::SetLineWidth(float width)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetLineWidth(float *width)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gfxFloat d = mThebes->CurrentLineWidth();
|
||||
*width = static_cast<float>(d);
|
||||
return NS_OK;
|
||||
@ -3044,6 +3188,9 @@ nsCanvasRenderingContext2D::GetLineWidth(float *width)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetLineCap(const nsAString& capstyle)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gfxContext::GraphicsLineCap cap;
|
||||
|
||||
if (capstyle.EqualsLiteral("butt"))
|
||||
@ -3063,6 +3210,9 @@ nsCanvasRenderingContext2D::SetLineCap(const nsAString& capstyle)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetLineCap(nsAString& capstyle)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gfxContext::GraphicsLineCap cap = mThebes->CurrentLineCap();
|
||||
|
||||
if (cap == gfxContext::LINE_CAP_BUTT)
|
||||
@ -3080,6 +3230,9 @@ nsCanvasRenderingContext2D::GetLineCap(nsAString& capstyle)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetLineJoin(const nsAString& joinstyle)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gfxContext::GraphicsLineJoin j;
|
||||
|
||||
if (joinstyle.EqualsLiteral("round"))
|
||||
@ -3099,6 +3252,9 @@ nsCanvasRenderingContext2D::SetLineJoin(const nsAString& joinstyle)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetLineJoin(nsAString& joinstyle)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gfxContext::GraphicsLineJoin j = mThebes->CurrentLineJoin();
|
||||
|
||||
if (j == gfxContext::LINE_JOIN_ROUND)
|
||||
@ -3116,6 +3272,9 @@ nsCanvasRenderingContext2D::GetLineJoin(nsAString& joinstyle)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetMiterLimit(float miter)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(miter) || miter <= 0.0)
|
||||
return NS_OK;
|
||||
|
||||
@ -3126,6 +3285,9 @@ nsCanvasRenderingContext2D::SetMiterLimit(float miter)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetMiterLimit(float *miter)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gfxFloat d = mThebes->CurrentMiterLimit();
|
||||
*miter = static_cast<float>(d);
|
||||
return NS_OK;
|
||||
@ -3134,6 +3296,9 @@ nsCanvasRenderingContext2D::GetMiterLimit(float *miter)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetMozDash(JSContext *cx, const jsval& patternArray)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
AutoFallibleTArray<gfxFloat, 10> dashes;
|
||||
nsresult rv = JSValToDashArray(cx, patternArray, dashes);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
@ -3146,6 +3311,9 @@ nsCanvasRenderingContext2D::SetMozDash(JSContext *cx, const jsval& patternArray)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetMozDash(JSContext* cx, jsval* dashArray)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
AutoFallibleTArray<gfxFloat, 10> dashes;
|
||||
if (!mThebes->CurrentDash(dashes, nsnull)) {
|
||||
dashes.SetLength(0);
|
||||
@ -3156,6 +3324,9 @@ nsCanvasRenderingContext2D::GetMozDash(JSContext* cx, jsval* dashArray)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetMozDashOffset(float offset)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(offset)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
@ -3180,6 +3351,9 @@ nsCanvasRenderingContext2D::SetMozDashOffset(float offset)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetMozDashOffset(float* offset)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*offset = float(mThebes->CurrentDashOffset());
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3187,6 +3361,9 @@ nsCanvasRenderingContext2D::GetMozDashOffset(float* offset)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::IsPointInPath(float x, float y, PRBool *retVal)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!FloatValidate(x,y)) {
|
||||
*retVal = PR_FALSE;
|
||||
return NS_OK;
|
||||
@ -3214,6 +3391,9 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
|
||||
float a6, float a7, float a8,
|
||||
PRUint8 optional_argc)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!imgElt) {
|
||||
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
|
||||
}
|
||||
@ -3398,6 +3578,9 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gfxContext::GraphicsOperator thebes_op;
|
||||
|
||||
#define CANVAS_OP_TO_THEBES_OP(cvsop,thebesop) \
|
||||
@ -3427,6 +3610,9 @@ nsCanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetGlobalCompositeOperation(nsAString& op)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gfxContext::GraphicsOperator thebes_op = mThebes->CurrentOperator();
|
||||
|
||||
#define CANVAS_OP_TO_THEBES_OP(cvsop,thebesop) \
|
||||
@ -3457,6 +3643,9 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY
|
||||
const nsAString& aBGColor,
|
||||
PRUint32 flags)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ENSURE_ARG(aWindow != nsnull);
|
||||
|
||||
// protect against too-large surfaces that will cause allocation
|
||||
@ -3547,6 +3736,9 @@ nsCanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* aElem, float a
|
||||
const nsAString& aBGColor,
|
||||
PRUint32 flags)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ENSURE_ARG(aElem != nsnull);
|
||||
|
||||
// We can't allow web apps to call this until we fix at least the
|
||||
@ -3660,7 +3852,7 @@ NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetImageData_explicit(PRInt32 x, PRInt32 y, PRUint32 w, PRUint32 h,
|
||||
PRUint8 *aData, PRUint32 aDataLen)
|
||||
{
|
||||
if (!mValid)
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!mCanvasElement && !mDocShell) {
|
||||
@ -3792,7 +3984,7 @@ nsCanvasRenderingContext2D::PutImageData_explicit(PRInt32 x, PRInt32 y, PRUint32
|
||||
PRBool hasDirtyRect, PRInt32 dirtyX, PRInt32 dirtyY,
|
||||
PRInt32 dirtyWidth, PRInt32 dirtyHeight)
|
||||
{
|
||||
if (!mValid)
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (w == 0 || h == 0)
|
||||
@ -3898,7 +4090,7 @@ nsCanvasRenderingContext2D::PutImageData_explicit(PRInt32 x, PRInt32 y, PRUint32
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetThebesSurface(gfxASurface **surface)
|
||||
{
|
||||
if (!mSurface) {
|
||||
if (!EnsureSurface()) {
|
||||
*surface = nsnull;
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
@ -3954,7 +4146,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
CanvasLayer *aOldLayer,
|
||||
LayerManager *aManager)
|
||||
{
|
||||
if (!mValid)
|
||||
if (!EnsureSurface())
|
||||
return nsnull;
|
||||
|
||||
if (!mResetLayer && aOldLayer &&
|
||||
|
@ -605,8 +605,7 @@ protected:
|
||||
* Gets the pres shell from either the canvas element or the doc shell
|
||||
*/
|
||||
nsIPresShell *GetPresShell() {
|
||||
nsCOMPtr<nsIContent> content =
|
||||
do_QueryInterface(static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
|
||||
nsCOMPtr<nsIContent> content = do_QueryObject(mCanvasElement);
|
||||
if (content) {
|
||||
nsIDocument* ownerDoc = content->GetOwnerDoc();
|
||||
return ownerDoc ? ownerDoc->GetShell() : nsnull;
|
||||
@ -1235,8 +1234,7 @@ nsCanvasRenderingContext2DAzure::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
if (size.width <= 0xFFFF && size.height <= 0xFFFF &&
|
||||
size.width >= 0 && size.height >= 0) {
|
||||
SurfaceFormat format = GetSurfaceFormat();
|
||||
nsCOMPtr<nsIContent> content =
|
||||
do_QueryInterface(static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
|
||||
nsCOMPtr<nsIContent> content = do_QueryObject(mCanvasElement);
|
||||
nsIDocument* ownerDoc = nsnull;
|
||||
if (content) {
|
||||
ownerDoc = content->GetOwnerDoc();
|
||||
|
@ -85,7 +85,8 @@ if (!gl) {
|
||||
testPassed("Successfully enabled OES_texture_float extension");
|
||||
runTextureCreationTest(testProgram, true);
|
||||
runRenderTargetTest(testProgram);
|
||||
runUniqueObjectTest();
|
||||
// bug 683216, see the discussion in bug 630672
|
||||
// runUniqueObjectTest();
|
||||
}
|
||||
}
|
||||
|
||||
|
25
content/canvas/test/webgl/remove-uniqueObjectTest.patch
Normal file
25
content/canvas/test/webgl/remove-uniqueObjectTest.patch
Normal file
@ -0,0 +1,25 @@
|
||||
# HG changeset patch
|
||||
# Parent 6c8a909977d32284bbddd60a45e1780e824b5d7c
|
||||
diff --git a/content/canvas/test/webgl/conformance/oes-texture-float.html b/content/canvas/test/webgl/conformance/oes-texture-float.html
|
||||
--- a/content/canvas/test/webgl/conformance/oes-texture-float.html
|
||||
+++ b/content/canvas/test/webgl/conformance/oes-texture-float.html
|
||||
@@ -80,17 +80,18 @@ if (!gl) {
|
||||
runTextureCreationTest(testProgram, false);
|
||||
|
||||
if (!gl.getExtension("OES_texture_float")) {
|
||||
testPassed("No OES_texture_float support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled OES_texture_float extension");
|
||||
runTextureCreationTest(testProgram, true);
|
||||
runRenderTargetTest(testProgram);
|
||||
- runUniqueObjectTest();
|
||||
+ // bug 683216, see the discussion in bug 630672
|
||||
+ // runUniqueObjectTest();
|
||||
}
|
||||
}
|
||||
|
||||
// Needs to be global for shouldBe to see it.
|
||||
var pixels;
|
||||
|
||||
function allocateTexture()
|
||||
{
|
@ -1214,8 +1214,7 @@ nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
// If the element is subject to constraint validaton and is invalid, we need
|
||||
// to update our internal counter.
|
||||
if (aUpdateValidity) {
|
||||
nsCOMPtr<nsIConstraintValidation> cvElmt =
|
||||
do_QueryInterface(static_cast<nsGenericHTMLElement*>(aChild));
|
||||
nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aChild);
|
||||
if (cvElmt &&
|
||||
cvElmt->IsCandidateForConstraintValidation() && !cvElmt->IsValid()) {
|
||||
UpdateValidity(PR_FALSE);
|
||||
@ -1301,8 +1300,7 @@ nsHTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
|
||||
// If the element was subject to constraint validaton and is invalid, we need
|
||||
// to update our internal counter.
|
||||
if (aUpdateValidity) {
|
||||
nsCOMPtr<nsIConstraintValidation> cvElmt =
|
||||
do_QueryInterface(static_cast<nsGenericHTMLElement*>(aChild));
|
||||
nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aChild);
|
||||
if (cvElmt &&
|
||||
cvElmt->IsCandidateForConstraintValidation() && !cvElmt->IsValid()) {
|
||||
UpdateValidity(PR_TRUE);
|
||||
@ -2350,8 +2348,7 @@ nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
list->AppendElement(newFirst ? content : aChild);
|
||||
|
||||
|
||||
nsCOMPtr<nsISupports> listSupports =
|
||||
do_QueryInterface(static_cast<nsIDOMNodeList*>(list));
|
||||
nsCOMPtr<nsISupports> listSupports = do_QueryObject(list);
|
||||
|
||||
// Replace the element with the list.
|
||||
NS_ENSURE_TRUE(mNameLookupTable.Put(aName, listSupports),
|
||||
|
@ -2255,8 +2255,7 @@ ImageContainer* nsHTMLMediaElement::GetImageContainer()
|
||||
return nsnull;
|
||||
|
||||
// Only video frames need an image container.
|
||||
nsCOMPtr<nsIDOMHTMLVideoElement> video =
|
||||
do_QueryInterface(static_cast<nsIContent*>(this));
|
||||
nsCOMPtr<nsIDOMHTMLVideoElement> video = do_QueryObject(this);
|
||||
if (!video)
|
||||
return nsnull;
|
||||
|
||||
@ -2283,7 +2282,7 @@ nsresult nsHTMLMediaElement::DispatchAudioAvailableEvent(float* aFrameBuffer,
|
||||
nsAutoArrayPtr<float> frameBuffer(aFrameBuffer);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(GetOwnerDoc());
|
||||
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(static_cast<nsIContent*>(this)));
|
||||
nsCOMPtr<nsIDOMEventTarget> target(do_QueryObject(this));
|
||||
NS_ENSURE_TRUE(domDoc && target, NS_ERROR_INVALID_ARG);
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
@ -2496,8 +2495,7 @@ void nsHTMLMediaElement::NotifyAddedSource()
|
||||
nsIContent* nsHTMLMediaElement::GetNextSource()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> thisDomNode =
|
||||
do_QueryInterface(static_cast<nsGenericElement*>(this));
|
||||
nsCOMPtr<nsIDOMNode> thisDomNode = do_QueryObject(this);
|
||||
|
||||
mSourceLoadCandidate = nsnull;
|
||||
|
||||
|
@ -47,7 +47,6 @@
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -145,13 +144,20 @@ PluginStreamListener::SetupPlugin()
|
||||
// nsObjectFrame does that at the end of reflow.
|
||||
shell->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(embed));
|
||||
if (!olc) {
|
||||
nsIFrame* frame = embed->GetPrimaryFrame();
|
||||
if (!frame) {
|
||||
mPluginDoc->AllowNormalInstantiation();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIObjectFrame* objFrame = do_QueryFrame(frame);
|
||||
if (!objFrame) {
|
||||
mPluginDoc->AllowNormalInstantiation();
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
nsObjectLoadingContent* olcc = static_cast<nsObjectLoadingContent*>(olc.get());
|
||||
nsresult rv = olcc->InstantiatePluginInstance(mPluginDoc->GetType().get(),
|
||||
mDocument->nsIDocument::GetDocumentURI());
|
||||
|
||||
nsresult rv = objFrame->Instantiate(mPluginDoc->GetType().get(),
|
||||
mDocument->nsIDocument::GetDocumentURI());
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -349,7 +355,7 @@ PluginDocument::Print()
|
||||
nsIObjectFrame* objectFrame =
|
||||
do_QueryFrame(mPluginContent->GetPrimaryFrame());
|
||||
if (objectFrame) {
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsCOMPtr<nsNPAPIPluginInstance> pi;
|
||||
objectFrame->GetPluginInstance(getter_AddRefs(pi));
|
||||
if (pi) {
|
||||
NPPrint npprint;
|
||||
|
@ -780,8 +780,8 @@ void nsBuiltinDecoder::SeekingStoppedAtEnd()
|
||||
seekWasAborted = PR_TRUE;
|
||||
} else {
|
||||
UnpinForSeek();
|
||||
fireEnded = mNextState != PLAY_STATE_PLAYING;
|
||||
ChangeState(fireEnded ? PLAY_STATE_ENDED : mNextState);
|
||||
fireEnded = PR_TRUE;
|
||||
ChangeState(PLAY_STATE_ENDED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,10 +330,13 @@ function MediaTestManager() {
|
||||
// to start every test, but if you call started() you *must* call finish()
|
||||
// else you'll timeout.
|
||||
this.runTests = function(tests, startTest) {
|
||||
this.startTime = new Date();
|
||||
SimpleTest.info("Started " + this.startTime + " (" + this.startTime.getTime()/1000 + "s)");
|
||||
this.testNum = 0;
|
||||
this.tests = tests;
|
||||
this.startTest = startTest;
|
||||
this.tokens = [];
|
||||
this.isShutdown = false;
|
||||
// Always wait for explicit finish.
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
this.nextTest();
|
||||
@ -355,7 +358,7 @@ function MediaTestManager() {
|
||||
// Remove the element from the list of running tests.
|
||||
this.tokens.splice(i, 1);
|
||||
}
|
||||
if (this.tokens.length == 0) {
|
||||
if (this.tokens.length < PARALLEL_TESTS) {
|
||||
this.nextTest();
|
||||
}
|
||||
}
|
||||
@ -368,14 +371,7 @@ function MediaTestManager() {
|
||||
// thread stacks' address space.
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
Components.utils.forceGC();
|
||||
if (this.testNum == this.tests.length && !DEBUG_TEST_LOOP_FOREVER) {
|
||||
if (this.onFinished) {
|
||||
this.onFinished();
|
||||
}
|
||||
mediaTestCleanup();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
while (this.testNum < this.tests.length && this.tokens.length < PARALLEL_TESTS) {
|
||||
var test = this.tests[this.testNum];
|
||||
var token = (test.name ? (test.name + "-"): "") + this.testNum;
|
||||
@ -391,11 +387,23 @@ function MediaTestManager() {
|
||||
|
||||
// Do the init. This should start the test.
|
||||
this.startTest(test, token);
|
||||
|
||||
}
|
||||
if (this.tokens.length == 0) {
|
||||
// No tests were added, we must have tried everything, exit.
|
||||
|
||||
if (this.testNum == this.tests.length &&
|
||||
!DEBUG_TEST_LOOP_FOREVER &&
|
||||
this.tokens.length == 0 &&
|
||||
!this.isShutdown)
|
||||
{
|
||||
this.isShutdown = true;
|
||||
if (this.onFinished) {
|
||||
this.onFinished();
|
||||
}
|
||||
mediaTestCleanup();
|
||||
var end = new Date();
|
||||
SimpleTest.info("Finished at " + end + " (" + (end.getTime() / 1000) + "s)");
|
||||
SimpleTest.info("Running time: " + (end.getTime() - this.startTime.getTime())/1000 + "s");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,13 @@ var gFragmentParams = [
|
||||
{ fragment: "#t=3,3", start: null, end: null },
|
||||
{ fragment: "#t=7,3", start: null, end: null },
|
||||
{ fragment: "#t=7,15", start: 7, end: null },
|
||||
{ fragment: "#t=15,20", start: 9.287981, end: null, todo: "See Bug 679262" },
|
||||
{ fragment: "#t=15,20", start: 9.287981, end: null },
|
||||
{ fragment: "#t=5", start: 5, end: null },
|
||||
{ fragment: "#t=5.5", start: 5.5, end: null },
|
||||
{ fragment: "#t=5,", start: null, end: null },
|
||||
{ fragment: "#t=,5", start: 0, end: 5 },
|
||||
{ fragment: "#t=2.5,5.5", start: 2.5, end: 5.5 },
|
||||
{ fragment: "#t=1,2.5", start: 1, end: 2.5 },
|
||||
{ fragment: "#t=2.5,5.5", start: 2.5, end: 5.5, todo: "See Bug 682141" },
|
||||
{ fragment: "#t=1,2.5", start: 1, end: 2.5, todo: "See Bug 682141" },
|
||||
{ fragment: "#t=,15", start: 0, end: null }
|
||||
];
|
||||
|
||||
|
@ -1490,6 +1490,7 @@ nsSVGElement::SetLength(nsIAtom* aName, const nsSVGLength2 &aLength)
|
||||
for (PRUint32 i = 0; i < lengthInfo.mLengthCount; i++) {
|
||||
if (aName == *lengthInfo.mLengthInfo[i].mName) {
|
||||
lengthInfo.mLengths[i] = aLength;
|
||||
DidChangeLength(i, PR_TRUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2342,16 +2343,14 @@ nsSVGElement::GetAnimatedAttr(PRInt32 aNamespaceID, nsIAtom* aName)
|
||||
// Transforms:
|
||||
nsCOMPtr<nsIDOMSVGAnimatedTransformList> transformList;
|
||||
if (aName == nsGkAtoms::transform) {
|
||||
nsCOMPtr<nsIDOMSVGTransformable> transformable(
|
||||
do_QueryInterface(static_cast<nsIContent*>(this)));
|
||||
nsCOMPtr<nsIDOMSVGTransformable> transformable(do_QueryObject(this));
|
||||
if (!transformable)
|
||||
return nsnull;
|
||||
nsresult rv = transformable->GetTransform(getter_AddRefs(transformList));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
}
|
||||
if (aName == nsGkAtoms::gradientTransform) {
|
||||
nsCOMPtr<nsIDOMSVGGradientElement> gradientElement(
|
||||
do_QueryInterface(static_cast<nsIContent*>(this)));
|
||||
nsCOMPtr<nsIDOMSVGGradientElement> gradientElement(do_QueryObject(this));
|
||||
if (!gradientElement)
|
||||
return nsnull;
|
||||
|
||||
@ -2359,8 +2358,7 @@ nsSVGElement::GetAnimatedAttr(PRInt32 aNamespaceID, nsIAtom* aName)
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
}
|
||||
if (aName == nsGkAtoms::patternTransform) {
|
||||
nsCOMPtr<nsIDOMSVGPatternElement> patternElement(
|
||||
do_QueryInterface(static_cast<nsIContent*>(this)));
|
||||
nsCOMPtr<nsIDOMSVGPatternElement> patternElement(do_QueryObject(this));
|
||||
if (!patternElement)
|
||||
return nsnull;
|
||||
|
||||
|
@ -647,14 +647,28 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
|
||||
}
|
||||
}
|
||||
// Look for <link rel="dns-prefetch" href="hostname">
|
||||
// and look for <link rel="next" href="hostname"> like in HTML sink
|
||||
if (nodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) {
|
||||
nsAutoString relVal;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
|
||||
if (relVal.EqualsLiteral("dns-prefetch")) {
|
||||
nsAutoString hrefVal;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchDNS(hrefVal);
|
||||
if (!relVal.IsEmpty()) {
|
||||
// XXX seems overkill to generate this string array
|
||||
nsAutoTArray<nsString, 4> linkTypes;
|
||||
nsStyleLinkElement::ParseLinkTypes(relVal, linkTypes);
|
||||
PRBool hasPrefetch = linkTypes.Contains(NS_LITERAL_STRING("prefetch"));
|
||||
if (hasPrefetch || linkTypes.Contains(NS_LITERAL_STRING("next"))) {
|
||||
nsAutoString hrefVal;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchHref(hrefVal, aContent, hasPrefetch);
|
||||
}
|
||||
}
|
||||
if (linkTypes.Contains(NS_LITERAL_STRING("dns-prefetch"))) {
|
||||
nsAutoString hrefVal;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchDNS(hrefVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -580,8 +580,7 @@ nsXULElement::IsFocusable(PRInt32 *aTabIndex, PRBool aWithMouse)
|
||||
return PR_FALSE;
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIDOMXULControlElement> xulControl =
|
||||
do_QueryInterface(static_cast<nsIContent*>(this));
|
||||
nsCOMPtr<nsIDOMXULControlElement> xulControl = do_QueryObject(this);
|
||||
if (xulControl) {
|
||||
// a disabled element cannot be focused and is not part of the tab order
|
||||
PRBool disabled;
|
||||
@ -958,7 +957,7 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
|
||||
// and cells going away.
|
||||
// First, retrieve the tree.
|
||||
// Check first whether this element IS the tree
|
||||
controlElement = do_QueryInterface(static_cast<nsIContent*>(this));
|
||||
controlElement = do_QueryObject(this);
|
||||
|
||||
// If it's not, look at our parent
|
||||
if (!controlElement)
|
||||
@ -2057,7 +2056,7 @@ NS_IMETHODIMP
|
||||
nsXULElement::Focus()
|
||||
{
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(static_cast<nsIContent*>(this));
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryObject(this);
|
||||
return fm ? fm->SetFocus(this, 0) : NS_OK;
|
||||
}
|
||||
|
||||
|
@ -379,7 +379,7 @@ bool nsDSURIContentListener::CheckFrameOptions(nsIRequest* request)
|
||||
|
||||
// cancel the load and display about:blank
|
||||
httpChannel->Cancel(NS_BINDING_ABORTED);
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(static_cast<nsIDocShell*>(mDocShell)));
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_QueryObject(mDocShell));
|
||||
if (webNav) {
|
||||
webNav->LoadURI(NS_LITERAL_STRING("about:blank").get(),
|
||||
0, nsnull, nsnull, nsnull);
|
||||
|
@ -5083,7 +5083,7 @@ nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
|
||||
|
||||
// Pull the global scope polluter out of the prototype chain so
|
||||
// that it can be freed.
|
||||
::JS_SetPrototype(cx, obj, ::JS_GetPrototype(cx, proto));
|
||||
::JS_SplicePrototype(cx, obj, ::JS_GetPrototype(cx, proto));
|
||||
|
||||
break;
|
||||
}
|
||||
@ -5105,7 +5105,7 @@ nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSObject *gsp = ::JS_NewObject(cx, &sGlobalScopePolluterClass, nsnull, obj);
|
||||
JSObject *gsp = ::JS_NewObjectWithUniqueType(cx, &sGlobalScopePolluterClass, nsnull, obj);
|
||||
if (!gsp) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -5118,9 +5118,7 @@ nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
|
||||
while ((proto = ::JS_GetPrototype(cx, o))) {
|
||||
if (JS_GET_CLASS(cx, proto) == sObjectClass) {
|
||||
// Set the global scope polluters prototype to Object.prototype
|
||||
if (!::JS_SetPrototype(cx, gsp, proto)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
::JS_SplicePrototype(cx, gsp, proto);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -5130,9 +5128,7 @@ nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
|
||||
|
||||
// And then set the prototype of the object whose prototype was
|
||||
// Object.prototype to be the global scope polluter.
|
||||
if (!::JS_SetPrototype(cx, o, gsp)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
::JS_SplicePrototype(cx, o, gsp);
|
||||
|
||||
if (!::JS_SetPrivate(cx, gsp, doc)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
@ -9234,7 +9230,14 @@ nsHTMLPluginObjElementSH::GetPluginInstanceIfSafe(nsIXPConnectWrappedNative *wra
|
||||
nsCOMPtr<nsIObjectLoadingContent> objlc(do_QueryInterface(content));
|
||||
NS_ASSERTION(objlc, "Object nodes must implement nsIObjectLoadingContent");
|
||||
|
||||
return objlc->GetPluginInstance(_result);
|
||||
// If it's not safe to run script we'll only return the instance if it
|
||||
// exists.
|
||||
if (!nsContentUtils::IsSafeToRunScript()) {
|
||||
return objlc->GetPluginInstance(_result);
|
||||
}
|
||||
|
||||
// Make sure that there is a plugin
|
||||
return objlc->EnsureInstantiation(_result);
|
||||
}
|
||||
|
||||
// Check if proto is already in obj's prototype chain.
|
||||
@ -9338,9 +9341,20 @@ nsHTMLPluginObjElementSH::SetupProtoChain(nsIXPConnectWrappedNative *wrapper,
|
||||
|
||||
if (!pi_obj) {
|
||||
// Didn't get a plugin instance JSObject, nothing we can do then.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (IsObjInProtoChain(cx, obj, pi_obj)) {
|
||||
// We must have re-entered ::PostCreate() from nsObjectFrame()
|
||||
// (through the EnsureInstantiation() call in
|
||||
// GetPluginInstanceIfSafe()), this means that we've already done what
|
||||
// we're about to do in this function so we can just return here.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// If we got an xpconnect-wrapped plugin object, set obj's
|
||||
// prototype's prototype to the scriptable plugin.
|
||||
|
||||
|
@ -103,6 +103,8 @@ nsDOMMemoryReporter::GetAmount(PRInt64* aAmount) {
|
||||
*aAmount = 0;
|
||||
|
||||
nsGlobalWindow::WindowByIdTable* windows = nsGlobalWindow::GetWindowsTable();
|
||||
NS_ENSURE_TRUE(windows, NS_OK);
|
||||
|
||||
windows->Enumerate(GetWindowsMemoryUsage, aAmount);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1101,8 +1101,7 @@ nsGlobalWindow::CleanUp(PRBool aIgnoreModalDialog)
|
||||
{
|
||||
if (IsOuterWindow() && !aIgnoreModalDialog) {
|
||||
nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
|
||||
nsCOMPtr<nsIDOMModalContentWindow>
|
||||
dlg(do_QueryInterface(static_cast<nsPIDOMWindow*>(inner)));
|
||||
nsCOMPtr<nsIDOMModalContentWindow> dlg(do_QueryObject(inner));
|
||||
if (dlg) {
|
||||
// The window we're trying to clean up is the outer window of a
|
||||
// modal dialog. Defer cleanup until the window closes, and let
|
||||
@ -9779,8 +9778,7 @@ nsGlobalWindow::BuildURIfromBase(const char *aURL, nsIURI **aBuiltURI,
|
||||
if (!scx || !mDocument)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMChromeWindow> chrome_win =
|
||||
do_QueryInterface(static_cast<nsIDOMWindow *>(this));
|
||||
nsCOMPtr<nsIDOMChromeWindow> chrome_win = do_QueryObject(this);
|
||||
|
||||
if (nsContentUtils::IsCallerChrome() && !chrome_win) {
|
||||
// If open() is called from chrome on a non-chrome window, we'll
|
||||
|
@ -915,6 +915,7 @@ static const char js_methodjit_chrome_str[] = JS_OPTIONS_DOT_STR "methodjit.ch
|
||||
static const char js_profiling_content_str[] = JS_OPTIONS_DOT_STR "jitprofiling.content";
|
||||
static const char js_profiling_chrome_str[] = JS_OPTIONS_DOT_STR "jitprofiling.chrome";
|
||||
static const char js_methodjit_always_str[] = JS_OPTIONS_DOT_STR "methodjit_always";
|
||||
static const char js_typeinfer_str[] = JS_OPTIONS_DOT_STR "typeinference";
|
||||
static const char js_memlog_option_str[] = JS_OPTIONS_DOT_STR "mem.log";
|
||||
|
||||
int
|
||||
@ -947,6 +948,7 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
|
||||
js_profiling_chrome_str :
|
||||
js_profiling_content_str);
|
||||
PRBool useMethodJITAlways = Preferences::GetBool(js_methodjit_always_str);
|
||||
PRBool useTypeInference = !chromeWindow && Preferences::GetBool(js_typeinfer_str);
|
||||
nsCOMPtr<nsIXULRuntime> xr = do_GetService(XULRUNTIME_SERVICE_CONTRACTID);
|
||||
if (xr) {
|
||||
PRBool safeMode = PR_FALSE;
|
||||
@ -955,6 +957,7 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
|
||||
useTraceJIT = PR_FALSE;
|
||||
useMethodJIT = PR_FALSE;
|
||||
useProfiling = PR_FALSE;
|
||||
useTypeInference = PR_FALSE;
|
||||
useMethodJITAlways = PR_TRUE;
|
||||
}
|
||||
}
|
||||
@ -979,6 +982,11 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
|
||||
else
|
||||
newDefaultJSOptions &= ~JSOPTION_METHODJIT_ALWAYS;
|
||||
|
||||
if (useTypeInference)
|
||||
newDefaultJSOptions |= JSOPTION_TYPE_INFERENCE;
|
||||
else
|
||||
newDefaultJSOptions &= ~JSOPTION_TYPE_INFERENCE;
|
||||
|
||||
#ifdef DEBUG
|
||||
// In debug builds, warnings are enabled in chrome context if
|
||||
// javascript.options.strict.debug is true
|
||||
|
@ -290,8 +290,7 @@ AsyncConnectionHelper::Run()
|
||||
#ifdef DEBUG
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsISupports> handlerSupports(do_QueryInterface(handler));
|
||||
nsCOMPtr<nsISupports> thisSupports =
|
||||
do_QueryInterface(static_cast<nsIRunnable*>(this));
|
||||
nsCOMPtr<nsISupports> thisSupports = do_QueryObject(this);
|
||||
NS_ASSERTION(thisSupports == handlerSupports, "Mismatch!");
|
||||
}
|
||||
#endif
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include "nsIDOMHTMLElement.idl"
|
||||
|
||||
/**
|
||||
* The nsIDOMHTMLVideoElement interface is the interface to a HTML
|
||||
* The nsIDOMHTMLSourceElement interface is the interface to a HTML
|
||||
* <source> element.
|
||||
*
|
||||
* For more information on this interface, please see
|
||||
|
52
dom/interfaces/threads/Makefile.in
Normal file
52
dom/interfaces/threads/Makefile.in
Normal file
@ -0,0 +1,52 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
# Ben Turner <bent.mozilla@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = dom
|
||||
XPIDL_MODULE = dom_threads
|
||||
GRE_MODULE = 1
|
||||
|
||||
XPIDLSRCS = nsIDOMWorkers.idl
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
156
dom/interfaces/threads/nsIDOMWorkers.idl
Normal file
156
dom/interfaces/threads/nsIDOMWorkers.idl
Normal file
@ -0,0 +1,156 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* From http://www.whatwg.org/specs/web-workers/current-work
|
||||
*/
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
|
||||
interface nsIDOMEventListener;
|
||||
|
||||
[scriptable, uuid(ab3725b8-3fca-40cc-a42c-92fb154ef01d)]
|
||||
interface nsIWorkerMessagePort : nsISupports
|
||||
{
|
||||
void postMessage(/* in JSObject aMessage */);
|
||||
};
|
||||
|
||||
[scriptable, uuid(508f2d49-e9a0-4fe8-bd33-321820173b4a)]
|
||||
interface nsIWorkerMessageEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute DOMString data;
|
||||
readonly attribute DOMString origin;
|
||||
|
||||
readonly attribute nsISupports source;
|
||||
|
||||
void initMessageEvent(in DOMString aTypeArg,
|
||||
in boolean aCanBubbleArg,
|
||||
in boolean aCancelableArg,
|
||||
in DOMString aDataArg,
|
||||
in DOMString aOriginArg,
|
||||
in nsISupports aSourceArg);
|
||||
};
|
||||
|
||||
[scriptable, uuid(73d82c1d-05de-49c9-a23b-7121ff09a67a)]
|
||||
interface nsIWorkerErrorEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute DOMString message;
|
||||
readonly attribute DOMString filename;
|
||||
|
||||
readonly attribute unsigned long lineno;
|
||||
|
||||
void initErrorEvent(in DOMString aTypeArg,
|
||||
in boolean aCanBubbleArg,
|
||||
in boolean aCancelableArg,
|
||||
in DOMString aMessageArg,
|
||||
in DOMString aFilenameArg,
|
||||
in unsigned long aLinenoArg);
|
||||
};
|
||||
|
||||
[scriptable, uuid(17a005c3-4f2f-4bb6-b169-c181fa6873de)]
|
||||
interface nsIWorkerLocation : nsISupports
|
||||
{
|
||||
readonly attribute AUTF8String href;
|
||||
readonly attribute AUTF8String protocol;
|
||||
readonly attribute AUTF8String host;
|
||||
readonly attribute AUTF8String hostname;
|
||||
readonly attribute AUTF8String port;
|
||||
readonly attribute AUTF8String pathname;
|
||||
readonly attribute AUTF8String search;
|
||||
readonly attribute AUTF8String hash;
|
||||
|
||||
AUTF8String toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(74fb665a-e477-4ce2-b3c6-c58b1b28b6c3)]
|
||||
interface nsIWorkerNavigator : nsISupports
|
||||
{
|
||||
readonly attribute DOMString appName;
|
||||
readonly attribute DOMString appVersion;
|
||||
readonly attribute DOMString platform;
|
||||
readonly attribute DOMString userAgent;
|
||||
};
|
||||
|
||||
[scriptable, uuid(c111e7d3-8044-4458-aa7b-637696ffb841)]
|
||||
interface nsIWorkerGlobalScope : nsISupports
|
||||
{
|
||||
readonly attribute nsIWorkerGlobalScope self;
|
||||
readonly attribute nsIWorkerNavigator navigator;
|
||||
readonly attribute nsIWorkerLocation location;
|
||||
|
||||
attribute nsIDOMEventListener onerror;
|
||||
};
|
||||
|
||||
[scriptable, uuid(5c55ea4b-e4ac-4ceb-bfeb-46bd5e521b8a)]
|
||||
interface nsIWorkerScope : nsIWorkerGlobalScope
|
||||
{
|
||||
void postMessage(/* in JSObject aMessage */);
|
||||
|
||||
void close();
|
||||
|
||||
attribute nsIDOMEventListener onmessage;
|
||||
attribute nsIDOMEventListener onclose;
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(b90b7561-b5e2-4545-84b0-280dbaaa94ea)]
|
||||
interface nsIAbstractWorker : nsIDOMEventTarget
|
||||
{
|
||||
attribute nsIDOMEventListener onerror;
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(daf945c3-8d29-4724-8939-dd383f7d27a7)]
|
||||
interface nsIWorker : nsIAbstractWorker
|
||||
{
|
||||
void postMessage(/* in JSObject aMessage */);
|
||||
|
||||
attribute nsIDOMEventListener onmessage;
|
||||
|
||||
void terminate();
|
||||
};
|
||||
|
||||
[scriptable, uuid(cfc4bb32-ca83-4d58-9b6f-66f8054a333a)]
|
||||
interface nsIWorkerFactory : nsISupports
|
||||
{
|
||||
nsIWorker newChromeWorker(/* in DOMString aScriptURL */);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#define NS_WORKERFACTORY_CONTRACTID \
|
||||
"@mozilla.org/threads/workerfactory;1"
|
||||
%}
|
@ -687,8 +687,10 @@ bool
|
||||
ContentChild::RecvAddPermission(const IPC::Permission& permission)
|
||||
{
|
||||
#if MOZ_PERMISSIONS
|
||||
nsRefPtr<nsPermissionManager> permissionManager =
|
||||
nsPermissionManager::GetSingleton();
|
||||
nsCOMPtr<nsIPermissionManager> permissionManagerIface =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
nsPermissionManager* permissionManager =
|
||||
static_cast<nsPermissionManager*>(permissionManagerIface.get());
|
||||
NS_ABORT_IF_FALSE(permissionManager,
|
||||
"We have no permissionManager in the Content process !");
|
||||
|
||||
|
@ -269,6 +269,7 @@ ContentParent::OnChannelConnected(int32 pid)
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
|
||||
{
|
||||
@ -276,6 +277,20 @@ DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
|
||||
->PostTask(FROM_HERE,
|
||||
new DeleteTask<GeckoChildProcessHost>(aSubprocess));
|
||||
}
|
||||
|
||||
// This runnable only exists to delegate ownership of the
|
||||
// ContentParent to this runnable, until it's deleted by the event
|
||||
// system.
|
||||
struct DelayedDeleteContentParentTask : public nsRunnable
|
||||
{
|
||||
DelayedDeleteContentParentTask(ContentParent* aObj) : mObj(aObj) { }
|
||||
|
||||
// No-op
|
||||
NS_IMETHODIMP Run() { return NS_OK; }
|
||||
|
||||
nsRefPtr<ContentParent> mObj;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@ -366,6 +381,15 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
PostTask(FROM_HERE,
|
||||
NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess));
|
||||
mSubprocess = NULL;
|
||||
|
||||
// IPDL rules require actors to live on past ActorDestroy, but it
|
||||
// may be that the kungFuDeathGrip above is the last reference to
|
||||
// |this|. If so, when we go out of scope here, we're deleted and
|
||||
// all hell breaks loose.
|
||||
//
|
||||
// This runnable ensures that a reference to |this| lives on at
|
||||
// least until after the current task finishes running.
|
||||
NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
|
||||
}
|
||||
|
||||
TabParent*
|
||||
@ -455,8 +479,10 @@ bool
|
||||
ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions)
|
||||
{
|
||||
#ifdef MOZ_PERMISSIONS
|
||||
nsRefPtr<nsPermissionManager> permissionManager =
|
||||
nsPermissionManager::GetSingleton();
|
||||
nsCOMPtr<nsIPermissionManager> permissionManagerIface =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
nsPermissionManager* permissionManager =
|
||||
static_cast<nsPermissionManager*>(permissionManagerIface.get());
|
||||
NS_ABORT_IF_FALSE(permissionManager,
|
||||
"We have no permissionManager in the Chrome process !");
|
||||
|
||||
|
@ -246,6 +246,17 @@ PluginPRLibrary::AsyncSetWindow(NPP instance, NPWindow* window)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
nsresult
|
||||
PluginPRLibrary::HandleGUIEvent(NPP instance, const nsGUIEvent& anEvent,
|
||||
bool* handled)
|
||||
{
|
||||
nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
|
||||
NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
PluginPRLibrary::GetImage(NPP instance, ImageContainer* aContainer, Image** aImage)
|
||||
{
|
||||
|
@ -154,6 +154,10 @@ public:
|
||||
NS_OVERRIDE
|
||||
virtual nsresult EndUpdateBackground(NPP instance,
|
||||
gfxContext* aCtx, const nsIntRect&);
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
virtual nsresult HandleGUIEvent(NPP instance,
|
||||
const nsGUIEvent& anEvent, bool* handled);
|
||||
#endif
|
||||
|
||||
private:
|
||||
NP_InitializeFunc mNP_Initialize;
|
||||
|
@ -80,6 +80,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
|
||||
#endif
|
||||
mRunning(NOT_STARTED),
|
||||
mWindowless(PR_FALSE),
|
||||
mWindowlessLocal(PR_FALSE),
|
||||
mTransparent(PR_FALSE),
|
||||
mUsesDOMForCursor(PR_FALSE),
|
||||
mInPluginInitCall(PR_FALSE),
|
||||
@ -659,6 +660,12 @@ NPError nsNPAPIPluginInstance::SetWindowless(PRBool aWindowless)
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError nsNPAPIPluginInstance::SetWindowlessLocal(PRBool aWindowlessLocal)
|
||||
{
|
||||
mWindowlessLocal = aWindowlessLocal;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError nsNPAPIPluginInstance::SetTransparent(PRBool aTransparent)
|
||||
{
|
||||
mTransparent = aTransparent;
|
||||
@ -835,6 +842,23 @@ nsNPAPIPluginInstance::AsyncSetWindow(NPWindow* window)
|
||||
return library->AsyncSetWindow(&mNPP, window);
|
||||
}
|
||||
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
nsresult
|
||||
nsNPAPIPluginInstance::HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled)
|
||||
{
|
||||
if (RUNNING != mRunning) {
|
||||
*handled = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return library->HandleGUIEvent(&mNPP, anEvent, handled);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsNPAPIPluginInstance::GetImage(ImageContainer* aContainer, Image** aImage)
|
||||
{
|
||||
|
@ -114,6 +114,9 @@ public:
|
||||
nsresult SetOwner(nsIPluginInstanceOwner *aOwner);
|
||||
nsresult ShowStatus(const char* message);
|
||||
nsresult InvalidateOwner();
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
nsresult HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled);
|
||||
#endif
|
||||
|
||||
nsNPAPIPlugin* GetPlugin();
|
||||
|
||||
@ -124,6 +127,8 @@ public:
|
||||
|
||||
NPError SetWindowless(PRBool aWindowless);
|
||||
|
||||
NPError SetWindowlessLocal(PRBool aWindowlessLocal);
|
||||
|
||||
NPError SetTransparent(PRBool aTransparent);
|
||||
|
||||
NPError SetWantsAllNetworkStreams(PRBool aWantsAllNetworkStreams);
|
||||
@ -212,6 +217,7 @@ protected:
|
||||
// these are used to store the windowless properties
|
||||
// which the browser will later query
|
||||
PRPackedBool mWindowless;
|
||||
PRPackedBool mWindowlessLocal;
|
||||
PRPackedBool mTransparent;
|
||||
PRPackedBool mUsesDOMForCursor;
|
||||
|
||||
|
@ -3656,6 +3656,12 @@ nsPluginHost::NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow)
|
||||
return PLUG_NewPluginNativeWindow(aPluginNativeWindow);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPluginHost::DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
|
||||
{
|
||||
return PLUG_DeletePluginNativeWindow(aPluginNativeWindow);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPluginHost::InstantiateDummyJavaPlugin(nsIPluginInstanceOwner *aOwner)
|
||||
{
|
||||
|
@ -148,6 +148,7 @@ public:
|
||||
char **outPostData, PRUint32 *outPostDataLen);
|
||||
nsresult CreateTempFileToPost(const char *aPostDataURL, nsIFile **aTmpFile);
|
||||
nsresult NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow);
|
||||
nsresult DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow);
|
||||
nsresult InstantiateDummyJavaPlugin(nsIPluginInstanceOwner *aOwner);
|
||||
|
||||
void AddIdleTimeTarget(nsIPluginInstanceOwner* objectFrame, PRBool isVisible);
|
||||
|
@ -99,7 +99,6 @@ using mozilla::DefaultXDisplay;
|
||||
static NS_DEFINE_CID(kRangeCID, NS_RANGE_CID);
|
||||
|
||||
#include "nsWidgetsCID.h"
|
||||
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
|
||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
|
||||
#ifdef XP_WIN
|
||||
@ -178,7 +177,7 @@ nsPluginInstanceOwner::NotifyPaintWaiter(nsDisplayListBuilder* aBuilder)
|
||||
#ifdef XP_MACOSX
|
||||
static void DrawPlugin(ImageContainer* aContainer, void* aPluginInstanceOwner)
|
||||
{
|
||||
nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetFrame();
|
||||
nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetOwner();
|
||||
if (frame) {
|
||||
frame->UpdateImageLayer(aContainer, gfxRect(0,0,0,0));
|
||||
}
|
||||
@ -285,16 +284,14 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
|
||||
// create nsPluginNativeWindow object, it is derived from NPWindow
|
||||
// struct and allows to manipulate native window procedure
|
||||
nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
|
||||
mPluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (mPluginHost)
|
||||
mPluginHost->NewPluginNativeWindow(&mPluginWindow);
|
||||
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (pluginHost)
|
||||
pluginHost->NewPluginNativeWindow(&mPluginWindow);
|
||||
else
|
||||
mPluginWindow = nsnull;
|
||||
|
||||
mObjectFrame = nsnull;
|
||||
mContent = nsnull;
|
||||
mTagText = nsnull;
|
||||
mWidgetCreationComplete = PR_FALSE;
|
||||
#ifdef XP_MACOSX
|
||||
memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext));
|
||||
#ifndef NP_NO_QUICKDRAW
|
||||
@ -313,6 +310,7 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
|
||||
mNumCachedParams = 0;
|
||||
mCachedAttrParamNames = nsnull;
|
||||
mCachedAttrParamValues = nsnull;
|
||||
mDestroyWidget = PR_FALSE;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#ifndef NP_NO_QUICKDRAW
|
||||
@ -369,8 +367,13 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
|
||||
mTagText = nsnull;
|
||||
}
|
||||
|
||||
PLUG_DeletePluginNativeWindow(mPluginWindow);
|
||||
mPluginWindow = nsnull;
|
||||
// clean up plugin native window object
|
||||
nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
|
||||
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (pluginHost) {
|
||||
pluginHost->DeletePluginNativeWindow(mPluginWindow);
|
||||
mPluginWindow = nsnull;
|
||||
}
|
||||
|
||||
if (mInstance) {
|
||||
mInstance->InvalidateOwner();
|
||||
@ -1105,6 +1108,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||
!mCachedAttrParamNames,
|
||||
"re-cache of attrs/params not implemented! use the DOM "
|
||||
"node directy instead");
|
||||
NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// Convert to a 16-bit count. Subtract 2 in case we add an extra
|
||||
// "src" or "wmode" entry below.
|
||||
@ -1177,6 +1181,9 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||
}
|
||||
}
|
||||
|
||||
// We're done with DOM method calls now. Make sure we still have a frame.
|
||||
NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Convert to a 16-bit count.
|
||||
PRUint32 cparams = ourParams.Count();
|
||||
if (cparams < 0x0000FFFF) {
|
||||
@ -1681,6 +1688,29 @@ nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
nsresult nsPluginInstanceOwner::Text(nsIDOMEvent* aTextEvent)
|
||||
{
|
||||
if (mInstance) {
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aTextEvent));
|
||||
if (privateEvent) {
|
||||
nsEvent *event = privateEvent->GetInternalNSEvent();
|
||||
if (event && event->eventStructType == NS_TEXT_EVENT) {
|
||||
nsEventStatus rv = ProcessEvent(*static_cast<nsGUIEvent*>(event));
|
||||
if (nsEventStatus_eConsumeNoDefault == rv) {
|
||||
aTextEvent->PreventDefault();
|
||||
aTextEvent->StopPropagation();
|
||||
}
|
||||
}
|
||||
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchTextToPlugin failed, textEvent null");
|
||||
}
|
||||
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchTextToPlugin failed, privateEvent null");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult nsPluginInstanceOwner::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
@ -1864,6 +1894,11 @@ nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent)
|
||||
if (eventType.EqualsLiteral("keypress")) {
|
||||
return KeyPress(aEvent);
|
||||
}
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
if (eventType.EqualsLiteral("text")) {
|
||||
return Text(aEvent);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aEvent));
|
||||
if (dragEvent && mInstance) {
|
||||
@ -2361,10 +2396,29 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
|
||||
// DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and
|
||||
// gdk_keymap_get_entries_for_keyval will be useful, but the
|
||||
// mappings will not be unique.
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
bool handled;
|
||||
if (NS_SUCCEEDED(mInstance->HandleGUIEvent(anEvent, &handled)) &&
|
||||
handled) {
|
||||
rv = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
#else
|
||||
NS_WARNING("Synthesized key event not sent to plugin");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
case NS_TEXT_EVENT:
|
||||
{
|
||||
bool handled;
|
||||
if (NS_SUCCEEDED(mInstance->HandleGUIEvent(anEvent, &handled)) &&
|
||||
handled) {
|
||||
rv = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
switch (anEvent.message)
|
||||
{
|
||||
@ -2445,18 +2499,76 @@ nsPluginInstanceOwner::Destroy()
|
||||
mContent->RemoveEventListener(NS_LITERAL_STRING("dragstart"), this, PR_TRUE);
|
||||
mContent->RemoveEventListener(NS_LITERAL_STRING("draggesture"), this, PR_TRUE);
|
||||
mContent->RemoveEventListener(NS_LITERAL_STRING("dragend"), this, PR_TRUE);
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
mContent->RemoveEventListener(NS_LITERAL_STRING("text"), this, PR_TRUE);
|
||||
#endif
|
||||
|
||||
if (mWidget) {
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
||||
if (pluginWidget) {
|
||||
if (pluginWidget)
|
||||
pluginWidget->SetPluginInstanceOwner(nsnull);
|
||||
}
|
||||
mWidget->Destroy();
|
||||
|
||||
if (mDestroyWidget)
|
||||
mWidget->Destroy();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare to stop
|
||||
*/
|
||||
void
|
||||
nsPluginInstanceOwner::PrepareToStop(PRBool aDelayedStop)
|
||||
{
|
||||
// Drop image reference because the child may destroy the surface after we return.
|
||||
nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
|
||||
if (container) {
|
||||
#ifdef XP_MACOSX
|
||||
nsRefPtr<Image> image = container->GetCurrentImage();
|
||||
if (image && (image->GetFormat() == Image::MAC_IO_SURFACE) && mObjectFrame) {
|
||||
// Undo what we did to the current image in SetCurrentImage().
|
||||
MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image.get());
|
||||
oglImage->SetUpdateCallback(nsnull, nsnull);
|
||||
oglImage->SetDestroyCallback(nsnull);
|
||||
// If we have a current image here, its destructor hasn't yet been
|
||||
// called, so OnDestroyImage() can't yet have been called. So we need
|
||||
// to do ourselves what OnDestroyImage() would have done.
|
||||
NS_RELEASE_THIS();
|
||||
}
|
||||
#endif
|
||||
container->SetCurrentImage(nsnull);
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) || defined(MOZ_X11)
|
||||
if (aDelayedStop && mWidget) {
|
||||
// To delay stopping a plugin we need to reparent the plugin
|
||||
// so that we can safely tear down the
|
||||
// plugin after its frame (and view) is gone.
|
||||
|
||||
// Also hide and disable the widget to avoid it from appearing in
|
||||
// odd places after reparenting it, but before it gets destroyed.
|
||||
mWidget->Show(PR_FALSE);
|
||||
mWidget->Enable(PR_FALSE);
|
||||
|
||||
// Reparent the plugins native window. This relies on the widget
|
||||
// and plugin et al not holding any other references to its
|
||||
// parent.
|
||||
mWidget->SetParent(nsnull);
|
||||
|
||||
mDestroyWidget = PR_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unregister scroll position listeners
|
||||
for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(f);
|
||||
if (sf) {
|
||||
sf->RemoveScrollPositionListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Paints are handled differently, so we just simulate an update event.
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
@ -2792,19 +2904,25 @@ void nsPluginInstanceOwner::CancelTimer()
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult nsPluginInstanceOwner::Init(nsObjectFrame* aFrame, nsIContent* aContent)
|
||||
nsresult nsPluginInstanceOwner::Init(nsPresContext* aPresContext,
|
||||
nsObjectFrame* aFrame,
|
||||
nsIContent* aContent)
|
||||
{
|
||||
mLastEventloopNestingLevel = GetEventloopNestingLevel();
|
||||
|
||||
mObjectFrame = aFrame;
|
||||
mContent = aContent;
|
||||
|
||||
if (aFrame) {
|
||||
SetFrame(aFrame);
|
||||
// Some plugins require a specific sequence of shutdown and startup when
|
||||
// a page is reloaded. Shutdown happens usually when the last instance
|
||||
// is destroyed. Here we make sure the plugin instance in the old
|
||||
// document is destroyed before we try to create the new one.
|
||||
aFrame->PresContext()->EnsureVisible();
|
||||
nsWeakFrame weakFrame(aFrame);
|
||||
|
||||
// Some plugins require a specific sequence of shutdown and startup when
|
||||
// a page is reloaded. Shutdown happens usually when the last instance
|
||||
// is destroyed. Here we make sure the plugin instance in the old
|
||||
// document is destroyed before we try to create the new one.
|
||||
aPresContext->EnsureVisible();
|
||||
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// register context menu listener
|
||||
@ -2844,6 +2962,19 @@ nsresult nsPluginInstanceOwner::Init(nsObjectFrame* aFrame, nsIContent* aContent
|
||||
mContent->AddEventListener(NS_LITERAL_STRING("dragstart"), this, PR_TRUE);
|
||||
mContent->AddEventListener(NS_LITERAL_STRING("draggesture"), this, PR_TRUE);
|
||||
mContent->AddEventListener(NS_LITERAL_STRING("dragend"), this, PR_TRUE);
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
mContent->AddEventListener(NS_LITERAL_STRING("text"), this, PR_TRUE);
|
||||
#endif
|
||||
|
||||
// Register scroll position listeners
|
||||
// We need to register a scroll position listener on every scrollable
|
||||
// frame up to the top
|
||||
for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(f);
|
||||
if (sf) {
|
||||
sf->AddScrollPositionListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2885,99 +3016,88 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
|
||||
{
|
||||
NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
// Can't call this twice!
|
||||
if (mWidget) {
|
||||
NS_WARNING("Trying to create a plugin widget twice!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRBool windowless = PR_FALSE;
|
||||
mInstance->IsWindowless(&windowless);
|
||||
if (!windowless && !nsIWidget::UsePuppetWidgets()) {
|
||||
// Try to get a parent widget, on some platforms widget creation will fail without
|
||||
// a parent.
|
||||
nsCOMPtr<nsIWidget> parentWidget;
|
||||
if (mContent) {
|
||||
nsIDocument *doc = mContent->GetOwnerDoc();
|
||||
if (doc) {
|
||||
parentWidget = nsContentUtils::WidgetForDocument(doc);
|
||||
}
|
||||
}
|
||||
|
||||
mWidget = do_CreateInstance(kWidgetCID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsWidgetInitData initData;
|
||||
initData.mWindowType = eWindowType_plugin;
|
||||
initData.mUnicode = PR_FALSE;
|
||||
initData.clipChildren = PR_TRUE;
|
||||
initData.clipSiblings = PR_TRUE;
|
||||
rv = mWidget->Create(parentWidget.get(), nsnull, nsIntRect(0,0,0,0),
|
||||
nsnull, nsnull, nsnull, nsnull, &initData);
|
||||
if (NS_FAILED(rv)) {
|
||||
mWidget->Destroy();
|
||||
mWidget = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
mWidget->EnableDragDrop(PR_TRUE);
|
||||
mWidget->Show(PR_FALSE);
|
||||
mWidget->Enable(PR_FALSE);
|
||||
}
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
if (mObjectFrame) {
|
||||
// This has to be called even if we don't have a widget! The object
|
||||
// frame will do windowless setup.
|
||||
mObjectFrame->SetWidget(mWidget);
|
||||
}
|
||||
if (!mWidget) {
|
||||
PRBool windowless = PR_FALSE;
|
||||
mInstance->IsWindowless(&windowless);
|
||||
|
||||
if (windowless) {
|
||||
mPluginWindow->type = NPWindowTypeDrawable;
|
||||
|
||||
// this needs to be a HDC according to the spec, but I do
|
||||
// not see the right way to release it so let's postpone
|
||||
// passing HDC till paint event when it is really
|
||||
// needed. Change spec?
|
||||
mPluginWindow->window = nsnull;
|
||||
// always create widgets in Twips, not pixels
|
||||
nsPresContext* context = mObjectFrame->PresContext();
|
||||
rv = mObjectFrame->CreateWidget(context->DevPixelsToAppUnits(mPluginWindow->width),
|
||||
context->DevPixelsToAppUnits(mPluginWindow->height),
|
||||
windowless);
|
||||
if (NS_OK == rv) {
|
||||
mWidget = mObjectFrame->GetWidget();
|
||||
|
||||
if (PR_TRUE == windowless) {
|
||||
mPluginWindow->type = NPWindowTypeDrawable;
|
||||
|
||||
// this needs to be a HDC according to the spec, but I do
|
||||
// not see the right way to release it so let's postpone
|
||||
// passing HDC till paint event when it is really
|
||||
// needed. Change spec?
|
||||
mPluginWindow->window = nsnull;
|
||||
#ifdef MOZ_X11
|
||||
// Fill in the display field.
|
||||
NPSetWindowCallbackStruct* ws_info =
|
||||
static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
|
||||
ws_info->display = DefaultXDisplay();
|
||||
|
||||
nsCAutoString description;
|
||||
GetPluginDescription(description);
|
||||
NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
|
||||
mFlash10Quirks = StringBeginsWith(description, flash10Head);
|
||||
// Fill in the display field.
|
||||
NPSetWindowCallbackStruct* ws_info =
|
||||
static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
|
||||
ws_info->display = DefaultXDisplay();
|
||||
|
||||
nsCAutoString description;
|
||||
GetPluginDescription(description);
|
||||
NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
|
||||
mFlash10Quirks = StringBeginsWith(description, flash10Head);
|
||||
#endif
|
||||
} else if (mWidget) {
|
||||
// mPluginWindow->type is used in |GetPluginPort| so it must
|
||||
// be initialized first
|
||||
mPluginWindow->type = NPWindowTypeWindow;
|
||||
mPluginWindow->window = GetPluginPortFromWidget();
|
||||
|
||||
|
||||
// Changing to windowless mode changes the NPWindow geometry.
|
||||
mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
|
||||
} else if (mWidget) {
|
||||
nsIWidget* parent = mWidget->GetParent();
|
||||
NS_ASSERTION(parent, "Plugin windows must not be toplevel");
|
||||
// Set the plugin window to have an empty cliprect. The cliprect
|
||||
// will be reset when nsRootPresContext::UpdatePluginGeometry
|
||||
// runs later. The plugin window does need to have the correct
|
||||
// size here. GetEmptyClipConfiguration will probably give it the
|
||||
// size, but just in case we haven't been reflowed or something, set
|
||||
// the size explicitly.
|
||||
nsAutoTArray<nsIWidget::Configuration,1> configuration;
|
||||
mObjectFrame->GetEmptyClipConfiguration(&configuration);
|
||||
if (configuration.Length() > 0) {
|
||||
configuration[0].mBounds.width = mPluginWindow->width;
|
||||
configuration[0].mBounds.height = mPluginWindow->height;
|
||||
}
|
||||
parent->ConfigureChildren(configuration);
|
||||
|
||||
// mPluginWindow->type is used in |GetPluginPort| so it must
|
||||
// be initialized first
|
||||
mPluginWindow->type = NPWindowTypeWindow;
|
||||
mPluginWindow->window = GetPluginPortFromWidget();
|
||||
|
||||
#ifdef MAC_CARBON_PLUGINS
|
||||
// start the idle timer.
|
||||
StartTimer(PR_TRUE);
|
||||
// start the idle timer.
|
||||
StartTimer(PR_TRUE);
|
||||
#endif
|
||||
|
||||
// tell the plugin window about the widget
|
||||
mPluginWindow->SetPluginWidget(mWidget);
|
||||
|
||||
// tell the widget about the current plugin instance owner.
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
||||
if (pluginWidget) {
|
||||
pluginWidget->SetPluginInstanceOwner(this);
|
||||
|
||||
// tell the plugin window about the widget
|
||||
mPluginWindow->SetPluginWidget(mWidget);
|
||||
|
||||
// tell the widget about the current plugin instance owner.
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
||||
if (pluginWidget)
|
||||
pluginWidget->SetPluginInstanceOwner(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mWidgetCreationComplete = PR_TRUE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost* aHost)
|
||||
{
|
||||
mPluginHost = static_cast<nsPluginHost*>(aHost);
|
||||
}
|
||||
|
||||
// Mac specific code to fix up the port location and clipping region
|
||||
@ -3221,85 +3341,6 @@ nsPluginInstanceOwner::CallSetWindow()
|
||||
}
|
||||
}
|
||||
|
||||
void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
|
||||
{
|
||||
// Don't do anything if the frame situation hasn't changed.
|
||||
if (mObjectFrame == aFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Deal with things that depend on whether or not we used to have a frame.
|
||||
if (mObjectFrame) {
|
||||
// We have an old frame.
|
||||
// Drop image reference because the child may destroy the surface after we return.
|
||||
nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
|
||||
if (container) {
|
||||
#ifdef XP_MACOSX
|
||||
nsRefPtr<Image> image = container->GetCurrentImage();
|
||||
if (image && (image->GetFormat() == Image::MAC_IO_SURFACE) && mObjectFrame) {
|
||||
// Undo what we did to the current image in SetCurrentImage().
|
||||
MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image.get());
|
||||
oglImage->SetUpdateCallback(nsnull, nsnull);
|
||||
oglImage->SetDestroyCallback(nsnull);
|
||||
// If we have a current image here, its destructor hasn't yet been
|
||||
// called, so OnDestroyImage() can't yet have been called. So we need
|
||||
// to do ourselves what OnDestroyImage() would have done.
|
||||
NS_RELEASE_THIS();
|
||||
}
|
||||
#endif
|
||||
container->SetCurrentImage(nsnull);
|
||||
}
|
||||
|
||||
// If we had an old frame and we're not going to have a new one then
|
||||
// we should unregister for some things.
|
||||
if (!aFrame) {
|
||||
// Unregister scroll position listeners
|
||||
for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(f);
|
||||
if (sf) {
|
||||
sf->RemoveScrollPositionListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the old frame isn't holding a reference to us.
|
||||
mObjectFrame->SetInstanceOwner(nsnull);
|
||||
} else {
|
||||
if (aFrame) {
|
||||
// We didn't have an object frame before but we do now!
|
||||
// We need to register a scroll position listener on every scrollable
|
||||
// frame up to the top
|
||||
for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(f);
|
||||
if (sf) {
|
||||
sf->AddScrollPositionListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Swap in the new frame (or no frame)
|
||||
mObjectFrame = aFrame;
|
||||
|
||||
// Set up a new frame
|
||||
if (mObjectFrame) {
|
||||
mObjectFrame->SetInstanceOwner(this);
|
||||
// Can only call SetWidget on an object frame once. Don't do it here unless
|
||||
// widget creation is complete. Whether or not one was actually created and
|
||||
// mWidget is NULL is irrelevant.
|
||||
if (mWidgetCreationComplete) {
|
||||
mObjectFrame->SetWidget(mWidget);
|
||||
}
|
||||
mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
|
||||
mObjectFrame->Invalidate(mObjectFrame->GetContentRectRelativeToSelf());
|
||||
}
|
||||
}
|
||||
|
||||
nsObjectFrame* nsPluginInstanceOwner::GetFrame()
|
||||
{
|
||||
return mObjectFrame;
|
||||
}
|
||||
|
||||
// Little helper function to resolve relative URL in
|
||||
// |value| for certain inputs of |name|
|
||||
void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value)
|
||||
|
@ -69,7 +69,7 @@
|
||||
#endif
|
||||
|
||||
class nsIInputStream;
|
||||
class nsIntRect;
|
||||
struct nsIntRect;
|
||||
class nsPluginDOMContextMenuListener;
|
||||
class nsObjectFrame;
|
||||
class nsDisplayListBuilder;
|
||||
@ -130,9 +130,14 @@ public:
|
||||
|
||||
nsresult MouseDown(nsIDOMEvent* aKeyEvent);
|
||||
nsresult KeyPress(nsIDOMEvent* aKeyEvent);
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
nsresult Text(nsIDOMEvent* aTextEvent);
|
||||
#endif
|
||||
|
||||
nsresult Destroy();
|
||||
|
||||
|
||||
void PrepareToStop(PRBool aDelayedStop);
|
||||
|
||||
#ifdef XP_WIN
|
||||
void Paint(const RECT& aDirty, HDC aDC);
|
||||
#elif defined(XP_MACOSX)
|
||||
@ -159,11 +164,14 @@ public:
|
||||
|
||||
//locals
|
||||
|
||||
nsresult Init(nsObjectFrame* aFrame, nsIContent* aContent);
|
||||
nsresult Init(nsPresContext* aPresContext, nsObjectFrame* aFrame,
|
||||
nsIContent* aContent);
|
||||
|
||||
void* GetPluginPortFromWidget();
|
||||
void ReleasePluginPort(void* pluginPort);
|
||||
|
||||
|
||||
void SetPluginHost(nsIPluginHost* aHost);
|
||||
|
||||
nsEventStatus ProcessEvent(const nsGUIEvent & anEvent);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
@ -202,10 +210,15 @@ public:
|
||||
void UpdateDocumentActiveState(PRBool aIsActive);
|
||||
#endif // XP_MACOSX
|
||||
void CallSetWindow();
|
||||
|
||||
void SetFrame(nsObjectFrame *aFrame);
|
||||
nsObjectFrame* GetFrame();
|
||||
|
||||
|
||||
void SetOwner(nsObjectFrame *aOwner)
|
||||
{
|
||||
mObjectFrame = aOwner;
|
||||
}
|
||||
nsObjectFrame* GetOwner() {
|
||||
return mObjectFrame;
|
||||
}
|
||||
|
||||
PRUint32 GetLastEventloopNestingLevel() const {
|
||||
return mLastEventloopNestingLevel;
|
||||
}
|
||||
@ -298,11 +311,10 @@ private:
|
||||
|
||||
nsPluginNativeWindow *mPluginWindow;
|
||||
nsRefPtr<nsNPAPIPluginInstance> mInstance;
|
||||
nsObjectFrame *mObjectFrame;
|
||||
nsIContent *mContent; // WEAK, content owns us
|
||||
nsObjectFrame *mObjectFrame; // owns nsPluginInstanceOwner
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsCString mDocumentBase;
|
||||
char *mTagText;
|
||||
PRBool mWidgetCreationComplete;
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
nsRefPtr<nsPluginHost> mPluginHost;
|
||||
|
||||
@ -338,7 +350,10 @@ private:
|
||||
#endif
|
||||
PRPackedBool mPluginWindowVisible;
|
||||
PRPackedBool mPluginDocumentActiveState;
|
||||
|
||||
|
||||
// If true, destroy the widget on destruction. Used when plugin stop
|
||||
// is being delayed to a safer point in time.
|
||||
PRPackedBool mDestroyWidget;
|
||||
PRUint16 mNumCachedAttrs;
|
||||
PRUint16 mNumCachedParams;
|
||||
char **mCachedAttrParamNames;
|
||||
|
@ -46,6 +46,7 @@ include protocol PStreamNotify;
|
||||
include protocol PPluginSurface;
|
||||
|
||||
include "mozilla/plugins/PluginMessageUtils.h";
|
||||
include "IPC/nsGUIEventIPC.h";
|
||||
|
||||
using NPError;
|
||||
using NPRemoteWindow;
|
||||
@ -59,6 +60,8 @@ using gfxIntSize;
|
||||
using mozilla::null_t;
|
||||
using mozilla::plugins::WindowsSharedMemoryHandle;
|
||||
using nsIntRect;
|
||||
using nsTextEvent;
|
||||
using nsKeyEvent;
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
@ -147,6 +150,11 @@ child:
|
||||
// refer to the existing background or a fresh descriptor.
|
||||
async UpdateBackground(SurfaceDescriptor background, nsIntRect rect);
|
||||
|
||||
rpc HandleTextEvent(nsTextEvent event)
|
||||
returns (bool handled);
|
||||
rpc HandleKeyEvent(nsKeyEvent event)
|
||||
returns (bool handled);
|
||||
|
||||
rpc NPP_Destroy()
|
||||
returns (NPError rv);
|
||||
|
||||
|
@ -37,6 +37,14 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QApplication>
|
||||
#include <QInputMethodEvent>
|
||||
#include "nsQtKeyUtils.h"
|
||||
#endif
|
||||
|
||||
#include "PluginBackgroundDestroyer.h"
|
||||
#include "PluginInstanceChild.h"
|
||||
#include "PluginModuleChild.h"
|
||||
@ -74,6 +82,8 @@ using namespace mozilla::plugins;
|
||||
|
||||
#elif defined(MOZ_WIDGET_QT)
|
||||
#include <QX11Info>
|
||||
#undef KeyPress
|
||||
#undef KeyRelease
|
||||
#elif defined(OS_WIN)
|
||||
#ifndef WM_MOUSEHWHEEL
|
||||
#define WM_MOUSEHWHEEL 0x020E
|
||||
@ -2317,6 +2327,57 @@ PluginInstanceChild::RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::AnswerHandleKeyEvent(const nsKeyEvent& aKeyEvent,
|
||||
bool* handled)
|
||||
{
|
||||
AssertPluginThread();
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
Qt::KeyboardModifiers modifier;
|
||||
if (aKeyEvent.isShift)
|
||||
modifier |= Qt::ShiftModifier;
|
||||
if (aKeyEvent.isControl)
|
||||
modifier |= Qt::ControlModifier;
|
||||
if (aKeyEvent.isAlt)
|
||||
modifier |= Qt::AltModifier;
|
||||
if (aKeyEvent.isMeta)
|
||||
modifier |= Qt::MetaModifier;
|
||||
|
||||
QEvent::Type type;
|
||||
if (aKeyEvent.message == NS_KEY_DOWN) {
|
||||
type = QEvent::KeyPress;
|
||||
} else if (aKeyEvent.message == NS_KEY_UP) {
|
||||
type = QEvent::KeyRelease;
|
||||
} else {
|
||||
*handled = false;
|
||||
return true;
|
||||
}
|
||||
QKeyEvent keyEv(type, DOMKeyCodeToQtKeyCode(aKeyEvent.keyCode), modifier);
|
||||
*handled = QApplication::sendEvent(qApp, &keyEv);
|
||||
#else
|
||||
NS_ERROR("Not implemented");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::AnswerHandleTextEvent(const nsTextEvent& aEvent,
|
||||
bool* handled)
|
||||
{
|
||||
AssertPluginThread();
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
QInputMethodEvent event;
|
||||
event.setCommitString(QString((const QChar*)aEvent.theText.get(),
|
||||
aEvent.theText.Length()));
|
||||
*handled = QApplication::sendEvent(qApp, &event);
|
||||
#else
|
||||
NS_ERROR("Not implemented");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
||||
const NPRemoteWindow& aWindow,
|
||||
|
@ -120,6 +120,11 @@ protected:
|
||||
const NPRemoteWindow& aWindow,
|
||||
bool aIsAsync);
|
||||
|
||||
virtual bool
|
||||
AnswerHandleKeyEvent(const nsKeyEvent& aEvent, bool* handled);
|
||||
virtual bool
|
||||
AnswerHandleTextEvent(const nsTextEvent& aEvent, bool* handled);
|
||||
|
||||
virtual PPluginSurfaceChild* AllocPPluginSurface(const WindowsSharedMemoryHandle&,
|
||||
const gfxIntSize&, const bool&) {
|
||||
return new PPluginSurfaceChild();
|
||||
|
@ -618,6 +618,31 @@ PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
nsresult
|
||||
PluginInstanceParent::HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled)
|
||||
{
|
||||
switch (anEvent.eventStructType) {
|
||||
case NS_KEY_EVENT:
|
||||
if (!CallHandleKeyEvent(static_cast<const nsKeyEvent&>(anEvent),
|
||||
handled)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
break;
|
||||
case NS_TEXT_EVENT:
|
||||
if (!CallHandleTextEvent(static_cast<const nsTextEvent&>(anEvent),
|
||||
handled)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Not implemented for this event type");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage)
|
||||
{
|
||||
|
@ -57,6 +57,7 @@
|
||||
#ifdef MOZ_X11
|
||||
class gfxXlibSurface;
|
||||
#endif
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
@ -290,6 +291,9 @@ public:
|
||||
gfxContext** aCtx);
|
||||
nsresult EndUpdateBackground(gfxContext* aCtx,
|
||||
const nsIntRect& aRect);
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
nsresult HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled);
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Create an appropriate platform surface for a background of size
|
||||
|
@ -52,6 +52,7 @@ class nsCString;
|
||||
struct nsIntRect;
|
||||
struct nsIntSize;
|
||||
class nsNPAPIPlugin;
|
||||
class nsGUIEvent;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -116,6 +117,9 @@ public:
|
||||
const nsIntRect&, gfxContext**) = 0;
|
||||
virtual nsresult EndUpdateBackground(NPP instance,
|
||||
gfxContext*, const nsIntRect&) = 0;
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
virtual nsresult HandleGUIEvent(NPP instance, const nsGUIEvent&, bool*) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -703,6 +703,20 @@ PluginModuleParent::AsyncSetWindow(NPP instance, NPWindow* window)
|
||||
return i->AsyncSetWindow(window);
|
||||
}
|
||||
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
nsresult
|
||||
PluginModuleParent::HandleGUIEvent(NPP instance,
|
||||
const nsGUIEvent& anEvent,
|
||||
bool* handled)
|
||||
{
|
||||
PluginInstanceParent* i = InstCast(instance);
|
||||
if (!i)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return i->HandleGUIEvent(anEvent, handled);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
PluginModuleParent::GetImage(NPP instance,
|
||||
mozilla::layers::ImageContainer* aContainer,
|
||||
|
@ -296,6 +296,10 @@ private:
|
||||
#if defined(XP_MACOSX)
|
||||
virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, PRBool *aDrawing);
|
||||
#endif
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
virtual nsresult HandleGUIEvent(NPP instance, const nsGUIEvent& anEvent,
|
||||
bool* handled);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void WritePluginExtraDataForMinidump(const nsAString& id);
|
||||
|
@ -102,11 +102,6 @@ _MOCHITEST_FILES = \
|
||||
test_zero_opacity.html \
|
||||
test_NPPVpluginWantsAllNetworkStreams.html \
|
||||
test_npruntime_npnsetexception.html \
|
||||
test_display_none.html \
|
||||
test_instance_re-parent.html \
|
||||
test_instance_unparent1.html \
|
||||
test_instance_unparent2.html \
|
||||
test_instance_unparent3.html \
|
||||
$(NULL)
|
||||
|
||||
# test_plugin_scroll_painting.html \ bug 596491
|
||||
@ -131,7 +126,6 @@ _MOCHICHROME_FILES = \
|
||||
|
||||
ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
|
||||
_MOCHITEST_FILES += \
|
||||
test_instance_re-parent-windowed.html \
|
||||
test_visibility.html \
|
||||
$(NULL)
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test npruntime and paint count for instance in a display:none div</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="startTest()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div style="display: none;">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function startTest() {
|
||||
var paintCount = -1;
|
||||
var exceptionThrown = false;
|
||||
|
||||
var p = document.getElementById('plugin1');
|
||||
try {
|
||||
paintCount = p.getPaintCount();
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
|
||||
is(paintCount, 0, "Paint count test.");
|
||||
is(exceptionThrown, false, "Exception test.");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,59 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test re-parentinging an instance's DOM node</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="startTest()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="div1">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200" wmode="window"></embed>
|
||||
</div>
|
||||
<div id="div2">
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var destroyed = false;
|
||||
function onDestroy() {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
var exceptionThrown = false;
|
||||
|
||||
var p = document.getElementById('plugin1');
|
||||
var d1 = document.getElementById('div1');
|
||||
var d2 = document.getElementById('div2');
|
||||
|
||||
p.startWatchingInstanceCount();
|
||||
p.callOnDestroy(onDestroy);
|
||||
|
||||
try {
|
||||
d1.removeChild(p);
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
is(exceptionThrown, false, "Testing for exception after removeChild.");
|
||||
|
||||
try {
|
||||
d2.appendChild(p);
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
is(exceptionThrown, false, "Testing for exception after appendChild.");
|
||||
|
||||
is(destroyed, false, "No instances should have been destroyed at this point.");
|
||||
is(p.getInstanceCount(), 0, "No new instances should have been created at this point.");
|
||||
|
||||
p.stopWatchingInstanceCount();
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,59 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test re-parentinging an instance's DOM node</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="startTest()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="div1">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
|
||||
</div>
|
||||
<div id="div2">
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var destroyed = false;
|
||||
function onDestroy() {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
var exceptionThrown = false;
|
||||
|
||||
var p = document.getElementById('plugin1');
|
||||
var d1 = document.getElementById('div1');
|
||||
var d2 = document.getElementById('div2');
|
||||
|
||||
p.startWatchingInstanceCount();
|
||||
p.callOnDestroy(onDestroy);
|
||||
|
||||
try {
|
||||
d1.removeChild(p);
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
is(exceptionThrown, false, "Testing for exception after removeChild.");
|
||||
|
||||
try {
|
||||
d2.appendChild(p);
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
is(exceptionThrown, false, "Testing for exception after appendChild.");
|
||||
|
||||
is(destroyed, false, "No instances should have been destroyed at this point.");
|
||||
is(p.getInstanceCount(), 0, "No new instances should have been created at this point.");
|
||||
|
||||
p.stopWatchingInstanceCount();
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,41 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test removing an instance's DOM node</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="startTest()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="div1">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var destroyed = false;
|
||||
function onDestroy() {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
function checkPluginAlreadyDestroyed() {
|
||||
is(destroyed, true, "Plugin instance should have been destroyed.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
var p1 = document.getElementById('plugin1');
|
||||
var d1 = document.getElementById('div1');
|
||||
|
||||
p1.callOnDestroy(onDestroy);
|
||||
|
||||
setTimeout(checkPluginAlreadyDestroyed, 0);
|
||||
|
||||
d1.removeChild(p1);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,50 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test removing an instance's DOM node</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="startTest()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="div1">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
|
||||
</div>
|
||||
|
||||
<div id="div2">
|
||||
<div id="div3">
|
||||
<embed id="plugin2" type="application/x-test" width="200" height="200"></embed>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var destroyed = false;
|
||||
function onDestroy() {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
function checkPluginAlreadyDestroyed() {
|
||||
is(destroyed, true, "Plugin instance should have been destroyed.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
var p1 = document.getElementById('plugin1');
|
||||
var d1 = document.getElementById('div1');
|
||||
|
||||
p1.callOnDestroy(onDestroy);
|
||||
|
||||
setTimeout(checkPluginAlreadyDestroyed, 0);
|
||||
|
||||
// Get two parent check events to run.
|
||||
d1.removeChild(p1);
|
||||
d1.appendChild(p1);
|
||||
d1.removeChild(p1);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,44 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test removing an instance's DOM node</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="startTest()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="div1">
|
||||
<div id="div2">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
|
||||
</div<
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var destroyed = false;
|
||||
function onDestroy() {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
function checkPluginAlreadyDestroyed() {
|
||||
is(destroyed, true, "Plugin instance should have been destroyed.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
var p1 = document.getElementById('plugin1');
|
||||
var d1 = document.getElementById('div1');
|
||||
var d2 = document.getElementById('div2');
|
||||
|
||||
p1.callOnDestroy(onDestroy);
|
||||
|
||||
setTimeout(checkPluginAlreadyDestroyed, 0);
|
||||
|
||||
d1.removeChild(d2);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
1608
dom/src/threads/nsDOMThreadService.cpp
Normal file
1608
dom/src/threads/nsDOMThreadService.cpp
Normal file
File diff suppressed because it is too large
Load Diff
212
dom/src/threads/nsDOMThreadService.h
Normal file
212
dom/src/threads/nsDOMThreadService.h
Normal file
@ -0,0 +1,212 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMTHREADSERVICE_H__
|
||||
#define __NSDOMTHREADSERVICE_H__
|
||||
|
||||
// Interfaces
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIThreadPool.h"
|
||||
|
||||
// Other includes
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTPtrArray.h"
|
||||
|
||||
#include "prlog.h"
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gDOMThreadsLog;
|
||||
#endif
|
||||
|
||||
class nsDOMWorker;
|
||||
class nsDOMWorkerPool;
|
||||
class nsDOMWorkerRunnable;
|
||||
class nsDOMWorkerTimeout;
|
||||
class nsIJSRuntimeService;
|
||||
class nsIScriptGlobalObject;
|
||||
class nsIThreadJSContextStack;
|
||||
class nsIXPConnect;
|
||||
class nsIXPCSecurityManager;
|
||||
|
||||
enum ThreadsafeStatus
|
||||
{
|
||||
Threadsafe,
|
||||
NotThreadsafe,
|
||||
Unknown
|
||||
};
|
||||
|
||||
class nsDOMThreadService : public nsIEventTarget,
|
||||
public nsIObserver,
|
||||
public nsIThreadPoolListener
|
||||
{
|
||||
friend class nsDOMWorker;
|
||||
friend class nsDOMWorkerNavigator;
|
||||
friend class nsDOMWorkerPool;
|
||||
friend class nsDOMWorkerRunnable;
|
||||
friend class nsDOMWorkerThread;
|
||||
friend class nsDOMWorkerTimeout;
|
||||
friend class nsDOMWorkerXHR;
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
friend class nsLayoutStatics;
|
||||
friend class nsReportErrorRunnable;
|
||||
|
||||
friend void DOMWorkerErrorReporter(JSContext* aCx,
|
||||
const char* aMessage,
|
||||
JSErrorReport* aReport);
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIEVENTTARGET
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSITHREADPOOLLISTENER
|
||||
|
||||
// Any DOM consumers that need access to this service should use this method.
|
||||
static already_AddRefed<nsDOMThreadService> GetOrInitService();
|
||||
|
||||
// Simple getter for this service. This does not create the service if it
|
||||
// hasn't been created already, and it never AddRef's!
|
||||
static nsDOMThreadService* get();
|
||||
|
||||
static JSContext* GetCurrentContext();
|
||||
|
||||
// Easy access to the services we care about.
|
||||
static nsIJSRuntimeService* JSRuntimeService();
|
||||
static nsIThreadJSContextStack* ThreadJSContextStack();
|
||||
static nsIXPCSecurityManager* WorkerSecurityManager();
|
||||
|
||||
void CancelWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
|
||||
void SuspendWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
|
||||
void ResumeWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
|
||||
|
||||
nsresult ChangeThreadPoolMaxThreads(PRInt16 aDelta);
|
||||
|
||||
void NoteThreadsafeContractId(const nsACString& aContractId,
|
||||
PRBool aIsThreadsafe);
|
||||
|
||||
ThreadsafeStatus GetContractIdThreadsafeStatus(const nsACString& aContractId);
|
||||
|
||||
private:
|
||||
nsDOMThreadService();
|
||||
~nsDOMThreadService();
|
||||
|
||||
nsresult Init();
|
||||
void Cleanup();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
nsresult Dispatch(nsDOMWorker* aWorker,
|
||||
nsIRunnable* aRunnable,
|
||||
PRIntervalTime aTimeoutInterval = 0,
|
||||
PRBool aClearQueue = PR_FALSE);
|
||||
|
||||
void SetWorkerTimeout(nsDOMWorker* aWorker,
|
||||
PRIntervalTime aTimeoutInterval);
|
||||
|
||||
void WorkerComplete(nsDOMWorkerRunnable* aRunnable);
|
||||
|
||||
static JSContext* CreateJSContext();
|
||||
|
||||
already_AddRefed<nsDOMWorkerPool>
|
||||
GetPoolForGlobal(nsIScriptGlobalObject* aGlobalObject,
|
||||
PRBool aRemove);
|
||||
|
||||
void TriggerOperationCallbackForPool(nsDOMWorkerPool* aPool);
|
||||
void RescheduleSuspendedWorkerForPool(nsDOMWorkerPool* aPool);
|
||||
|
||||
void NoteEmptyPool(nsDOMWorkerPool* aPool);
|
||||
|
||||
void TimeoutReady(nsDOMWorkerTimeout* aTimeout);
|
||||
|
||||
nsresult RegisterWorker(nsDOMWorker* aWorker,
|
||||
nsIScriptGlobalObject* aGlobalObject);
|
||||
|
||||
void GetAppName(nsAString& aAppName);
|
||||
void GetAppVersion(nsAString& aAppVersion);
|
||||
void GetPlatform(nsAString& aPlatform);
|
||||
void GetUserAgent(nsAString& aUserAgent);
|
||||
|
||||
void RegisterPrefCallbacks();
|
||||
void UnregisterPrefCallbacks();
|
||||
|
||||
static int PrefCallback(const char* aPrefName,
|
||||
void* aClosure);
|
||||
|
||||
static PRUint32 GetWorkerCloseHandlerTimeoutMS();
|
||||
|
||||
PRBool QueueSuspendedWorker(nsDOMWorkerRunnable* aRunnable);
|
||||
|
||||
// Our internal thread pool.
|
||||
nsCOMPtr<nsIThreadPool> mThreadPool;
|
||||
|
||||
// Maps nsIScriptGlobalObject* to nsDOMWorkerPool.
|
||||
nsRefPtrHashtable<nsVoidPtrHashKey, nsDOMWorkerPool> mPools;
|
||||
|
||||
// mReentrantMonitor protects all access to mWorkersInProgress and
|
||||
// mCreationsInProgress.
|
||||
mozilla::ReentrantMonitor mReentrantMonitor;
|
||||
|
||||
// A map from nsDOMWorkerThread to nsDOMWorkerRunnable.
|
||||
nsRefPtrHashtable<nsVoidPtrHashKey, nsDOMWorkerRunnable> mWorkersInProgress;
|
||||
|
||||
// A list of active JSContexts that we've created. Always protected with
|
||||
// mReentrantMonitor.
|
||||
nsTArray<JSContext*> mJSContexts;
|
||||
|
||||
// A list of worker runnables that were never started because the worker was
|
||||
// suspended. Always protected with mReentrantMonitor.
|
||||
nsTArray<nsDOMWorkerRunnable*> mSuspendedWorkers;
|
||||
|
||||
// Always protected with mReentrantMonitor.
|
||||
nsDataHashtable<nsCStringHashKey, PRBool> mThreadsafeContractIDs;
|
||||
|
||||
nsString mAppName;
|
||||
nsString mAppVersion;
|
||||
nsString mPlatform;
|
||||
nsString mUserAgent;
|
||||
|
||||
PRBool mNavigatorStringsLoaded;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMTHREADSERVICE_H__ */
|
2752
dom/src/threads/nsDOMWorker.cpp
Normal file
2752
dom/src/threads/nsDOMWorker.cpp
Normal file
File diff suppressed because it is too large
Load Diff
471
dom/src/threads/nsDOMWorker.h
Normal file
471
dom/src/threads/nsDOMWorker.h
Normal file
@ -0,0 +1,471 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKER_H__
|
||||
#define __NSDOMWORKER_H__
|
||||
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMWorkers.h"
|
||||
#include "nsIJSNativeInitializer.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTPtrArray.h"
|
||||
|
||||
#include "nsDOMWorkerMessageHandler.h"
|
||||
|
||||
// {1295EFB5-8644-42B2-8B8E-80EEF56E4284}
|
||||
#define NS_WORKERFACTORY_CID \
|
||||
{0x1295efb5, 0x8644, 0x42b2, \
|
||||
{0x8b, 0x8e, 0x80, 0xee, 0xf5, 0x6e, 0x42, 0x84} }
|
||||
|
||||
class nsDOMWorker;
|
||||
class nsDOMWorkerFeature;
|
||||
class nsDOMWorkerMessageHandler;
|
||||
class nsDOMWorkerNavigator;
|
||||
class nsDOMWorkerPool;
|
||||
class nsDOMWorkerTimeout;
|
||||
class nsICancelable;
|
||||
class nsIDOMEventListener;
|
||||
class nsIEventTarget;
|
||||
class nsIRunnable;
|
||||
class nsIScriptGlobalObject;
|
||||
class nsIXPConnectWrappedNative;
|
||||
|
||||
class nsDOMWorkerScope : public nsDOMWorkerMessageHandler,
|
||||
public nsIWorkerScope,
|
||||
public nsIXPCScriptable
|
||||
{
|
||||
friend class nsDOMWorker;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDOMEventHandler
|
||||
NS_FORWARD_INTERNAL_NSIDOMEVENTTARGET(nsDOMWorkerMessageHandler::)
|
||||
NS_IMETHOD AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 optional_argc);
|
||||
NS_IMETHOD RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture);
|
||||
NS_IMETHOD DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval);
|
||||
NS_DECL_NSIWORKERGLOBALSCOPE
|
||||
NS_DECL_NSIWORKERSCOPE
|
||||
NS_DECL_NSIXPCSCRIPTABLE
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
typedef NS_STDCALL_FUNCPROTO(nsresult, SetListenerFunc, nsDOMWorkerScope,
|
||||
SetOnmessage, (nsIDOMEventListener*));
|
||||
|
||||
nsDOMWorkerScope(nsDOMWorker* aWorker);
|
||||
|
||||
protected:
|
||||
already_AddRefed<nsIXPConnectWrappedNative> GetWrappedNative();
|
||||
|
||||
private:
|
||||
nsDOMWorker* mWorker;
|
||||
nsIXPConnectWrappedNative* mWrappedNative;
|
||||
|
||||
nsRefPtr<nsDOMWorkerNavigator> mNavigator;
|
||||
|
||||
PRPackedBool mHasOnerror;
|
||||
};
|
||||
|
||||
class nsLazyAutoRequest
|
||||
{
|
||||
public:
|
||||
nsLazyAutoRequest() : mCx(nsnull) {}
|
||||
|
||||
~nsLazyAutoRequest() {
|
||||
if (mCx)
|
||||
JS_EndRequest(mCx);
|
||||
}
|
||||
|
||||
void enter(JSContext *aCx) {
|
||||
JS_BeginRequest(aCx);
|
||||
mCx = aCx;
|
||||
}
|
||||
|
||||
bool entered() const { return mCx != nsnull; }
|
||||
|
||||
void swap(nsLazyAutoRequest &other) {
|
||||
JSContext *tmp = mCx;
|
||||
mCx = other.mCx;
|
||||
other.mCx = tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
JSContext *mCx;
|
||||
};
|
||||
|
||||
class nsDOMWorker : public nsDOMWorkerMessageHandler,
|
||||
public nsIWorker,
|
||||
public nsITimerCallback,
|
||||
public nsIJSNativeInitializer,
|
||||
public nsIXPCScriptable
|
||||
{
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
friend class nsDOMWorkerFeature;
|
||||
friend class nsDOMWorkerFunctions;
|
||||
friend class nsDOMWorkerScope;
|
||||
friend class nsDOMWorkerScriptLoader;
|
||||
friend class nsDOMWorkerTimeout;
|
||||
friend class nsDOMWorkerXHR;
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
friend class nsReportErrorRunnable;
|
||||
friend class nsDOMFireEventRunnable;
|
||||
|
||||
friend JSBool DOMWorkerOperationCallback(JSContext* aCx);
|
||||
friend void DOMWorkerErrorReporter(JSContext* aCx,
|
||||
const char* aMessage,
|
||||
JSErrorReport* aReport);
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDOMEventHandler
|
||||
NS_FORWARD_INTERNAL_NSIDOMEVENTTARGET(nsDOMWorkerMessageHandler::)
|
||||
NS_IMETHOD AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 optional_argc);
|
||||
NS_IMETHOD RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture);
|
||||
NS_IMETHOD DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval);
|
||||
|
||||
NS_DECL_NSIABSTRACTWORKER
|
||||
NS_DECL_NSIWORKER
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSICLASSINFO
|
||||
NS_DECL_NSIXPCSCRIPTABLE
|
||||
|
||||
static nsresult NewWorker(nsISupports** aNewObject);
|
||||
static nsresult NewChromeWorker(nsISupports** aNewObject);
|
||||
static nsresult NewChromeDOMWorker(nsDOMWorker** aNewObject);
|
||||
|
||||
enum WorkerPrivilegeModel { CONTENT, CHROME };
|
||||
|
||||
nsDOMWorker(nsDOMWorker* aParent,
|
||||
nsIXPConnectWrappedNative* aParentWN,
|
||||
WorkerPrivilegeModel aModel);
|
||||
|
||||
NS_IMETHOD Initialize(nsISupports* aOwner,
|
||||
JSContext* aCx,
|
||||
JSObject* aObj,
|
||||
PRUint32 aArgc,
|
||||
jsval* aArgv);
|
||||
|
||||
nsresult InitializeInternal(nsIScriptGlobalObject* aOwner,
|
||||
JSContext* aCx,
|
||||
JSObject* aObj,
|
||||
PRUint32 aArgc,
|
||||
jsval* aArgv);
|
||||
|
||||
void Cancel();
|
||||
void Kill();
|
||||
void Suspend();
|
||||
void Resume();
|
||||
|
||||
// This just calls IsCanceledNoLock with an autolock around the call.
|
||||
PRBool IsCanceled();
|
||||
|
||||
PRBool IsClosing();
|
||||
PRBool IsSuspended();
|
||||
|
||||
PRBool SetGlobalForContext(JSContext* aCx, nsLazyAutoRequest *aRequest, JSAutoEnterCompartment *aComp);
|
||||
|
||||
void SetPool(nsDOMWorkerPool* aPool);
|
||||
|
||||
nsDOMWorkerPool* Pool() {
|
||||
return mPool;
|
||||
}
|
||||
|
||||
Mutex& GetLock() {
|
||||
return mLock;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIXPConnectWrappedNative> GetWrappedNative();
|
||||
already_AddRefed<nsDOMWorker> GetParent();
|
||||
|
||||
nsDOMWorkerScope* GetInnerScope() {
|
||||
return mInnerScope;
|
||||
}
|
||||
|
||||
void SetExpirationTime(PRIntervalTime aExpirationTime);
|
||||
#ifdef DEBUG
|
||||
PRIntervalTime GetExpirationTime();
|
||||
#endif
|
||||
|
||||
PRBool IsPrivileged() {
|
||||
return mPrivilegeModel == CHROME;
|
||||
}
|
||||
|
||||
static JSObject* ReadStructuredClone(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32 aTag,
|
||||
uint32 aData,
|
||||
void* aClosure);
|
||||
|
||||
/**
|
||||
* Use this chart to help figure out behavior during each of the closing
|
||||
* statuses. Details below.
|
||||
*
|
||||
* +=============+=============+=================+=======================+
|
||||
* | status | clear queue | abort execution | close handler timeout |
|
||||
* +=============+=============+=================+=======================+
|
||||
* | eClosed | yes | no | no |
|
||||
* +-------------+-------------+-----------------+-----------------------+
|
||||
* | eTerminated | yes | yes | no |
|
||||
* +-------------+-------------+-----------------+-----------------------+
|
||||
* | eCanceled | yes | yes | yes |
|
||||
* +-------------+-------------+-----------------+-----------------------+
|
||||
*
|
||||
*/
|
||||
|
||||
enum DOMWorkerStatus {
|
||||
// This status means that the close handler has not yet been scheduled.
|
||||
eRunning = 0,
|
||||
|
||||
// Inner script called Close() on the worker global scope. Setting this
|
||||
// status causes the worker to clear its queue of events but does not abort
|
||||
// the currently running script. The close handler is also scheduled with
|
||||
// no expiration time. This status may be superseded by 'eTerminated' in
|
||||
// which case the currently running script will be aborted as detailed
|
||||
// below. It may also be superseded by 'eCanceled' at which point the close
|
||||
// handler will be assigned an expiration time. Once the close handler has
|
||||
// completed or timed out the status will be changed to 'eKilled'.
|
||||
eClosed,
|
||||
|
||||
// Outer script called Terminate() on the worker or the worker object was
|
||||
// garbage collected in its outer script. Setting this status causes the
|
||||
// worker to abort immediately, clear its queue of events, and schedules the
|
||||
// close handler with no expiration time. This status may be superseded by
|
||||
// 'eCanceled' at which point the close handler will have an expiration time
|
||||
// assigned. Once the close handler has completed or timed out the status
|
||||
// will be changed to 'eKilled'.
|
||||
eTerminated,
|
||||
|
||||
// Either the user navigated away from the owning page, the owning page fell
|
||||
// out of bfcache, or the user quit the application. Setting this status
|
||||
// causes the worker to abort immediately and schedules the close handler
|
||||
// with an expiration time. Since the page has gone away the worker may not
|
||||
// post any messages. Once the close handler has completed or timed out the
|
||||
// status will be changed to 'eKilled'.
|
||||
eCanceled,
|
||||
|
||||
// The close handler has run and the worker is effectively dead.
|
||||
eKilled
|
||||
};
|
||||
|
||||
private:
|
||||
~nsDOMWorker();
|
||||
|
||||
nsresult PostMessageInternal(PRBool aToInner);
|
||||
|
||||
PRBool CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest, JSAutoEnterCompartment *aComp);
|
||||
|
||||
PRUint32 NextTimeoutId() {
|
||||
return ++mNextTimeoutId;
|
||||
}
|
||||
|
||||
nsresult AddFeature(nsDOMWorkerFeature* aFeature,
|
||||
JSContext* aCx);
|
||||
void RemoveFeature(nsDOMWorkerFeature* aFeature,
|
||||
JSContext* aCx);
|
||||
void CancelTimeoutWithId(PRUint32 aId);
|
||||
void SuspendFeatures();
|
||||
void ResumeFeatures();
|
||||
|
||||
nsIPrincipal* GetPrincipal() {
|
||||
return mPrincipal;
|
||||
}
|
||||
|
||||
void SetPrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
nsIURI* GetBaseURI() {
|
||||
return mBaseURI;
|
||||
}
|
||||
|
||||
nsresult SetBaseURI(nsIURI* aURI);
|
||||
|
||||
void ClearBaseURI();
|
||||
|
||||
nsresult FireCloseRunnable(PRIntervalTime aTimeoutInterval,
|
||||
PRBool aClearQueue,
|
||||
PRBool aFromFinalize);
|
||||
nsresult Close();
|
||||
|
||||
nsresult TerminateInternal(PRBool aFromFinalize);
|
||||
|
||||
nsIWorkerLocation* GetLocation() {
|
||||
return mLocation;
|
||||
}
|
||||
|
||||
PRBool QueueSuspendedRunnable(nsIRunnable* aRunnable);
|
||||
|
||||
// Determines if the worker should be considered "canceled". See the large
|
||||
// comment in the implementation for more details.
|
||||
PRBool IsCanceledNoLock();
|
||||
|
||||
private:
|
||||
|
||||
// mParent will live as long as mParentWN but only mParentWN will keep the JS
|
||||
// reflection alive, so we only hold one strong reference to mParentWN.
|
||||
nsDOMWorker* mParent;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mParentWN;
|
||||
|
||||
// Whether or not this worker has chrome privileges. Never changed after the
|
||||
// worker is created.
|
||||
WorkerPrivilegeModel mPrivilegeModel;
|
||||
|
||||
Mutex mLock;
|
||||
|
||||
nsRefPtr<nsDOMWorkerPool> mPool;
|
||||
|
||||
nsDOMWorkerScope* mInnerScope;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mScopeWN;
|
||||
JSObject* mGlobal;
|
||||
|
||||
PRUint32 mNextTimeoutId;
|
||||
|
||||
nsTArray<nsDOMWorkerFeature*> mFeatures;
|
||||
PRUint32 mFeatureSuspendDepth;
|
||||
|
||||
nsString mScriptURL;
|
||||
|
||||
nsIXPConnectWrappedNative* mWrappedNative;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIURI> mBaseURI;
|
||||
|
||||
PRInt32 mErrorHandlerRecursionCount;
|
||||
|
||||
// Always protected by mLock
|
||||
DOMWorkerStatus mStatus;
|
||||
|
||||
// Always protected by mLock
|
||||
PRIntervalTime mExpirationTime;
|
||||
|
||||
nsCOMPtr<nsITimer> mKillTimer;
|
||||
|
||||
nsCOMPtr<nsIWorkerLocation> mLocation;
|
||||
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > mQueuedRunnables;
|
||||
|
||||
PRPackedBool mSuspended;
|
||||
PRPackedBool mCompileAttempted;
|
||||
};
|
||||
|
||||
/**
|
||||
* A worker "feature" holds the worker alive yet can be canceled, paused, and
|
||||
* resumed by the worker. It is up to each derived class to implement these
|
||||
* methods. This class uses a custom implementation of Release in order to
|
||||
* ensure no races between Cancel and object destruction can occur, so derived
|
||||
* classes must use the ISUPPORTS_INHERITED macros.
|
||||
*
|
||||
* To use this class you should inherit it and use the ISUPPORTS_INHERITED
|
||||
* macros. Then add or remove an instance to the worker using the
|
||||
* AddFeature/RemoveFeature functions.
|
||||
*/
|
||||
class nsDOMWorkerFeature : public nsISupports
|
||||
{
|
||||
friend class nsDOMWorker;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsDOMWorkerFeature(nsDOMWorker* aWorker)
|
||||
: mWorker(aWorker), mWorkerWN(aWorker->GetWrappedNative()), mId(0),
|
||||
mHasId(PR_FALSE), mFreeToDie(PR_TRUE) { }
|
||||
|
||||
nsDOMWorkerFeature(nsDOMWorker* aWorker, PRUint32 aId)
|
||||
: mWorker(aWorker), mWorkerWN(aWorker->GetWrappedNative()), mId(aId),
|
||||
mHasId(PR_TRUE), mFreeToDie(PR_TRUE) { }
|
||||
|
||||
virtual void Cancel() = 0;
|
||||
virtual void Suspend() { }
|
||||
virtual void Resume() { }
|
||||
|
||||
PRUint32 GetId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
PRBool HasId() {
|
||||
return mHasId;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerFeature() { }
|
||||
|
||||
private:
|
||||
void FreeToDie(PRBool aFreeToDie) {
|
||||
mFreeToDie = aFreeToDie;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsRefPtr<nsDOMWorker> mWorker;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mWorkerWN;
|
||||
PRUint32 mId;
|
||||
|
||||
private:
|
||||
PRPackedBool mHasId;
|
||||
PRPackedBool mFreeToDie;
|
||||
};
|
||||
|
||||
class nsWorkerFactory : public nsIWorkerFactory
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWORKERFACTORY
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKER_H__ */
|
635
dom/src/threads/nsDOMWorkerEvents.cpp
Normal file
635
dom/src/threads/nsDOMWorkerEvents.cpp
Normal file
@ -0,0 +1,635 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerEvents.h"
|
||||
|
||||
#include "nsIXMLHttpRequest.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsAXPCNativeCallContext.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "nsDOMWorkerMessageHandler.h"
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerXHR.h"
|
||||
#include "nsDOMWorkerXHRProxy.h"
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDOMWorkerPrivateEvent,
|
||||
NS_IDOMWORKERPRIVATEEVENT_IID)
|
||||
|
||||
nsDOMWorkerPrivateEvent::nsDOMWorkerPrivateEvent(nsIDOMEvent* aEvent)
|
||||
: mEvent(aEvent),
|
||||
mProgressEvent(do_QueryInterface(aEvent)),
|
||||
mMessageEvent(do_QueryInterface(aEvent)),
|
||||
mErrorEvent(do_QueryInterface(aEvent)),
|
||||
mPreventDefaultCalled(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(aEvent, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsDOMWorkerPrivateEvent)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsDOMWorkerPrivateEvent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMWorkerPrivateEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWorkerPrivateEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEvent, nsIDOMWorkerPrivateEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMWorkerPrivateEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMProgressEvent, mProgressEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIWorkerMessageEvent, mMessageEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIWorkerErrorEvent, mErrorEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerPrivateEvent, nsIDOMEvent)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_HELPER(nsDOMWorkerPrivateEvent)
|
||||
NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(nsDOMWorkerPrivateEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::GetInterfaces(PRUint32* aCount, nsIID*** aArray)
|
||||
{
|
||||
nsCOMPtr<nsIClassInfo> ci(do_QueryInterface(mEvent));
|
||||
if (ci) {
|
||||
return ci->GetInterfaces(aCount, aArray);
|
||||
}
|
||||
return NS_CI_INTERFACE_GETTER_NAME(nsDOMWorkerPrivateEvent)(aCount, aArray);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::PreventDefault()
|
||||
{
|
||||
PRBool cancelable = PR_FALSE;
|
||||
mEvent->GetCancelable(&cancelable);
|
||||
|
||||
if (cancelable) {
|
||||
mPreventDefaultCalled = PR_TRUE;
|
||||
}
|
||||
|
||||
return mEvent->PreventDefault();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::GetDefaultPrevented(PRBool* aRetVal)
|
||||
{
|
||||
*aRetVal = mPreventDefaultCalled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::InitEvent(const nsAString& aEventType,
|
||||
PRBool aCanBubble,
|
||||
PRBool aCancelable)
|
||||
{
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
return mEvent->InitEvent(aEventType, aCanBubble, aCancelable);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::InitProgressEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
PRBool aLengthComputableArg,
|
||||
PRUint64 aLoadedArg,
|
||||
PRUint64 aTotalArg)
|
||||
{
|
||||
NS_ASSERTION(mProgressEvent, "Impossible!");
|
||||
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
return mProgressEvent->InitProgressEvent(aTypeArg, aCanBubbleArg,
|
||||
aCancelableArg, aLengthComputableArg,
|
||||
aLoadedArg, aTotalArg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::InitMessageEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aDataArg,
|
||||
const nsAString& aOriginArg,
|
||||
nsISupports* aSourceArg)
|
||||
{
|
||||
NS_ASSERTION(mMessageEvent, "Impossible!");
|
||||
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
return mMessageEvent->InitMessageEvent(aTypeArg, aCanBubbleArg,
|
||||
aCancelableArg, aDataArg, aOriginArg,
|
||||
aSourceArg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::InitErrorEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aMessageArg,
|
||||
const nsAString& aFilenameArg,
|
||||
PRUint32 aLinenoArg)
|
||||
{
|
||||
NS_ASSERTION(mErrorEvent, "Impossible!");
|
||||
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
return mErrorEvent->InitErrorEvent(aTypeArg, aCanBubbleArg, aCancelableArg,
|
||||
aMessageArg, aFilenameArg, aLinenoArg);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMWorkerPrivateEvent::PreventDefaultCalled()
|
||||
{
|
||||
return mPreventDefaultCalled;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsDOMWorkerEvent, nsIDOMEvent,
|
||||
nsIClassInfo)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerEvent, nsIDOMEvent)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI(nsDOMWorkerEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetType(nsAString& aType)
|
||||
{
|
||||
aType.Assign(mType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetTarget(nsIDOMEventTarget** aTarget)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTarget);
|
||||
NS_IF_ADDREF(*aTarget = mTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCurrentTarget);
|
||||
NS_IF_ADDREF(*aCurrentTarget = mTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetEventPhase(PRUint16* aEventPhase)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEventPhase);
|
||||
*aEventPhase = mEventPhase;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetBubbles(PRBool* aBubbles)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aBubbles);
|
||||
*aBubbles = mBubbles;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetCancelable(PRBool* aCancelable)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCancelable);
|
||||
*aCancelable = mCancelable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetTimeStamp(DOMTimeStamp* aTimeStamp)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTimeStamp);
|
||||
*aTimeStamp = mTimeStamp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::StopPropagation()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::PreventDefault()
|
||||
{
|
||||
mPreventDefaultCalled = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetDefaultPrevented(PRBool* aRetVal)
|
||||
{
|
||||
*aRetVal = mPreventDefaultCalled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::InitEvent(const nsAString& aEventTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg)
|
||||
{
|
||||
NS_ENSURE_FALSE(aEventTypeArg.IsEmpty(), NS_ERROR_INVALID_ARG);
|
||||
|
||||
mType.Assign(aEventTypeArg);
|
||||
mBubbles = aCanBubbleArg;
|
||||
mCancelable = aCancelableArg;
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
mTimeStamp = PR_Now();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerMessageEvent::~nsDOMWorkerMessageEvent()
|
||||
{
|
||||
if (mData) {
|
||||
JSContext* cx = nsDOMThreadService::GetCurrentContext();
|
||||
if (cx) {
|
||||
JS_free(cx, mData);
|
||||
}
|
||||
else {
|
||||
NS_WARNING("Failed to get safe JSContext, leaking event data!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerMessageEvent, nsDOMWorkerEvent,
|
||||
nsIWorkerMessageEvent)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerMessageEvent, nsIDOMEvent,
|
||||
nsIWorkerMessageEvent)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerMessageEvent)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageEvent::SetJSData(
|
||||
JSContext* aCx,
|
||||
JSAutoStructuredCloneBuffer& aBuffer,
|
||||
nsTArray<nsCOMPtr<nsISupports> >& aWrappedNatives)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Null context!");
|
||||
|
||||
if (!mDataVal.Hold(aCx)) {
|
||||
NS_WARNING("Failed to hold jsval!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!mWrappedNatives.SwapElements(aWrappedNatives)) {
|
||||
NS_ERROR("This should never fail!");
|
||||
}
|
||||
|
||||
aBuffer.steal(&mData, &mDataLen);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageEvent::GetData(nsAString& aData)
|
||||
{
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
NS_ENSURE_TRUE(xpc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsAXPCNativeCallContext* cc;
|
||||
nsresult rv = xpc->GetCurrentNativeCallContext(&cc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(cc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (mData) {
|
||||
JSContext* cx;
|
||||
rv = cc->GetJSContext(&cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
buffer.adopt(cx, mData, mDataLen);
|
||||
mData = nsnull;
|
||||
mDataLen = 0;
|
||||
|
||||
JSStructuredCloneCallbacks callbacks = {
|
||||
nsDOMWorker::ReadStructuredClone, nsnull, nsnull
|
||||
};
|
||||
|
||||
JSBool ok = buffer.read(mDataVal.ToJSValPtr(), cx, &callbacks);
|
||||
|
||||
// Release wrapped natives now, regardless of whether or not the deserialize
|
||||
// succeeded.
|
||||
mWrappedNatives.Clear();
|
||||
|
||||
if (!ok) {
|
||||
NS_WARNING("Failed to deserialize!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
jsval* retval;
|
||||
rv = cc->GetRetValPtr(&retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
cc->SetReturnValueWasSet(PR_TRUE);
|
||||
*retval = mDataVal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageEvent::GetOrigin(nsAString& aOrigin)
|
||||
{
|
||||
aOrigin.Assign(mOrigin);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageEvent::GetSource(nsISupports** aSource)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSource);
|
||||
NS_IF_ADDREF(*aSource = mSource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageEvent::InitMessageEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aDataArg,
|
||||
const nsAString& aOriginArg,
|
||||
nsISupports* aSourceArg)
|
||||
{
|
||||
mOrigin.Assign(aOriginArg);
|
||||
mSource = aSourceArg;
|
||||
return nsDOMWorkerEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerProgressEvent, nsDOMWorkerEvent,
|
||||
nsIDOMProgressEvent)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerProgressEvent, nsIDOMEvent,
|
||||
nsIDOMProgressEvent)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerProgressEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerProgressEvent::GetLengthComputable(PRBool* aLengthComputable)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLengthComputable);
|
||||
*aLengthComputable = mLengthComputable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerProgressEvent::GetLoaded(PRUint64* aLoaded)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLoaded);
|
||||
*aLoaded = mLoaded;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerProgressEvent::GetTotal(PRUint64* aTotal)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTotal);
|
||||
*aTotal = mTotal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerProgressEvent::InitProgressEvent(const nsAString_internal& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
PRBool aLengthComputableArg,
|
||||
PRUint64 aLoadedArg,
|
||||
PRUint64 aTotalArg)
|
||||
{
|
||||
mLengthComputable = aLengthComputableArg;
|
||||
mLoaded = aLoadedArg;
|
||||
mTotal = aTotalArg;
|
||||
return nsDOMWorkerEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsDOMWorkerXHRState)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsDOMWorkerXHRState)
|
||||
|
||||
nsDOMWorkerXHREvent::nsDOMWorkerXHREvent(nsDOMWorkerXHRProxy* aXHRProxy)
|
||||
: mXHRProxy(aXHRProxy),
|
||||
mXHREventType(PR_UINT32_MAX),
|
||||
mChannelID(-1),
|
||||
mUploadEvent(PR_FALSE),
|
||||
mProgressEvent(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(aXHRProxy, "Can't be null!");
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMWorkerXHREvent, nsDOMWorkerProgressEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMWorkerXHREvent, nsDOMWorkerProgressEvent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMWorkerXHREvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRunnable)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMProgressEvent, mProgressEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMWorkerEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREvent::GetInterfaces(PRUint32* aCount,
|
||||
nsIID*** aArray)
|
||||
{
|
||||
PRUint32 count = *aCount = mProgressEvent ? 2 : 1;
|
||||
|
||||
*aArray = (nsIID**)nsMemory::Alloc(sizeof(nsIID*) * count);
|
||||
|
||||
if (mProgressEvent) {
|
||||
(*aArray)[--count] =
|
||||
(nsIID*)nsMemory::Clone(&NS_GET_IID(nsIDOMProgressEvent), sizeof(nsIID));
|
||||
}
|
||||
|
||||
(*aArray)[--count] =
|
||||
(nsIID *)nsMemory::Clone(&NS_GET_IID(nsIDOMEvent), sizeof(nsIID));
|
||||
|
||||
NS_ASSERTION(!count, "Bad math!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHREvent::Init(PRUint32 aXHREventType,
|
||||
const nsAString& aType,
|
||||
nsIDOMEvent* aEvent,
|
||||
SnapshotChoice aSnapshot)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aEvent, "Don't pass null here!");
|
||||
|
||||
mXHREventType = aXHREventType;
|
||||
|
||||
// Only set a channel id if we're not going to be run immediately.
|
||||
mChannelID = mXHRProxy->mSyncEventQueue ? -1 : mXHRProxy->ChannelID();
|
||||
|
||||
mTarget = static_cast<nsDOMWorkerMessageHandler*>(mXHRProxy->mWorkerXHR);
|
||||
NS_ENSURE_TRUE(mTarget, NS_ERROR_UNEXPECTED);
|
||||
|
||||
mXHRWN = mXHRProxy->mWorkerXHR->GetWrappedNative();
|
||||
NS_ENSURE_STATE(mXHRWN);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> mainThreadTarget;
|
||||
nsresult rv = aEvent->GetTarget(getter_AddRefs(mainThreadTarget));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_STATE(mainThreadTarget);
|
||||
|
||||
nsCOMPtr<nsIXMLHttpRequestUpload> upload(do_QueryInterface(mainThreadTarget));
|
||||
if (upload) {
|
||||
mUploadEvent = PR_TRUE;
|
||||
mTarget =
|
||||
static_cast<nsDOMWorkerMessageHandler*>(mXHRProxy->mWorkerXHR->mUpload);
|
||||
}
|
||||
else {
|
||||
mUploadEvent = PR_FALSE;
|
||||
mTarget = static_cast<nsDOMWorkerMessageHandler*>(mXHRProxy->mWorkerXHR);
|
||||
}
|
||||
NS_ASSERTION(mTarget, "Null target!");
|
||||
|
||||
PRBool bubbles;
|
||||
rv = aEvent->GetBubbles(&bubbles);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool cancelable;
|
||||
rv = aEvent->GetCancelable(&cancelable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aEvent->GetTimeStamp(&mTimeStamp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aEvent->GetEventPhase(&mEventPhase);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(mEventPhase == nsIDOMEvent::AT_TARGET, "Unsupported phase!");
|
||||
|
||||
nsCOMPtr<nsIDOMProgressEvent> progressEvent(do_QueryInterface(aEvent));
|
||||
if (progressEvent) {
|
||||
mProgressEvent = PR_TRUE;
|
||||
|
||||
PRBool lengthComputable;
|
||||
rv = progressEvent->GetLengthComputable(&lengthComputable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint64 loaded;
|
||||
rv = progressEvent->GetLoaded(&loaded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint64 total;
|
||||
rv = progressEvent->GetTotal(&total);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = InitProgressEvent(aType, bubbles, cancelable, lengthComputable, loaded,
|
||||
total);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
mProgressEvent = PR_FALSE;
|
||||
|
||||
rv = InitEvent(aType, bubbles, cancelable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
mState = new nsDOMWorkerXHRState();
|
||||
NS_ENSURE_TRUE(mState, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (aSnapshot == SNAPSHOT) {
|
||||
SnapshotXHRState(mXHRProxy->mXHR, mState);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsDOMWorkerXHREvent::SnapshotXHRState(nsIXMLHttpRequest* aXHR,
|
||||
nsDOMWorkerXHRState* aState)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aXHR && aState, "Don't pass null here!");
|
||||
|
||||
aState->responseTextResult = aXHR->GetResponseText(aState->responseText);
|
||||
aState->statusTextResult = aXHR->GetStatusText(aState->statusText);
|
||||
aState->statusResult = aXHR->GetStatus(&aState->status);
|
||||
aState->readyStateResult = aXHR->GetReadyState(&aState->readyState);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREvent::Run()
|
||||
{
|
||||
nsresult rv = mXHRProxy->HandleWorkerEvent(this, mUploadEvent);
|
||||
|
||||
// Prevent reference cycles by releasing this here.
|
||||
mXHRProxy = nsnull;
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerErrorEvent, nsDOMWorkerEvent,
|
||||
nsIWorkerErrorEvent)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerErrorEvent, nsIDOMEvent,
|
||||
nsIWorkerErrorEvent)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerErrorEvent)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerErrorEvent::GetMessage(nsAString& aMessage)
|
||||
{
|
||||
aMessage.Assign(mMessage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerErrorEvent::GetFilename(nsAString& aFilename)
|
||||
{
|
||||
aFilename.Assign(mFilename);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerErrorEvent::GetLineno(PRUint32* aLineno)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLineno);
|
||||
*aLineno = mLineno;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerErrorEvent::InitErrorEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aMessageArg,
|
||||
const nsAString& aFilenameArg,
|
||||
PRUint32 aLinenoArg)
|
||||
{
|
||||
mMessage.Assign(aMessageArg);
|
||||
mFilename.Assign(aFilenameArg);
|
||||
mLineno = aLinenoArg;
|
||||
return InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||
}
|
340
dom/src/threads/nsDOMWorkerEvents.h
Normal file
340
dom/src/threads/nsDOMWorkerEvents.h
Normal file
@ -0,0 +1,340 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKEREVENTS_H__
|
||||
#define __NSDOMWORKEREVENTS_H__
|
||||
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMProgressEvent.h"
|
||||
#include "nsIDOMWorkers.h"
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsutil.h"
|
||||
#include "nsAutoJSValHolder.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
#include "nsDOMWorkerMacros.h"
|
||||
|
||||
class nsDOMWorkerXHRProxy;
|
||||
class nsIXMLHttpRequest;
|
||||
class nsIXPConnectWrappedNative;
|
||||
|
||||
/* 4d5794d6-98ab-4a6b-ad5a-8ed1fa1d4839 */
|
||||
#define NS_IDOMWORKERPRIVATEEVENT_IID \
|
||||
{ \
|
||||
0x4d5794d6, \
|
||||
0x98ab, \
|
||||
0x4a6b, \
|
||||
{ 0xad, 0x5a, 0x8e, 0xd1, 0xfa, 0x1d, 0x48, 0x39 } \
|
||||
}
|
||||
|
||||
class nsIDOMWorkerPrivateEvent : public nsIDOMEvent
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOMWORKERPRIVATEEVENT_IID)
|
||||
virtual PRBool PreventDefaultCalled() = 0;
|
||||
};
|
||||
|
||||
#define NS_FORWARD_NSIDOMEVENT_SPECIAL \
|
||||
NS_IMETHOD GetType(nsAString& aType) \
|
||||
{ return mEvent->GetType(aType); } \
|
||||
NS_IMETHOD GetTarget(nsIDOMEventTarget** aTarget) \
|
||||
{ return mEvent->GetTarget(aTarget); } \
|
||||
NS_IMETHOD GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) \
|
||||
{ return mEvent->GetCurrentTarget(aCurrentTarget); } \
|
||||
NS_IMETHOD GetEventPhase(PRUint16* aEventPhase) \
|
||||
{ return mEvent->GetEventPhase(aEventPhase); } \
|
||||
NS_IMETHOD GetBubbles(PRBool* aBubbles) \
|
||||
{ return mEvent->GetBubbles(aBubbles); } \
|
||||
NS_IMETHOD GetCancelable(PRBool* aCancelable) \
|
||||
{ return mEvent->GetCancelable(aCancelable); } \
|
||||
NS_IMETHOD GetTimeStamp(DOMTimeStamp* aTimeStamp) \
|
||||
{ return mEvent->GetTimeStamp(aTimeStamp); } \
|
||||
NS_IMETHOD StopPropagation() \
|
||||
{ return mEvent->StopPropagation(); }
|
||||
|
||||
#define NS_FORWARD_NSIDOMPROGRESSEVENT_SPECIAL \
|
||||
NS_IMETHOD GetLengthComputable(PRBool* aLengthComputable) \
|
||||
{ return mProgressEvent->GetLengthComputable(aLengthComputable); } \
|
||||
NS_IMETHOD GetLoaded(PRUint64* aLoaded) \
|
||||
{ return mProgressEvent->GetLoaded(aLoaded); } \
|
||||
NS_IMETHOD GetTotal(PRUint64* aTotal) \
|
||||
{ return mProgressEvent->GetTotal(aTotal); }
|
||||
|
||||
#define NS_FORWARD_NSIWORKERMESSAGEEVENT_SPECIAL \
|
||||
NS_IMETHOD GetData(nsAString& aData) \
|
||||
{ return mMessageEvent->GetData(aData); } \
|
||||
NS_IMETHOD GetOrigin(nsAString& aOrigin) \
|
||||
{ return mMessageEvent->GetOrigin(aOrigin); } \
|
||||
NS_IMETHOD GetSource(nsISupports** aSource) \
|
||||
{ return mMessageEvent->GetSource(aSource); }
|
||||
|
||||
#define NS_FORWARD_NSIWORKERERROREVENT_SPECIAL \
|
||||
NS_IMETHOD GetMessage(nsAString& aMessage) \
|
||||
{ return mErrorEvent->GetMessage(aMessage); } \
|
||||
NS_IMETHOD GetFilename(nsAString& aFilename) \
|
||||
{ return mErrorEvent->GetFilename(aFilename); } \
|
||||
NS_IMETHOD GetLineno(PRUint32* aLineno) \
|
||||
{ return mErrorEvent->GetLineno(aLineno); }
|
||||
|
||||
class nsDOMWorkerPrivateEvent : public nsIDOMWorkerPrivateEvent,
|
||||
public nsIDOMProgressEvent,
|
||||
public nsIWorkerMessageEvent,
|
||||
public nsIWorkerErrorEvent,
|
||||
public nsIClassInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_NSIDOMEVENT_SPECIAL
|
||||
NS_FORWARD_NSIWORKERMESSAGEEVENT_SPECIAL
|
||||
NS_FORWARD_NSIDOMPROGRESSEVENT_SPECIAL
|
||||
NS_FORWARD_NSIWORKERERROREVENT_SPECIAL
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
nsDOMWorkerPrivateEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
NS_IMETHOD PreventDefault();
|
||||
|
||||
NS_IMETHOD InitEvent(const nsAString& aEventType,
|
||||
PRBool aCanBubble,
|
||||
PRBool aCancelable);
|
||||
|
||||
NS_IMETHOD InitProgressEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
PRBool aLengthComputableArg,
|
||||
PRUint64 aLoadedArg,
|
||||
PRUint64 aTotalArg);
|
||||
|
||||
NS_IMETHOD InitMessageEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aDataArg,
|
||||
const nsAString& aOriginArg,
|
||||
nsISupports* aSourceArg);
|
||||
|
||||
NS_IMETHOD InitErrorEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aMessageArg,
|
||||
const nsAString& aFilenameArg,
|
||||
PRUint32 aLinenoArg);
|
||||
|
||||
NS_IMETHOD GetDefaultPrevented(PRBool* aRetVal);
|
||||
|
||||
virtual PRBool PreventDefaultCalled();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDOMEvent> mEvent;
|
||||
nsCOMPtr<nsIDOMProgressEvent> mProgressEvent;
|
||||
nsCOMPtr<nsIWorkerMessageEvent> mMessageEvent;
|
||||
nsCOMPtr<nsIWorkerErrorEvent> mErrorEvent;
|
||||
PRBool mPreventDefaultCalled;
|
||||
};
|
||||
|
||||
class nsDOMWorkerEvent : public nsIDOMEvent,
|
||||
public nsIClassInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENT
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
nsDOMWorkerEvent()
|
||||
: mEventPhase(nsIDOMEvent::AT_TARGET), mTimeStamp(0), mBubbles(PR_FALSE),
|
||||
mCancelable(PR_FALSE), mPreventDefaultCalled(PR_FALSE) { }
|
||||
|
||||
void SetTarget(nsIDOMEventTarget* aTarget) {
|
||||
mTarget = aTarget;
|
||||
}
|
||||
|
||||
PRBool PreventDefaultCalled() {
|
||||
return PRBool(mPreventDefaultCalled);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerEvent() { }
|
||||
|
||||
nsString mType;
|
||||
nsCOMPtr<nsIDOMEventTarget> mTarget;
|
||||
PRUint16 mEventPhase;
|
||||
DOMTimeStamp mTimeStamp;
|
||||
PRPackedBool mBubbles;
|
||||
PRPackedBool mCancelable;
|
||||
PRPackedBool mPreventDefaultCalled;
|
||||
};
|
||||
|
||||
class nsDOMWorkerMessageEvent : public nsDOMWorkerEvent,
|
||||
public nsIWorkerMessageEvent
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIDOMEVENT(nsDOMWorkerEvent::)
|
||||
NS_DECL_NSIWORKERMESSAGEEVENT
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
nsDOMWorkerMessageEvent() : mData(nsnull) { }
|
||||
~nsDOMWorkerMessageEvent();
|
||||
|
||||
nsresult SetJSData(JSContext* aCx,
|
||||
JSAutoStructuredCloneBuffer& aBuffer,
|
||||
nsTArray<nsCOMPtr<nsISupports> >& aWrappedNatives);
|
||||
|
||||
protected:
|
||||
nsString mOrigin;
|
||||
nsCOMPtr<nsISupports> mSource;
|
||||
|
||||
nsAutoJSValHolder mDataVal;
|
||||
uint64* mData;
|
||||
size_t mDataLen;
|
||||
nsTArray<nsCOMPtr<nsISupports> > mWrappedNatives;
|
||||
};
|
||||
|
||||
class nsDOMWorkerProgressEvent : public nsDOMWorkerEvent,
|
||||
public nsIDOMProgressEvent
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIDOMEVENT(nsDOMWorkerEvent::)
|
||||
NS_DECL_NSIDOMPROGRESSEVENT
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
nsDOMWorkerProgressEvent()
|
||||
: mLoaded(0), mTotal(0), mLengthComputable(PR_FALSE) { }
|
||||
|
||||
protected:
|
||||
PRUint64 mLoaded;
|
||||
PRUint64 mTotal;
|
||||
PRBool mLengthComputable;
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHRState
|
||||
{
|
||||
public:
|
||||
nsDOMWorkerXHRState()
|
||||
: responseTextResult(NS_OK), statusTextResult(NS_OK), status(NS_OK),
|
||||
statusResult(NS_OK), readyState(0), readyStateResult(NS_OK) { }
|
||||
|
||||
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||
NS_IMETHOD_(nsrefcnt) Release();
|
||||
|
||||
nsString responseText;
|
||||
nsresult responseTextResult;
|
||||
|
||||
nsCString statusText;
|
||||
nsresult statusTextResult;
|
||||
|
||||
nsresult status;
|
||||
nsresult statusResult;
|
||||
|
||||
PRUint16 readyState;
|
||||
nsresult readyStateResult;
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerXHRState() { }
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHREvent : public nsDOMWorkerProgressEvent,
|
||||
public nsIRunnable
|
||||
{
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
enum SnapshotChoice {
|
||||
SNAPSHOT,
|
||||
NO_SNAPSHOT
|
||||
};
|
||||
|
||||
nsDOMWorkerXHREvent(nsDOMWorkerXHRProxy* aXHRProxy);
|
||||
|
||||
nsresult Init(PRUint32 aXHREventType,
|
||||
const nsAString& aType,
|
||||
nsIDOMEvent* aEvent,
|
||||
SnapshotChoice = SNAPSHOT);
|
||||
|
||||
static void SnapshotXHRState(nsIXMLHttpRequest* aXHR,
|
||||
nsDOMWorkerXHRState* aState);
|
||||
|
||||
already_AddRefed<nsDOMWorkerXHRState> ForgetState() {
|
||||
return mState.forget();
|
||||
}
|
||||
|
||||
protected:
|
||||
nsDOMWorkerXHRState* GetState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHRProxy;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mXHRWN;
|
||||
nsRefPtr<nsDOMWorkerXHRState> mState;
|
||||
PRUint32 mXHREventType;
|
||||
PRInt32 mChannelID;
|
||||
PRPackedBool mUploadEvent;
|
||||
PRPackedBool mProgressEvent;
|
||||
};
|
||||
|
||||
class nsDOMWorkerErrorEvent : public nsDOMWorkerEvent,
|
||||
public nsIWorkerErrorEvent
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIDOMEVENT(nsDOMWorkerEvent::)
|
||||
NS_DECL_NSIWORKERERROREVENT
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
nsDOMWorkerErrorEvent()
|
||||
: mLineno(0) { }
|
||||
|
||||
protected:
|
||||
nsString mMessage;
|
||||
nsString mFilename;
|
||||
PRUint32 mLineno;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKEREVENTS_H__ */
|
135
dom/src/threads/nsDOMWorkerMacros.h
Normal file
135
dom/src/threads/nsDOMWorkerMacros.h
Normal file
@ -0,0 +1,135 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERMACROS_H__
|
||||
#define __NSDOMWORKERMACROS_H__
|
||||
|
||||
// Macro to generate nsIClassInfo methods for these threadsafe DOM classes
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(_class) \
|
||||
NS_IMETHODIMP \
|
||||
_class::GetInterfaces(PRUint32* _count, nsIID*** _array) \
|
||||
{ \
|
||||
return NS_CI_INTERFACE_GETTER_NAME(_class)(_count, _array); \
|
||||
} \
|
||||
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI_HELPER(_class) \
|
||||
NS_IMETHODIMP \
|
||||
_class::GetHelperForLanguage(PRUint32 _language, nsISupports** _retval) \
|
||||
{ \
|
||||
*_retval = nsnull; \
|
||||
return NS_OK; \
|
||||
}
|
||||
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(_class) \
|
||||
NS_IMETHODIMP \
|
||||
_class::GetContractID(char** _contractID) \
|
||||
{ \
|
||||
*_contractID = nsnull; \
|
||||
return NS_OK; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
_class::GetClassDescription(char** _classDescription) \
|
||||
{ \
|
||||
*_classDescription = nsnull; \
|
||||
return NS_OK; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
_class::GetClassID(nsCID** _classID) \
|
||||
{ \
|
||||
*_classID = nsnull; \
|
||||
return NS_OK; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
_class::GetImplementationLanguage(PRUint32* _language) \
|
||||
{ \
|
||||
*_language = nsIProgrammingLanguage::CPLUSPLUS; \
|
||||
return NS_OK; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
_class::GetFlags(PRUint32* _flags) \
|
||||
{ \
|
||||
*_flags = nsIClassInfo::THREADSAFE | nsIClassInfo::DOM_OBJECT; \
|
||||
return NS_OK; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
_class::GetClassIDNoAlloc(nsCID* _classIDNoAlloc) \
|
||||
{ \
|
||||
return NS_ERROR_NOT_AVAILABLE; \
|
||||
}
|
||||
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI(_class) \
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(_class) \
|
||||
NS_IMPL_THREADSAFE_DOM_CI_HELPER(_class) \
|
||||
NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(_class)
|
||||
|
||||
#define NS_FORWARD_NSICLASSINFO_NOGETINTERFACES(_to) \
|
||||
NS_IMETHOD GetHelperForLanguage(PRUint32 aLanguage, nsISupports** _retval) \
|
||||
{ return _to GetHelperForLanguage(aLanguage, _retval); } \
|
||||
NS_IMETHOD GetContractID(char** aContractID) \
|
||||
{ return _to GetContractID(aContractID); } \
|
||||
NS_IMETHOD GetClassDescription(char** aClassDescription) \
|
||||
{ return _to GetClassDescription(aClassDescription); } \
|
||||
NS_IMETHOD GetClassID(nsCID** aClassID) \
|
||||
{ return _to GetClassID(aClassID); } \
|
||||
NS_IMETHOD GetImplementationLanguage(PRUint32* aImplementationLanguage) \
|
||||
{ return _to GetImplementationLanguage(aImplementationLanguage); } \
|
||||
NS_IMETHOD GetFlags(PRUint32* aFlags) \
|
||||
{ return _to GetFlags(aFlags); } \
|
||||
NS_IMETHOD GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) \
|
||||
{ return _to GetClassIDNoAlloc(aClassIDNoAlloc); }
|
||||
|
||||
#define NS_DECL_NSICLASSINFO_GETINTERFACES \
|
||||
NS_IMETHOD GetInterfaces(PRUint32* aCount, nsIID*** aArray);
|
||||
|
||||
// Don't know why nsISupports.idl defines this out...
|
||||
#define NS_FORWARD_NSISUPPORTS(_to) \
|
||||
NS_IMETHOD QueryInterface(const nsIID& uuid, void** result) { \
|
||||
return _to QueryInterface(uuid, result); \
|
||||
} \
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) { return _to AddRef(); } \
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) { return _to Release(); }
|
||||
|
||||
#define JSON_PRIMITIVE_PROPNAME \
|
||||
"primitive"
|
||||
|
||||
#endif /* __NSDOMWORKERMACROS_H__ */
|
440
dom/src/threads/nsDOMWorkerMessageHandler.cpp
Normal file
440
dom/src/threads/nsDOMWorkerMessageHandler.cpp
Normal file
@ -0,0 +1,440 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerMessageHandler.h"
|
||||
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerEvents.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsDOMWorkerEventListenerBase)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsDOMWorkerEventListenerBase)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerWeakEventListener::Init(nsIDOMEventListener* aListener)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS(do_QueryInterface(aListener));
|
||||
NS_ENSURE_TRUE(wrappedJS, NS_NOINTERFACE);
|
||||
|
||||
JSObject* obj;
|
||||
nsresult rv = wrappedJS->GetJSObject(&obj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mObj = obj;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMEventListener>
|
||||
nsDOMWorkerWeakEventListener::GetListener()
|
||||
{
|
||||
JSContext* cx = nsDOMThreadService::GetCurrentContext();
|
||||
NS_ENSURE_TRUE(cx, nsnull);
|
||||
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener;
|
||||
nsresult rv = xpc->WrapJS(cx, mObj, NS_GET_IID(nsIDOMEventListener),
|
||||
getter_AddRefs(listener));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
return listener.forget();
|
||||
}
|
||||
|
||||
nsDOMWorkerWrappedWeakEventListener::
|
||||
nsDOMWorkerWrappedWeakEventListener(nsDOMWorkerWeakEventListener* aInner)
|
||||
: mInner(aInner)
|
||||
{
|
||||
NS_ASSERTION(aInner, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsDOMWorkerMessageHandler,
|
||||
nsIDOMEventTarget,
|
||||
nsIClassInfo)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerMessageHandler,
|
||||
nsIDOMEventTarget)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI(nsDOMWorkerMessageHandler)
|
||||
|
||||
const nsDOMWorkerMessageHandler::ListenerCollection*
|
||||
nsDOMWorkerMessageHandler::GetListenerCollection(const nsAString& aType) const
|
||||
{
|
||||
PRUint32 count = mCollections.Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
const ListenerCollection& collection = mCollections[index];
|
||||
if (collection.type.Equals(aType)) {
|
||||
return &collection;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerMessageHandler::GetListenersForType(const nsAString& aType,
|
||||
ListenerArray& _retval) const
|
||||
{
|
||||
_retval.Clear();
|
||||
|
||||
const ListenerCollection* collection = GetListenerCollection(aType);
|
||||
if (collection) {
|
||||
PRUint32 count = collection->listeners.Length();
|
||||
|
||||
if (!_retval.SetLength(count)) {
|
||||
NS_WARNING("Out of memory!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
nsCOMPtr<nsIDOMEventListener> listener =
|
||||
collection->listeners[index]->GetListener();
|
||||
_retval[index].swap(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener)
|
||||
{
|
||||
nsRefPtr<nsDOMWorkerWrappedWeakEventListener> wrappedListener;
|
||||
|
||||
ListenerCollection* collection =
|
||||
const_cast<ListenerCollection*>(GetListenerCollection(aType));
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool removed;
|
||||
#endif
|
||||
|
||||
if (collection) {
|
||||
wrappedListener.swap(collection->onXListener);
|
||||
if (wrappedListener) {
|
||||
#ifdef DEBUG
|
||||
removed =
|
||||
#endif
|
||||
collection->listeners.RemoveElement(wrappedListener);
|
||||
NS_ASSERTION(removed, "Element wasn't in the list!");
|
||||
}
|
||||
}
|
||||
|
||||
if (!aListener) {
|
||||
if (collection && !collection->listeners.Length()) {
|
||||
#ifdef DEBUG
|
||||
removed =
|
||||
#endif
|
||||
mCollections.RemoveElement(*collection);
|
||||
NS_ASSERTION(removed, "Element wasn't in the list!");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerWeakEventListener> weakListener =
|
||||
new nsDOMWorkerWeakEventListener();
|
||||
NS_ENSURE_TRUE(weakListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = weakListener->Init(aListener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
wrappedListener = new nsDOMWorkerWrappedWeakEventListener(weakListener);
|
||||
NS_ENSURE_TRUE(wrappedListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (!collection) {
|
||||
collection = mCollections.AppendElement(aType);
|
||||
NS_ENSURE_TRUE(collection, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
WeakListener* newListener =
|
||||
collection->listeners.AppendElement(wrappedListener);
|
||||
NS_ENSURE_TRUE(newListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
wrappedListener.swap(collection->onXListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMEventListener>
|
||||
nsDOMWorkerMessageHandler::GetOnXListener(const nsAString& aType) const
|
||||
{
|
||||
const ListenerCollection* collection = GetListenerCollection(aType);
|
||||
if (collection && collection->onXListener) {
|
||||
return collection->onXListener->GetListener();
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerMessageHandler::ClearListeners(const nsAString& aType)
|
||||
{
|
||||
PRUint32 count = mCollections.Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
if (mCollections[index].type.Equals(aType)) {
|
||||
mCollections.RemoveElementAt(index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMWorkerMessageHandler::HasListeners(const nsAString& aType)
|
||||
{
|
||||
const ListenerCollection* collection = GetListenerCollection(aType);
|
||||
return collection && collection->listeners.Length();
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerMessageHandler::ClearAllListeners()
|
||||
{
|
||||
mCollections.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerMessageHandler::Trace(JSTracer* aTracer)
|
||||
{
|
||||
PRUint32 cCount = mCollections.Length();
|
||||
for (PRUint32 cIndex = 0; cIndex < cCount; cIndex++) {
|
||||
const ListenerCollection& collection = mCollections[cIndex];
|
||||
PRUint32 lCount = collection.listeners.Length();
|
||||
for (PRUint32 lIndex = 0; lIndex < lCount; lIndex++) {
|
||||
JSObject* obj = collection.listeners[lIndex]->GetJSObject();
|
||||
NS_ASSERTION(obj, "Null object!");
|
||||
JS_SET_TRACING_DETAILS(aTracer, nsnull, this, 0);
|
||||
JS_CallTracer(aTracer, obj, JSTRACE_OBJECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See nsIDOMEventTarget
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageHandler::RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture)
|
||||
{
|
||||
ListenerCollection* collection =
|
||||
const_cast<ListenerCollection*>(GetListenerCollection(aType));
|
||||
|
||||
if (collection) {
|
||||
PRUint32 count = collection->listeners.Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
WeakListener& weakListener = collection->listeners[index];
|
||||
if (weakListener == collection->onXListener) {
|
||||
continue;
|
||||
}
|
||||
nsCOMPtr<nsIDOMEventListener> listener = weakListener->GetListener();
|
||||
if (listener == aListener) {
|
||||
collection->listeners.RemoveElementAt(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!collection->listeners.Length()) {
|
||||
#ifdef DEBUG
|
||||
PRBool removed =
|
||||
#endif
|
||||
mCollections.RemoveElement(*collection);
|
||||
NS_ASSERTION(removed, "Somehow this wasn't in the list!");
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* See nsIDOMEventTarget
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageHandler::DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
|
||||
nsCOMPtr<nsIDOMWorkerPrivateEvent> event;
|
||||
|
||||
if (_retval) {
|
||||
event = do_QueryInterface(aEvent);
|
||||
if (!event) {
|
||||
event = new nsDOMWorkerPrivateEvent(aEvent);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
aEvent = event;
|
||||
}
|
||||
|
||||
nsAutoString type;
|
||||
nsresult rv = aEvent->GetType(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoTArray<Listener, 10> listeners;
|
||||
GetListenersForType(type, listeners);
|
||||
|
||||
PRUint32 count = listeners.Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
const Listener& listener = listeners[index];
|
||||
NS_ASSERTION(listener, "Null listener in array!");
|
||||
|
||||
listener->HandleEvent(aEvent);
|
||||
}
|
||||
|
||||
if (_retval) {
|
||||
*_retval = event->PreventDefaultCalled();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* See nsIDOMEventTarget
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageHandler::AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 aOptionalArgc)
|
||||
{
|
||||
// We don't support aWantsUntrusted yet.
|
||||
NS_ENSURE_TRUE(aOptionalArgc < 2, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
ListenerCollection* collection =
|
||||
const_cast<ListenerCollection*>(GetListenerCollection(aType));
|
||||
|
||||
if (!collection) {
|
||||
collection = mCollections.AppendElement(aType);
|
||||
NS_ENSURE_TRUE(collection, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerWeakEventListener> weakListener =
|
||||
new nsDOMWorkerWeakEventListener();
|
||||
NS_ENSURE_TRUE(weakListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = weakListener->Init(aListener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
WeakListener* newListener = collection->listeners.AppendElement(weakListener);
|
||||
NS_ENSURE_TRUE(newListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDOMEventTarget *
|
||||
nsDOMWorkerMessageHandler::GetTargetForDOMEvent()
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsIDOMEventTarget *
|
||||
nsDOMWorkerMessageHandler::GetTargetForEventTargetChain()
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::PreHandleEvent(nsEventChainPreVisitor & aVisitor)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::WillHandleEvent(nsEventChainPostVisitor & aVisitor)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::PostHandleEvent(nsEventChainPostVisitor & aVisitor)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::DispatchDOMEvent(nsEvent *aEvent, nsIDOMEvent *aDOMEvent,
|
||||
nsPresContext *aPresContext,
|
||||
nsEventStatus *aEventStatus)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsEventListenerManager*
|
||||
nsDOMWorkerMessageHandler::GetListenerManager(PRBool aMayCreate)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::AddEventListenerByIID(nsIDOMEventListener *aListener,
|
||||
const nsIID & aIID)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::RemoveEventListenerByIID(nsIDOMEventListener *aListener,
|
||||
const nsIID & aIID)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsIScriptContext*
|
||||
nsDOMWorkerMessageHandler::GetContextForEventHandlers(nsresult *aRv)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
*aRv = NS_ERROR_NOT_IMPLEMENTED;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSContext*
|
||||
nsDOMWorkerMessageHandler::GetJSContextForEventHandlers()
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return nsnull;
|
||||
}
|
175
dom/src/threads/nsDOMWorkerMessageHandler.h
Normal file
175
dom/src/threads/nsDOMWorkerMessageHandler.h
Normal file
@ -0,0 +1,175 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERMESSAGEHANDLER_H__
|
||||
#define __NSDOMWORKERMESSAGEHANDLER_H__
|
||||
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMWorkers.h"
|
||||
|
||||
#include "nsIProgrammingLanguage.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIWeakReference.h"
|
||||
|
||||
class nsDOMWorkerEventListenerBase
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||
NS_IMETHOD_(nsrefcnt) Release();
|
||||
|
||||
virtual already_AddRefed<nsIDOMEventListener> GetListener() = 0;
|
||||
virtual JSObject* GetJSObject() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerEventListenerBase() { }
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
};
|
||||
|
||||
class nsDOMWorkerWeakEventListener : public nsDOMWorkerEventListenerBase
|
||||
{
|
||||
public:
|
||||
nsDOMWorkerWeakEventListener()
|
||||
: mObj(NULL) { }
|
||||
|
||||
nsresult Init(nsIDOMEventListener* aListener);
|
||||
|
||||
already_AddRefed<nsIDOMEventListener> GetListener();
|
||||
|
||||
virtual JSObject* GetJSObject() {
|
||||
return mObj;
|
||||
}
|
||||
|
||||
private:
|
||||
JSObject* mObj;
|
||||
};
|
||||
|
||||
class nsDOMWorkerWrappedWeakEventListener : public nsDOMWorkerEventListenerBase
|
||||
{
|
||||
public:
|
||||
nsDOMWorkerWrappedWeakEventListener(nsDOMWorkerWeakEventListener* aInner);
|
||||
|
||||
already_AddRefed<nsIDOMEventListener> GetListener() {
|
||||
return mInner->GetListener();
|
||||
}
|
||||
|
||||
virtual JSObject* GetJSObject() {
|
||||
return mInner->GetJSObject();
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsDOMWorkerWeakEventListener> mInner;
|
||||
};
|
||||
|
||||
class nsDOMWorkerMessageHandler : public nsIDOMEventTarget,
|
||||
public nsIClassInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTTARGET
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
virtual nsresult SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener);
|
||||
|
||||
already_AddRefed<nsIDOMEventListener>
|
||||
GetOnXListener(const nsAString& aType) const;
|
||||
|
||||
void ClearListeners(const nsAString& aType);
|
||||
|
||||
PRBool HasListeners(const nsAString& aType);
|
||||
|
||||
void ClearAllListeners();
|
||||
|
||||
void Trace(JSTracer* aTracer);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerMessageHandler() { }
|
||||
|
||||
private:
|
||||
|
||||
typedef nsCOMPtr<nsIDOMEventListener> Listener;
|
||||
typedef nsTArray<Listener> ListenerArray;
|
||||
|
||||
typedef nsRefPtr<nsDOMWorkerEventListenerBase> WeakListener;
|
||||
typedef nsTArray<WeakListener> WeakListenerArray;
|
||||
|
||||
struct ListenerCollection {
|
||||
PRBool operator==(const ListenerCollection& aOther) const {
|
||||
return this == &aOther;
|
||||
}
|
||||
|
||||
ListenerCollection(const nsAString& aType)
|
||||
: type(aType) { }
|
||||
|
||||
nsString type;
|
||||
WeakListenerArray listeners;
|
||||
nsRefPtr<nsDOMWorkerWrappedWeakEventListener> onXListener;
|
||||
};
|
||||
|
||||
const ListenerCollection* GetListenerCollection(const nsAString& aType) const;
|
||||
|
||||
void GetListenersForType(const nsAString& aType,
|
||||
ListenerArray& _retval) const;
|
||||
|
||||
nsTArray<ListenerCollection> mCollections;
|
||||
};
|
||||
|
||||
#define NS_FORWARD_INTERNAL_NSIDOMEVENTTARGET(_to) \
|
||||
virtual nsIDOMEventTarget * GetTargetForDOMEvent(void) { return _to GetTargetForDOMEvent(); } \
|
||||
virtual nsIDOMEventTarget * GetTargetForEventTargetChain(void) { return _to GetTargetForEventTargetChain(); } \
|
||||
virtual nsresult PreHandleEvent(nsEventChainPreVisitor & aVisitor) { return _to PreHandleEvent(aVisitor); } \
|
||||
virtual nsresult WillHandleEvent(nsEventChainPostVisitor & aVisitor) { return _to WillHandleEvent(aVisitor); } \
|
||||
virtual nsresult PostHandleEvent(nsEventChainPostVisitor & aVisitor) { return _to PostHandleEvent(aVisitor); } \
|
||||
virtual nsresult DispatchDOMEvent(nsEvent *aEvent, nsIDOMEvent *aDOMEvent, nsPresContext *aPresContext, nsEventStatus *aEventStatus) { return _to DispatchDOMEvent(aEvent, aDOMEvent, aPresContext, aEventStatus); } \
|
||||
virtual nsEventListenerManager * GetListenerManager(PRBool aMayCreate) { return _to GetListenerManager(aMayCreate); } \
|
||||
virtual nsresult AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID & aIID) { return _to AddEventListenerByIID(aListener, aIID); } \
|
||||
virtual nsresult RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID & aIID) { return _to RemoveEventListenerByIID(aListener, aIID); } \
|
||||
virtual nsIScriptContext * GetContextForEventHandlers(nsresult *aRv NS_OUTPARAM) { return _to GetContextForEventHandlers(aRv); } \
|
||||
virtual JSContext * GetJSContextForEventHandlers(void) { return _to GetJSContextForEventHandlers(); }
|
||||
|
||||
|
||||
#endif /* __NSDOMWORKERMESSAGEHANDLER_H__ */
|
238
dom/src/threads/nsDOMWorkerPool.cpp
Normal file
238
dom/src/threads/nsDOMWorkerPool.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerPool.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIThreadManager.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorker.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
|
||||
|
||||
nsDOMWorkerPool::nsDOMWorkerPool(nsIScriptGlobalObject* aGlobalObject,
|
||||
nsIDocument* aDocument)
|
||||
: mParentGlobal(aGlobalObject),
|
||||
mParentDocument(aDocument),
|
||||
mReentrantMonitor("nsDOMWorkerPool.mReentrantMonitor"),
|
||||
mCanceled(PR_FALSE),
|
||||
mSuspended(PR_FALSE),
|
||||
mWindowID(aDocument ? aDocument->OuterWindowID() : 0)
|
||||
{
|
||||
}
|
||||
|
||||
nsDOMWorkerPool::~nsDOMWorkerPool()
|
||||
{
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
|
||||
nsIScriptGlobalObject* global;
|
||||
mParentGlobal.forget(&global);
|
||||
if (global) {
|
||||
NS_ProxyRelease(mainThread, global, PR_FALSE);
|
||||
}
|
||||
|
||||
nsIDocument* document;
|
||||
mParentDocument.forget(&document);
|
||||
if (document) {
|
||||
NS_ProxyRelease(mainThread, document, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsDOMWorkerPool)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsDOMWorkerPool)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerPool::Init()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerPool::NoteWorker(nsDOMWorker* aWorker)
|
||||
{
|
||||
NS_ASSERTION(aWorker, "Null pointer!");
|
||||
|
||||
PRBool suspendWorker;
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsDOMWorker** newWorker = mWorkers.AppendElement(aWorker);
|
||||
NS_ENSURE_TRUE(newWorker, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
suspendWorker = mSuspended;
|
||||
}
|
||||
|
||||
if (suspendWorker) {
|
||||
aWorker->Suspend();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerPool::NoteDyingWorker(nsDOMWorker* aWorker)
|
||||
{
|
||||
NS_ASSERTION(aWorker, "Null pointer!");
|
||||
|
||||
PRBool removeFromThreadService = PR_FALSE;
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
NS_ASSERTION(mWorkers.Contains(aWorker), "Worker from a different pool?!");
|
||||
mWorkers.RemoveElement(aWorker);
|
||||
|
||||
if (!mCanceled && !mWorkers.Length()) {
|
||||
removeFromThreadService = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeFromThreadService) {
|
||||
nsRefPtr<nsDOMWorkerPool> kungFuDeathGrip(this);
|
||||
nsDOMThreadService::get()->NoteEmptyPool(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerPool::GetWorkers(nsTArray<nsDOMWorker*>& aArray)
|
||||
{
|
||||
mReentrantMonitor.AssertCurrentThreadIn();
|
||||
NS_ASSERTION(!aArray.Length(), "Should be empty!");
|
||||
|
||||
#ifdef DEBUG
|
||||
nsDOMWorker** newWorkers =
|
||||
#endif
|
||||
aArray.AppendElements(mWorkers);
|
||||
NS_WARN_IF_FALSE(newWorkers, "Out of memory!");
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerPool::Cancel()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!mCanceled, "Canceled more than once!");
|
||||
|
||||
nsAutoTArray<nsDOMWorker*, 10> workers;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
mCanceled = PR_TRUE;
|
||||
|
||||
GetWorkers(workers);
|
||||
}
|
||||
|
||||
PRUint32 count = workers.Length();
|
||||
if (count) {
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
workers[index]->Cancel();
|
||||
}
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mon.NotifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerPool::Suspend()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoTArray<nsDOMWorker*, 10> workers;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
NS_ASSERTION(!mSuspended, "Suspended more than once!");
|
||||
mSuspended = PR_TRUE;
|
||||
|
||||
GetWorkers(workers);
|
||||
}
|
||||
|
||||
PRUint32 count = workers.Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
workers[index]->Suspend();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerPool::Resume()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoTArray<nsDOMWorker*, 10> workers;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
NS_ASSERTION(mSuspended, "Not suspended!");
|
||||
mSuspended = PR_FALSE;
|
||||
|
||||
GetWorkers(workers);
|
||||
}
|
||||
|
||||
PRUint32 count = workers.Length();
|
||||
if (count) {
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
workers[index]->Resume();
|
||||
}
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mon.NotifyAll();
|
||||
}
|
||||
}
|
118
dom/src/threads/nsDOMWorkerPool.h
Normal file
118
dom/src/threads/nsDOMWorkerPool.h
Normal file
@ -0,0 +1,118 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERPOOL_H__
|
||||
#define __NSDOMWORKERPOOL_H__
|
||||
|
||||
// Other includes
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsDOMWorker;
|
||||
class nsIDocument;
|
||||
class nsIScriptContext;
|
||||
class nsIScriptError;
|
||||
class nsIScriptGlobalObject;
|
||||
|
||||
class nsDOMWorkerPool
|
||||
{
|
||||
typedef mozilla::ReentrantMonitor ReentrantMonitor;
|
||||
|
||||
public:
|
||||
nsDOMWorkerPool(nsIScriptGlobalObject* aGlobalObject,
|
||||
nsIDocument* aDocument);
|
||||
|
||||
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||
NS_IMETHOD_(nsrefcnt) Release();
|
||||
|
||||
nsIScriptGlobalObject* ScriptGlobalObject() {
|
||||
return mParentGlobal;
|
||||
}
|
||||
|
||||
nsIDocument* ParentDocument() {
|
||||
return mParentDocument;
|
||||
}
|
||||
|
||||
nsresult Init();
|
||||
|
||||
void Cancel();
|
||||
void Suspend();
|
||||
void Resume();
|
||||
|
||||
nsresult NoteWorker(nsDOMWorker* aWorker);
|
||||
void NoteDyingWorker(nsDOMWorker* aWorker);
|
||||
|
||||
ReentrantMonitor& GetReentrantMonitor() {
|
||||
return mReentrantMonitor;
|
||||
}
|
||||
|
||||
const PRUint64 WindowID() const {
|
||||
return mWindowID;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~nsDOMWorkerPool();
|
||||
|
||||
void GetWorkers(nsTArray<nsDOMWorker*>& aArray);
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
|
||||
// Reference to the window that created and owns this pool.
|
||||
nsCOMPtr<nsIScriptGlobalObject> mParentGlobal;
|
||||
|
||||
// Reference to the document that created this pool.
|
||||
nsCOMPtr<nsIDocument> mParentDocument;
|
||||
|
||||
// Weak array of workers. The idea is that workers can be garbage collected
|
||||
// independently of the owning pool and other workers.
|
||||
nsTArray<nsDOMWorker*> mWorkers;
|
||||
|
||||
// ReentrantMonitor for suspending and resuming workers.
|
||||
ReentrantMonitor mReentrantMonitor;
|
||||
|
||||
PRPackedBool mCanceled;
|
||||
PRPackedBool mSuspended;
|
||||
|
||||
const PRUint64 mWindowID;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERPOOL_H__ */
|
881
dom/src/threads/nsDOMWorkerScriptLoader.cpp
Normal file
881
dom/src/threads/nsDOMWorkerScriptLoader.cpp
Normal file
@ -0,0 +1,881 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerScriptLoader.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIStreamLoader.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsContentErrors.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsNetError.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "pratom.h"
|
||||
#include "nsDocShellCID.h"
|
||||
#include "nsIChannelPolicy.h"
|
||||
#include "nsChannelPolicy.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMWorkerPool.h"
|
||||
#include "nsDOMWorkerSecurityManager.h"
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerTimeout.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
|
||||
|
||||
nsDOMWorkerScriptLoader::nsDOMWorkerScriptLoader(nsDOMWorker* aWorker)
|
||||
: nsDOMWorkerFeature(aWorker),
|
||||
mTarget(nsnull),
|
||||
mScriptCount(0),
|
||||
mCanceled(PR_FALSE),
|
||||
mForWorker(PR_FALSE)
|
||||
{
|
||||
// Created on worker thread.
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aWorker, "Null worker!");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsDOMWorkerScriptLoader, nsDOMWorkerFeature,
|
||||
nsIRunnable,
|
||||
nsIStreamLoaderObserver)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::LoadScripts(JSContext* aCx,
|
||||
const nsTArray<nsString>& aURLs,
|
||||
PRBool aExecute)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aCx, "Null context!");
|
||||
|
||||
mTarget = NS_GetCurrentThread();
|
||||
NS_ASSERTION(mTarget, "This should never be null!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
mScriptCount = aURLs.Length();
|
||||
if (!mScriptCount) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Do all the memory work for these arrays now rather than checking for
|
||||
// failures all along the way.
|
||||
PRBool success = mLoadInfos.SetCapacity(mScriptCount);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Need one runnable per script and then an extra for the finished
|
||||
// notification.
|
||||
success = mPendingRunnables.SetCapacity(mScriptCount + 1);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo* newInfo = mLoadInfos.AppendElement();
|
||||
NS_ASSERTION(newInfo, "Shouldn't fail if SetCapacity succeeded above!");
|
||||
|
||||
newInfo->url.Assign(aURLs[index]);
|
||||
if (newInfo->url.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
success = newInfo->scriptObj.Hold(aCx);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
// Don't want timeouts, etc., from queuing up while we're waiting on the
|
||||
// network or compiling.
|
||||
AutoSuspendWorkerEvents aswe(this);
|
||||
|
||||
nsresult rv = DoRunLoop(aCx);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Verify that all scripts downloaded and compiled.
|
||||
rv = VerifyScripts(aCx);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (aExecute) {
|
||||
rv = ExecuteScripts(aCx);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::LoadWorkerScript(JSContext* aCx,
|
||||
const nsString& aURL)
|
||||
{
|
||||
mForWorker = PR_TRUE;
|
||||
|
||||
nsAutoTArray<nsString, 1> url;
|
||||
url.AppendElement(aURL);
|
||||
|
||||
return LoadScripts(aCx, url, PR_FALSE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::DoRunLoop(JSContext* aCx)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
volatile PRBool done = PR_FALSE;
|
||||
mDoneRunnable = new ScriptLoaderDone(this, &done);
|
||||
NS_ENSURE_TRUE(mDoneRunnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = NS_DispatchToMainThread(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
while (!(done || mCanceled)) {
|
||||
JSAutoSuspendRequest asr(aCx);
|
||||
NS_ProcessNextEvent(mTarget);
|
||||
}
|
||||
|
||||
return mCanceled ? NS_ERROR_ABORT : NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::VerifyScripts(JSContext* aCx)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Shouldn't be null!");
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
NS_ASSERTION(loadInfo.done, "Inconsistent state!");
|
||||
|
||||
if (NS_SUCCEEDED(loadInfo.result) && loadInfo.scriptObj.ToJSObject()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!loadInfo.scriptObj.ToJSObject(), "Inconsistent state!");
|
||||
|
||||
// Flag failure before worrying about whether or not to report an error.
|
||||
rv = NS_FAILED(loadInfo.result) ? loadInfo.result : NS_ERROR_FAILURE;
|
||||
|
||||
// If loadInfo.result is a success code then the compiler probably reported
|
||||
// an error already. Also we don't really care about NS_BINDING_ABORTED
|
||||
// since that's the code we set when some other script had a problem and the
|
||||
// rest were canceled.
|
||||
if (NS_SUCCEEDED(loadInfo.result) || loadInfo.result == NS_BINDING_ABORTED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok, this is the script that caused us to fail.
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
|
||||
// Only throw an error if there is no other pending exception.
|
||||
if (!JS_IsExceptionPending(aCx)) {
|
||||
const char* message;
|
||||
switch (loadInfo.result) {
|
||||
case NS_ERROR_MALFORMED_URI:
|
||||
message = "Malformed script URI: %s";
|
||||
break;
|
||||
case NS_ERROR_FILE_NOT_FOUND:
|
||||
case NS_ERROR_NOT_AVAILABLE:
|
||||
message = "Script file not found: %s";
|
||||
break;
|
||||
default:
|
||||
message = "Failed to load script: %s (nsresult = 0x%x)";
|
||||
break;
|
||||
}
|
||||
NS_ConvertUTF16toUTF8 url(loadInfo.url);
|
||||
JS_ReportError(aCx, message, url.get(), loadInfo.result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::ExecuteScripts(JSContext* aCx)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Shouldn't be null!");
|
||||
|
||||
// Now execute all the scripts.
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
|
||||
JSObject* scriptObj = loadInfo.scriptObj.ToJSObject();
|
||||
NS_ASSERTION(scriptObj, "This shouldn't ever be null!");
|
||||
|
||||
JSObject* global = mWorker->mGlobal ?
|
||||
mWorker->mGlobal :
|
||||
JS_GetGlobalObject(aCx);
|
||||
NS_ENSURE_STATE(global);
|
||||
|
||||
// Because we may have nested calls to this function we don't want the
|
||||
// execution to automatically report errors. We let them propagate instead.
|
||||
uint32 oldOpts =
|
||||
JS_SetOptions(aCx, JS_GetOptions(aCx) | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
|
||||
PRBool success = JS_ExecuteScript(aCx, global, scriptObj, NULL);
|
||||
|
||||
JS_SetOptions(aCx, oldOpts);
|
||||
|
||||
if (!success) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerScriptLoader::Cancel()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ASSERTION(!mCanceled, "Cancel called more than once!");
|
||||
mCanceled = PR_TRUE;
|
||||
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
|
||||
nsIRequest* request =
|
||||
static_cast<nsIRequest*>(loadInfo.channel.get());
|
||||
if (request) {
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
request->Cancel(NS_BINDING_ABORTED);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to cancel channel!");
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoTArray<ScriptLoaderRunnable*, 10> runnables;
|
||||
{
|
||||
MutexAutoLock lock(mWorker->GetLock());
|
||||
runnables.AppendElements(mPendingRunnables);
|
||||
mPendingRunnables.Clear();
|
||||
}
|
||||
|
||||
PRUint32 runnableCount = runnables.Length();
|
||||
for (PRUint32 index = 0; index < runnableCount; index++) {
|
||||
runnables[index]->Revoke();
|
||||
}
|
||||
|
||||
// We're about to post a revoked event to the worker thread, which seems
|
||||
// silly, but we have to do this because the worker thread may be sleeping
|
||||
// waiting on its event queue.
|
||||
NotifyDone();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerScriptLoader::Run()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// We may have been canceled already.
|
||||
if (mCanceled) {
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
nsresult rv = RunInternal();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Ok, something failed beyond a normal cancel.
|
||||
|
||||
// If necko is holding a ref to us then we'll end up notifying in the
|
||||
// OnStreamComplete method, not here.
|
||||
PRBool needsNotify = PR_TRUE;
|
||||
|
||||
// Cancel any async channels that were already opened.
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
|
||||
nsIRequest* request = static_cast<nsIRequest*>(loadInfo.channel.get());
|
||||
if (request) {
|
||||
#ifdef DEBUG
|
||||
nsresult rvInner =
|
||||
#endif
|
||||
request->Cancel(NS_BINDING_ABORTED);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rvInner), "Failed to cancel channel!");
|
||||
|
||||
// Necko is holding a ref to us so make sure that the OnStreamComplete
|
||||
// code sends the done event.
|
||||
needsNotify = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
// Make sure to set this so that the OnStreamComplete code will dispatch
|
||||
// the done event.
|
||||
loadInfo.done = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsNotify) {
|
||||
NotifyDone();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus,
|
||||
PRUint32 aStringLen,
|
||||
const PRUint8* aString)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// We may have been canceled already.
|
||||
if (mCanceled) {
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
nsresult rv = OnStreamCompleteInternal(aLoader, aContext, aStatus, aStringLen,
|
||||
aString);
|
||||
|
||||
// Dispatch the done event if we've received all the data.
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
if (!mLoadInfos[index].done) {
|
||||
// Some async load is still outstanding, don't notify yet.
|
||||
break;
|
||||
}
|
||||
|
||||
if (index == mScriptCount - 1) {
|
||||
// All loads complete, signal the thread.
|
||||
NotifyDone();
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::RunInternal()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mForWorker) {
|
||||
NS_ASSERTION(mScriptCount == 1, "Bad state!");
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorker> parentWorker = mWorker->GetParent();
|
||||
|
||||
// Figure out which principal to use.
|
||||
nsIPrincipal* principal = mWorker->GetPrincipal();
|
||||
if (!principal) {
|
||||
if (!parentWorker) {
|
||||
NS_ERROR("Must have a principal if this is not a subworker!");
|
||||
}
|
||||
principal = parentWorker->GetPrincipal();
|
||||
}
|
||||
NS_ASSERTION(principal, "This should never be null here!");
|
||||
|
||||
// Figure out our base URI.
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
if (mForWorker) {
|
||||
if (parentWorker) {
|
||||
baseURI = parentWorker->GetBaseURI();
|
||||
NS_ASSERTION(baseURI, "Should have been set already!");
|
||||
}
|
||||
else {
|
||||
// May be null.
|
||||
baseURI = mWorker->GetBaseURI();
|
||||
|
||||
// Don't leave a temporary URI hanging around.
|
||||
mWorker->ClearBaseURI();
|
||||
}
|
||||
NS_ASSERTION(!mWorker->GetBaseURI(), "Should not be set here!");
|
||||
}
|
||||
else {
|
||||
baseURI = mWorker->GetBaseURI();
|
||||
NS_ASSERTION(baseURI, "Should have been set already!");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> parentDoc = mWorker->Pool()->ParentDocument();
|
||||
|
||||
// All of these can potentially be null, but that should be ok. We'll either
|
||||
// succeed without them or fail below.
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
if (parentDoc) {
|
||||
loadGroup = parentDoc->GetDocumentLoadGroup();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIIOService> ios(do_GetIOService());
|
||||
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
NS_ASSERTION(secMan, "This should never be null!");
|
||||
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
nsresult& rv = loadInfo.result;
|
||||
|
||||
nsCOMPtr<nsIURI>& uri = loadInfo.finalURI;
|
||||
rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
|
||||
loadInfo.url, parentDoc,
|
||||
baseURI);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If we're part of a document then check the content load policy.
|
||||
if (parentDoc) {
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT, uri,
|
||||
principal, parentDoc,
|
||||
NS_LITERAL_CSTRING("text/javascript"),
|
||||
nsnull, &shouldLoad,
|
||||
nsContentUtils::GetContentPolicy(),
|
||||
secMan);
|
||||
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
|
||||
if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
|
||||
return (rv = NS_ERROR_CONTENT_BLOCKED);
|
||||
}
|
||||
return (rv = NS_ERROR_CONTENT_BLOCKED_SHOW_ALT);
|
||||
}
|
||||
}
|
||||
|
||||
// If this script loader is being used to make a new worker then we need to
|
||||
// do a same-origin check. Otherwise we need to clear the load with the
|
||||
// security manager.
|
||||
rv = mForWorker ?
|
||||
principal->CheckMayLoad(uri, PR_FALSE):
|
||||
secMan->CheckLoadURIWithPrincipal(principal, uri, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We need to know which index we're on in OnStreamComplete so we know where
|
||||
// to put the result.
|
||||
nsCOMPtr<nsISupportsPRUint32> indexSupports =
|
||||
do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = indexSupports->SetData(index);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We don't care about progress so just use the simple stream loader for
|
||||
// OnStreamComplete notification only.
|
||||
nsCOMPtr<nsIStreamLoader> loader;
|
||||
rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get Content Security Policy from parent document to pass into channel
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = principal->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannelPolicy> channelPolicy;
|
||||
if (csp) {
|
||||
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = channelPolicy->SetContentSecurityPolicy(csp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SCRIPT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = NS_NewChannel(getter_AddRefs(loadInfo.channel),
|
||||
uri, ios, loadGroup, nsnull,
|
||||
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI,
|
||||
channelPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = loadInfo.channel->AsyncOpen(loader, indexSupports);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Null this out so we don't try to cancel it later.
|
||||
loadInfo.channel = nsnull;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::OnStreamCompleteInternal(nsIStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus,
|
||||
PRUint32 aStringLen,
|
||||
const PRUint8* aString)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsCOMPtr<nsISupportsPRUint32> indexSupports(do_QueryInterface(aContext));
|
||||
NS_ENSURE_TRUE(indexSupports, NS_ERROR_NO_INTERFACE);
|
||||
|
||||
PRUint32 index = PR_UINT32_MAX;
|
||||
indexSupports->GetData(&index);
|
||||
|
||||
if (index >= mScriptCount) {
|
||||
NS_NOTREACHED("This really can't fail or we'll hang!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
|
||||
NS_ASSERTION(!loadInfo.done, "Got complete on the same load twice!");
|
||||
loadInfo.done = PR_TRUE;
|
||||
|
||||
// Use an alias to keep rv and loadInfo.result in sync.
|
||||
nsresult& rv = loadInfo.result;
|
||||
|
||||
if (NS_FAILED(aStatus)) {
|
||||
return rv = aStatus;
|
||||
}
|
||||
|
||||
if (!(aStringLen && aString)) {
|
||||
return rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Make sure we're not seeing the result of a 404 or something by checking the
|
||||
// 'requestSucceeded' attribute on the http channel.
|
||||
nsCOMPtr<nsIRequest> request;
|
||||
rv = aLoader->GetRequest(getter_AddRefs(request));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request);
|
||||
if (httpChannel) {
|
||||
PRBool requestSucceeded;
|
||||
rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!requestSucceeded) {
|
||||
return rv = NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
// May be null.
|
||||
nsIDocument* parentDoc = mWorker->Pool()->ParentDocument();
|
||||
|
||||
// Use the regular nsScriptLoader for this grunt work! Should be just fine
|
||||
// because we're running on the main thread.
|
||||
rv = nsScriptLoader::ConvertToUTF16(loadInfo.channel, aString, aStringLen,
|
||||
EmptyString(), parentDoc,
|
||||
loadInfo.scriptText);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (loadInfo.scriptText.IsEmpty()) {
|
||||
return rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCString filename;
|
||||
rv = loadInfo.finalURI->GetSpec(filename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (filename.IsEmpty()) {
|
||||
filename.Assign(NS_LossyConvertUTF16toASCII(loadInfo.url));
|
||||
}
|
||||
else {
|
||||
// This will help callers figure out what their script url resolved to in
|
||||
// case of errors.
|
||||
loadInfo.url.Assign(NS_ConvertUTF8toUTF16(filename));
|
||||
}
|
||||
|
||||
// Update the principal of the worker and its base URI if we just loaded the
|
||||
// worker's primary script.
|
||||
if (mForWorker) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
NS_ASSERTION(channel, "This should never fail!");
|
||||
|
||||
// Take care of the base URI first.
|
||||
nsCOMPtr<nsIURI> finalURI;
|
||||
rv = NS_GetFinalChannelURI(channel, getter_AddRefs(finalURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mWorker->SetBaseURI(finalURI);
|
||||
|
||||
// Now to figure out which principal to give this worker.
|
||||
nsRefPtr<nsDOMWorker> parent = mWorker->GetParent();
|
||||
NS_ASSERTION(mWorker->GetPrincipal() || parent, "Must have one of these!");
|
||||
|
||||
nsCOMPtr<nsIPrincipal> loadPrincipal = mWorker->GetPrincipal() ?
|
||||
mWorker->GetPrincipal() :
|
||||
parent->GetPrincipal();
|
||||
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
NS_ASSERTION(ssm, "Should never be null!");
|
||||
|
||||
nsCOMPtr<nsIPrincipal> channelPrincipal;
|
||||
rv = ssm->GetChannelPrincipal(channel, getter_AddRefs(channelPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// See if this is a resource URI. Since JSMs usually come from resource://
|
||||
// URIs we're currently considering all URIs with the URI_IS_UI_RESOURCE
|
||||
// flag as valid for creating privileged workers.
|
||||
if (!nsContentUtils::IsSystemPrincipal(channelPrincipal)) {
|
||||
PRBool isResource;
|
||||
rv = NS_URIChainHasFlags(finalURI,
|
||||
nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
||||
&isResource);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isResource) {
|
||||
rv = ssm->GetSystemPrincipal(getter_AddRefs(channelPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
// If the load principal is the system principal then the channel principal
|
||||
// must also be the system principal (we do not allow chrome code to create
|
||||
// workers with non-chrome scripts). Otherwise this channel principal must
|
||||
// be same origin with the load principal (we check again here in case
|
||||
// redirects changed the location of the script).
|
||||
if (nsContentUtils::IsSystemPrincipal(loadPrincipal)) {
|
||||
if (!nsContentUtils::IsSystemPrincipal(channelPrincipal)) {
|
||||
return rv = NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
}
|
||||
else if (NS_FAILED(loadPrincipal->CheckMayLoad(finalURI, PR_FALSE))) {
|
||||
return rv = NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
mWorker->SetPrincipal(channelPrincipal);
|
||||
}
|
||||
|
||||
nsRefPtr<ScriptCompiler> compiler =
|
||||
new ScriptCompiler(this, loadInfo.scriptText, filename, loadInfo.scriptObj);
|
||||
NS_ASSERTION(compiler, "Out of memory!");
|
||||
if (!compiler) {
|
||||
return rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
rv = mTarget->Dispatch(compiler, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerScriptLoader::NotifyDone()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!mDoneRunnable) {
|
||||
// We've already completed, no need to cancel anything.
|
||||
return;
|
||||
}
|
||||
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
// Null both of these out because they aren't threadsafe and must be
|
||||
// destroyed on this thread.
|
||||
loadInfo.channel = nsnull;
|
||||
loadInfo.finalURI = nsnull;
|
||||
|
||||
if (mCanceled) {
|
||||
// Simulate a complete, yet failed, load.
|
||||
loadInfo.done = PR_TRUE;
|
||||
loadInfo.result = NS_BINDING_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
mTarget->Dispatch(mDoneRunnable, NS_DISPATCH_NORMAL);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Couldn't dispatch done event!");
|
||||
|
||||
mDoneRunnable = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerScriptLoader::SuspendWorkerEvents()
|
||||
{
|
||||
NS_ASSERTION(mWorker, "No worker yet!");
|
||||
mWorker->SuspendFeatures();
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerScriptLoader::ResumeWorkerEvents()
|
||||
{
|
||||
NS_ASSERTION(mWorker, "No worker yet!");
|
||||
mWorker->ResumeFeatures();
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
ScriptLoaderRunnable::ScriptLoaderRunnable(nsDOMWorkerScriptLoader* aLoader)
|
||||
: mRevoked(PR_FALSE),
|
||||
mLoader(aLoader)
|
||||
{
|
||||
MutexAutoLock lock(aLoader->GetLock());
|
||||
#ifdef DEBUG
|
||||
nsDOMWorkerScriptLoader::ScriptLoaderRunnable** added =
|
||||
#endif
|
||||
aLoader->mPendingRunnables.AppendElement(this);
|
||||
NS_ASSERTION(added, "This shouldn't fail because we SetCapacity earlier!");
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
ScriptLoaderRunnable::~ScriptLoaderRunnable()
|
||||
{
|
||||
if (!mRevoked) {
|
||||
MutexAutoLock lock(mLoader->GetLock());
|
||||
#ifdef DEBUG
|
||||
PRBool removed =
|
||||
#endif
|
||||
mLoader->mPendingRunnables.RemoveElement(this);
|
||||
NS_ASSERTION(removed, "Someone has changed the array!");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerScriptLoader::ScriptLoaderRunnable,
|
||||
nsIRunnable)
|
||||
|
||||
void
|
||||
nsDOMWorkerScriptLoader::ScriptLoaderRunnable::Revoke()
|
||||
{
|
||||
mRevoked = PR_TRUE;
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
ScriptCompiler::ScriptCompiler(nsDOMWorkerScriptLoader* aLoader,
|
||||
const nsString& aScriptText,
|
||||
const nsCString& aFilename,
|
||||
nsAutoJSValHolder& aScriptObj)
|
||||
: ScriptLoaderRunnable(aLoader),
|
||||
mScriptText(aScriptText),
|
||||
mFilename(aFilename),
|
||||
mScriptObj(aScriptObj)
|
||||
{
|
||||
NS_ASSERTION(!aScriptText.IsEmpty(), "No script to compile!");
|
||||
NS_ASSERTION(aScriptObj.IsHeld(), "Should be held!");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerScriptLoader::ScriptCompiler::Run()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mRevoked) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mScriptObj.ToJSObject(), "Already have a script object?!");
|
||||
NS_ASSERTION(mScriptObj.IsHeld(), "Not held?!");
|
||||
NS_ASSERTION(!mScriptText.IsEmpty(), "Shouldn't have empty source here!");
|
||||
|
||||
JSContext* cx = nsDOMThreadService::GetCurrentContext();
|
||||
NS_ENSURE_STATE(cx);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSObject* global = JS_GetGlobalObject(cx);
|
||||
NS_ENSURE_STATE(global);
|
||||
|
||||
// Because we may have nested calls to this function we don't want the
|
||||
// execution to automatically report errors. We let them propagate instead.
|
||||
uint32 oldOpts =
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT |
|
||||
JSOPTION_NO_SCRIPT_RVAL);
|
||||
|
||||
JSPrincipals* principal = nsDOMWorkerSecurityManager::WorkerPrincipal();
|
||||
|
||||
JSObject* scriptObj =
|
||||
JS_CompileUCScriptForPrincipals(cx, global, principal,
|
||||
reinterpret_cast<const jschar*>
|
||||
(mScriptText.BeginReading()),
|
||||
mScriptText.Length(), mFilename.get(), 1);
|
||||
|
||||
JS_SetOptions(cx, oldOpts);
|
||||
|
||||
if (!scriptObj) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mScriptObj = scriptObj;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
ScriptLoaderDone::ScriptLoaderDone(nsDOMWorkerScriptLoader* aLoader,
|
||||
volatile PRBool* aDoneFlag)
|
||||
: ScriptLoaderRunnable(aLoader),
|
||||
mDoneFlag(aDoneFlag)
|
||||
{
|
||||
NS_ASSERTION(aDoneFlag && !*aDoneFlag, "Bad setup!");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerScriptLoader::ScriptLoaderDone::Run()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mRevoked) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*mDoneFlag = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
AutoSuspendWorkerEvents::AutoSuspendWorkerEvents(nsDOMWorkerScriptLoader* aLoader)
|
||||
: mLoader(aLoader)
|
||||
{
|
||||
NS_ASSERTION(aLoader, "Don't hand me null!");
|
||||
aLoader->SuspendWorkerEvents();
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
AutoSuspendWorkerEvents::~AutoSuspendWorkerEvents()
|
||||
{
|
||||
mLoader->ResumeWorkerEvents();
|
||||
}
|
148
dom/src/threads/nsDOMWorkerSecurityManager.cpp
Normal file
148
dom/src/threads/nsDOMWorkerSecurityManager.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerSecurityManager.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIClassInfo.h"
|
||||
|
||||
// Other includes
|
||||
#include "jsapi.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorker.h"
|
||||
|
||||
#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
|
||||
|
||||
class nsDOMWorkerPrincipal
|
||||
{
|
||||
public:
|
||||
static void Destroy(JSContext*, JSPrincipals*) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
static JSBool Subsume(JSPrincipals*, JSPrincipals*) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
static JSPrincipals gWorkerPrincipal =
|
||||
{ "domworkerthread" /* codebase */,
|
||||
NULL /* getPrincipalArray */,
|
||||
NULL /* globalPrivilegesEnabled */,
|
||||
1 /* refcount */,
|
||||
nsDOMWorkerPrincipal::Destroy /* destroy */,
|
||||
nsDOMWorkerPrincipal::Subsume /* subsume */ };
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerSecurityManager,
|
||||
nsIXPCSecurityManager)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerSecurityManager::CanCreateWrapper(JSContext* aCx,
|
||||
const nsIID& aIID,
|
||||
nsISupports* aObj,
|
||||
nsIClassInfo* aClassInfo,
|
||||
void** aPolicy)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerSecurityManager::CanCreateInstance(JSContext* aCx,
|
||||
const nsCID& aCID)
|
||||
{
|
||||
return CanGetService(aCx, aCID);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerSecurityManager::CanGetService(JSContext* aCx,
|
||||
const nsCID& aCID)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
|
||||
NS_ASSERTION(worker, "This should be set by the DOM thread service!");
|
||||
|
||||
return worker->IsPrivileged() ? NS_OK : NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerSecurityManager::CanAccess(PRUint32 aAction,
|
||||
nsAXPCNativeCallContext* aCallContext,
|
||||
JSContext* aJSContext,
|
||||
JSObject* aJSObject,
|
||||
nsISupports* aObj,
|
||||
nsIClassInfo* aClassInfo,
|
||||
jsid aName,
|
||||
void** aPolicy)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSPrincipals*
|
||||
nsDOMWorkerSecurityManager::WorkerPrincipal()
|
||||
{
|
||||
return &gWorkerPrincipal;
|
||||
}
|
||||
|
||||
JSBool
|
||||
nsDOMWorkerSecurityManager::JSCheckAccess(JSContext* aCx,
|
||||
JSObject* aObj,
|
||||
jsid aId,
|
||||
JSAccessMode aMode,
|
||||
jsval* aVp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSPrincipals*
|
||||
nsDOMWorkerSecurityManager::JSFindPrincipal(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
return WorkerPrincipal();
|
||||
}
|
||||
|
||||
JSBool
|
||||
nsDOMWorkerSecurityManager::JSTranscodePrincipals(JSXDRState* aXdr,
|
||||
JSPrincipals** aJsprinp)
|
||||
{
|
||||
NS_NOTREACHED("Shouldn't ever call this!");
|
||||
return JS_FALSE;
|
||||
}
|
62
dom/src/threads/nsDOMWorkerSecurityManager.h
Normal file
62
dom/src/threads/nsDOMWorkerSecurityManager.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERSECURITYMANAGER_H__
|
||||
#define __NSDOMWORKERSECURITYMANAGER_H__
|
||||
|
||||
#include "nsIXPCSecurityManager.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
class nsDOMWorkerSecurityManager : public nsIXPCSecurityManager
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIXPCSECURITYMANAGER
|
||||
|
||||
static JSPrincipals* WorkerPrincipal();
|
||||
|
||||
static JSBool JSCheckAccess(JSContext* aCx, JSObject* aObj, jsid aId,
|
||||
JSAccessMode aMode, jsval* aVp);
|
||||
|
||||
static JSPrincipals* JSFindPrincipal(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
static JSBool JSTranscodePrincipals(JSXDRState* aXdr,
|
||||
JSPrincipals** aJsprinp);
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERSECURITYMANAGER_H__ */
|
485
dom/src/threads/nsDOMWorkerTimeout.cpp
Normal file
485
dom/src/threads/nsDOMWorkerTimeout.cpp
Normal file
@ -0,0 +1,485 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerTimeout.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "pratom.h"
|
||||
#include "prtime.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerSecurityManager.h"
|
||||
|
||||
#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
|
||||
|
||||
#define CONSTRUCTOR_ENSURE_TRUE(_cond, _rv) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (NS_UNLIKELY(!(_cond))) { \
|
||||
NS_WARNING("CONSTRUCTOR_ENSURE_TRUE(" #_cond ") failed"); \
|
||||
(_rv) = NS_ERROR_FAILURE; \
|
||||
return; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
#define SUSPEND_SPINLOCK_COUNT 5000
|
||||
|
||||
static const char* kSetIntervalStr = "setInterval";
|
||||
static const char* kSetTimeoutStr = "setTimeout";
|
||||
|
||||
nsDOMWorkerTimeout::FunctionCallback::FunctionCallback(PRUint32 aArgc,
|
||||
jsval* aArgv,
|
||||
nsresult* aRv)
|
||||
: mCallbackArgsLength(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDOMWorkerTimeout::FunctionCallback);
|
||||
|
||||
JSRuntime* rt;
|
||||
*aRv = nsDOMThreadService::JSRuntimeService()->GetRuntime(&rt);
|
||||
if (NS_FAILED(*aRv))
|
||||
return;
|
||||
|
||||
JSBool ok = mCallback.Hold(rt);
|
||||
CONSTRUCTOR_ENSURE_TRUE(ok, *aRv);
|
||||
|
||||
mCallback = aArgv[0];
|
||||
|
||||
// We want enough space for an extra lateness arg.
|
||||
mCallbackArgsLength = aArgc > 2 ? aArgc - 1 : 1;
|
||||
|
||||
PRBool success = mCallbackArgs.SetLength(mCallbackArgsLength);
|
||||
CONSTRUCTOR_ENSURE_TRUE(success, *aRv);
|
||||
|
||||
PRUint32 index = 0;
|
||||
for (; index < mCallbackArgsLength - 1; index++) {
|
||||
ok = mCallbackArgs[index].Hold(rt);
|
||||
CONSTRUCTOR_ENSURE_TRUE(ok, *aRv);
|
||||
|
||||
mCallbackArgs[index] = aArgv[index + 2];
|
||||
}
|
||||
|
||||
// Take care of the last arg.
|
||||
index = mCallbackArgsLength - 1;
|
||||
|
||||
ok = mCallbackArgs[index].Hold(rt);
|
||||
CONSTRUCTOR_ENSURE_TRUE(ok, *aRv);
|
||||
|
||||
*aRv = NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerTimeout::FunctionCallback::~FunctionCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsDOMWorkerTimeout::FunctionCallback);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerTimeout::FunctionCallback::Run(nsDOMWorkerTimeout* aTimeout,
|
||||
JSContext* aCx)
|
||||
{
|
||||
PRInt32 lateness = NS_MAX(0, PRInt32(PR_Now() - aTimeout->mTargetTime)) /
|
||||
(PRTime)PR_USEC_PER_MSEC;
|
||||
mCallbackArgs[mCallbackArgsLength - 1] = INT_TO_JSVAL(lateness);
|
||||
|
||||
JSObject* global = JS_GetGlobalObject(aCx);
|
||||
NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
|
||||
|
||||
nsTArray<jsval> argv;
|
||||
PRBool success = argv.SetCapacity(mCallbackArgsLength);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
for (PRUint32 index = 0; index < mCallbackArgsLength; index++) {
|
||||
argv.AppendElement(mCallbackArgs[index]);
|
||||
}
|
||||
|
||||
jsval rval;
|
||||
JSBool ok =
|
||||
JS_CallFunctionValue(aCx, global, mCallback, mCallbackArgsLength,
|
||||
argv.Elements(), &rval);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerTimeout::ExpressionCallback::ExpressionCallback(PRUint32 aArgc,
|
||||
jsval* aArgv,
|
||||
JSContext* aCx,
|
||||
nsresult* aRv)
|
||||
: mLineNumber(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDOMWorkerTimeout::ExpressionCallback);
|
||||
|
||||
JSString* expr = JS_ValueToString(aCx, aArgv[0]);
|
||||
*aRv = expr ? NS_OK : NS_ERROR_FAILURE;
|
||||
if (NS_FAILED(*aRv))
|
||||
return;
|
||||
|
||||
JSRuntime* rt;
|
||||
*aRv = nsDOMThreadService::JSRuntimeService()->GetRuntime(&rt);
|
||||
if (NS_FAILED(*aRv))
|
||||
return;
|
||||
|
||||
JSBool ok = mExpression.Hold(rt);
|
||||
CONSTRUCTOR_ENSURE_TRUE(ok, *aRv);
|
||||
|
||||
mExpression = aArgv[0];
|
||||
|
||||
// Get the calling location.
|
||||
const char* fileName;
|
||||
PRUint32 lineNumber;
|
||||
if (nsJSUtils::GetCallingLocation(aCx, &fileName, &lineNumber)) {
|
||||
mFileName.Assign(fileName);
|
||||
mLineNumber = lineNumber;
|
||||
}
|
||||
|
||||
*aRv = NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerTimeout::ExpressionCallback::~ExpressionCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsDOMWorkerTimeout::ExpressionCallback);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerTimeout::ExpressionCallback::Run(nsDOMWorkerTimeout* aTimeout,
|
||||
JSContext* aCx)
|
||||
{
|
||||
JSObject* global = JS_GetGlobalObject(aCx);
|
||||
NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
|
||||
|
||||
JSPrincipals* principal = nsDOMWorkerSecurityManager::WorkerPrincipal();
|
||||
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
|
||||
|
||||
JSString* expression = JS_ValueToString(aCx, mExpression);
|
||||
NS_ENSURE_TRUE(expression, NS_ERROR_FAILURE);
|
||||
|
||||
size_t stringLength;
|
||||
const jschar* string = JS_GetStringCharsAndLength(aCx, expression, &stringLength);
|
||||
NS_ENSURE_TRUE(string, NS_ERROR_FAILURE);
|
||||
|
||||
PRBool success = JS_EvaluateUCScriptForPrincipals(aCx, global, principal,
|
||||
string, stringLength,
|
||||
mFileName.get(),
|
||||
mLineNumber, nsnull);
|
||||
if (!success) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerTimeout::nsDOMWorkerTimeout(nsDOMWorker* aWorker,
|
||||
PRUint32 aId)
|
||||
: nsDOMWorkerFeature(aWorker, aId),
|
||||
mInterval(0),
|
||||
mSuspendSpinlock(0),
|
||||
mSuspendInterval(0),
|
||||
mIsInterval(PR_FALSE),
|
||||
mIsSuspended(PR_FALSE),
|
||||
mSuspendedBeforeStart(PR_FALSE),
|
||||
mStarted(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(mWorker, "Need a worker here!");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerTimeout, nsDOMWorkerFeature,
|
||||
nsITimerCallback)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerTimeout::Init(JSContext* aCx, PRUint32 aArgc, jsval* aArgv,
|
||||
PRBool aIsInterval)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Null pointer!");
|
||||
NS_ASSERTION(aArgv, "Null pointer!");
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
|
||||
if (!aArgc) {
|
||||
JS_ReportError(aCx, "Function %s requires at least 1 parameter",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
PRUint32 interval;
|
||||
if (aArgc > 1) {
|
||||
if (!JS_ValueToECMAUint32(aCx, aArgv[1], (uint32*)&interval)) {
|
||||
JS_ReportError(aCx, "Second argument to %s must be a millisecond value",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If no interval was specified, treat this like a timeout, to avoid
|
||||
// setting an interval of 0 milliseconds.
|
||||
interval = 0;
|
||||
aIsInterval = PR_FALSE;
|
||||
}
|
||||
|
||||
mInterval = interval;
|
||||
|
||||
mIsInterval = aIsInterval;
|
||||
|
||||
mTargetTime = PR_Now() + interval * (PRTime)PR_USEC_PER_MSEC;
|
||||
|
||||
nsresult rv;
|
||||
switch (JS_TypeOfValue(aCx, aArgv[0])) {
|
||||
case JSTYPE_FUNCTION:
|
||||
mCallback = new FunctionCallback(aArgc, aArgv, &rv);
|
||||
NS_ENSURE_TRUE(mCallback, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
break;
|
||||
|
||||
case JSTYPE_STRING:
|
||||
case JSTYPE_OBJECT:
|
||||
mCallback = new ExpressionCallback(aArgc, aArgv, aCx, &rv);
|
||||
NS_ENSURE_TRUE(mCallback, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
break;
|
||||
|
||||
default:
|
||||
JS_ReportError(aCx, "useless %s call (missing quotes around argument?)",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
|
||||
// Return an error that nsGlobalWindow can recognize and turn into NS_OK.
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIEventTarget* target =
|
||||
static_cast<nsIEventTarget*>(nsDOMThreadService::get());
|
||||
|
||||
rv = timer->SetTarget(target);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mTimer.swap(timer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerTimeout::Start()
|
||||
{
|
||||
if (IsSuspended()) {
|
||||
NS_ASSERTION(mSuspendedBeforeStart, "Bad state!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mTimer->InitWithCallback(this, mInterval,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mStarted = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerTimeout::Run()
|
||||
{
|
||||
NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED);
|
||||
LOG(("Worker [0x%p] running timeout [0x%p] with id %u",
|
||||
static_cast<void*>(mWorker.get()), static_cast<void*>(this), mId));
|
||||
|
||||
JSContext* cx;
|
||||
nsresult rv =
|
||||
nsDOMThreadService::ThreadJSContextStack()->GetSafeJSContext(&cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
rv = mCallback->Run(this, cx);
|
||||
|
||||
// Make sure any pending exceptions are converted to errors for the pool.
|
||||
JS_ReportPendingException(cx);
|
||||
|
||||
if (mIsInterval) {
|
||||
mTargetTime = PR_Now() + mInterval * (PRTime)PR_USEC_PER_MSEC;
|
||||
nsresult rv2 = mTimer->InitWithCallback(this, mInterval,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
NS_ENSURE_SUCCESS(rv2, rv2);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerTimeout::Cancel()
|
||||
{
|
||||
NS_ASSERTION(mTimer, "Impossible to get here without a timer!");
|
||||
|
||||
LOG(("Worker [0x%p] canceling timeout [0x%p] with id %u",
|
||||
static_cast<void*>(mWorker.get()), static_cast<void*>(this), mId));
|
||||
|
||||
{
|
||||
AutoSpinlock lock(this);
|
||||
|
||||
if (IsSuspendedNoLock()) {
|
||||
mIsSuspended = PR_FALSE;
|
||||
// This should kill us when all is said and done.
|
||||
mSuspendedRef = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// This call to Cancel should kill us.
|
||||
mTimer->Cancel();
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerTimeout::Suspend()
|
||||
{
|
||||
AutoSpinlock lock(this);
|
||||
|
||||
NS_ASSERTION(!IsSuspendedNoLock(), "Bad state!");
|
||||
|
||||
mIsSuspended = PR_TRUE;
|
||||
mSuspendedRef = this;
|
||||
|
||||
if (!mStarted) {
|
||||
mSuspendedBeforeStart = PR_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
mTimer->Cancel();
|
||||
|
||||
mSuspendInterval = NS_MAX(0, PRInt32(mTargetTime - PR_Now())) /
|
||||
(PRTime)PR_USEC_PER_MSEC;
|
||||
|
||||
LOG(("Worker [0x%p] suspending timeout [0x%p] with id %u (interval = %u)",
|
||||
static_cast<void*>(mWorker.get()), static_cast<void*>(this), mId,
|
||||
mSuspendInterval));
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerTimeout::Resume()
|
||||
{
|
||||
NS_ASSERTION(mTimer, "Impossible to get here without a timer!");
|
||||
|
||||
LOG(("Worker [0x%p] resuming timeout [0x%p] with id %u",
|
||||
static_cast<void*>(mWorker.get()), static_cast<void*>(this), mId));
|
||||
|
||||
AutoSpinlock lock(this);
|
||||
|
||||
NS_ASSERTION(IsSuspendedNoLock(), "Should be suspended!");
|
||||
|
||||
if (mSuspendedBeforeStart) {
|
||||
NS_ASSERTION(!mSuspendInterval, "Bad state!");
|
||||
mSuspendedBeforeStart = PR_FALSE;
|
||||
mSuspendInterval = mInterval;
|
||||
mStarted = PR_TRUE;
|
||||
}
|
||||
|
||||
mTargetTime = PR_Now() + mSuspendInterval * (PRTime)PR_USEC_PER_MSEC;
|
||||
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
mTimer->InitWithCallback(this, mSuspendInterval, nsITimer::TYPE_ONE_SHOT);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to init timer!");
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerTimeout::AcquireSpinlock()
|
||||
{
|
||||
PRUint32 loopCount = 0;
|
||||
while (PR_ATOMIC_SET(&mSuspendSpinlock, 1) == 1) {
|
||||
if (++loopCount > SUSPEND_SPINLOCK_COUNT) {
|
||||
LOG(("AcquireSpinlock taking too long (looped %u times), yielding.",
|
||||
loopCount));
|
||||
loopCount = 0;
|
||||
PR_Sleep(PR_INTERVAL_NO_WAIT);
|
||||
}
|
||||
}
|
||||
#ifdef PR_LOGGING
|
||||
if (loopCount) {
|
||||
LOG(("AcquireSpinlock needed %u loops", loopCount));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerTimeout::ReleaseSpinlock()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PRInt32 suspended =
|
||||
#endif
|
||||
PR_ATOMIC_SET(&mSuspendSpinlock, 0);
|
||||
NS_ASSERTION(suspended == 1, "Huh?!");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerTimeout::Notify(nsITimer* aTimer)
|
||||
{
|
||||
// Should be on the timer thread.
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aTimer == mTimer, "Wrong timer?!");
|
||||
|
||||
PRUint32 type;
|
||||
nsresult rv = aTimer->GetType(&type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We only care about one-shot timers here because that may be the one that
|
||||
// we set from Resume().
|
||||
if (type == nsITimer::TYPE_ONE_SHOT) {
|
||||
AutoSpinlock lock(this);
|
||||
if (mIsSuspended) {
|
||||
mIsSuspended = PR_FALSE;
|
||||
mSuspendedRef = nsnull;
|
||||
if (mIsInterval) {
|
||||
// This is the first fire since we resumed. Set our interval back to the
|
||||
// real interval.
|
||||
mTargetTime = PR_Now() + mInterval * (PRTime)PR_USEC_PER_MSEC;
|
||||
|
||||
rv = aTimer->InitWithCallback(this, mInterval,
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsDOMThreadService::get()->TimeoutReady(this);
|
||||
return NS_OK;
|
||||
}
|
190
dom/src/threads/nsDOMWorkerTimeout.h
Normal file
190
dom/src/threads/nsDOMWorkerTimeout.h
Normal file
@ -0,0 +1,190 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERTIMEOUT_H__
|
||||
#define __NSDOMWORKERTIMEOUT_H__
|
||||
|
||||
// Interfaces
|
||||
#include "nsITimer.h"
|
||||
|
||||
// Other includes
|
||||
#include "jsapi.h"
|
||||
#include "nsAutoJSValHolder.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMWorker.h"
|
||||
|
||||
/**
|
||||
* The nsDOMWorkerTimeout has a slightly complicated life cycle. It's created
|
||||
* by an nsDOMWorker (or one of its JS context functions) and immediately takes
|
||||
* a strong reference to the worker that created it. It does this so that the
|
||||
* worker can't be collected while a timeout is outstanding. However, the worker
|
||||
* needs a weak reference to the timeout so that it can be canceled if the
|
||||
* worker is canceled (in the event that the page falls out of the fastback
|
||||
* cache or the application is exiting, for instance). The only thing that holds
|
||||
* the timeout alive is its mTimer via the nsITimerCallback interface. If the
|
||||
* timer is single-shot and has run already or if the timer is canceled then
|
||||
* this object should die.
|
||||
*/
|
||||
class nsDOMWorkerTimeout : public nsDOMWorkerFeature,
|
||||
public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
nsDOMWorkerTimeout(nsDOMWorker* aWorker,
|
||||
PRUint32 aId);
|
||||
|
||||
nsresult Init(JSContext* aCx,
|
||||
PRUint32 aArgc,
|
||||
jsval* aArgv,
|
||||
PRBool aIsInterval);
|
||||
|
||||
nsresult Start();
|
||||
|
||||
nsresult Run();
|
||||
|
||||
virtual void Cancel();
|
||||
virtual void Suspend();
|
||||
virtual void Resume();
|
||||
|
||||
PRIntervalTime GetInterval() {
|
||||
return mInterval;
|
||||
}
|
||||
|
||||
nsDOMWorker* GetWorker() {
|
||||
return mWorker;
|
||||
}
|
||||
|
||||
PRBool IsSuspended() {
|
||||
AutoSpinlock lock(this);
|
||||
return IsSuspendedNoLock();
|
||||
}
|
||||
|
||||
private:
|
||||
~nsDOMWorkerTimeout() { }
|
||||
|
||||
void AcquireSpinlock();
|
||||
void ReleaseSpinlock();
|
||||
|
||||
PRBool IsSuspendedNoLock() {
|
||||
return mIsSuspended;
|
||||
}
|
||||
|
||||
class AutoSpinlock
|
||||
{
|
||||
public:
|
||||
AutoSpinlock(nsDOMWorkerTimeout* aTimeout)
|
||||
: mTimeout(aTimeout) {
|
||||
aTimeout->AcquireSpinlock();
|
||||
}
|
||||
|
||||
~AutoSpinlock() {
|
||||
mTimeout->ReleaseSpinlock();
|
||||
}
|
||||
private:
|
||||
nsDOMWorkerTimeout* mTimeout;
|
||||
};
|
||||
|
||||
// We support two types of callbacks (functions and expressions) just like the
|
||||
// normal window timeouts. Each type has its own member and rooting needs so
|
||||
// we split them into two classes with a common base.
|
||||
class CallbackBase
|
||||
{
|
||||
public:
|
||||
virtual ~CallbackBase() { }
|
||||
virtual nsresult Run(nsDOMWorkerTimeout* aTimeout,
|
||||
JSContext* aCx) = 0;
|
||||
};
|
||||
|
||||
class FunctionCallback : public CallbackBase
|
||||
{
|
||||
public:
|
||||
FunctionCallback(PRUint32 aArgc,
|
||||
jsval* aArgv,
|
||||
nsresult* aRv);
|
||||
virtual ~FunctionCallback();
|
||||
virtual nsresult Run(nsDOMWorkerTimeout* aTimeout,
|
||||
JSContext* aCx);
|
||||
protected:
|
||||
nsAutoJSValHolder mCallback;
|
||||
nsTArray<nsAutoJSValHolder> mCallbackArgs;
|
||||
PRUint32 mCallbackArgsLength;
|
||||
};
|
||||
|
||||
class ExpressionCallback : public CallbackBase
|
||||
{
|
||||
public:
|
||||
ExpressionCallback(PRUint32 aArgc,
|
||||
jsval* aArgv,
|
||||
JSContext* aCx,
|
||||
nsresult* aRv);
|
||||
virtual ~ExpressionCallback();
|
||||
virtual nsresult Run(nsDOMWorkerTimeout* aTimeout,
|
||||
JSContext* aCx);
|
||||
protected:
|
||||
nsAutoJSValHolder mExpression;
|
||||
nsCString mFileName;
|
||||
PRUint32 mLineNumber;
|
||||
};
|
||||
|
||||
// Hold this object alive!
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
PRUint32 mInterval;
|
||||
|
||||
PRTime mTargetTime;
|
||||
|
||||
nsAutoPtr<CallbackBase> mCallback;
|
||||
|
||||
PRInt32 mSuspendSpinlock;
|
||||
PRUint32 mSuspendInterval;
|
||||
nsRefPtr<nsDOMWorkerTimeout> mSuspendedRef;
|
||||
|
||||
PRPackedBool mIsInterval;
|
||||
PRPackedBool mIsSuspended;
|
||||
PRPackedBool mSuspendedBeforeStart;
|
||||
PRPackedBool mStarted;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERTIMEOUT_H__ */
|
910
dom/src/threads/nsDOMWorkerXHR.cpp
Normal file
910
dom/src/threads/nsDOMWorkerXHR.cpp
Normal file
@ -0,0 +1,910 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerXHR.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsAXPCNativeCallContext.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerEvents.h"
|
||||
#include "nsDOMWorkerPool.h"
|
||||
#include "nsDOMWorkerXHRProxy.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// The list of event types that we support. This list and the defines based on
|
||||
// it determine the sizes of the listener arrays in nsDOMWorkerXHRProxy. Make
|
||||
// sure that any event types shared by both the XHR and Upload objects are
|
||||
// together at the beginning of the list. Any changes made to this list may
|
||||
// affect sMaxUploadEventTypes, so make sure that it is adjusted accordingly or
|
||||
// things will break!
|
||||
const char* const nsDOMWorkerXHREventTarget::sListenerTypes[] = {
|
||||
// nsIXMLHttpRequestEventTarget listeners.
|
||||
"abort", /* LISTENER_TYPE_ABORT */
|
||||
"error", /* LISTENER_TYPE_ERROR */
|
||||
"load", /* LISTENER_TYPE_LOAD */
|
||||
"loadstart", /* LISTENER_TYPE_LOADSTART */
|
||||
"progress", /* LISTENER_TYPE_PROGRESS */
|
||||
|
||||
// nsIXMLHttpRequest listeners.
|
||||
"readystatechange", /* LISTENER_TYPE_READYSTATECHANGE */
|
||||
"loadend"
|
||||
};
|
||||
|
||||
// This should always be set to the length of sListenerTypes.
|
||||
const PRUint32 nsDOMWorkerXHREventTarget::sMaxXHREventTypes =
|
||||
NS_ARRAY_LENGTH(nsDOMWorkerXHREventTarget::sListenerTypes);
|
||||
|
||||
// This should be set to the index of the first event type that is *not*
|
||||
// supported by the Upload object.
|
||||
const PRUint32 nsDOMWorkerXHREventTarget::sMaxUploadEventTypes =
|
||||
LISTENER_TYPE_READYSTATECHANGE;
|
||||
|
||||
// Enforce the invariant that the upload object supports no more event types
|
||||
// than the xhr object.
|
||||
PR_STATIC_ASSERT(nsDOMWorkerXHREventTarget::sMaxXHREventTypes >=
|
||||
nsDOMWorkerXHREventTarget::sMaxUploadEventTypes);
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerXHREventTarget,
|
||||
nsDOMWorkerMessageHandler,
|
||||
nsIXMLHttpRequestEventTarget)
|
||||
|
||||
PRUint32
|
||||
nsDOMWorkerXHREventTarget::GetListenerTypeFromString(const nsAString& aString)
|
||||
{
|
||||
for (PRUint32 index = 0; index < sMaxXHREventTypes; index++) {
|
||||
if (aString.EqualsASCII(sListenerTypes[index])) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return PR_UINT32_MAX;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnabort(nsIDOMEventListener** aOnabort)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aOnabort);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_ABORT]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnabort);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnabort(nsIDOMEventListener* aOnabort)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_ABORT]);
|
||||
|
||||
return SetOnXListener(type, aOnabort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnerror(nsIDOMEventListener** aOnerror)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnerror);
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_ERROR]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnerror);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnerror(nsIDOMEventListener* aOnerror)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_ERROR]);
|
||||
|
||||
return SetOnXListener(type, aOnerror);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnload(nsIDOMEventListener** aOnload)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aOnload);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOAD]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnload);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnload(nsIDOMEventListener* aOnload)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOAD]);
|
||||
|
||||
return SetOnXListener(type, aOnload);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnloadstart(nsIDOMEventListener** aOnloadstart)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aOnloadstart);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOADSTART]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnloadstart);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnloadstart(nsIDOMEventListener* aOnloadstart)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOADSTART]);
|
||||
|
||||
return SetOnXListener(type, aOnloadstart);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnprogress(nsIDOMEventListener** aOnprogress)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aOnprogress);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_PROGRESS]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnprogress);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnprogress(nsIDOMEventListener* aOnprogress)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_PROGRESS]);
|
||||
|
||||
return SetOnXListener(type, aOnprogress);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnloadend(nsIDOMEventListener** aOnloadend)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aOnloadend);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOADEND]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnloadend);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnloadend(nsIDOMEventListener* aOnloadend)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOADEND]);
|
||||
|
||||
return SetOnXListener(type, aOnloadend);
|
||||
}
|
||||
|
||||
nsDOMWorkerXHRUpload::nsDOMWorkerXHRUpload(nsDOMWorkerXHR* aWorkerXHR)
|
||||
: mWorkerXHR(aWorkerXHR)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aWorkerXHR, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerXHRUpload, nsDOMWorkerXHREventTarget,
|
||||
nsIXMLHttpRequestUpload)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER3(nsDOMWorkerXHRUpload, nsIDOMEventTarget,
|
||||
nsIXMLHttpRequestEventTarget,
|
||||
nsIXMLHttpRequestUpload)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerXHRUpload)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHRUpload::RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
|
||||
if (mWorkerXHR->mWorker->IsCanceled()) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return nsDOMWorkerXHREventTarget::RemoveEventListener(aType, aListener,
|
||||
aUseCapture);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHRUpload::DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
|
||||
if (mWorkerXHR->mWorker->IsCanceled()) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return nsDOMWorkerXHREventTarget::DispatchEvent(aEvent, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHRUpload::AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 optional_argc)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
|
||||
if (mWorkerXHR->mWorker->IsCanceled()) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = nsDOMWorkerXHREventTarget::AddEventListener(aType, aListener,
|
||||
aUseCapture,
|
||||
aWantsUntrusted,
|
||||
optional_argc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mWorkerXHR->mXHRProxy->UploadEventListenerAdded();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("UploadEventListenerAdded failed!");
|
||||
RemoveEventListener(aType, aListener, aUseCapture);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRUpload::SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mWorkerXHR->mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
PRUint32 type = GetListenerTypeFromString(aType);
|
||||
if (type > sMaxUploadEventTypes) {
|
||||
// Silently ignore junk events.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsDOMWorkerXHREventTarget::SetOnXListener(aType, aListener);
|
||||
}
|
||||
|
||||
nsDOMWorkerXHR::nsDOMWorkerXHR(nsDOMWorker* aWorker)
|
||||
: nsDOMWorkerFeature(aWorker),
|
||||
mWrappedNative(nsnull),
|
||||
mCanceled(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aWorker, "Must have a worker!");
|
||||
}
|
||||
|
||||
nsDOMWorkerXHR::~nsDOMWorkerXHR()
|
||||
{
|
||||
if (mXHRProxy) {
|
||||
if (!NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(mXHRProxy, &nsDOMWorkerXHRProxy::Destroy);
|
||||
|
||||
if (runnable) {
|
||||
mXHRProxy = nsnull;
|
||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mXHRProxy->Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tricky! We use the AddRef/Release method of nsDOMWorkerFeature (to make sure
|
||||
// we properly remove ourselves from the worker array) but inherit the QI of
|
||||
// nsDOMWorkerXHREventTarget.
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMWorkerXHR, nsDOMWorkerFeature)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMWorkerXHR, nsDOMWorkerFeature)
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE_INHERITED2(nsDOMWorkerXHR, nsDOMWorkerXHREventTarget,
|
||||
nsIXMLHttpRequest,
|
||||
nsIXPCScriptable)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER3(nsDOMWorkerXHR, nsIDOMEventTarget,
|
||||
nsIXMLHttpRequestEventTarget,
|
||||
nsIXMLHttpRequest)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerXHR)
|
||||
|
||||
#define XPC_MAP_CLASSNAME nsDOMWorkerXHR
|
||||
#define XPC_MAP_QUOTED_CLASSNAME "XMLHttpRequest"
|
||||
#define XPC_MAP_WANT_POSTCREATE
|
||||
#define XPC_MAP_WANT_TRACE
|
||||
#define XPC_MAP_WANT_FINALIZE
|
||||
|
||||
#define XPC_MAP_FLAGS \
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
|
||||
nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY | \
|
||||
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES
|
||||
|
||||
#include "xpc_map_end.h"
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Trace(nsIXPConnectWrappedNative* /* aWrapper */,
|
||||
JSTracer* aTracer,
|
||||
JSObject* /*aObj */)
|
||||
{
|
||||
if (!mCanceled) {
|
||||
nsDOMWorkerMessageHandler::Trace(aTracer);
|
||||
if (mUpload) {
|
||||
mUpload->Trace(aTracer);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Finalize(nsIXPConnectWrappedNative* /* aWrapper */,
|
||||
JSContext* /* aCx */,
|
||||
JSObject* /* aObj */)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsDOMWorkerMessageHandler::ClearAllListeners();
|
||||
|
||||
if (mUpload) {
|
||||
mUpload->ClearAllListeners();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::PostCreate(nsIXPConnectWrappedNative* aWrapper,
|
||||
JSContext* /* aCx */,
|
||||
JSObject* /* aObj */)
|
||||
{
|
||||
mWrappedNative = aWrapper;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHR::Init()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> proxy = new nsDOMWorkerXHRProxy(this);
|
||||
NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = proxy->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
proxy.swap(mXHRProxy);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerXHR::Cancel()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// Just in case mUpload holds the only ref to this object we make sure to stay
|
||||
// alive through this call.
|
||||
nsRefPtr<nsDOMWorkerXHR> kungFuDeathGrip(this);
|
||||
|
||||
{
|
||||
// This lock is here to prevent a race between Cancel and GetUpload, not to
|
||||
// protect mCanceled.
|
||||
MutexAutoLock lock(mWorker->GetLock());
|
||||
|
||||
mCanceled = PR_TRUE;
|
||||
mUpload = nsnull;
|
||||
}
|
||||
|
||||
if (mXHRProxy) {
|
||||
mXHRProxy->Destroy();
|
||||
mXHRProxy = nsnull;
|
||||
}
|
||||
|
||||
mWorker = nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHR::SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
PRUint32 type = GetListenerTypeFromString(aType);
|
||||
if (type > sMaxXHREventTypes) {
|
||||
// Silently ignore junk events.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsDOMWorkerXHREventTarget::SetOnXListener(aType, aListener);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetChannel(nsIChannel** aChannel)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aChannel);
|
||||
*aChannel = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseXML(nsIDOMDocument** aResponseXML)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aResponseXML);
|
||||
*aResponseXML = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseText(nsAString& aResponseText)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetResponseText(aResponseText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetStatus(PRUint32* aStatus)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aStatus);
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetStatus(aStatus);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetStatusText(nsACString& aStatusText)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetStatusText(aStatusText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Abort()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->Abort();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetAllResponseHeaders(char** _retval)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetAllResponseHeaders(_retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseHeader(const nsACString& aHeader,
|
||||
nsACString& _retval)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetResponseHeader(aHeader, _retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Open(const nsACString& aMethod, const nsACString& aUrl,
|
||||
PRBool aAsync, const nsAString& aUser,
|
||||
const nsAString& aPassword, PRUint8 optional_argc)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
if (!optional_argc) {
|
||||
aAsync = PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->Open(aMethod, aUrl, aAsync, aUser, aPassword);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Send(nsIVariant* aBody)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
if (mWorker->IsClosing() && !mXHRProxy->mSyncRequest) {
|
||||
// Cheat and don't start this request since we know we'll never be able to
|
||||
// use the data.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->Send(aBody);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SendAsBinary(const nsAString& aBody)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
if (mWorker->IsClosing() && !mXHRProxy->mSyncRequest) {
|
||||
// Cheat and don't start this request since we know we'll never be able to
|
||||
// use the data.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SendAsBinary(aBody);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetRequestHeader(const nsACString& aHeader,
|
||||
const nsACString& aValue)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SetRequestHeader(aHeader, aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetReadyState(PRUint16* aReadyState)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aReadyState);
|
||||
|
||||
nsresult rv = mXHRProxy->GetReadyState(aReadyState);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::OverrideMimeType(const nsACString& aMimetype)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->OverrideMimeType(aMimetype);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetMultipart(PRBool* aMultipart)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aMultipart);
|
||||
|
||||
nsresult rv = mXHRProxy->GetMultipart(aMultipart);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetMultipart(PRBool aMultipart)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SetMultipart(aMultipart);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetMozBackgroundRequest(PRBool* aMozBackgroundRequest)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aMozBackgroundRequest);
|
||||
|
||||
*aMozBackgroundRequest = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetMozBackgroundRequest(PRBool aMozBackgroundRequest)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (aMozBackgroundRequest) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Init(nsIPrincipal* aPrincipal,
|
||||
nsIScriptContext* aScriptContext,
|
||||
nsPIDOMWindow* aOwnerWindow,
|
||||
nsIURI* aBaseURI)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_NOTREACHED("No one should be calling this!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetUpload(nsIXMLHttpRequestUpload** aUpload)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<nsDOMWorker> worker = mWorker;
|
||||
if (!worker) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(worker->GetLock());
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aUpload);
|
||||
|
||||
if (!mUpload) {
|
||||
mUpload = new nsDOMWorkerXHRUpload(this);
|
||||
NS_ENSURE_TRUE(mUpload, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
NS_ADDREF(*aUpload = mUpload);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetOnreadystatechange(nsIDOMEventListener** aOnreadystatechange)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnreadystatechange);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_READYSTATECHANGE]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnreadystatechange);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetOnreadystatechange(nsIDOMEventListener* aOnreadystatechange)
|
||||
{
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_READYSTATECHANGE]);
|
||||
|
||||
return SetOnXListener(type, aOnreadystatechange);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetWithCredentials(PRBool* aWithCredentials)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aWithCredentials);
|
||||
|
||||
nsresult rv = mXHRProxy->GetWithCredentials(aWithCredentials);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetWithCredentials(PRBool aWithCredentials)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SetWithCredentials(aWithCredentials);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseType(nsAString& aResponseText)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetResponseType(const nsAString& aResponseText)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* readonly attribute jsval response; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponse(JSContext *aCx, jsval *aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
172
dom/src/threads/nsDOMWorkerXHR.h
Normal file
172
dom/src/threads/nsDOMWorkerXHR.h
Normal file
@ -0,0 +1,172 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERXHR_H__
|
||||
#define __NSDOMWORKERXHR_H__
|
||||
|
||||
// Bases
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIXMLHttpRequest.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMWorker.h"
|
||||
#include "nsDOMWorkerMacros.h"
|
||||
#include "nsDOMWorkerXHRProxy.h"
|
||||
|
||||
// Convenience defines for event *indexes* in the sListenerTypes array.
|
||||
#define LISTENER_TYPE_ABORT 0
|
||||
#define LISTENER_TYPE_ERROR 1
|
||||
#define LISTENER_TYPE_LOAD 2
|
||||
#define LISTENER_TYPE_LOADSTART 3
|
||||
#define LISTENER_TYPE_PROGRESS 4
|
||||
#define LISTENER_TYPE_READYSTATECHANGE 5
|
||||
#define LISTENER_TYPE_LOADEND 6
|
||||
|
||||
class nsIXPConnectWrappedNative;
|
||||
|
||||
class nsDOMWorkerXHREventTarget : public nsDOMWorkerMessageHandler,
|
||||
public nsIXMLHttpRequestEventTarget
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMWorkerMessageHandler::)
|
||||
NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET
|
||||
|
||||
static const char* const sListenerTypes[];
|
||||
static const PRUint32 sMaxXHREventTypes;
|
||||
static const PRUint32 sMaxUploadEventTypes;
|
||||
|
||||
static PRUint32 GetListenerTypeFromString(const nsAString& aString);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerXHREventTarget() { }
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHRUpload;
|
||||
|
||||
class nsDOMWorkerXHR : public nsDOMWorkerFeature,
|
||||
public nsDOMWorkerXHREventTarget,
|
||||
public nsIXMLHttpRequest,
|
||||
public nsIXPCScriptable
|
||||
{
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
friend class nsDOMWorkerXHREvent;
|
||||
friend class nsDOMWorkerXHRLastProgressOrLoadEvent;
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
friend class nsDOMWorkerXHRUpload;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIXMLHTTPREQUEST
|
||||
NS_FORWARD_NSICLASSINFO_NOGETINTERFACES(nsDOMWorkerXHREventTarget::)
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
NS_DECL_NSIXPCSCRIPTABLE
|
||||
|
||||
nsDOMWorkerXHR(nsDOMWorker* aWorker);
|
||||
|
||||
nsresult Init();
|
||||
|
||||
virtual void Cancel();
|
||||
|
||||
virtual nsresult SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~nsDOMWorkerXHR();
|
||||
|
||||
Mutex& GetLock() {
|
||||
return mWorker->GetLock();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIXPConnectWrappedNative> GetWrappedNative() {
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative(mWrappedNative);
|
||||
return wrappedNative.forget();
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHRProxy;
|
||||
nsRefPtr<nsDOMWorkerXHRUpload> mUpload;
|
||||
|
||||
nsIXPConnectWrappedNative* mWrappedNative;
|
||||
|
||||
volatile PRBool mCanceled;
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHRUpload : public nsDOMWorkerXHREventTarget,
|
||||
public nsIXMLHttpRequestUpload
|
||||
{
|
||||
friend class nsDOMWorkerXHR;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDOMEventHandler
|
||||
NS_FORWARD_INTERNAL_NSIDOMEVENTTARGET(nsDOMWorkerMessageHandler::)
|
||||
NS_IMETHOD AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 optional_argc);
|
||||
NS_IMETHOD RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture);
|
||||
NS_IMETHOD DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval);
|
||||
NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsDOMWorkerXHREventTarget::)
|
||||
NS_DECL_NSIXMLHTTPREQUESTUPLOAD
|
||||
NS_FORWARD_NSICLASSINFO_NOGETINTERFACES(nsDOMWorkerXHREventTarget::)
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
nsDOMWorkerXHRUpload(nsDOMWorkerXHR* aWorkerXHR);
|
||||
|
||||
virtual nsresult SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerXHRUpload() { }
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHR> mWorkerXHR;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERXHR_H__ */
|
182
dom/src/threads/nsDOMWorkerXHRProxiedFunctions.h
Normal file
182
dom/src/threads/nsDOMWorkerXHRProxiedFunctions.h
Normal file
@ -0,0 +1,182 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERXHRPROXIEDFUNCTIONS_H__
|
||||
#define __NSDOMWORKERXHRPROXIEDFUNCTIONS_H__
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION0(_name) \
|
||||
class _name : public SyncEventCapturingRunnable \
|
||||
{ \
|
||||
public: \
|
||||
virtual nsresult RunInternal() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION1(_name, _arg1) \
|
||||
class _name : public SyncEventCapturingRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (_arg1 aArg1) : mArg1(aArg1) { } \
|
||||
\
|
||||
virtual nsresult RunInternal() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (mArg1); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
private: \
|
||||
_arg1 mArg1; \
|
||||
}
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION2(_name, _arg1, _arg2) \
|
||||
class _name : public SyncEventCapturingRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (_arg1 aArg1, _arg2 aArg2) : mArg1(aArg1), mArg2(aArg2) { } \
|
||||
\
|
||||
virtual nsresult RunInternal() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (mArg1, mArg2); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
private: \
|
||||
_arg1 mArg1; \
|
||||
_arg2 mArg2; \
|
||||
}
|
||||
|
||||
namespace nsDOMWorkerProxiedXHRFunctions
|
||||
{
|
||||
typedef nsDOMWorkerXHRProxy::SyncEventQueue SyncEventQueue;
|
||||
|
||||
class SyncEventCapturingRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
SyncEventCapturingRunnable()
|
||||
: mXHR(nsnull), mQueue(nsnull) { }
|
||||
|
||||
void Init(nsDOMWorkerXHRProxy* aXHR,
|
||||
SyncEventQueue* aQueue) {
|
||||
NS_ASSERTION(aXHR, "Null pointer!");
|
||||
NS_ASSERTION(aQueue, "Null pointer!");
|
||||
|
||||
mXHR = aXHR;
|
||||
mQueue = aQueue;
|
||||
}
|
||||
|
||||
virtual nsresult RunInternal() = 0;
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
NS_ASSERTION(mXHR && mQueue, "Forgot to call Init!");
|
||||
|
||||
SyncEventQueue* oldQueue = mXHR->SetSyncEventQueue(mQueue);
|
||||
|
||||
nsresult rv = RunInternal();
|
||||
|
||||
mXHR->SetSyncEventQueue(oldQueue);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHR;
|
||||
SyncEventQueue* mQueue;
|
||||
};
|
||||
|
||||
class Abort : public SyncEventCapturingRunnable
|
||||
{
|
||||
public:
|
||||
virtual nsresult RunInternal() {
|
||||
return mXHR->Abort();
|
||||
}
|
||||
};
|
||||
|
||||
class Open : public SyncEventCapturingRunnable
|
||||
{
|
||||
public:
|
||||
Open(const nsACString& aMethod, const nsACString& aUrl,
|
||||
PRBool aAsync, const nsAString& aUser,
|
||||
const nsAString& aPassword)
|
||||
: mMethod(aMethod), mUrl(aUrl), mAsync(aAsync), mUser(aUser),
|
||||
mPassword(aPassword) { }
|
||||
|
||||
virtual nsresult RunInternal() {
|
||||
return mXHR->Open(mMethod, mUrl, mAsync, mUser, mPassword);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCString mMethod;
|
||||
nsCString mUrl;
|
||||
PRBool mAsync;
|
||||
nsString mUser;
|
||||
nsString mPassword;
|
||||
};
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(GetAllResponseHeaders, char**);
|
||||
|
||||
MAKE_PROXIED_FUNCTION2(GetResponseHeader, const nsACString&, nsACString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(Send, nsIVariant*);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(SendAsBinary, const nsAString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION2(SetRequestHeader, const nsACString&,
|
||||
const nsACString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(OverrideMimeType, const nsACString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(SetMultipart, PRBool);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(GetMultipart, PRBool*);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(GetWithCredentials, PRBool*);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(SetWithCredentials, PRBool);
|
||||
}
|
||||
|
||||
#endif /* __NSDOMWORKERXHRPROXIEDFUNCTIONS_H__ */
|
1187
dom/src/threads/nsDOMWorkerXHRProxy.cpp
Normal file
1187
dom/src/threads/nsDOMWorkerXHRProxy.cpp
Normal file
File diff suppressed because it is too large
Load Diff
198
dom/src/threads/nsDOMWorkerXHRProxy.h
Normal file
198
dom/src/threads/nsDOMWorkerXHRProxy.h
Normal file
@ -0,0 +1,198 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERXHRPROXY_H__
|
||||
#define __NSDOMWORKERXHRPROXY_H__
|
||||
|
||||
// Bases
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIJSXMLHttpRequest;
|
||||
class nsIThread;
|
||||
class nsIVariant;
|
||||
class nsIXMLHttpRequest;
|
||||
class nsIXMLHttpRequestUpload;
|
||||
class nsIXPConnectWrappedNative;
|
||||
class nsDOMWorkerXHR;
|
||||
class nsDOMWorkerXHREvent;
|
||||
class nsDOMWorkerXHRFinishSyncXHRRunnable;
|
||||
class nsDOMWorkerXHRState;
|
||||
class nsDOMWorkerXHRWrappedListener;
|
||||
class nsXMLHttpRequest;
|
||||
|
||||
class nsDOMWorkerXHRProxy : public nsIRunnable,
|
||||
public nsIDOMEventListener,
|
||||
public nsIRequestObserver
|
||||
{
|
||||
friend class nsDOMWorkerXHRAttachUploadListenersRunnable;
|
||||
friend class nsDOMWorkerXHREvent;
|
||||
friend class nsDOMWorkerXHRFinishSyncXHRRunnable;
|
||||
friend class nsDOMWorkerXHRLastProgressOrLoadEvent;
|
||||
friend class nsDOMWorkerXHR;
|
||||
friend class nsDOMWorkerXHRUpload;
|
||||
|
||||
public:
|
||||
typedef nsAutoTArray<nsCOMPtr<nsIRunnable>, 5> SyncEventQueue;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
||||
nsDOMWorkerXHRProxy(nsDOMWorkerXHR* aWorkerXHR);
|
||||
virtual ~nsDOMWorkerXHRProxy();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
nsIXMLHttpRequest* GetXMLHttpRequest();
|
||||
|
||||
nsresult Open(const nsACString& aMethod,
|
||||
const nsACString& aUrl,
|
||||
PRBool aAsync,
|
||||
const nsAString& aUser,
|
||||
const nsAString& aPassword);
|
||||
|
||||
nsresult Abort();
|
||||
|
||||
SyncEventQueue* SetSyncEventQueue(SyncEventQueue* aQueue);
|
||||
|
||||
PRInt32 ChannelID() {
|
||||
return mChannelID;
|
||||
}
|
||||
|
||||
protected:
|
||||
struct ProgressInfo {
|
||||
ProgressInfo() : computable(PR_FALSE), loaded(0), total(0) { }
|
||||
|
||||
PRBool computable;
|
||||
PRUint64 loaded;
|
||||
PRUint64 total;
|
||||
};
|
||||
|
||||
nsresult InitInternal();
|
||||
void DestroyInternal();
|
||||
|
||||
nsresult Destroy();
|
||||
|
||||
void AddRemoveXHRListeners(PRBool aAdd);
|
||||
void FlipOwnership();
|
||||
|
||||
nsresult UploadEventListenerAdded();
|
||||
|
||||
nsresult HandleWorkerEvent(nsDOMWorkerXHREvent* aEvent,
|
||||
PRBool aUploadEvent);
|
||||
|
||||
nsresult HandleEventRunnable(nsIRunnable* aRunnable);
|
||||
|
||||
// Methods of nsIXMLHttpRequest that we implement
|
||||
nsresult GetAllResponseHeaders(char** _retval);
|
||||
nsresult GetResponseHeader(const nsACString& aHeader,
|
||||
nsACString& _retval);
|
||||
nsresult Send(nsIVariant* aBody);
|
||||
nsresult SendAsBinary(const nsAString& aBody);
|
||||
nsresult GetResponseText(nsAString& _retval);
|
||||
nsresult GetStatusText(nsACString& _retval);
|
||||
nsresult GetStatus(nsresult* _retval);
|
||||
nsresult GetReadyState(PRUint16* _retval);
|
||||
nsresult SetRequestHeader(const nsACString& aHeader,
|
||||
const nsACString& aValue);
|
||||
nsresult OverrideMimeType(const nsACString& aMimetype);
|
||||
nsresult GetMultipart(PRBool* aMultipart);
|
||||
nsresult SetMultipart(PRBool aMultipart);
|
||||
nsresult GetWithCredentials(PRBool* aWithCredentials);
|
||||
nsresult SetWithCredentials(PRBool aWithCredentials);
|
||||
|
||||
nsresult RunSyncEventLoop();
|
||||
|
||||
PRBool IsUploadEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
nsresult DispatchPrematureAbortEvents(PRUint32 aType,
|
||||
nsIDOMEventTarget* aTarget,
|
||||
ProgressInfo* aProgressInfo);
|
||||
|
||||
nsresult MaybeDispatchPrematureAbortEvents(PRBool aFromOpenRequest);
|
||||
|
||||
// May be weak or strong, check mOwnedByXHR.
|
||||
nsDOMWorkerXHR* mWorkerXHR;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mWorkerXHRWN;
|
||||
|
||||
// May be weak or strong, check mOwnedByXHR.
|
||||
nsIXMLHttpRequest* mXHR;
|
||||
|
||||
// Always weak!
|
||||
nsXMLHttpRequest* mConcreteXHR;
|
||||
nsIXMLHttpRequestUpload* mUpload;
|
||||
|
||||
nsCOMPtr<nsIThread> mMainThread;
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRState> mLastXHRState;
|
||||
nsRefPtr<nsDOMWorkerXHREvent> mLastProgressOrLoadEvent;
|
||||
|
||||
SyncEventQueue* mSyncEventQueue;
|
||||
|
||||
PRInt32 mChannelID;
|
||||
|
||||
// Only touched on the worker thread!
|
||||
nsCOMPtr<nsIThread> mSyncXHRThread;
|
||||
|
||||
// Touched on more than one thread, protected by the worker's lock.
|
||||
nsRefPtr<nsDOMWorkerXHRFinishSyncXHRRunnable> mSyncFinishedRunnable;
|
||||
|
||||
nsAutoPtr<ProgressInfo> mDownloadProgressInfo;
|
||||
nsAutoPtr<ProgressInfo> mUploadProgressInfo;
|
||||
|
||||
// Whether or not this object is owned by the real XHR object.
|
||||
PRPackedBool mOwnedByXHR;
|
||||
|
||||
PRPackedBool mWantUploadListeners;
|
||||
PRPackedBool mCanceled;
|
||||
|
||||
PRPackedBool mSyncRequest;
|
||||
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERXHRPROXY_H__ */
|
26
dom/src/threads/test/errorPropagation_worker1.js
Normal file
26
dom/src/threads/test/errorPropagation_worker1.js
Normal file
@ -0,0 +1,26 @@
|
||||
var worker = new Worker("errorPropagation_worker2.js");
|
||||
|
||||
var errorCount = 0;
|
||||
worker.onerror = function(event) {
|
||||
switch (errorCount++) {
|
||||
case 0:
|
||||
case 1:
|
||||
// Let it propagate.
|
||||
break;
|
||||
case 2:
|
||||
// Stop and rethrow.
|
||||
event.preventDefault();
|
||||
throw event.message;
|
||||
break;
|
||||
case 3:
|
||||
event.preventDefault();
|
||||
postMessage(event.message);
|
||||
worker.onerror = null;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
onmessage = function(event) {
|
||||
worker.postMessage(event.data);
|
||||
};
|
26
dom/src/threads/test/regExpStatics_worker.js
Normal file
26
dom/src/threads/test/regExpStatics_worker.js
Normal file
@ -0,0 +1,26 @@
|
||||
var runCount = 0;
|
||||
var timeout;
|
||||
|
||||
onmessage = function() {
|
||||
run();
|
||||
timeout = setTimeout(run, 0);
|
||||
timeout = setTimeout(run, 5000);
|
||||
};
|
||||
|
||||
function run() {
|
||||
if (RegExp.$1) {
|
||||
throw "RegExp.$1 already set!";
|
||||
cancelTimeout(timeout);
|
||||
}
|
||||
|
||||
var match = /a(sd)f/.exec("asdf");
|
||||
if (!RegExp.$1) {
|
||||
throw "RegExp.$1 didn't get set!";
|
||||
cancelTimeout(timeout);
|
||||
}
|
||||
|
||||
if (++runCount == 3) {
|
||||
postMessage("done");
|
||||
}
|
||||
}
|
||||
|
88
dom/src/threads/test/test_chromeWorkerComponent.xul
Normal file
88
dom/src/threads/test/test_chromeWorkerComponent.xul
Normal file
@ -0,0 +1,88 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is DOM Worker tests.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- The Mozilla Foundation.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2010
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Ben Turner <bent.mozilla@gmail.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<window title="DOM Worker Threads Test"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="test();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function test()
|
||||
{
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
var wf = Cc["@mozilla.org/threads/workerfactory;1"]
|
||||
.createInstance(Ci.nsIWorkerFactory);
|
||||
|
||||
var worker = wf.newChromeWorker("chromeWorker_worker.js");
|
||||
worker.onmessage = function(event) {
|
||||
is(event.data, "Done!", "Wrong message!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
worker.onerror = function(event) {
|
||||
ok(false, "Worker had an error: " + event.message);
|
||||
worker.terminate();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// Test passing a wrapped native to the worker.
|
||||
var thread = Components.classes["@mozilla.org/thread-manager;1"]
|
||||
.getService().newThread(0);
|
||||
|
||||
worker.postMessage(thread);
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display:none;"></div>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
<label id="test-result"/>
|
||||
</window>
|
36
dom/src/threads/test/test_functionHandlers.html
Normal file
36
dom/src/threads/test/test_functionHandlers.html
Normal file
@ -0,0 +1,36 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Tests of DOM Worker Threads
|
||||
-->
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads Recursion</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<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"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var worker = new Worker("functionHandlers_worker.js");
|
||||
|
||||
var message = "hello!";
|
||||
|
||||
worker.onmessage = function(event) {
|
||||
is(event.data, "uncaught exception: " + message, "Bad message!");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
worker.postMessage(message);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
47
dom/src/threads/test/test_regExpStatics.html
Normal file
47
dom/src/threads/test/test_regExpStatics.html
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Tests of DOM Worker Threads RegExp statics
|
||||
-->
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads RegExp statics</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<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"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
const WORKER_COUNT = 25;
|
||||
|
||||
var doneWorkers = 0;
|
||||
function onmessage(event) {
|
||||
if (++doneWorkers == WORKER_COUNT) {
|
||||
ok(true, "All messages received from workers");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function onerror(event) {
|
||||
ok(false, "Worker had an error: " + event.data);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
for (var i = 0; i < WORKER_COUNT; i++) {
|
||||
var worker = new Worker("regExpStatics_worker.js");
|
||||
worker.onmessage = onmessage;
|
||||
worker.onerror = onerror;
|
||||
worker.postMessage("start");
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
44
dom/src/threads/test/test_scopeOnerror.html
Normal file
44
dom/src/threads/test/test_scopeOnerror.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Tests of DOM Worker Threads
|
||||
-->
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<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 class="testbody" type="text/javascript">
|
||||
|
||||
var errors = [
|
||||
"This exception should make it to onerror",
|
||||
"This error should not make it back out"
|
||||
];
|
||||
|
||||
var worker = new Worker("scopeOnerror_worker.js");
|
||||
|
||||
worker.onmessage = function(event) {
|
||||
ok(event.data == "Done");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
worker.onerror = function(event) {
|
||||
is(event.target, worker);
|
||||
is(event.message, "uncaught exception: " + errors[0]);
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
for (var index in errors) {
|
||||
worker.postMessage(errors[index]);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -408,7 +408,7 @@ nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
|
||||
nsCOMPtr<nsIEditorMailSupport> mailEditor;
|
||||
if (ctrlKey)
|
||||
mailEditor = do_QueryInterface(static_cast<nsIEditor*>(mEditor));
|
||||
mailEditor = do_QueryObject(mEditor);
|
||||
|
||||
PRInt32 clipboard;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user