mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-24 02:35:41 +00:00
Back out bug 813978 on a CLOSED TREE.
This commit is contained in:
commit
1ffd79274e
@ -11,7 +11,7 @@
|
|||||||
],
|
],
|
||||||
"zip_files": [
|
"zip_files": [
|
||||||
["{workdir}/out/target/product/otoro/*.img", "out/target/product/otoro/"],
|
["{workdir}/out/target/product/otoro/*.img", "out/target/product/otoro/"],
|
||||||
"{workdir}/boot.img",
|
["{workdir}/boot.img", "out/target/product/otoro/"],
|
||||||
"{workdir}/flash.sh",
|
"{workdir}/flash.sh",
|
||||||
"{workdir}/load-config.sh",
|
"{workdir}/load-config.sh",
|
||||||
"{workdir}/.config",
|
"{workdir}/.config",
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
],
|
],
|
||||||
"zip_files": [
|
"zip_files": [
|
||||||
["{workdir}/out/target/product/unagi/*.img", "out/target/product/unagi/"],
|
["{workdir}/out/target/product/unagi/*.img", "out/target/product/unagi/"],
|
||||||
"{workdir}/boot.img",
|
["{workdir}/boot.img", "out/target/product/unagi/"],
|
||||||
"{workdir}/flash.sh",
|
"{workdir}/flash.sh",
|
||||||
"{workdir}/load-config.sh",
|
"{workdir}/load-config.sh",
|
||||||
"{workdir}/.config",
|
"{workdir}/.config",
|
||||||
|
@ -31,11 +31,8 @@ DEFINES += \
|
|||||||
-DNEWWINDOW_ICO=\"$(DIST)/branding/newwindow.ico\" \
|
-DNEWWINDOW_ICO=\"$(DIST)/branding/newwindow.ico\" \
|
||||||
-DNEWTAB_ICO=\"$(DIST)/branding/newtab.ico\" \
|
-DNEWTAB_ICO=\"$(DIST)/branding/newtab.ico\" \
|
||||||
-DPBMODE_ICO=\"$(DIST)/branding/pbmode.ico\" \
|
-DPBMODE_ICO=\"$(DIST)/branding/pbmode.ico\" \
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
ifdef MOZILLA_OFFICIAL
|
$(NULL)
|
||||||
DEFINES += -DMOZILLA_OFFICIAL
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef LIBXUL_SDK #{
|
ifdef LIBXUL_SDK #{
|
||||||
PREF_JS_EXPORTS += $(srcdir)/profile/channel-prefs.js
|
PREF_JS_EXPORTS += $(srcdir)/profile/channel-prefs.js
|
||||||
|
@ -734,12 +734,6 @@ pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-erro
|
|||||||
pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
|
pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
|
||||||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||||
|
|
||||||
#ifdef MOZILLA_OFFICIAL
|
|
||||||
// Normally the "client ID" sent in updates is appinfo.name, but for
|
|
||||||
// official Firefox releases from Mozilla we use a special identifier.
|
|
||||||
pref("browser.safebrowsing.id", "navclient-auto-ffox");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Name of the about: page contributed by safebrowsing to handle display of error
|
// Name of the about: page contributed by safebrowsing to handle display of error
|
||||||
// pages on phishing/malware hits. (bug 399233)
|
// pages on phishing/malware hits. (bug 399233)
|
||||||
pref("urlclassifier.alternate_error_page", "blocked");
|
pref("urlclassifier.alternate_error_page", "blocked");
|
||||||
|
@ -35,6 +35,9 @@
|
|||||||
|
|
||||||
<toolbar id="placesToolbar">
|
<toolbar id="placesToolbar">
|
||||||
<toolbarbutton id="clearDownloadsButton"
|
<toolbarbutton id="clearDownloadsButton"
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
class="tabbable"
|
||||||
|
#endif
|
||||||
insertbefore="libraryToolbarSpacer"
|
insertbefore="libraryToolbarSpacer"
|
||||||
label="&clearDownloadsButton.label;"
|
label="&clearDownloadsButton.label;"
|
||||||
command="downloadsCmd_clearDownloads"
|
command="downloadsCmd_clearDownloads"
|
||||||
|
@ -31,4 +31,4 @@ browser.jar:
|
|||||||
content/browser/places/moveBookmarks.js (content/moveBookmarks.js)
|
content/browser/places/moveBookmarks.js (content/moveBookmarks.js)
|
||||||
content/browser/places/editBookmarkOverlay.xul (content/editBookmarkOverlay.xul)
|
content/browser/places/editBookmarkOverlay.xul (content/editBookmarkOverlay.xul)
|
||||||
content/browser/places/editBookmarkOverlay.js (content/editBookmarkOverlay.js)
|
content/browser/places/editBookmarkOverlay.js (content/editBookmarkOverlay.js)
|
||||||
content/browser/places/downloadsViewOverlay.xul (content/downloadsViewOverlay.xul)
|
* content/browser/places/downloadsViewOverlay.xul (content/downloadsViewOverlay.xul)
|
||||||
|
@ -374,8 +374,6 @@
|
|||||||
@BINPATH@/components/nsDownloadManagerUI.js
|
@BINPATH@/components/nsDownloadManagerUI.js
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
|
||||||
@BINPATH@/components/GPSDGeolocationProvider.js
|
|
||||||
@BINPATH@/components/nsSidebar.manifest
|
@BINPATH@/components/nsSidebar.manifest
|
||||||
@BINPATH@/components/nsSidebar.js
|
@BINPATH@/components/nsSidebar.js
|
||||||
@BINPATH@/components/extensions.manifest
|
@BINPATH@/components/extensions.manifest
|
||||||
|
@ -318,8 +318,10 @@ toolbar[iconsize="large"] > #downloads-indicator[attention] > #downloads-indicat
|
|||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||||
|
background-clip: padding-box, border-box;
|
||||||
background-color: rgb(255, 135, 94);
|
background-color: rgb(255, 135, 94);
|
||||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||||
border-radius: 2px 0 0 2px;
|
border-radius: 2px 0 0 2px;
|
||||||
|
@ -492,8 +492,10 @@ richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:acti
|
|||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||||
|
background-clip: padding-box, border-box;
|
||||||
background-color: rgb(90, 185, 255);
|
background-color: rgb(90, 185, 255);
|
||||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||||
border-radius: 2px 0 0 2px;
|
border-radius: 2px 0 0 2px;
|
||||||
|
@ -343,8 +343,10 @@ richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:acti
|
|||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||||
|
background-clip: padding-box, border-box;
|
||||||
background-color: rgb(90, 201, 66);
|
background-color: rgb(90, 201, 66);
|
||||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||||
border-radius: 2px 0 0 2px;
|
border-radius: 2px 0 0 2px;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
import sys, re, os, posixpath, ntpath
|
import sys, re, os, posixpath, ntpath
|
||||||
|
import errno
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
# Standalone js doesn't have virtualenv.
|
# Standalone js doesn't have virtualenv.
|
||||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'config'))
|
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'config'))
|
||||||
|
@ -274,38 +274,37 @@ class Automation(object):
|
|||||||
cursor.execute("PRAGMA user_version=3");
|
cursor.execute("PRAGMA user_version=3");
|
||||||
|
|
||||||
# SQL copied from nsPermissionManager.cpp
|
# SQL copied from nsPermissionManager.cpp
|
||||||
cursor.execute("""CREATE TABLE moz_hosts (
|
cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
host TEXT,
|
host TEXT,
|
||||||
type TEXT,
|
type TEXT,
|
||||||
permission INTEGER,
|
permission INTEGER,
|
||||||
expireType INTEGER,
|
expireType INTEGER,
|
||||||
expireTime INTEGER,
|
expireTime INTEGER,
|
||||||
appId INTEGER,
|
appId INTEGER,
|
||||||
isInBrowserElement INTEGER)""")
|
isInBrowserElement INTEGER)""")
|
||||||
|
|
||||||
# Insert desired permissions
|
# Insert desired permissions
|
||||||
c = 0
|
|
||||||
for perm in permissions.keys():
|
for perm in permissions.keys():
|
||||||
for host,allow in permissions[perm]:
|
for host,allow in permissions[perm]:
|
||||||
c += 1
|
cursor.execute("INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0)",
|
||||||
cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, ?, 0, 0, 0, 0)",
|
(host, perm, 1 if allow else 2))
|
||||||
(c, host, perm, 1 if allow else 2))
|
|
||||||
|
|
||||||
# Commit and close
|
# Commit and close
|
||||||
permDB.commit()
|
permDB.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
def setupTestApps(self, profileDir, apps):
|
def setupTestApps(self, profileDir, apps):
|
||||||
webappJSONTemplate = Template(""""$name": {
|
webappJSONTemplate = Template(""""$id": {
|
||||||
"origin": "$origin",
|
"origin": "$origin",
|
||||||
"installOrigin": "$origin",
|
"installOrigin": "$origin",
|
||||||
"receipt": null,
|
"receipt": null,
|
||||||
"installTime": 132333986000,
|
"installTime": 132333986000,
|
||||||
"manifestURL": "$manifestURL",
|
"manifestURL": "$manifestURL",
|
||||||
"localId": $localId,
|
"localId": $localId,
|
||||||
"appStatus": $appStatus,
|
"id": "$id",
|
||||||
"csp": "$csp"
|
"appStatus": $appStatus,
|
||||||
|
"csp": "$csp"
|
||||||
}""")
|
}""")
|
||||||
|
|
||||||
manifestTemplate = Template("""{
|
manifestTemplate = Template("""{
|
||||||
@ -333,16 +332,73 @@ class Automation(object):
|
|||||||
|
|
||||||
# Create webapps/webapps.json
|
# Create webapps/webapps.json
|
||||||
webappsDir = os.path.join(profileDir, "webapps")
|
webappsDir = os.path.join(profileDir, "webapps")
|
||||||
os.mkdir(webappsDir);
|
if not os.access(webappsDir, os.F_OK):
|
||||||
|
os.mkdir(webappsDir)
|
||||||
|
|
||||||
|
lineRe = re.compile(r'(.*?)"(.*?)": (.*)')
|
||||||
|
|
||||||
|
webappsJSONFilename = os.path.join(webappsDir, "webapps.json")
|
||||||
webappsJSON = []
|
webappsJSON = []
|
||||||
for localId, app in enumerate(apps):
|
if os.access(webappsJSONFilename, os.F_OK):
|
||||||
app['localId'] = localId + 1 # Has to be 1..n
|
# If there is an existing webapps.json file (which will be the case for
|
||||||
webappsJSON.append(webappJSONTemplate.substitute(app))
|
# b2g), we parse the data in the existing file before appending test
|
||||||
webappsJSON = '{\n' + ',\n'.join(webappsJSON) + '\n}\n'
|
# test apps to it.
|
||||||
|
startId = 1
|
||||||
|
webappsJSONFile = open(webappsJSONFilename, "r")
|
||||||
|
contents = webappsJSONFile.read()
|
||||||
|
|
||||||
webappsJSONFile = open(os.path.join(webappsDir, "webapps.json"), "a")
|
for app_content in contents.split('},'):
|
||||||
webappsJSONFile.write(webappsJSON)
|
app = {}
|
||||||
|
# ghetto json parser needed due to lack of json/simplejson on test slaves
|
||||||
|
for line in app_content.split('\n'):
|
||||||
|
m = lineRe.match(line)
|
||||||
|
if m:
|
||||||
|
value = m.groups()[2]
|
||||||
|
# remove any trailing commas
|
||||||
|
if value[-1:] == ',':
|
||||||
|
value = value[:-1]
|
||||||
|
# set the app name from a line that looks like this:
|
||||||
|
# "name.gaiamobile.org": {
|
||||||
|
if value == '{':
|
||||||
|
app['id'] = m.groups()[1]
|
||||||
|
# parse string, None, bool and int types
|
||||||
|
elif value[0:1] == '"':
|
||||||
|
app[m.groups()[1]] = value[1:-1]
|
||||||
|
elif value == "null":
|
||||||
|
app[m.groups()[1]] = None
|
||||||
|
elif value == "true":
|
||||||
|
app[m.groups()[1]] = True
|
||||||
|
elif value == "false":
|
||||||
|
app[m.groups()[1]] = False
|
||||||
|
else:
|
||||||
|
app[m.groups()[1]] = int(value)
|
||||||
|
if app:
|
||||||
|
webappsJSON.append(app)
|
||||||
|
|
||||||
|
webappsJSONFile.close()
|
||||||
|
|
||||||
|
startId = 1
|
||||||
|
for app in webappsJSON:
|
||||||
|
if app['localId'] >= startId:
|
||||||
|
startId = app['localId'] + 1
|
||||||
|
if not app.get('csp'):
|
||||||
|
app['csp'] = ''
|
||||||
|
if not app.get('appStatus'):
|
||||||
|
app['appStatus'] = 3
|
||||||
|
|
||||||
|
for localId, app in enumerate(apps):
|
||||||
|
app['localId'] = localId + startId # localId must be from 1..N
|
||||||
|
if not app.get('id'):
|
||||||
|
app['id'] = app['name']
|
||||||
|
webappsJSON.append(app)
|
||||||
|
|
||||||
|
contents = []
|
||||||
|
for app in webappsJSON:
|
||||||
|
contents.append(webappJSONTemplate.substitute(app))
|
||||||
|
contents = '{\n' + ',\n'.join(contents) + '\n}\n'
|
||||||
|
|
||||||
|
webappsJSONFile = open(webappsJSONFilename, "w")
|
||||||
|
webappsJSONFile.write(contents)
|
||||||
webappsJSONFile.close()
|
webappsJSONFile.close()
|
||||||
|
|
||||||
# Create manifest file for each app.
|
# Create manifest file for each app.
|
||||||
@ -356,13 +412,19 @@ class Automation(object):
|
|||||||
manifestFile.write(manifest)
|
manifestFile.write(manifest)
|
||||||
manifestFile.close()
|
manifestFile.close()
|
||||||
|
|
||||||
def initializeProfile(self, profileDir, extraPrefs = [], useServerLocations = False):
|
def initializeProfile(self, profileDir, extraPrefs=[],
|
||||||
|
useServerLocations=False,
|
||||||
|
initialProfile=None):
|
||||||
" Sets up the standard testing profile."
|
" Sets up the standard testing profile."
|
||||||
|
|
||||||
prefs = []
|
prefs = []
|
||||||
# Start with a clean slate.
|
# Start with a clean slate.
|
||||||
shutil.rmtree(profileDir, True)
|
shutil.rmtree(profileDir, True)
|
||||||
os.mkdir(profileDir)
|
|
||||||
|
if initialProfile:
|
||||||
|
shutil.copytree(initialProfile, profileDir)
|
||||||
|
else:
|
||||||
|
os.mkdir(profileDir)
|
||||||
|
|
||||||
# Set up permissions database
|
# Set up permissions database
|
||||||
locations = self.readLocations()
|
locations = self.readLocations()
|
||||||
@ -600,7 +662,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||||||
'manifestURL': 'https://example.com/manifest_csp_cert.webapp',
|
'manifestURL': 'https://example.com/manifest_csp_cert.webapp',
|
||||||
'description': 'https://example.com Certified App with manifest policy',
|
'description': 'https://example.com Certified App with manifest policy',
|
||||||
'appStatus': _APP_STATUS_CERTIFIED
|
'appStatus': _APP_STATUS_CERTIFIED
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'https_example_csp_installed',
|
'name': 'https_example_csp_installed',
|
||||||
'csp': "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'",
|
'csp': "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'",
|
||||||
@ -608,7 +670,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||||||
'manifestURL': 'https://example.com/manifest_csp_inst.webapp',
|
'manifestURL': 'https://example.com/manifest_csp_inst.webapp',
|
||||||
'description': 'https://example.com Installed App with manifest policy',
|
'description': 'https://example.com Installed App with manifest policy',
|
||||||
'appStatus': _APP_STATUS_INSTALLED
|
'appStatus': _APP_STATUS_INSTALLED
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'https_example_csp_privileged',
|
'name': 'https_example_csp_privileged',
|
||||||
'csp': "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'",
|
'csp': "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'",
|
||||||
@ -616,15 +678,15 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||||||
'manifestURL': 'https://example.com/manifest_csp_priv.webapp',
|
'manifestURL': 'https://example.com/manifest_csp_priv.webapp',
|
||||||
'description': 'https://example.com Privileged App with manifest policy',
|
'description': 'https://example.com Privileged App with manifest policy',
|
||||||
'appStatus': _APP_STATUS_PRIVILEGED
|
'appStatus': _APP_STATUS_PRIVILEGED
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'https_a_domain_certified',
|
'name': 'https_a_domain_certified',
|
||||||
'csp' : "",
|
'csp': "",
|
||||||
'origin': 'https://acertified.com',
|
'origin': 'https://acertified.com',
|
||||||
'manifestURL': 'https://acertified.com/manifest.webapp',
|
'manifestURL': 'https://acertified.com/manifest.webapp',
|
||||||
'description': 'https://acertified.com Certified App',
|
'description': 'https://acertified.com Certified App',
|
||||||
'appStatus': _APP_STATUS_CERTIFIED
|
'appStatus': _APP_STATUS_CERTIFIED
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'https_a_domain_privileged',
|
'name': 'https_a_domain_privileged',
|
||||||
'csp': "",
|
'csp': "",
|
||||||
@ -632,7 +694,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||||||
'manifestURL': 'https://aprivileged.com/manifest.webapp',
|
'manifestURL': 'https://aprivileged.com/manifest.webapp',
|
||||||
'description': 'https://aprivileged.com Privileged App ',
|
'description': 'https://aprivileged.com Privileged App ',
|
||||||
'appStatus': _APP_STATUS_PRIVILEGED
|
'appStatus': _APP_STATUS_PRIVILEGED
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
self.setupTestApps(profileDir, apps)
|
self.setupTestApps(profileDir, apps)
|
||||||
|
|
||||||
@ -1033,7 +1095,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||||||
runSSLTunnel = False, utilityPath = None,
|
runSSLTunnel = False, utilityPath = None,
|
||||||
xrePath = None, certPath = None,
|
xrePath = None, certPath = None,
|
||||||
debuggerInfo = None, symbolsPath = None,
|
debuggerInfo = None, symbolsPath = None,
|
||||||
timeout = -1, maxTime = None):
|
timeout = -1, maxTime = None, onLaunch = None):
|
||||||
"""
|
"""
|
||||||
Run the app, log the duration it took to execute, return the status code.
|
Run the app, log the duration it took to execute, return the status code.
|
||||||
Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
|
Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
|
||||||
@ -1090,6 +1152,11 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||||||
stderr = subprocess.STDOUT)
|
stderr = subprocess.STDOUT)
|
||||||
self.log.info("INFO | automation.py | Application pid: %d", proc.pid)
|
self.log.info("INFO | automation.py | Application pid: %d", proc.pid)
|
||||||
|
|
||||||
|
if onLaunch is not None:
|
||||||
|
# Allow callers to specify an onLaunch callback to be fired after the
|
||||||
|
# app is launched.
|
||||||
|
onLaunch()
|
||||||
|
|
||||||
status = self.waitForFinish(proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath)
|
status = self.waitForFinish(proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath)
|
||||||
self.log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
|
self.log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class B2GRemoteAutomation(Automation):
|
|||||||
self._product = "b2g"
|
self._product = "b2g"
|
||||||
self.lastTestSeen = "b2gautomation.py"
|
self.lastTestSeen = "b2gautomation.py"
|
||||||
# Default log finish to mochitest standard
|
# Default log finish to mochitest standard
|
||||||
self.logFinish = 'INFO SimpleTest FINISHED'
|
self.logFinish = 'INFO SimpleTest FINISHED'
|
||||||
Automation.__init__(self)
|
Automation.__init__(self)
|
||||||
|
|
||||||
def setEmulator(self, is_emulator):
|
def setEmulator(self, is_emulator):
|
||||||
@ -85,7 +85,7 @@ class B2GRemoteAutomation(Automation):
|
|||||||
env['MOZ_HIDE_RESULTS_TABLE'] = '1'
|
env['MOZ_HIDE_RESULTS_TABLE'] = '1'
|
||||||
return env
|
return env
|
||||||
|
|
||||||
def waitForNet(self):
|
def waitForNet(self):
|
||||||
active = False
|
active = False
|
||||||
time_out = 0
|
time_out = 0
|
||||||
while not active and time_out < 40:
|
while not active and time_out < 40:
|
||||||
@ -106,15 +106,20 @@ class B2GRemoteAutomation(Automation):
|
|||||||
self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
|
self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
|
||||||
crashed = automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
|
crashed = automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(dumpDir)
|
shutil.rmtree(dumpDir)
|
||||||
except:
|
except:
|
||||||
print "WARNING: unable to remove directory: %s" % (dumpDir)
|
print "WARNING: unable to remove directory: %s" % (dumpDir)
|
||||||
return crashed
|
return crashed
|
||||||
|
|
||||||
def initializeProfile(self, profileDir, extraPrefs = [], useServerLocations = False):
|
def initializeProfile(self, profileDir, extraPrefs=[],
|
||||||
|
useServerLocations=False,
|
||||||
|
initialProfile=None):
|
||||||
# add b2g specific prefs
|
# add b2g specific prefs
|
||||||
extraPrefs.extend(["browser.manifestURL='dummy (bug 772307)'"])
|
extraPrefs.extend(["browser.manifestURL='dummy (bug 772307)'"])
|
||||||
return Automation.initializeProfile(self, profileDir, extraPrefs, useServerLocations)
|
return Automation.initializeProfile(self, profileDir,
|
||||||
|
extraPrefs,
|
||||||
|
useServerLocations,
|
||||||
|
initialProfile)
|
||||||
|
|
||||||
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
|
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
|
||||||
# if remote profile is specified, use that instead
|
# if remote profile is specified, use that instead
|
||||||
@ -165,7 +170,7 @@ class B2GRemoteAutomation(Automation):
|
|||||||
status = 'unknown'
|
status = 'unknown'
|
||||||
|
|
||||||
for line in self._devicemanager._runCmd(['devices']).stdout.readlines():
|
for line in self._devicemanager._runCmd(['devices']).stdout.readlines():
|
||||||
result = re.match('(.*?)\t(.*)', line)
|
result = re.match('(.*?)\t(.*)', line)
|
||||||
if result:
|
if result:
|
||||||
thisSerial = result.group(1)
|
thisSerial = result.group(1)
|
||||||
if not serial or thisSerial == serial:
|
if not serial or thisSerial == serial:
|
||||||
@ -223,9 +228,9 @@ class B2GRemoteAutomation(Automation):
|
|||||||
if not self._is_emulator:
|
if not self._is_emulator:
|
||||||
self.rebootDevice()
|
self.rebootDevice()
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
#wait for wlan to come up
|
#wait for wlan to come up
|
||||||
if not self.waitForNet():
|
if not self.waitForNet():
|
||||||
raise Exception("network did not come up, please configure the network" +
|
raise Exception("network did not come up, please configure the network" +
|
||||||
" prior to running before running the automation framework")
|
" prior to running before running the automation framework")
|
||||||
|
|
||||||
# stop b2g
|
# stop b2g
|
||||||
@ -334,10 +339,33 @@ class B2GRemoteAutomation(Automation):
|
|||||||
break
|
break
|
||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
|
||||||
def wait(self, timeout = None):
|
def wait(self, timeout=None):
|
||||||
# this should never happen
|
# this should never happen
|
||||||
raise Exception("'wait' called on B2GInstance")
|
raise Exception("'wait' called on B2GInstance")
|
||||||
|
|
||||||
def kill(self):
|
def kill(self):
|
||||||
# this should never happen
|
# this should never happen
|
||||||
raise Exception("'kill' called on B2GInstance")
|
raise Exception("'kill' called on B2GInstance")
|
||||||
|
|
||||||
|
|
||||||
|
class B2GDesktopAutomation(Automation):
|
||||||
|
|
||||||
|
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
|
||||||
|
""" build the application command line """
|
||||||
|
|
||||||
|
cmd = os.path.abspath(app)
|
||||||
|
args = []
|
||||||
|
|
||||||
|
if debuggerInfo:
|
||||||
|
args.extend(debuggerInfo["args"])
|
||||||
|
args.append(cmd)
|
||||||
|
cmd = os.path.abspath(debuggerInfo["path"])
|
||||||
|
|
||||||
|
if self.IS_MAC:
|
||||||
|
args.append("-foreground")
|
||||||
|
|
||||||
|
profileDirectory = profileDir + "/"
|
||||||
|
|
||||||
|
args.extend(("-profile", profileDirectory))
|
||||||
|
args.extend(extraArgs)
|
||||||
|
return cmd, args
|
||||||
|
@ -73,7 +73,7 @@ GCONF_VERSION=1.2.1
|
|||||||
GIO_VERSION=2.20
|
GIO_VERSION=2.20
|
||||||
STARTUP_NOTIFICATION_VERSION=0.8
|
STARTUP_NOTIFICATION_VERSION=0.8
|
||||||
DBUS_VERSION=0.60
|
DBUS_VERSION=0.60
|
||||||
SQLITE_VERSION=3.7.15.1
|
SQLITE_VERSION=3.7.15.2
|
||||||
|
|
||||||
MSMANIFEST_TOOL=
|
MSMANIFEST_TOOL=
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ include $(DEPTH)/config/autoconf.mk
|
|||||||
MOCHITEST_FILES := \
|
MOCHITEST_FILES := \
|
||||||
webaudio.js \
|
webaudio.js \
|
||||||
test_bug808374.html \
|
test_bug808374.html \
|
||||||
|
test_bug827541.html \
|
||||||
test_AudioBuffer.html \
|
test_AudioBuffer.html \
|
||||||
test_AudioContext.html \
|
test_AudioContext.html \
|
||||||
test_AudioListener.html \
|
test_AudioListener.html \
|
||||||
|
25
content/media/webaudio/test/test_bug827541.html
Normal file
25
content/media/webaudio/test/test_bug827541.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tell the cycle collector about the audio contexts owned by nsGlobalWindow</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
|
||||||
|
|
||||||
|
var iframe = document.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
|
||||||
|
document.body.appendChild(iframe);
|
||||||
|
var frameWin = iframe.contentWindow;
|
||||||
|
frameWin.mozAudioContext;
|
||||||
|
document.body.removeChild(iframe);
|
||||||
|
frameWin.mozAudioContext();
|
||||||
|
|
||||||
|
ok(true, "This test should not leak");
|
||||||
|
SpecialPowers.clearUserPref("media.webaudio.enabled");
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,6 +1,6 @@
|
|||||||
This is sqlite 3.7.15.1
|
This is sqlite 3.7.15.2
|
||||||
|
|
||||||
-- Ryan VanderMeulen <ryanvm@gmail.com>, 12/2012
|
-- Ryan VanderMeulen <ryanvm@gmail.com>, 01/2013
|
||||||
|
|
||||||
See http://www.sqlite.org/ for more info.
|
See http://www.sqlite.org/ for more info.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
** This file is an amalgamation of many separate C source files from SQLite
|
** This file is an amalgamation of many separate C source files from SQLite
|
||||||
** version 3.7.15.1. By combining all the individual C code files into this
|
** version 3.7.15.2. By combining all the individual C code files into this
|
||||||
** single large file, the entire code can be compiled as a single translation
|
** single large file, the entire code can be compiled as a single translation
|
||||||
** unit. This allows many compilers to do optimizations that would not be
|
** unit. This allows many compilers to do optimizations that would not be
|
||||||
** possible if the files were compiled separately. Performance improvements
|
** possible if the files were compiled separately. Performance improvements
|
||||||
@ -673,9 +673,9 @@ extern "C" {
|
|||||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||||
** [sqlite_version()] and [sqlite_source_id()].
|
** [sqlite_version()] and [sqlite_source_id()].
|
||||||
*/
|
*/
|
||||||
#define SQLITE_VERSION "3.7.15.1"
|
#define SQLITE_VERSION "3.7.15.2"
|
||||||
#define SQLITE_VERSION_NUMBER 3007015
|
#define SQLITE_VERSION_NUMBER 3007015
|
||||||
#define SQLITE_SOURCE_ID "2012-12-19 20:39:10 6b85b767d0ff7975146156a99ad673f2c1a23318"
|
#define SQLITE_SOURCE_ID "2013-01-09 11:53:05 c0e09560d26f0a6456be9dd3447f5311eb4f238f"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Run-Time Library Version Numbers
|
** CAPI3REF: Run-Time Library Version Numbers
|
||||||
@ -105723,7 +105723,7 @@ static void bestBtreeIndex(WhereBestIdx *p){
|
|||||||
pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev);
|
pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev);
|
||||||
WHERETRACE((" --> after isSortingIndex: bRev=%d nOBSat=%d\n",
|
WHERETRACE((" --> after isSortingIndex: bRev=%d nOBSat=%d\n",
|
||||||
bRev, pc.plan.nOBSat));
|
bRev, pc.plan.nOBSat));
|
||||||
if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_UNIQUE)!=0 ){
|
if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
|
||||||
pc.plan.wsFlags |= WHERE_ORDERED;
|
pc.plan.wsFlags |= WHERE_ORDERED;
|
||||||
}
|
}
|
||||||
if( nOrderBy==pc.plan.nOBSat ){
|
if( nOrderBy==pc.plan.nOBSat ){
|
||||||
|
@ -107,9 +107,9 @@ extern "C" {
|
|||||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||||
** [sqlite_version()] and [sqlite_source_id()].
|
** [sqlite_version()] and [sqlite_source_id()].
|
||||||
*/
|
*/
|
||||||
#define SQLITE_VERSION "3.7.15.1"
|
#define SQLITE_VERSION "3.7.15.2"
|
||||||
#define SQLITE_VERSION_NUMBER 3007015
|
#define SQLITE_VERSION_NUMBER 3007015
|
||||||
#define SQLITE_SOURCE_ID "2012-12-19 20:39:10 6b85b767d0ff7975146156a99ad673f2c1a23318"
|
#define SQLITE_SOURCE_ID "2013-01-09 11:53:05 c0e09560d26f0a6456be9dd3447f5311eb4f238f"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Run-Time Library Version Numbers
|
** CAPI3REF: Run-Time Library Version Numbers
|
||||||
|
@ -1228,15 +1228,19 @@ this.DOMApplicationRegistry = {
|
|||||||
// "downloadapplied".
|
// "downloadapplied".
|
||||||
let updateObserver = {
|
let updateObserver = {
|
||||||
observe: function(aSubject, aTopic, aObsData) {
|
observe: function(aSubject, aTopic, aObsData) {
|
||||||
|
debug("updateHostedApp: updateSvc.checkForUpdate return for " +
|
||||||
|
app.manifestURL + " - event is " + aTopic);
|
||||||
aData.event =
|
aData.event =
|
||||||
aTopic == "offline-cache-update-available" ? "downloadavailable"
|
aTopic == "offline-cache-update-available" ? "downloadavailable"
|
||||||
: "downloadapplied";
|
: "downloadapplied";
|
||||||
aData.app.downloadAvailable = (aTopic == "downloadavailable");
|
aData.app.downloadAvailable = (aData.event == "downloadavailable");
|
||||||
DOMApplicationRegistry.broadcastMessage("Webapps:CheckForUpdate:Return:OK",
|
DOMApplicationRegistry.broadcastMessage("Webapps:CheckForUpdate:Return:OK",
|
||||||
aData);
|
aData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateSvc.checkForUpdate(Services.io.newURI(aData.manifestURL, null, null),
|
debug("updateHostedApp: updateSvc.checkForUpdate for " +
|
||||||
|
manifest.fullAppcachePath());
|
||||||
|
updateSvc.checkForUpdate(Services.io.newURI(manifest.fullAppcachePath(), null, null),
|
||||||
app.localId, false, updateObserver);
|
app.localId, false, updateObserver);
|
||||||
}
|
}
|
||||||
delete app.manifest;
|
delete app.manifest;
|
||||||
@ -1287,7 +1291,9 @@ this.DOMApplicationRegistry = {
|
|||||||
// "downloadapplied".
|
// "downloadapplied".
|
||||||
let updateObserver = {
|
let updateObserver = {
|
||||||
observe: function(aSubject, aTopic, aObsData) {
|
observe: function(aSubject, aTopic, aObsData) {
|
||||||
if (aData.event == "offline-cache-update-available") {
|
debug("onlyCheckAppCache updateSvc.checkForUpdate return for " +
|
||||||
|
app.manifestURL + " - event is " + aTopic);
|
||||||
|
if (aTopic == "offline-cache-update-available") {
|
||||||
aData.event = "downloadavailable";
|
aData.event = "downloadavailable";
|
||||||
app.downloadAvailable = true;
|
app.downloadAvailable = true;
|
||||||
aData.app = app;
|
aData.app = app;
|
||||||
@ -1299,7 +1305,10 @@ this.DOMApplicationRegistry = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateSvc.checkForUpdate(Services.io.newURI(aData.manifestURL, null, null),
|
let helper = new ManifestHelper(manifest);
|
||||||
|
debug("onlyCheckAppCache - launch updateSvc.checkForUpdate for " +
|
||||||
|
helper.fullAppcachePath());
|
||||||
|
updateSvc.checkForUpdate(Services.io.newURI(helper.fullAppcachePath(), null, null),
|
||||||
app.localId, false, updateObserver);
|
app.localId, false, updateObserver);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@ -1312,6 +1321,7 @@ this.DOMApplicationRegistry = {
|
|||||||
xhr.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
xhr.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
||||||
xhr.responseType = "json";
|
xhr.responseType = "json";
|
||||||
if (app.etag) {
|
if (app.etag) {
|
||||||
|
debug("adding manifest etag:" + app.etag);
|
||||||
xhr.setRequestHeader("If-None-Match", app.etag);
|
xhr.setRequestHeader("If-None-Match", app.etag);
|
||||||
}
|
}
|
||||||
xhr.channel.notificationCallbacks =
|
xhr.channel.notificationCallbacks =
|
||||||
@ -1333,6 +1343,7 @@ this.DOMApplicationRegistry = {
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
app.etag = xhr.getResponseHeader("Etag");
|
app.etag = xhr.getResponseHeader("Etag");
|
||||||
|
debug("at update got app etag=" + app.etag);
|
||||||
app.lastCheckedUpdate = Date.now();
|
app.lastCheckedUpdate = Date.now();
|
||||||
if (app.origin.startsWith("app://")) {
|
if (app.origin.startsWith("app://")) {
|
||||||
updatePackagedApp.call(this, manifest);
|
updatePackagedApp.call(this, manifest);
|
||||||
@ -1509,6 +1520,7 @@ this.DOMApplicationRegistry = {
|
|||||||
sendError("INSTALL_FROM_DENIED");
|
sendError("INSTALL_FROM_DENIED");
|
||||||
} else {
|
} else {
|
||||||
app.etag = xhr.getResponseHeader("Etag");
|
app.etag = xhr.getResponseHeader("Etag");
|
||||||
|
debug("at install package got app etag=" + app.etag);
|
||||||
Services.obs.notifyObservers(aMm, "webapps-ask-install",
|
Services.obs.notifyObservers(aMm, "webapps-ask-install",
|
||||||
JSON.stringify(aData));
|
JSON.stringify(aData));
|
||||||
}
|
}
|
||||||
@ -1832,7 +1844,7 @@ this.DOMApplicationRegistry = {
|
|||||||
.QueryInterface(Ci.nsIHttpChannel);
|
.QueryInterface(Ci.nsIHttpChannel);
|
||||||
requestChannel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
requestChannel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
||||||
if (app.packageEtag) {
|
if (app.packageEtag) {
|
||||||
debug('Add If-None-Match header: ' + app.packageEtag);
|
debug("Add If-None-Match header: " + app.packageEtag);
|
||||||
requestChannel.setRequestHeader("If-None-Match", app.packageEtag, false);
|
requestChannel.setRequestHeader("If-None-Match", app.packageEtag, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1293,18 +1293,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
|
|||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleService)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleService)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingStorageEvents)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
|
||||||
|
|
||||||
// Traverse stuff from nsPIDOMWindow
|
// Traverse stuff from nsPIDOMWindow
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedNode)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedNode)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioContexts)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingStorageEvents)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
||||||
@ -1333,20 +1331,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
|||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingStorageEvents)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
|
||||||
|
|
||||||
// Unlink stuff from nsPIDOMWindow
|
// Unlink stuff from nsPIDOMWindow
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedNode)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedNode)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioContexts)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingStorageEvents)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
struct TraceData
|
struct TraceData
|
||||||
|
@ -56,13 +56,20 @@ GlobalPCList.prototype = {
|
|||||||
addPC: function(pc) {
|
addPC: function(pc) {
|
||||||
let winID = pc._winID;
|
let winID = pc._winID;
|
||||||
if (this._list[winID]) {
|
if (this._list[winID]) {
|
||||||
this._list[winID].push(pc);
|
this._list[winID].push(Components.utils.getWeakReference(pc));
|
||||||
} else {
|
} else {
|
||||||
this._list[winID] = [pc];
|
this._list[winID] = [Components.utils.getWeakReference(pc)];
|
||||||
}
|
}
|
||||||
|
this.removeNullRefs(winID);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeNullRefs: function(winID) {
|
||||||
|
this._list[winID] = this._list[winID].filter(
|
||||||
|
function (e,i,a) { return e.get() !== null; });
|
||||||
},
|
},
|
||||||
|
|
||||||
hasActivePeerConnection: function(winID) {
|
hasActivePeerConnection: function(winID) {
|
||||||
|
this.removeNullRefs(winID);
|
||||||
return this._list[winID] ? true : false;
|
return this._list[winID] ? true : false;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -70,10 +77,13 @@ GlobalPCList.prototype = {
|
|||||||
if (topic == "inner-window-destroyed") {
|
if (topic == "inner-window-destroyed") {
|
||||||
let winID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
let winID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||||
if (this._list[winID]) {
|
if (this._list[winID]) {
|
||||||
this._list[winID].forEach(function(pc) {
|
this._list[winID].forEach(function(pcref) {
|
||||||
pc._pc.close(false);
|
let pc = pcref.get();
|
||||||
delete pc._observer;
|
if (pc !== null) {
|
||||||
pc._pc = null;
|
pc._pc.close(false);
|
||||||
|
delete pc._observer;
|
||||||
|
pc._pc = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
delete this._list[winID];
|
delete this._list[winID];
|
||||||
}
|
}
|
||||||
@ -85,10 +95,13 @@ GlobalPCList.prototype = {
|
|||||||
// while offline, but attempts to connect them should fail.
|
// while offline, but attempts to connect them should fail.
|
||||||
let array;
|
let array;
|
||||||
while ((array = this._list.pop()) != undefined) {
|
while ((array = this._list.pop()) != undefined) {
|
||||||
array.forEach(function(pc) {
|
array.forEach(function(pcref) {
|
||||||
pc._pc.close(true);
|
let pc = pcref.get();
|
||||||
delete pc._observer;
|
if (pc !== null) {
|
||||||
pc._pc = null;
|
pc._pc.close(true);
|
||||||
|
delete pc._observer;
|
||||||
|
pc._pc = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
this._networkdown = true;
|
this._networkdown = true;
|
||||||
@ -230,7 +243,9 @@ PeerConnection.prototype = {
|
|||||||
flags: Ci.nsIClassInfo.DOM_OBJECT}),
|
flags: Ci.nsIClassInfo.DOM_OBJECT}),
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([
|
QueryInterface: XPCOMUtils.generateQI([
|
||||||
Ci.nsIDOMRTCPeerConnection, Ci.nsIDOMGlobalObjectConstructor
|
Ci.nsIDOMRTCPeerConnection,
|
||||||
|
Ci.nsIDOMGlobalObjectConstructor,
|
||||||
|
Ci.nsISupportsWeakReference,
|
||||||
]),
|
]),
|
||||||
|
|
||||||
// Constructor is an explicit function, because of nsIDOMGlobalObjectConstructor.
|
// Constructor is an explicit function, because of nsIDOMGlobalObjectConstructor.
|
||||||
@ -546,7 +561,8 @@ function PeerConnectionObserver(dompc) {
|
|||||||
this._dompc = dompc;
|
this._dompc = dompc;
|
||||||
}
|
}
|
||||||
PeerConnectionObserver.prototype = {
|
PeerConnectionObserver.prototype = {
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.IPeerConnectionObserver]),
|
QueryInterface: XPCOMUtils.generateQI([Ci.IPeerConnectionObserver,
|
||||||
|
Ci.nsISupportsWeakReference]),
|
||||||
|
|
||||||
onCreateOfferSuccess: function(offer) {
|
onCreateOfferSuccess: function(offer) {
|
||||||
if (this._dompc._onCreateOfferSuccess) {
|
if (this._dompc._onCreateOfferSuccess) {
|
||||||
|
@ -39,7 +39,7 @@ const kMessages =["SystemMessageManager:GetPendingMessages",
|
|||||||
"child-process-shutdown"]
|
"child-process-shutdown"]
|
||||||
|
|
||||||
function debug(aMsg) {
|
function debug(aMsg) {
|
||||||
//dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n");
|
dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of the component used by internal users.
|
// Implementation of the component used by internal users.
|
||||||
@ -48,6 +48,12 @@ function SystemMessageInternal() {
|
|||||||
// The set of pages registered by installed apps. We keep the
|
// The set of pages registered by installed apps. We keep the
|
||||||
// list of pending messages for each page here also.
|
// list of pending messages for each page here also.
|
||||||
this._pages = [];
|
this._pages = [];
|
||||||
|
|
||||||
|
// The set of listeners. This is a multi-dimensional object. The _listeners
|
||||||
|
// object itself is a map from manifest ID -> an array mapping proccesses to
|
||||||
|
// windows. We do this so that we can track both what processes we have to
|
||||||
|
// send system messages to as well as supporting the single-process case
|
||||||
|
// where we track windows instead.
|
||||||
this._listeners = {};
|
this._listeners = {};
|
||||||
|
|
||||||
this._webappsRegistryReady = false;
|
this._webappsRegistryReady = false;
|
||||||
@ -63,6 +69,16 @@ function SystemMessageInternal() {
|
|||||||
Services.obs.notifyObservers(this, "system-message-internal-ready", null);
|
Services.obs.notifyObservers(this, "system-message-internal-ready", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findTarget(aListeners, aTarget) {
|
||||||
|
for (let i = 0; i < aListeners.length; ++i) {
|
||||||
|
let listener = aListeners[i];
|
||||||
|
if (listener.target === aTarget)
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
SystemMessageInternal.prototype = {
|
SystemMessageInternal.prototype = {
|
||||||
sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI) {
|
sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI) {
|
||||||
// Buffer system messages until the webapps' registration is ready,
|
// Buffer system messages until the webapps' registration is ready,
|
||||||
@ -189,10 +205,19 @@ SystemMessageInternal.prototype = {
|
|||||||
case "SystemMessageManager:Register":
|
case "SystemMessageManager:Register":
|
||||||
{
|
{
|
||||||
debug("Got Register from " + msg.manifest);
|
debug("Got Register from " + msg.manifest);
|
||||||
if (!this._listeners[msg.manifest]) {
|
let targets, target;
|
||||||
this._listeners[msg.manifest] = {};
|
if (!(targets = this._listeners[msg.manifest])) {
|
||||||
|
this._listeners[msg.manifest] =
|
||||||
|
[ { target: aMessage.target, winCount: 1 } ];
|
||||||
|
} else if (!(target = findTarget(targets, aMessage.target))) {
|
||||||
|
targets[msg.manifest].push({
|
||||||
|
target: aMessage.target,
|
||||||
|
winCount: 1
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
target.winCount++;
|
||||||
}
|
}
|
||||||
this._listeners[msg.manifest][msg.innerWindowID] = aMessage.target;
|
|
||||||
debug("listeners for " + msg.manifest + " innerWinID " + msg.innerWindowID);
|
debug("listeners for " + msg.manifest + " innerWinID " + msg.innerWindowID);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -200,11 +225,20 @@ SystemMessageInternal.prototype = {
|
|||||||
{
|
{
|
||||||
debug("Got child-process-shutdown from " + aMessage.target);
|
debug("Got child-process-shutdown from " + aMessage.target);
|
||||||
for (let manifest in this._listeners) {
|
for (let manifest in this._listeners) {
|
||||||
for (let winID in this._listeners[manifest]) {
|
// See if any processes in this manifest have this target.
|
||||||
if (aMessage.target === this._listeners[manifest][winID]) {
|
let targets = this._listeners[manifest];
|
||||||
debug("remove " + manifest );
|
for (let target = 0; target < targets.length; ++target) {
|
||||||
delete this._listeners[manifest];
|
if (targets[target].target === aMessage.target) {
|
||||||
return;
|
// One does: if it's the only one, get rid of this manifest
|
||||||
|
// entirely.
|
||||||
|
if (targets.length === 1) {
|
||||||
|
debug("remove " + manifest );
|
||||||
|
delete this._listeners[manifest];
|
||||||
|
} else {
|
||||||
|
// There are other targets for this manifest, get rid of this
|
||||||
|
// one.
|
||||||
|
targets.splice(target, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,7 +247,22 @@ SystemMessageInternal.prototype = {
|
|||||||
case "SystemMessageManager:Unregister":
|
case "SystemMessageManager:Unregister":
|
||||||
{
|
{
|
||||||
debug("Got Unregister from " + aMessage.target + "innerWinID " + msg.innerWindowID);
|
debug("Got Unregister from " + aMessage.target + "innerWinID " + msg.innerWindowID);
|
||||||
delete this._listeners[msg.manifest][msg.innerWindowID];
|
let targets = this._listeners[msg.manifest];
|
||||||
|
for (let i = 0; i < targets.length; ++i) {
|
||||||
|
if (targets[i].target === aMessage.target) {
|
||||||
|
if (--targets[i].winCount === 0) {
|
||||||
|
if (targets.length === 1) {
|
||||||
|
// Only one listener left, remove the target.
|
||||||
|
delete this._listeners[msg.manifest];
|
||||||
|
} else {
|
||||||
|
// More than one left, remove this one and leave the rest.
|
||||||
|
targets.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
debug("Removing " + aMessage.target + "innerWinID " + msg.innerWindowID );
|
debug("Removing " + aMessage.target + "innerWinID " + msg.innerWindowID );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -391,13 +440,14 @@ SystemMessageInternal.prototype = {
|
|||||||
|
|
||||||
let winTargets = this._listeners[aManifestURI];
|
let winTargets = this._listeners[aManifestURI];
|
||||||
if (winTargets) {
|
if (winTargets) {
|
||||||
for (let winID in winTargets) {
|
for (let target = 0; target < winTargets.length; ++target) {
|
||||||
winTargets[winID].sendAsyncMessage("SystemMessageManager:Message",
|
let manager = winTargets[target].target;
|
||||||
{ type: aType,
|
manager.sendAsyncMessage("SystemMessageManager:Message",
|
||||||
msg: aMessage,
|
{ type: aType,
|
||||||
manifest: aManifestURI,
|
msg: aMessage,
|
||||||
uri: aPageURI,
|
manifest: aManifestURI,
|
||||||
msgID: aMessageID });
|
uri: aPageURI,
|
||||||
|
msgID: aMessageID });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,204 +0,0 @@
|
|||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
|
|
||||||
const Ci = Components.interfaces;
|
|
||||||
const Cc = Components.classes;
|
|
||||||
|
|
||||||
var gLoggingEnabled = false;
|
|
||||||
|
|
||||||
function LOG(aMsg) {
|
|
||||||
if (gLoggingEnabled)
|
|
||||||
{
|
|
||||||
aMsg = ("*** GPSD GEO: " + aMsg);
|
|
||||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(aMsg);
|
|
||||||
dump(aMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function GeoPositionCoordsObject(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed) {
|
|
||||||
|
|
||||||
this.latitude = latitude;
|
|
||||||
this.longitude = longitude;
|
|
||||||
this.altitude = altitude;
|
|
||||||
this.accuracy = accuracy;
|
|
||||||
this.altitudeAccuracy = altitudeAccuracy;
|
|
||||||
this.heading = heading;
|
|
||||||
this.speed = speed;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
GeoPositionCoordsObject.prototype = {
|
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionCoords]),
|
|
||||||
|
|
||||||
// Class Info is required to be able to pass objects back into the DOM.
|
|
||||||
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPositionCoords],
|
|
||||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
|
||||||
classDescription: "Geoposition Coordinate Object"}),
|
|
||||||
|
|
||||||
latitude: null,
|
|
||||||
longitude: null,
|
|
||||||
altitude: null,
|
|
||||||
accuracy: null,
|
|
||||||
altitudeAccuracy: null,
|
|
||||||
heading: null,
|
|
||||||
speed: null,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
function GeoPositionObject(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed, timestamp) {
|
|
||||||
this.coords = new GeoPositionCoordsObject(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed);
|
|
||||||
this.timestamp = timestamp;
|
|
||||||
};
|
|
||||||
|
|
||||||
GeoPositionObject.prototype = {
|
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPosition]),
|
|
||||||
|
|
||||||
// Class Info is required to be able to pass objects back into the DOM.
|
|
||||||
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPosition],
|
|
||||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
|
||||||
classDescription: "Geoposition Object"}),
|
|
||||||
|
|
||||||
coords: null,
|
|
||||||
timestamp: null,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
function GPSDProvider() {
|
|
||||||
this.prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch).QueryInterface(Ci.nsIPrefService);
|
|
||||||
|
|
||||||
try {
|
|
||||||
gLoggingEnabled = this.prefService.getBoolPref("geo.gpsd.logging.enabled");
|
|
||||||
} catch (e) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
GPSDProvider.prototype = {
|
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIGeolocationProvider]),
|
|
||||||
|
|
||||||
classID: Components.ID("{0A3BE523-0F2A-32CC-CCD8-1E5986D5A79D}"),
|
|
||||||
|
|
||||||
prefService: null,
|
|
||||||
|
|
||||||
transport: null,
|
|
||||||
outputStream: null,
|
|
||||||
inputStream: null,
|
|
||||||
|
|
||||||
startup: function() {
|
|
||||||
|
|
||||||
LOG("startup called\n");
|
|
||||||
var socketTransportService = Cc["@mozilla.org/network/socket-transport-service;1"].getService(Ci.nsISocketTransportService);
|
|
||||||
|
|
||||||
var hostIPAddr = "127.0.0.1";
|
|
||||||
var hostPort = "2947";
|
|
||||||
|
|
||||||
try {
|
|
||||||
hostIPAddr = this.prefService.getCharPref("geo.gpsd.host.ipaddr");
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
try {
|
|
||||||
hostPort = this.prefService.getCharPref("geo.gpsd.host.port");
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
LOG("Host info: " + hostIPAddr + ":" + hostPort + "\n");
|
|
||||||
|
|
||||||
this.transport = socketTransportService.createTransport(null, 0, hostIPAddr, hostPort, null);
|
|
||||||
|
|
||||||
// Alright to open streams here as they are non-blocking by default
|
|
||||||
this.outputStream = this.transport.openOutputStream(0,0,0);
|
|
||||||
this.inputStream = this.transport.openInputStream(0,0,0);
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
shutdown: function() {
|
|
||||||
LOG("shutdown called\n");
|
|
||||||
this.outputStream.close();
|
|
||||||
this.inputStream.close();
|
|
||||||
this.transport.close(Components.results.NS_OK);
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: function(c, isPrivate) {
|
|
||||||
LOG("watch called\n");
|
|
||||||
try {
|
|
||||||
// Go into "watcher" mode
|
|
||||||
var mode = '?WATCH={"enable":true,"json":true}';
|
|
||||||
this.outputStream.write(mode, mode.length);
|
|
||||||
} catch (e) { return; }
|
|
||||||
|
|
||||||
var dataListener = {
|
|
||||||
onStartRequest: function(request, context) {},
|
|
||||||
onStopRequest: function(request, context, status) {},
|
|
||||||
onDataAvailable: function(request, context, inputStream, offset, count) {
|
|
||||||
|
|
||||||
var sInputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
|
|
||||||
sInputStream.init(inputStream);
|
|
||||||
|
|
||||||
var responseSentence = sInputStream.read(count);
|
|
||||||
|
|
||||||
var response = null;
|
|
||||||
try {
|
|
||||||
response = JSON.parse(responseSentence);
|
|
||||||
} catch (e) { return; }
|
|
||||||
|
|
||||||
// is the right kind of sentence?
|
|
||||||
if (response.class != 'TPV') {
|
|
||||||
//don't do anything
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is there a fix?
|
|
||||||
if (response.mode == '1') {
|
|
||||||
// don't do anything
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG("Got info: " + responseSentence);
|
|
||||||
|
|
||||||
// The API requires these values, if one is missing
|
|
||||||
// we return without updating the position.
|
|
||||||
if (response.time && response.lat && response.lon
|
|
||||||
&& response.epx && response.epy) {
|
|
||||||
var timestamp = response.time; // UTC
|
|
||||||
var latitude = response.lat; // degrees
|
|
||||||
var longitude = response.lon; // degrees
|
|
||||||
var horizontalError = Math.max(response.epx,response.epy); } // meters
|
|
||||||
else { return; }
|
|
||||||
|
|
||||||
// Altitude is optional, but if it's present, so must be vertical precision.
|
|
||||||
var altitude = null;
|
|
||||||
var verticalError = null;
|
|
||||||
if (response.alt && response.epv) {
|
|
||||||
altitude = response.alt; // meters
|
|
||||||
verticalError = response.epv; // meters
|
|
||||||
}
|
|
||||||
|
|
||||||
var speed = null;
|
|
||||||
if (response.speed) { var speed = response.speed; } // meters/sec
|
|
||||||
|
|
||||||
var course = null;
|
|
||||||
if (response.track) { var course = response.track; } // degrees
|
|
||||||
|
|
||||||
var geoPos = new GeoPositionObject(latitude, longitude, altitude, horizontalError, verticalError, course, speed, timestamp);
|
|
||||||
|
|
||||||
c.update(geoPos);
|
|
||||||
LOG("Position updated:" + timestamp + "," + latitude + "," + longitude + ","
|
|
||||||
+ horizontalError + "," + altitude + "," + verticalError + "," + course
|
|
||||||
+ "," + speed);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var pump = Cc["@mozilla.org/network/input-stream-pump;1"].createInstance(Ci.nsIInputStreamPump);
|
|
||||||
pump.init(this.inputStream, -1, -1, 0, 0, false);
|
|
||||||
pump.asyncRead(dataListener, null);
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([GPSDProvider]);
|
|
@ -1,3 +0,0 @@
|
|||||||
component {0A3BE523-0F2A-32CC-CCD8-1E5986D5A79D} GPSDGeolocationProvider.js
|
|
||||||
contract @mozilla.org/geolocation/gpsd/provider;1 {0A3BE523-0F2A-32CC-CCD8-1E5986D5A79D}
|
|
||||||
category geolocation-provider GPSDProvider @mozilla.org/geolocation/gpsd/provider;1
|
|
@ -55,8 +55,6 @@ ifneq (Android,$(OS_TARGET))
|
|||||||
EXTRA_COMPONENTS = \
|
EXTRA_COMPONENTS = \
|
||||||
NetworkGeolocationProvider.js \
|
NetworkGeolocationProvider.js \
|
||||||
NetworkGeolocationProvider.manifest \
|
NetworkGeolocationProvider.manifest \
|
||||||
GPSDGeolocationProvider.js \
|
|
||||||
GPSDGeolocationProvider.manifest \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -2799,7 +2799,7 @@ DrawTargetD2D::PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID
|
|||||||
D2D1_LAYER_OPTIONS options = D2D1_LAYER_OPTIONS_NONE;
|
D2D1_LAYER_OPTIONS options = D2D1_LAYER_OPTIONS_NONE;
|
||||||
D2D1_LAYER_OPTIONS1 options1 = D2D1_LAYER_OPTIONS1_NONE;
|
D2D1_LAYER_OPTIONS1 options1 = D2D1_LAYER_OPTIONS1_NONE;
|
||||||
|
|
||||||
if (mFormat == FORMAT_B8G8R8X8) {
|
if (aRT->GetPixelFormat().alphaMode == D2D1_ALPHA_MODE_IGNORE) {
|
||||||
options = D2D1_LAYER_OPTIONS_INITIALIZE_FOR_CLEARTYPE;
|
options = D2D1_LAYER_OPTIONS_INITIALIZE_FOR_CLEARTYPE;
|
||||||
options1 = D2D1_LAYER_OPTIONS1_IGNORE_ALPHA | D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
|
options1 = D2D1_LAYER_OPTIONS1_IGNORE_ALPHA | D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ ImageContainer::SetCurrentImage(Image *aImage)
|
|||||||
if (aImage) {
|
if (aImage) {
|
||||||
mImageContainerChild->SendImageAsync(this, aImage);
|
mImageContainerChild->SendImageAsync(this, aImage);
|
||||||
} else {
|
} else {
|
||||||
mImageContainerChild->DispatchSetIdle();
|
mImageContainerChild->SetIdle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,12 +73,33 @@ void ImageContainerChild::SetIdleNow()
|
|||||||
mImageQueue.Clear();
|
mImageQueue.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageContainerChild::DispatchSetIdle()
|
void ImageContainerChild::SetIdleSync(Monitor* aBarrier, bool* aDone)
|
||||||
|
{
|
||||||
|
MonitorAutoLock autoMon(*aBarrier);
|
||||||
|
|
||||||
|
SetIdleNow();
|
||||||
|
*aDone = true;
|
||||||
|
aBarrier->NotifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageContainerChild::SetIdle()
|
||||||
{
|
{
|
||||||
if (mStop) return;
|
if (mStop) return;
|
||||||
|
|
||||||
|
if (InImageBridgeChildThread()) {
|
||||||
|
return SetIdleNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
Monitor barrier("SetIdle Lock");
|
||||||
|
MonitorAutoLock autoMon(barrier);
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
GetMessageLoop()->PostTask(FROM_HERE,
|
GetMessageLoop()->PostTask(FROM_HERE,
|
||||||
NewRunnableMethod(this, &ImageContainerChild::SetIdleNow));
|
NewRunnableMethod(this, &ImageContainerChild::SetIdleSync, &barrier, &done));
|
||||||
|
|
||||||
|
while (!done) {
|
||||||
|
barrier.Wait();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageContainerChild::StopChildAndParent()
|
void ImageContainerChild::StopChildAndParent()
|
||||||
|
@ -106,16 +106,9 @@ public:
|
|||||||
void DispatchDestroy();
|
void DispatchDestroy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatches a task on the ImageBridgeChild's thread that will call SendFlush
|
* Flush and deallocate the shared images in the pool.
|
||||||
* and deallocate the shared images in the pool.
|
|
||||||
* Can be called on any thread.
|
|
||||||
*/
|
*/
|
||||||
void DispatchSetIdle();
|
void SetIdle();
|
||||||
|
|
||||||
/**
|
|
||||||
* Must be called on the ImageBridgeChild's thread.
|
|
||||||
*/
|
|
||||||
void SetIdleNow();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can be called from any thread.
|
* Can be called from any thread.
|
||||||
@ -168,9 +161,21 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Must be called on the ImageBridgeCHild's thread.
|
* Must be called on the ImageBridgeChild's thread.
|
||||||
*/
|
*/
|
||||||
void DestroyNow();
|
void DestroyNow();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches a task on the ImageBridgeChild's thread that will call SendFlush
|
||||||
|
* and deallocate the shared images in the pool.
|
||||||
|
* Can be called on any thread.
|
||||||
|
*/
|
||||||
|
void SetIdleSync(Monitor* aBarrier, bool* aDone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called on the ImageBridgeChild's thread.
|
||||||
|
*/
|
||||||
|
void SetIdleNow();
|
||||||
|
|
||||||
inline void SetID(uint64_t id)
|
inline void SetID(uint64_t id)
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,7 @@ parent:
|
|||||||
|
|
||||||
// Tells the parent side to dispose of its shared images (most likely because the
|
// Tells the parent side to dispose of its shared images (most likely because the
|
||||||
// video element is still alive but will not be displayed for a moment).
|
// video element is still alive but will not be displayed for a moment).
|
||||||
async Flush();
|
sync Flush();
|
||||||
|
|
||||||
// After receiving this message, the ImageContainerParent will not return images
|
// After receiving this message, the ImageContainerParent will not return images
|
||||||
// back to the child side (to avoid a race between ReturnImage and __delete__)
|
// back to the child side (to avoid a race between ReturnImage and __delete__)
|
||||||
|
@ -915,19 +915,20 @@ jsdProperty::GetValue(jsdIValue **_rval)
|
|||||||
NS_IMPL_THREADSAFE_ISUPPORTS2(jsdScript, jsdIScript, jsdIEphemeral)
|
NS_IMPL_THREADSAFE_ISUPPORTS2(jsdScript, jsdIScript, jsdIEphemeral)
|
||||||
|
|
||||||
static NS_IMETHODIMP
|
static NS_IMETHODIMP
|
||||||
AssignToJSString(nsACString *x, JSString *str)
|
AssignToJSString(JSDContext *aCx, nsACString *x, JSString *str)
|
||||||
{
|
{
|
||||||
if (!str) {
|
if (!str) {
|
||||||
x->SetLength(0);
|
x->SetLength(0);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
size_t length = JS_GetStringEncodingLength(NULL, str);
|
JSContext *cx = JSD_GetDefaultJSContext(aCx);
|
||||||
|
size_t length = JS_GetStringEncodingLength(cx, str);
|
||||||
if (length == size_t(-1))
|
if (length == size_t(-1))
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
x->SetLength(uint32_t(length));
|
x->SetLength(uint32_t(length));
|
||||||
if (x->Length() != uint32_t(length))
|
if (x->Length() != uint32_t(length))
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
JS_EncodeStringToBuffer(str, x->BeginWriting(), length);
|
JS_EncodeStringToBuffer(cx, str, x->BeginWriting(), length);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -953,7 +954,7 @@ jsdScript::jsdScript (JSDContext *aCx, JSDScript *aScript) : mValid(false),
|
|||||||
if (mFunctionName) {
|
if (mFunctionName) {
|
||||||
JSString *str = JSD_GetScriptFunctionId(mCx, mScript);
|
JSString *str = JSD_GetScriptFunctionId(mCx, mScript);
|
||||||
if (str)
|
if (str)
|
||||||
AssignToJSString(mFunctionName, str);
|
AssignToJSString(mCx, mFunctionName, str);
|
||||||
}
|
}
|
||||||
mBaseLineNumber = JSD_GetScriptBaseLineNumber(mCx, mScript);
|
mBaseLineNumber = JSD_GetScriptBaseLineNumber(mCx, mScript);
|
||||||
mLineExtent = JSD_GetScriptLineExtent(mCx, mScript);
|
mLineExtent = JSD_GetScriptLineExtent(mCx, mScript);
|
||||||
@ -1908,7 +1909,7 @@ jsdStackFrame::GetFunctionName(nsACString &_rval)
|
|||||||
ASSERT_VALID_EPHEMERAL;
|
ASSERT_VALID_EPHEMERAL;
|
||||||
JSString *str = JSD_GetIdForStackFrame(mCx, mThreadState, mStackFrameInfo);
|
JSString *str = JSD_GetIdForStackFrame(mCx, mThreadState, mStackFrameInfo);
|
||||||
if (str)
|
if (str)
|
||||||
return AssignToJSString(&_rval, str);
|
return AssignToJSString(mCx, &_rval, str);
|
||||||
|
|
||||||
_rval.Assign("anonymous");
|
_rval.Assign("anonymous");
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -2238,7 +2239,7 @@ NS_IMETHODIMP
|
|||||||
jsdValue::GetJsFunctionName(nsACString &_rval)
|
jsdValue::GetJsFunctionName(nsACString &_rval)
|
||||||
{
|
{
|
||||||
ASSERT_VALID_EPHEMERAL;
|
ASSERT_VALID_EPHEMERAL;
|
||||||
return AssignToJSString(&_rval, JSD_GetValueFunctionId(mCx, mValue));
|
return AssignToJSString(mCx, &_rval, JSD_GetValueFunctionId(mCx, mValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
126
js/public/CharacterEncoding.h
Normal file
126
js/public/CharacterEncoding.h
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=8 sw=4 et tw=78:
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef js_CharacterEncoding_h___
|
||||||
|
#define js_CharacterEncoding_h___
|
||||||
|
|
||||||
|
#include "mozilla/Range.h"
|
||||||
|
|
||||||
|
#include "js/Utility.h"
|
||||||
|
|
||||||
|
#include "jspubtd.h"
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default, all C/C++ 1-byte-per-character strings passed into the JSAPI
|
||||||
|
* are treated as ISO/IEC 8859-1, also known as Latin-1. That is, each
|
||||||
|
* byte is treated as a 2-byte character, and there is no way to pass in a
|
||||||
|
* string containing characters beyond U+00FF.
|
||||||
|
*/
|
||||||
|
class Latin1Chars : public mozilla::Range<unsigned char>
|
||||||
|
{
|
||||||
|
typedef mozilla::Range<unsigned char> Base;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Latin1Chars() : Base() {}
|
||||||
|
Latin1Chars(char *bytes, size_t length) : Base(reinterpret_cast<unsigned char *>(bytes), length) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A Latin1Chars, but with \0 termination for C compatibility.
|
||||||
|
*/
|
||||||
|
class Latin1CharsZ : public mozilla::RangedPtr<unsigned char>
|
||||||
|
{
|
||||||
|
typedef mozilla::RangedPtr<unsigned char> Base;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Latin1CharsZ() : Base(NULL, 0) {}
|
||||||
|
|
||||||
|
Latin1CharsZ(char *bytes, size_t length)
|
||||||
|
: Base(reinterpret_cast<unsigned char *>(bytes), length)
|
||||||
|
{
|
||||||
|
JS_ASSERT(bytes[length] == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
Latin1CharsZ(unsigned char *bytes, size_t length)
|
||||||
|
: Base(bytes, length)
|
||||||
|
{
|
||||||
|
JS_ASSERT(bytes[length] == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
char *c_str() { return reinterpret_cast<char *>(get()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SpiderMonkey also deals directly with UTF-8 encoded text in some places.
|
||||||
|
*/
|
||||||
|
class UTF8CharsZ : public mozilla::RangedPtr<unsigned char>
|
||||||
|
{
|
||||||
|
typedef mozilla::RangedPtr<unsigned char> Base;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UTF8CharsZ() : Base(NULL, 0) {}
|
||||||
|
|
||||||
|
UTF8CharsZ(char *bytes, size_t length)
|
||||||
|
: Base(reinterpret_cast<unsigned char *>(bytes), length)
|
||||||
|
{
|
||||||
|
JS_ASSERT(bytes[length] == '\0');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SpiderMonkey uses a 2-byte character representation: it is a
|
||||||
|
* 2-byte-at-a-time view of a UTF-16 byte stream. This is similar to UCS-2,
|
||||||
|
* but unlike UCS-2, we do not strip UTF-16 extension bytes. This allows a
|
||||||
|
* sufficiently dedicated JavaScript program to be fully unicode-aware by
|
||||||
|
* manually interpreting UTF-16 extension characters embedded in the JS
|
||||||
|
* string.
|
||||||
|
*/
|
||||||
|
class TwoByteChars : public mozilla::Range<jschar>
|
||||||
|
{
|
||||||
|
typedef mozilla::Range<jschar> Base;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TwoByteChars() : Base() {}
|
||||||
|
TwoByteChars(jschar *chars, size_t length) : Base(chars, length) {}
|
||||||
|
TwoByteChars(const jschar *chars, size_t length) : Base(const_cast<jschar *>(chars), length) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A TwoByteChars, but \0 terminated for compatibility with JSFlatString.
|
||||||
|
*/
|
||||||
|
class TwoByteCharsZ : public mozilla::RangedPtr<jschar>
|
||||||
|
{
|
||||||
|
typedef mozilla::RangedPtr<jschar> Base;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TwoByteCharsZ(jschar *chars, size_t length)
|
||||||
|
: Base(chars, length)
|
||||||
|
{
|
||||||
|
JS_ASSERT(chars[length] = '\0');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a 2-byte character sequence to "ISO-Latin-1". This works by
|
||||||
|
* truncating each 2-byte pair in the sequence to a 1-byte pair. If the source
|
||||||
|
* contains any UTF-16 extension characters, then this may give invalid Latin1
|
||||||
|
* output. The returned string is zero terminated. The returned string or the
|
||||||
|
* returned string's |start()| must be freed with JS_free or js_free,
|
||||||
|
* respectively. If allocation fails, an OOM error will be set and the method
|
||||||
|
* will return a NULL chars (which can be tested for with the ! operator).
|
||||||
|
* This method cannot trigger GC.
|
||||||
|
*/
|
||||||
|
extern Latin1CharsZ
|
||||||
|
LossyTwoByteCharsToNewLatin1CharsZ(JSContext *cx, TwoByteChars tbchars);
|
||||||
|
|
||||||
|
} // namespace JS
|
||||||
|
|
||||||
|
inline void JS_free(JS::Latin1CharsZ &ptr) { js_free((void*)ptr.get()); }
|
||||||
|
|
||||||
|
#endif // js_CharacterEncoding_h___
|
@ -127,6 +127,7 @@ CPPSRCS = \
|
|||||||
String.cpp \
|
String.cpp \
|
||||||
BytecodeCompiler.cpp \
|
BytecodeCompiler.cpp \
|
||||||
BytecodeEmitter.cpp \
|
BytecodeEmitter.cpp \
|
||||||
|
CharacterEncoding.cpp \
|
||||||
FoldConstants.cpp \
|
FoldConstants.cpp \
|
||||||
Intl.cpp \
|
Intl.cpp \
|
||||||
NameFunctions.cpp \
|
NameFunctions.cpp \
|
||||||
@ -216,6 +217,7 @@ EXPORTS_NAMESPACES += js
|
|||||||
# that we ensure we don't over-expose our internal integer typedefs. Note that
|
# that we ensure we don't over-expose our internal integer typedefs. Note that
|
||||||
# LegacyIntTypes.h below is deliberately exempted from this requirement.
|
# LegacyIntTypes.h below is deliberately exempted from this requirement.
|
||||||
EXPORTS_js = \
|
EXPORTS_js = \
|
||||||
|
CharacterEncoding.h \
|
||||||
HashTable.h \
|
HashTable.h \
|
||||||
HeapAPI.h \
|
HeapAPI.h \
|
||||||
LegacyIntTypes.h \
|
LegacyIntTypes.h \
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
import sys, re, os, posixpath, ntpath
|
import sys, re, os, posixpath, ntpath
|
||||||
|
import errno
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
# Standalone js doesn't have virtualenv.
|
# Standalone js doesn't have virtualenv.
|
||||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'config'))
|
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'config'))
|
||||||
|
@ -159,7 +159,7 @@ obj_toSource(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
int valcnt = 0;
|
int valcnt = 0;
|
||||||
if (shape) {
|
if (shape) {
|
||||||
bool doGet = true;
|
bool doGet = true;
|
||||||
if (obj2->isNative() && !IsImplicitProperty(shape)) {
|
if (obj2->isNative() && !IsImplicitDenseElement(shape)) {
|
||||||
unsigned attrs = shape->attributes();
|
unsigned attrs = shape->attributes();
|
||||||
if (attrs & JSPROP_GETTER) {
|
if (attrs & JSPROP_GETTER) {
|
||||||
doGet = false;
|
doGet = false;
|
||||||
@ -456,7 +456,7 @@ obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
args.rval().setUndefined();
|
args.rval().setUndefined();
|
||||||
if (shape) {
|
if (shape) {
|
||||||
if (pobj->isNative() && !IsImplicitProperty(shape)) {
|
if (pobj->isNative() && !IsImplicitDenseElement(shape)) {
|
||||||
if (shape->hasGetterValue())
|
if (shape->hasGetterValue())
|
||||||
args.rval().set(shape->getterValue());
|
args.rval().set(shape->getterValue());
|
||||||
}
|
}
|
||||||
@ -492,7 +492,7 @@ obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
args.rval().setUndefined();
|
args.rval().setUndefined();
|
||||||
if (shape) {
|
if (shape) {
|
||||||
if (pobj->isNative() && !IsImplicitProperty(shape)) {
|
if (pobj->isNative() && !IsImplicitDenseElement(shape)) {
|
||||||
if (shape->hasSetterValue())
|
if (shape->hasSetterValue())
|
||||||
args.rval().set(shape->setterValue());
|
args.rval().set(shape->setterValue());
|
||||||
}
|
}
|
||||||
|
@ -1747,7 +1747,7 @@ ParallelArrayObject::lookupElement(JSContext *cx, HandleObject obj, uint32_t ind
|
|||||||
{
|
{
|
||||||
// No prototype walking for elements.
|
// No prototype walking for elements.
|
||||||
if (index < as(obj)->outermostDimension()) {
|
if (index < as(obj)->outermostDimension()) {
|
||||||
MarkImplicitPropertyFound(propp);
|
MarkNonNativePropertyFound(propp);
|
||||||
objp.set(obj);
|
objp.set(obj);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ js::CreateRegExpMatchResult(JSContext *cx, HandleString string, MatchPairs &matc
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegExpRunStatus
|
RegExpRunStatus
|
||||||
ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re, RegExpObject ®exp,
|
ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re,
|
||||||
JSLinearString *input, StableCharPtr chars, size_t length,
|
JSLinearString *input, StableCharPtr chars, size_t length,
|
||||||
size_t *lastIndex, MatchConduit &matches)
|
size_t *lastIndex, MatchConduit &matches)
|
||||||
{
|
{
|
||||||
@ -126,7 +126,7 @@ ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re, RegExpObj
|
|||||||
/* Only one MatchPair slot provided: execute short-circuiting regexp. */
|
/* Only one MatchPair slot provided: execute short-circuiting regexp. */
|
||||||
status = re.executeMatchOnly(cx, chars, length, lastIndex, *matches.u.pair);
|
status = re.executeMatchOnly(cx, chars, length, lastIndex, *matches.u.pair);
|
||||||
if (status == RegExpRunStatus_Success && res)
|
if (status == RegExpRunStatus_Success && res)
|
||||||
res->updateLazily(cx, input, ®exp, lastIndex_orig);
|
res->updateLazily(cx, input, &re, lastIndex_orig);
|
||||||
} else {
|
} else {
|
||||||
/* Vector of MatchPairs provided: execute full regexp. */
|
/* Vector of MatchPairs provided: execute full regexp. */
|
||||||
status = re.execute(cx, chars, length, lastIndex, *matches.u.pairs);
|
status = re.execute(cx, chars, length, lastIndex, *matches.u.pairs);
|
||||||
@ -151,7 +151,7 @@ js::ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
|
|||||||
MatchConduit conduit(&matches);
|
MatchConduit conduit(&matches);
|
||||||
|
|
||||||
RegExpRunStatus status =
|
RegExpRunStatus status =
|
||||||
ExecuteRegExpImpl(cx, res, *shared, reobj, input, chars, length, lastIndex, conduit);
|
ExecuteRegExpImpl(cx, res, *shared, input, chars, length, lastIndex, conduit);
|
||||||
|
|
||||||
if (status == RegExpRunStatus_Error)
|
if (status == RegExpRunStatus_Error)
|
||||||
return false;
|
return false;
|
||||||
@ -580,7 +580,7 @@ js::ExecuteRegExp(JSContext *cx, HandleObject regexp, HandleString string, Match
|
|||||||
/* Steps 8-21. */
|
/* Steps 8-21. */
|
||||||
size_t lastIndexInt(i);
|
size_t lastIndexInt(i);
|
||||||
RegExpRunStatus status =
|
RegExpRunStatus status =
|
||||||
ExecuteRegExpImpl(cx, res, *re, *reobj, stableInput, chars, length, &lastIndexInt, matches);
|
ExecuteRegExpImpl(cx, res, *re, stableInput, chars, length, &lastIndexInt, matches);
|
||||||
|
|
||||||
if (status == RegExpRunStatus_Error)
|
if (status == RegExpRunStatus_Error)
|
||||||
return RegExpRunStatus_Error;
|
return RegExpRunStatus_Error;
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include "frontend/Parser.h"
|
#include "frontend/Parser.h"
|
||||||
#include "frontend/TokenStream.h"
|
#include "frontend/TokenStream.h"
|
||||||
|
#include "js/CharacterEncoding.h"
|
||||||
#include "vm/Keywords.h"
|
#include "vm/Keywords.h"
|
||||||
#include "vm/RegExpObject.h"
|
#include "vm/RegExpObject.h"
|
||||||
#include "vm/StringBuffer.h"
|
#include "vm/StringBuffer.h"
|
||||||
@ -564,7 +565,8 @@ TokenStream::reportCompileErrorNumberVA(ParseNode *pn, unsigned flags, unsigned
|
|||||||
err.report.uclinebuf = windowBuf.extractWellSized();
|
err.report.uclinebuf = windowBuf.extractWellSized();
|
||||||
if (!err.report.uclinebuf)
|
if (!err.report.uclinebuf)
|
||||||
return false;
|
return false;
|
||||||
err.report.linebuf = DeflateString(cx, err.report.uclinebuf, windowLength);
|
TwoByteChars tbchars(err.report.uclinebuf, windowLength);
|
||||||
|
err.report.linebuf = LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||||
if (!err.report.linebuf)
|
if (!err.report.linebuf)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -728,7 +730,8 @@ TokenStream::getXMLEntity()
|
|||||||
bad:
|
bad:
|
||||||
/* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */
|
/* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */
|
||||||
JS_ASSERT((tb.end() - bp) >= 1);
|
JS_ASSERT((tb.end() - bp) >= 1);
|
||||||
bytes = DeflateString(cx, bp + 1, (tb.end() - bp) - 1);
|
TwoByteChars tbchars(bp + 1, (tb.end() - bp) - 1);
|
||||||
|
bytes = LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||||
if (bytes) {
|
if (bytes) {
|
||||||
reportError(msg, bytes);
|
reportError(msg, bytes);
|
||||||
js_free(bytes);
|
js_free(bytes);
|
||||||
|
@ -339,7 +339,6 @@ DeclMarkerImpl(Object, DebugScopeObject)
|
|||||||
DeclMarkerImpl(Object, GlobalObject)
|
DeclMarkerImpl(Object, GlobalObject)
|
||||||
DeclMarkerImpl(Object, JSObject)
|
DeclMarkerImpl(Object, JSObject)
|
||||||
DeclMarkerImpl(Object, JSFunction)
|
DeclMarkerImpl(Object, JSFunction)
|
||||||
DeclMarkerImpl(Object, RegExpObject)
|
|
||||||
DeclMarkerImpl(Object, ScopeObject)
|
DeclMarkerImpl(Object, ScopeObject)
|
||||||
DeclMarkerImpl(Script, JSScript)
|
DeclMarkerImpl(Script, JSScript)
|
||||||
DeclMarkerImpl(Shape, Shape)
|
DeclMarkerImpl(Shape, Shape)
|
||||||
|
@ -97,7 +97,6 @@ DeclMarker(Object, DebugScopeObject)
|
|||||||
DeclMarker(Object, GlobalObject)
|
DeclMarker(Object, GlobalObject)
|
||||||
DeclMarker(Object, JSObject)
|
DeclMarker(Object, JSObject)
|
||||||
DeclMarker(Object, JSFunction)
|
DeclMarker(Object, JSFunction)
|
||||||
DeclMarker(Object, RegExpObject)
|
|
||||||
DeclMarker(Object, ScopeObject)
|
DeclMarker(Object, ScopeObject)
|
||||||
DeclMarker(Script, JSScript)
|
DeclMarker(Script, JSScript)
|
||||||
DeclMarker(Shape, Shape)
|
DeclMarker(Shape, Shape)
|
||||||
|
@ -562,10 +562,8 @@ AutoGCRooter::trace(JSTracer *trc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case REGEXPSTATICS: {
|
case REGEXPSTATICS: {
|
||||||
/*
|
|
||||||
RegExpStatics::AutoRooter *rooter = static_cast<RegExpStatics::AutoRooter *>(this);
|
RegExpStatics::AutoRooter *rooter = static_cast<RegExpStatics::AutoRooter *>(this);
|
||||||
rooter->trace(trc);
|
rooter->trace(trc);
|
||||||
*/
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,15 +644,14 @@ Shape::Range::AutoRooter::trace(JSTracer *trc)
|
|||||||
void
|
void
|
||||||
RegExpStatics::AutoRooter::trace(JSTracer *trc)
|
RegExpStatics::AutoRooter::trace(JSTracer *trc)
|
||||||
{
|
{
|
||||||
if (statics->regexp)
|
|
||||||
MarkObjectRoot(trc, reinterpret_cast<JSObject**>(&statics->regexp),
|
|
||||||
"RegExpStatics::AutoRooter regexp");
|
|
||||||
if (statics->matchesInput)
|
if (statics->matchesInput)
|
||||||
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->matchesInput),
|
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->matchesInput),
|
||||||
"RegExpStatics::AutoRooter matchesInput");
|
"RegExpStatics::AutoRooter matchesInput");
|
||||||
if (statics->pendingInput)
|
if (statics->pendingInput)
|
||||||
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->pendingInput),
|
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->pendingInput),
|
||||||
"RegExpStatics::AutoRooter pendingInput");
|
"RegExpStatics::AutoRooter pendingInput");
|
||||||
|
if (statics->regexp.initialized())
|
||||||
|
statics->regexp->trace(trc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1435,6 +1435,9 @@ IsPropertySetterCallInlineable(JSContext *cx, HandleObject obj, HandleObject hol
|
|||||||
if (!shape)
|
if (!shape)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!holder->isNative())
|
||||||
|
return false;
|
||||||
|
|
||||||
if (shape->hasSlot())
|
if (shape->hasSlot())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
5
js/src/jit-test/tests/basic/bug820124-1.js
Normal file
5
js/src/jit-test/tests/basic/bug820124-1.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Don't assert.
|
||||||
|
verifyprebarriers();
|
||||||
|
r = /()()()\3/.test();
|
||||||
|
gc();
|
||||||
|
RegExp().test();
|
3
js/src/jit-test/tests/basic/bug820124-2.js
Normal file
3
js/src/jit-test/tests/basic/bug820124-2.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Don't assert.
|
||||||
|
'123456'.replace(/1(\d+)3/, '');
|
||||||
|
RegExp.lastMatch.toString();
|
8
js/src/jit-test/tests/basic/bug820124-3.js
Normal file
8
js/src/jit-test/tests/basic/bug820124-3.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Don't assert.
|
||||||
|
eval("\
|
||||||
|
x = RegExp(\"()\", \"y\");\
|
||||||
|
x.test();\
|
||||||
|
x = {};\
|
||||||
|
")
|
||||||
|
gc()
|
||||||
|
RegExp.$6
|
8
js/src/jit-test/tests/basic/bug820124-4.js
Normal file
8
js/src/jit-test/tests/basic/bug820124-4.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Don't assert.
|
||||||
|
eval("\
|
||||||
|
r = RegExp(\"(?!()(((!))))\", \"g\");\
|
||||||
|
\"^\".replace(r, '');\
|
||||||
|
r = (\"1+\")\
|
||||||
|
")
|
||||||
|
gc()
|
||||||
|
RegExp.$8
|
7
js/src/jit-test/tests/basic/bug829795.js
Normal file
7
js/src/jit-test/tests/basic/bug829795.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// |jit-test| error: TypeError
|
||||||
|
|
||||||
|
try {
|
||||||
|
x = [];
|
||||||
|
Array.prototype.forEach()
|
||||||
|
} catch (e) {}
|
||||||
|
x.forEach()
|
10
js/src/jit-test/tests/basic/bug830049.js
Normal file
10
js/src/jit-test/tests/basic/bug830049.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// |jit-test| error: InternalError
|
||||||
|
|
||||||
|
p = Proxy.create({
|
||||||
|
has: function() function r() s += ''
|
||||||
|
})
|
||||||
|
Object.prototype.__proto__ = p
|
||||||
|
function TestCase(n) {
|
||||||
|
this.name = n
|
||||||
|
}
|
||||||
|
new TestCase()
|
@ -68,6 +68,7 @@ CPPSRCS = \
|
|||||||
testStringBuffer.cpp \
|
testStringBuffer.cpp \
|
||||||
testTrap.cpp \
|
testTrap.cpp \
|
||||||
testTypedArrays.cpp \
|
testTypedArrays.cpp \
|
||||||
|
testUTF8.cpp \
|
||||||
testVersion.cpp \
|
testVersion.cpp \
|
||||||
testXDR.cpp \
|
testXDR.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
46
js/src/jsapi-tests/testUTF8.cpp
Normal file
46
js/src/jsapi-tests/testUTF8.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=8 sw=4 et tw=99:
|
||||||
|
*/
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "tests.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jsstr.h"
|
||||||
|
#include "js/CharacterEncoding.h"
|
||||||
|
|
||||||
|
BEGIN_TEST(testUTF8_badUTF8)
|
||||||
|
{
|
||||||
|
static const char badUTF8[] = "...\xC0...";
|
||||||
|
JSString *str = JS_NewStringCopyZ(cx, badUTF8);
|
||||||
|
CHECK(str);
|
||||||
|
const jschar *chars = JS_GetStringCharsZ(cx, str);
|
||||||
|
CHECK(chars);
|
||||||
|
CHECK(chars[3] == 0x00C0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
END_TEST(testUTF8_badUTF8)
|
||||||
|
|
||||||
|
BEGIN_TEST(testUTF8_bigUTF8)
|
||||||
|
{
|
||||||
|
static const char bigUTF8[] = "...\xFB\xBF\xBF\xBF\xBF...";
|
||||||
|
JSString *str = JS_NewStringCopyZ(cx, bigUTF8);
|
||||||
|
CHECK(str);
|
||||||
|
const jschar *chars = JS_GetStringCharsZ(cx, str);
|
||||||
|
CHECK(chars);
|
||||||
|
CHECK(chars[3] == 0x00FB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
END_TEST(testUTF8_bigUTF8)
|
||||||
|
|
||||||
|
BEGIN_TEST(testUTF8_badSurrogate)
|
||||||
|
{
|
||||||
|
static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
|
||||||
|
JS::TwoByteChars tbchars(badSurrogate, js_strlen(badSurrogate));
|
||||||
|
JS::Latin1CharsZ latin1 = JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars);
|
||||||
|
CHECK(latin1);
|
||||||
|
CHECK(latin1[3] == 0x00EE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
END_TEST(testUTF8_badSurrogate)
|
@ -64,6 +64,7 @@
|
|||||||
#include "frontend/BytecodeCompiler.h"
|
#include "frontend/BytecodeCompiler.h"
|
||||||
#include "gc/Marking.h"
|
#include "gc/Marking.h"
|
||||||
#include "gc/Memory.h"
|
#include "gc/Memory.h"
|
||||||
|
#include "js/CharacterEncoding.h"
|
||||||
#include "js/MemoryMetrics.h"
|
#include "js/MemoryMetrics.h"
|
||||||
#include "vm/Debugger.h"
|
#include "vm/Debugger.h"
|
||||||
#include "vm/NumericConversions.h"
|
#include "vm/NumericConversions.h"
|
||||||
@ -3572,7 +3573,7 @@ LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, jsid id,
|
|||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsImplicitProperty(shape)) {
|
if (!obj2->isNative()) {
|
||||||
if (obj2->isProxy()) {
|
if (obj2->isProxy()) {
|
||||||
AutoPropertyDescriptorRooter desc(cx);
|
AutoPropertyDescriptorRooter desc(cx);
|
||||||
if (!Proxy::getPropertyDescriptor(cx, obj2, id, &desc, 0))
|
if (!Proxy::getPropertyDescriptor(cx, obj2, id, &desc, 0))
|
||||||
@ -3581,10 +3582,10 @@ LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, jsid id,
|
|||||||
*vp = desc.value;
|
*vp = desc.value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (obj2->isNative()) {
|
|
||||||
*vp = obj2->getDenseElement(JSID_TO_INT(id));
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
} else if (IsImplicitDenseElement(shape)) {
|
||||||
|
*vp = obj2->getDenseElement(JSID_TO_INT(id));
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
/* Peek at the native property's slot value, without doing a Get. */
|
/* Peek at the native property's slot value, without doing a Get. */
|
||||||
if (shape->hasSlot()) {
|
if (shape->hasSlot()) {
|
||||||
@ -4062,7 +4063,7 @@ GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned
|
|||||||
|
|
||||||
desc->obj = obj2;
|
desc->obj = obj2;
|
||||||
if (obj2->isNative()) {
|
if (obj2->isNative()) {
|
||||||
if (IsImplicitProperty(shape)) {
|
if (IsImplicitDenseElement(shape)) {
|
||||||
desc->attrs = JSPROP_ENUMERATE;
|
desc->attrs = JSPROP_ENUMERATE;
|
||||||
desc->getter = NULL;
|
desc->getter = NULL;
|
||||||
desc->setter = NULL;
|
desc->setter = NULL;
|
||||||
@ -6231,27 +6232,24 @@ JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_
|
|||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(char *)
|
JS_PUBLIC_API(char *)
|
||||||
JS_EncodeString(JSContext *cx, JSRawString strArg)
|
JS_EncodeString(JSContext *cx, JSRawString str)
|
||||||
{
|
{
|
||||||
RootedString str(cx, strArg);
|
AutoAssertNoGC nogc;
|
||||||
|
|
||||||
AssertHeapIsIdle(cx);
|
AssertHeapIsIdle(cx);
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
|
|
||||||
const jschar *chars = str->getChars(cx);
|
JSLinearString *linear = str->ensureLinear(cx);
|
||||||
if (!chars)
|
if (!linear)
|
||||||
return NULL;
|
return NULL;
|
||||||
return DeflateString(cx, chars, str->length());
|
|
||||||
|
return LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(size_t)
|
JS_PUBLIC_API(size_t)
|
||||||
JS_GetStringEncodingLength(JSContext *cx, JSString *str)
|
JS_GetStringEncodingLength(JSContext *cx, JSString *str)
|
||||||
{
|
{
|
||||||
/* jsd calls us with a NULL cx. Ugh. */
|
AssertHeapIsIdle(cx);
|
||||||
if (cx) {
|
CHECK_REQUEST(cx);
|
||||||
AssertHeapIsIdle(cx);
|
|
||||||
CHECK_REQUEST(cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
const jschar *chars = str->getChars(cx);
|
const jschar *chars = str->getChars(cx);
|
||||||
if (!chars)
|
if (!chars)
|
||||||
@ -6260,8 +6258,11 @@ JS_GetStringEncodingLength(JSContext *cx, JSString *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(size_t)
|
JS_PUBLIC_API(size_t)
|
||||||
JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length)
|
JS_EncodeStringToBuffer(JSContext *cx, JSString *str, char *buffer, size_t length)
|
||||||
{
|
{
|
||||||
|
AssertHeapIsIdle(cx);
|
||||||
|
CHECK_REQUEST(cx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
|
* FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
|
||||||
* would allow to distinguish between insufficient buffer and encoding
|
* would allow to distinguish between insufficient buffer and encoding
|
||||||
|
@ -5554,7 +5554,7 @@ JS_GetStringEncodingLength(JSContext *cx, JSString *str);
|
|||||||
* written into the buffer.
|
* written into the buffer.
|
||||||
*/
|
*/
|
||||||
JS_PUBLIC_API(size_t)
|
JS_PUBLIC_API(size_t)
|
||||||
JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length);
|
JS_EncodeStringToBuffer(JSContext *cx, JSString *str, char *buffer, size_t length);
|
||||||
|
|
||||||
class JSAutoByteString
|
class JSAutoByteString
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
# include <string>
|
# include <string>
|
||||||
#endif // ANDROID
|
#endif // ANDROID
|
||||||
|
|
||||||
|
#include "mozilla/Util.h"
|
||||||
|
|
||||||
#include "jstypes.h"
|
#include "jstypes.h"
|
||||||
#include "jsutil.h"
|
#include "jsutil.h"
|
||||||
#include "jsclist.h"
|
#include "jsclist.h"
|
||||||
@ -55,6 +57,7 @@
|
|||||||
# include "methodjit/MethodJIT.h"
|
# include "methodjit/MethodJIT.h"
|
||||||
#endif
|
#endif
|
||||||
#include "gc/Marking.h"
|
#include "gc/Marking.h"
|
||||||
|
#include "js/CharacterEncoding.h"
|
||||||
#include "js/MemoryMetrics.h"
|
#include "js/MemoryMetrics.h"
|
||||||
#include "frontend/TokenStream.h"
|
#include "frontend/TokenStream.h"
|
||||||
#include "frontend/ParseMaps.h"
|
#include "frontend/ParseMaps.h"
|
||||||
@ -69,6 +72,7 @@ using namespace js;
|
|||||||
using namespace js::gc;
|
using namespace js::gc;
|
||||||
|
|
||||||
using mozilla::DebugOnly;
|
using mozilla::DebugOnly;
|
||||||
|
using mozilla::PointerRangeSize;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
js::AutoCycleDetector::init()
|
js::AutoCycleDetector::init()
|
||||||
@ -832,8 +836,10 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
|
|||||||
JS_ASSERT(expandedArgs == argCount);
|
JS_ASSERT(expandedArgs == argCount);
|
||||||
*out = 0;
|
*out = 0;
|
||||||
js_free(buffer);
|
js_free(buffer);
|
||||||
*messagep = DeflateString(cx, reportp->ucmessage,
|
TwoByteChars ucmsg(reportp->ucmessage,
|
||||||
size_t(out - reportp->ucmessage));
|
PointerRangeSize(static_cast<const jschar *>(reportp->ucmessage),
|
||||||
|
static_cast<const jschar *>(out)));
|
||||||
|
*messagep = LossyTwoByteCharsToNewLatin1CharsZ(cx, ucmsg).c_str();
|
||||||
if (!*messagep)
|
if (!*messagep)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -291,13 +291,13 @@ MakeTypeId(JSContext *cx, jsid id)
|
|||||||
*/
|
*/
|
||||||
if (JSID_IS_STRING(id)) {
|
if (JSID_IS_STRING(id)) {
|
||||||
JSFlatString *str = JSID_TO_FLAT_STRING(id);
|
JSFlatString *str = JSID_TO_FLAT_STRING(id);
|
||||||
const jschar *cp = str->getCharsZ(cx);
|
TwoByteChars cp = str->range();
|
||||||
if (JS7_ISDEC(*cp) || *cp == '-') {
|
if (JS7_ISDEC(cp[0]) || cp[0] == '-') {
|
||||||
cp++;
|
for (size_t i = 1; i < cp.length(); ++i) {
|
||||||
while (JS7_ISDEC(*cp))
|
if (!JS7_ISDEC(cp[i]))
|
||||||
cp++;
|
return id;
|
||||||
if (*cp == 0)
|
}
|
||||||
return JSID_VOID;
|
return JSID_VOID;
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -1103,7 +1103,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p
|
|||||||
if (prop) {
|
if (prop) {
|
||||||
unsigned attrs;
|
unsigned attrs;
|
||||||
if (obj2->isNative())
|
if (obj2->isNative())
|
||||||
attrs = IsImplicitProperty(prop) ? JSPROP_ENUMERATE : prop->attributes();
|
attrs = GetShapeAttributes(prop);
|
||||||
else if (!JSObject::getGenericAttributes(cx, obj2, id, &attrs))
|
else if (!JSObject::getGenericAttributes(cx, obj2, id, &attrs))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -631,7 +631,7 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD
|
|||||||
shapeHasGetterValue = false,
|
shapeHasGetterValue = false,
|
||||||
shapeHasSetterValue = false;
|
shapeHasSetterValue = false;
|
||||||
uint8_t shapeAttributes = JSPROP_ENUMERATE;
|
uint8_t shapeAttributes = JSPROP_ENUMERATE;
|
||||||
if (!IsImplicitProperty(shape)) {
|
if (!IsImplicitDenseElement(shape)) {
|
||||||
shapeDataDescriptor = shape->isDataDescriptor();
|
shapeDataDescriptor = shape->isDataDescriptor();
|
||||||
shapeAccessorDescriptor = shape->isAccessorDescriptor();
|
shapeAccessorDescriptor = shape->isAccessorDescriptor();
|
||||||
shapeWritable = shape->writable();
|
shapeWritable = shape->writable();
|
||||||
@ -672,7 +672,7 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD
|
|||||||
* avoid calling a getter; we won't need the value if it's not a
|
* avoid calling a getter; we won't need the value if it's not a
|
||||||
* data descriptor.
|
* data descriptor.
|
||||||
*/
|
*/
|
||||||
if (IsImplicitProperty(shape)) {
|
if (IsImplicitDenseElement(shape)) {
|
||||||
v = obj->getDenseElement(JSID_TO_INT(id));
|
v = obj->getDenseElement(JSID_TO_INT(id));
|
||||||
} else if (shape->isDataDescriptor()) {
|
} else if (shape->isDataDescriptor()) {
|
||||||
/*
|
/*
|
||||||
@ -814,8 +814,8 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD
|
|||||||
changed |= JSPROP_ENUMERATE;
|
changed |= JSPROP_ENUMERATE;
|
||||||
|
|
||||||
attrs = (shapeAttributes & ~changed) | (desc.attributes() & changed);
|
attrs = (shapeAttributes & ~changed) | (desc.attributes() & changed);
|
||||||
getter = IsImplicitProperty(shape) ? JS_PropertyStub : shape->getter();
|
getter = IsImplicitDenseElement(shape) ? JS_PropertyStub : shape->getter();
|
||||||
setter = IsImplicitProperty(shape) ? JS_StrictPropertyStub : shape->setter();
|
setter = IsImplicitDenseElement(shape) ? JS_StrictPropertyStub : shape->setter();
|
||||||
} else if (desc.isDataDescriptor()) {
|
} else if (desc.isDataDescriptor()) {
|
||||||
unsigned unchanged = 0;
|
unsigned unchanged = 0;
|
||||||
if (!desc.hasConfigurable())
|
if (!desc.hasConfigurable())
|
||||||
@ -3064,7 +3064,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal
|
|||||||
if (!baseops::LookupProperty(cx, obj, id, &pobj, &shape))
|
if (!baseops::LookupProperty(cx, obj, id, &pobj, &shape))
|
||||||
return false;
|
return false;
|
||||||
if (shape && pobj == obj) {
|
if (shape && pobj == obj) {
|
||||||
if (IsImplicitProperty(shape)) {
|
if (IsImplicitDenseElement(shape)) {
|
||||||
if (!JSObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
|
if (!JSObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
|
||||||
return false;
|
return false;
|
||||||
shape = obj->nativeLookup(cx, id);
|
shape = obj->nativeLookup(cx, id);
|
||||||
@ -3237,7 +3237,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (JSID_IS_INT(id) && objp->containsDenseElement(JSID_TO_INT(id))) {
|
if (JSID_IS_INT(id) && objp->containsDenseElement(JSID_TO_INT(id))) {
|
||||||
MarkImplicitPropertyFound(propp);
|
MarkDenseElementFound(propp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3263,7 +3263,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi
|
|||||||
{
|
{
|
||||||
if (JSID_IS_INT(id) && current->containsDenseElement(JSID_TO_INT(id))) {
|
if (JSID_IS_INT(id) && current->containsDenseElement(JSID_TO_INT(id))) {
|
||||||
objp.set(current);
|
objp.set(current);
|
||||||
MarkImplicitPropertyFound(propp);
|
MarkDenseElementFound(propp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3549,7 +3549,7 @@ js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receive
|
|||||||
: JSObject::getGeneric(cx, obj2, obj2, id, vp);
|
: JSObject::getGeneric(cx, obj2, obj2, id, vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsImplicitProperty(shape)) {
|
if (IsImplicitDenseElement(shape)) {
|
||||||
vp.set(obj2->getDenseElement(JSID_TO_INT(id)));
|
vp.set(obj2->getDenseElement(JSID_TO_INT(id)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3804,7 +3804,7 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive
|
|||||||
getter = clasp->getProperty;
|
getter = clasp->getProperty;
|
||||||
setter = clasp->setProperty;
|
setter = clasp->setProperty;
|
||||||
|
|
||||||
if (IsImplicitProperty(shape)) {
|
if (IsImplicitDenseElement(shape)) {
|
||||||
/* ES5 8.12.4 [[Put]] step 2, for a dense data property on pobj. */
|
/* ES5 8.12.4 [[Put]] step 2, for a dense data property on pobj. */
|
||||||
if (pobj != obj)
|
if (pobj != obj)
|
||||||
shape = NULL;
|
shape = NULL;
|
||||||
@ -3877,7 +3877,7 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsImplicitProperty(shape)) {
|
if (IsImplicitDenseElement(shape)) {
|
||||||
JSObject::setDenseElementWithType(cx, obj, JSID_TO_INT(id), vp);
|
JSObject::setDenseElementWithType(cx, obj, JSID_TO_INT(id), vp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -4006,7 +4006,7 @@ baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a
|
|||||||
return false;
|
return false;
|
||||||
if (!shape)
|
if (!shape)
|
||||||
return true;
|
return true;
|
||||||
if (nobj->isNative() && IsImplicitProperty(shape)) {
|
if (nobj->isNative() && IsImplicitDenseElement(shape)) {
|
||||||
if (!JSObject::sparsifyDenseElement(cx, nobj, JSID_TO_INT(id)))
|
if (!JSObject::sparsifyDenseElement(cx, nobj, JSID_TO_INT(id)))
|
||||||
return false;
|
return false;
|
||||||
shape = obj->nativeLookup(cx, id);
|
shape = obj->nativeLookup(cx, id);
|
||||||
@ -4025,7 +4025,7 @@ baseops::SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, u
|
|||||||
return false;
|
return false;
|
||||||
if (!shape)
|
if (!shape)
|
||||||
return true;
|
return true;
|
||||||
if (nobj->isNative() && IsImplicitProperty(shape)) {
|
if (nobj->isNative() && IsImplicitDenseElement(shape)) {
|
||||||
if (!JSObject::sparsifyDenseElement(cx, obj, index))
|
if (!JSObject::sparsifyDenseElement(cx, obj, index))
|
||||||
return false;
|
return false;
|
||||||
shape = obj->nativeLookup(cx, INT_TO_JSID(index));
|
shape = obj->nativeLookup(cx, INT_TO_JSID(index));
|
||||||
@ -4054,7 +4054,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHand
|
|||||||
|
|
||||||
GCPoke(cx->runtime);
|
GCPoke(cx->runtime);
|
||||||
|
|
||||||
if (IsImplicitProperty(shape)) {
|
if (IsImplicitDenseElement(shape)) {
|
||||||
if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, id, rval))
|
if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, id, rval))
|
||||||
return false;
|
return false;
|
||||||
if (rval.isFalse())
|
if (rval.isFalse())
|
||||||
@ -4295,7 +4295,7 @@ js::CheckAccess(JSContext *cx, JSObject *obj_, HandleId id, JSAccessMode mode,
|
|||||||
*attrsp = GetShapeAttributes(shape);
|
*attrsp = GetShapeAttributes(shape);
|
||||||
|
|
||||||
if (!writing) {
|
if (!writing) {
|
||||||
if (IsImplicitProperty(shape)) {
|
if (IsImplicitDenseElement(shape)) {
|
||||||
vp.set(pobj->getDenseElement(JSID_TO_INT(id)));
|
vp.set(pobj->getDenseElement(JSID_TO_INT(id)));
|
||||||
} else {
|
} else {
|
||||||
if (shape->hasSlot())
|
if (shape->hasSlot())
|
||||||
|
@ -38,9 +38,9 @@
|
|||||||
#include "jsstr.h"
|
#include "jsstr.h"
|
||||||
|
|
||||||
#include "ds/Sort.h"
|
#include "ds/Sort.h"
|
||||||
|
|
||||||
#include "frontend/BytecodeEmitter.h"
|
#include "frontend/BytecodeEmitter.h"
|
||||||
#include "frontend/TokenStream.h"
|
#include "frontend/TokenStream.h"
|
||||||
|
#include "js/CharacterEncoding.h"
|
||||||
#include "vm/Debugger.h"
|
#include "vm/Debugger.h"
|
||||||
#include "vm/StringBuffer.h"
|
#include "vm/StringBuffer.h"
|
||||||
|
|
||||||
@ -6262,10 +6262,11 @@ js::DecompileValueGenerator(JSContext *cx, int spindex, HandleValue v,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rooted<JSStableString *> stable(cx, fallback->ensureStable(cx));
|
Rooted<JSLinearString *> linear(cx, fallback->ensureLinear(cx));
|
||||||
if (!stable)
|
if (!linear)
|
||||||
return NULL;
|
return NULL;
|
||||||
return DeflateString(cx, stable->chars().get(), stable->length());
|
TwoByteChars tbchars(linear->chars(), linear->length());
|
||||||
|
return LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -6352,10 +6353,10 @@ js::DecompileArgument(JSContext *cx, int formalIndex, HandleValue v)
|
|||||||
if (!fallback)
|
if (!fallback)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Rooted<JSStableString *> stable(cx, fallback->ensureStable(cx));
|
Rooted<JSLinearString *> linear(cx, fallback->ensureLinear(cx));
|
||||||
if (!stable)
|
if (!linear)
|
||||||
return NULL;
|
return NULL;
|
||||||
return DeflateString(cx, stable->chars().get(), stable->length());
|
return LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#include "jspubtd.h"
|
#include "jspubtd.h"
|
||||||
#include "jsstr.h"
|
#include "jsstr.h"
|
||||||
|
|
||||||
|
#include "js/CharacterEncoding.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -360,8 +362,8 @@ static int cvt_s(SprintfState *ss, const char *s, int width, int prec,
|
|||||||
return fill2(ss, s ? s : "(null)", slen, width, flags);
|
return fill2(ss, s ? s : "(null)", slen, width, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec,
|
static int
|
||||||
int flags)
|
cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec, int flags)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
/*
|
/*
|
||||||
@ -369,12 +371,15 @@ static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec,
|
|||||||
* and malloc() is used to allocate the buffer buffer.
|
* and malloc() is used to allocate the buffer buffer.
|
||||||
*/
|
*/
|
||||||
if (ws) {
|
if (ws) {
|
||||||
int slen = js_strlen(ws);
|
size_t wslen = js_strlen(ws);
|
||||||
char *s = DeflateString(NULL, ws, slen);
|
char *latin1 = js_pod_malloc<char>(wslen + 1);
|
||||||
if (!s)
|
if (!latin1)
|
||||||
return -1; /* JSStuffFunc error indicator. */
|
return -1; /* JSStuffFunc error indicator. */
|
||||||
result = cvt_s(ss, s, width, prec, flags);
|
for (size_t i = 0; i < wslen; ++i)
|
||||||
js_free(s);
|
latin1[i] = (char)ws[i];
|
||||||
|
latin1[wslen] = '\0';
|
||||||
|
result = cvt_s(ss, latin1, width, prec, flags);
|
||||||
|
js_free(latin1);
|
||||||
} else {
|
} else {
|
||||||
result = cvt_s(ss, NULL, width, prec, flags);
|
result = cvt_s(ss, NULL, width, prec, flags);
|
||||||
}
|
}
|
||||||
|
@ -2551,7 +2551,7 @@ proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
MarkImplicitPropertyFound(propp);
|
MarkNonNativePropertyFound(propp);
|
||||||
objp.set(obj);
|
objp.set(obj);
|
||||||
} else {
|
} else {
|
||||||
objp.set(NULL);
|
objp.set(NULL);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "frontend/Parser.h"
|
#include "frontend/Parser.h"
|
||||||
#include "frontend/TokenStream.h"
|
#include "frontend/TokenStream.h"
|
||||||
|
#include "js/CharacterEncoding.h"
|
||||||
#include "vm/RegExpObject.h"
|
#include "vm/RegExpObject.h"
|
||||||
|
|
||||||
#include "jsscriptinlines.h"
|
#include "jsscriptinlines.h"
|
||||||
@ -3442,7 +3443,8 @@ reflect_parse(JSContext *cx, uint32_t argc, jsval *vp)
|
|||||||
if (!chars)
|
if (!chars)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
filename = DeflateString(cx, chars, length);
|
TwoByteChars tbchars(chars, length);
|
||||||
|
filename = LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||||
if (!filename)
|
if (!filename)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -496,17 +496,25 @@ BaseShape::markChildren(JSTracer *trc)
|
|||||||
/*
|
/*
|
||||||
* Property lookup hooks on objects are required to return a non-NULL shape to
|
* Property lookup hooks on objects are required to return a non-NULL shape to
|
||||||
* signify that the property has been found. For cases where the property is
|
* signify that the property has been found. For cases where the property is
|
||||||
* not actually represented by a Shape (dense elements, properties of
|
* not actually represented by a Shape, use a dummy value. This includes all
|
||||||
* non-native objects), use a dummy value.
|
* properties of non-native objects, and dense elements for native objects.
|
||||||
|
* Use separate APIs for these two cases.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
MarkImplicitPropertyFound(MutableHandleShape propp)
|
MarkNonNativePropertyFound(MutableHandleShape propp)
|
||||||
|
{
|
||||||
|
propp.set(reinterpret_cast<Shape*>(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
MarkDenseElementFound(MutableHandleShape propp)
|
||||||
{
|
{
|
||||||
propp.set(reinterpret_cast<Shape*>(1));
|
propp.set(reinterpret_cast<Shape*>(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
IsImplicitProperty(HandleShape prop)
|
IsImplicitDenseElement(HandleShape prop)
|
||||||
{
|
{
|
||||||
return prop.get() == reinterpret_cast<Shape*>(1);
|
return prop.get() == reinterpret_cast<Shape*>(1);
|
||||||
}
|
}
|
||||||
@ -514,7 +522,7 @@ IsImplicitProperty(HandleShape prop)
|
|||||||
static inline uint8_t
|
static inline uint8_t
|
||||||
GetShapeAttributes(HandleShape shape)
|
GetShapeAttributes(HandleShape shape)
|
||||||
{
|
{
|
||||||
return IsImplicitProperty(shape) ? JSPROP_ENUMERATE : shape->attributes();
|
return IsImplicitDenseElement(shape) ? JSPROP_ENUMERATE : shape->attributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
135
js/src/jsstr.cpp
135
js/src/jsstr.cpp
@ -2342,6 +2342,116 @@ BuildDollarReplacement(JSContext *cx, JSString *textstrArg, JSLinearString *reps
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StringRange
|
||||||
|
{
|
||||||
|
size_t start;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
StringRange(size_t s, size_t l)
|
||||||
|
: start(s), length(l)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static JSString *
|
||||||
|
AppendSubstrings(JSContext *cx, Handle<JSStableString*> stableStr,
|
||||||
|
const StringRange *ranges, size_t rangesLen)
|
||||||
|
{
|
||||||
|
JS_ASSERT(rangesLen);
|
||||||
|
|
||||||
|
/* For single substrings, construct a dependent string. */
|
||||||
|
if (rangesLen == 1)
|
||||||
|
return js_NewDependentString(cx, stableStr, ranges[0].start, ranges[0].length);
|
||||||
|
|
||||||
|
/* Collect substrings into a rope. */
|
||||||
|
RopeBuilder rope(cx);
|
||||||
|
for (size_t i = 0; i < rangesLen; i++) {
|
||||||
|
const StringRange &sr = ranges[i];
|
||||||
|
|
||||||
|
RootedString substr(cx, js_NewDependentString(cx, stableStr, sr.start, sr.length));
|
||||||
|
if (!substr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Appending to the rope permanently roots the substring. */
|
||||||
|
rope.append(substr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rope.result();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
str_replace_regexp_remove(JSContext *cx, CallArgs args, HandleString str, RegExpShared &re)
|
||||||
|
{
|
||||||
|
Rooted<JSStableString*> stableStr(cx, str->ensureStable(cx));
|
||||||
|
if (!stableStr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Vector<StringRange, 16, SystemAllocPolicy> ranges;
|
||||||
|
|
||||||
|
StableCharPtr chars = stableStr->chars();
|
||||||
|
size_t charsLen = stableStr->length();
|
||||||
|
|
||||||
|
MatchPair match;
|
||||||
|
size_t startIndex = 0; /* Index used for iterating through the string. */
|
||||||
|
size_t lastIndex = 0; /* Index after last successful match. */
|
||||||
|
size_t lazyIndex = 0; /* Index before last successful match. */
|
||||||
|
|
||||||
|
/* Accumulate StringRanges for unmatched substrings. */
|
||||||
|
while (startIndex <= charsLen) {
|
||||||
|
if (!JS_CHECK_OPERATION_LIMIT(cx))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RegExpRunStatus status = re.executeMatchOnly(cx, chars, charsLen, &startIndex, match);
|
||||||
|
if (status == RegExpRunStatus_Error)
|
||||||
|
return false;
|
||||||
|
if (status == RegExpRunStatus_Success_NotFound)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Include the latest unmatched substring. */
|
||||||
|
if (size_t(match.start) > lastIndex) {
|
||||||
|
if (!ranges.append(StringRange(lastIndex, match.start - lastIndex)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lazyIndex = lastIndex;
|
||||||
|
lastIndex = startIndex;
|
||||||
|
|
||||||
|
/* Non-global removal executes at most once. */
|
||||||
|
if (!re.global())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (match.isEmpty())
|
||||||
|
startIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If unmatched, return the input string. */
|
||||||
|
if (!lastIndex) {
|
||||||
|
args.rval().setString(str);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The last successful match updates the RegExpStatics. */
|
||||||
|
cx->regExpStatics()->updateLazily(cx, stableStr, &re, lazyIndex);
|
||||||
|
|
||||||
|
/* Include any remaining part of the string. */
|
||||||
|
if (lastIndex < charsLen) {
|
||||||
|
if (!ranges.append(StringRange(lastIndex, charsLen - lastIndex)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the empty string before calling .begin(). */
|
||||||
|
if (ranges.empty()) {
|
||||||
|
args.rval().setString(cx->runtime->emptyString);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSString *result = AppendSubstrings(cx, stableStr, ranges.begin(), ranges.length());
|
||||||
|
if (!result)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
args.rval().setString(result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
str_replace_regexp(JSContext *cx, CallArgs args, ReplaceData &rdata)
|
str_replace_regexp(JSContext *cx, CallArgs args, ReplaceData &rdata)
|
||||||
{
|
{
|
||||||
@ -2354,6 +2464,12 @@ str_replace_regexp(JSContext *cx, CallArgs args, ReplaceData &rdata)
|
|||||||
RegExpStatics *res = cx->regExpStatics();
|
RegExpStatics *res = cx->regExpStatics();
|
||||||
RegExpShared &re = rdata.g.regExp();
|
RegExpShared &re = rdata.g.regExp();
|
||||||
|
|
||||||
|
/* Optimize removal. */
|
||||||
|
if (rdata.repstr && rdata.repstr->length() == 0 && !rdata.dollar) {
|
||||||
|
JS_ASSERT(!rdata.lambda && !rdata.elembase);
|
||||||
|
return str_replace_regexp_remove(cx, args, rdata.str, re);
|
||||||
|
}
|
||||||
|
|
||||||
Value tmp;
|
Value tmp;
|
||||||
if (!DoMatch(cx, res, rdata.str, re, ReplaceRegExpCallback, &rdata, REPLACE_ARGS, &tmp))
|
if (!DoMatch(cx, res, rdata.str, re, ReplaceRegExpCallback, &rdata, REPLACE_ARGS, &tmp))
|
||||||
return false;
|
return false;
|
||||||
@ -3726,25 +3842,6 @@ js::InflateUTF8String(JSContext *cx, const char *bytes, size_t *lengthp)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* May be called with null cx.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
js::DeflateString(JSContext *maybecx, const jschar *chars, size_t nchars)
|
|
||||||
{
|
|
||||||
AutoAssertNoGC nogc;
|
|
||||||
size_t nbytes = nchars;
|
|
||||||
char *bytes = maybecx
|
|
||||||
? maybecx->pod_malloc<char>(nbytes + 1)
|
|
||||||
: js_pod_malloc<char>(nbytes + 1);
|
|
||||||
if (!bytes)
|
|
||||||
return NULL;
|
|
||||||
for (size_t i = 0; i < nbytes; i++)
|
|
||||||
bytes[i] = (char) chars[i];
|
|
||||||
bytes[nbytes] = 0;
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
js::GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t nchars)
|
js::GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t nchars)
|
||||||
{
|
{
|
||||||
|
@ -224,9 +224,6 @@ InflateString(JSContext *cx, const char *bytes, size_t *length);
|
|||||||
extern jschar *
|
extern jschar *
|
||||||
InflateUTF8String(JSContext *cx, const char *bytes, size_t *length);
|
InflateUTF8String(JSContext *cx, const char *bytes, size_t *length);
|
||||||
|
|
||||||
extern char *
|
|
||||||
DeflateString(JSContext *cx, const jschar *chars, size_t length);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inflate bytes to JS chars in an existing buffer. 'chars' must be large
|
* Inflate bytes to JS chars in an existing buffer. 'chars' must be large
|
||||||
* enough for 'length' jschars. The buffer is NOT null-terminated.
|
* enough for 'length' jschars. The buffer is NOT null-terminated.
|
||||||
|
@ -1015,7 +1015,7 @@ TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject tarray, HandleId id,
|
|||||||
JS_ASSERT(tarray->isTypedArray());
|
JS_ASSERT(tarray->isTypedArray());
|
||||||
|
|
||||||
if (isArrayIndex(tarray, id)) {
|
if (isArrayIndex(tarray, id)) {
|
||||||
MarkImplicitPropertyFound(propp);
|
MarkNonNativePropertyFound(propp);
|
||||||
objp.set(tarray);
|
objp.set(tarray);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1045,7 +1045,7 @@ TypedArray::obj_lookupElement(JSContext *cx, HandleObject tarray, uint32_t index
|
|||||||
JS_ASSERT(tarray->isTypedArray());
|
JS_ASSERT(tarray->isTypedArray());
|
||||||
|
|
||||||
if (index < length(tarray)) {
|
if (index < length(tarray)) {
|
||||||
MarkImplicitPropertyFound(propp);
|
MarkNonNativePropertyFound(propp);
|
||||||
objp.set(tarray);
|
objp.set(tarray);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -5086,6 +5086,7 @@ mjit::Compiler::jsop_getprop(HandlePropertyName name, JSValueType knownType,
|
|||||||
* must fit in an int32_t.
|
* must fit in an int32_t.
|
||||||
*/
|
*/
|
||||||
if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY)) {
|
if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY)) {
|
||||||
|
frame.forgetMismatchedObject(top);
|
||||||
bool isObject = top->isTypeKnown();
|
bool isObject = top->isTypeKnown();
|
||||||
if (!isObject) {
|
if (!isObject) {
|
||||||
Jump notObject = frame.testObject(Assembler::NotEqual, top);
|
Jump notObject = frame.testObject(Assembler::NotEqual, top);
|
||||||
@ -7593,6 +7594,7 @@ mjit::Compiler::jsop_in()
|
|||||||
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
|
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
|
||||||
!types::ArrayPrototypeHasIndexedProperty(cx, outerScript))
|
!types::ArrayPrototypeHasIndexedProperty(cx, outerScript))
|
||||||
{
|
{
|
||||||
|
frame.forgetMismatchedObject(obj);
|
||||||
bool isPacked = !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
|
bool isPacked = !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
|
||||||
|
|
||||||
if (!obj->isTypeKnown()) {
|
if (!obj->isTypeKnown()) {
|
||||||
|
@ -605,6 +605,9 @@ CompileStatus
|
|||||||
mjit::Compiler::compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *argTypes,
|
mjit::Compiler::compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *argTypes,
|
||||||
FrameEntry *thisValue, FrameEntry *argValue)
|
FrameEntry *thisValue, FrameEntry *argValue)
|
||||||
{
|
{
|
||||||
|
frame.forgetMismatchedObject(thisValue);
|
||||||
|
frame.forgetMismatchedObject(argValue);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Require the 'this' types to have a specific type matching the current
|
* Require the 'this' types to have a specific type matching the current
|
||||||
* global, so we can create the result object inline.
|
* global, so we can create the result object inline.
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include "jsinterpinlines.h"
|
#include "jsinterpinlines.h"
|
||||||
#include "jsautooplen.h"
|
#include "jsautooplen.h"
|
||||||
|
|
||||||
|
#include "js/CharacterEncoding.h"
|
||||||
|
|
||||||
#include "vm/ScopeObject-inl.h"
|
#include "vm/ScopeObject-inl.h"
|
||||||
#include "vm/StringObject-inl.h"
|
#include "vm/StringObject-inl.h"
|
||||||
|
|
||||||
@ -2409,12 +2411,12 @@ GetElementIC::attachGetProp(VMFrame &f, HandleObject obj, HandleValue v, HandleP
|
|||||||
|
|
||||||
CodeLocationLabel cs = buffer.finalize(f);
|
CodeLocationLabel cs = buffer.finalize(f);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
char *chars = DeflateString(cx, v.toString()->getChars(cx), v.toString()->length());
|
Latin1CharsZ latin1 = LossyTwoByteCharsToNewLatin1CharsZ(cx, v.toString()->ensureLinear(cx)->range());
|
||||||
JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom %p (\"%s\") shape %p (%s: %d)\n",
|
JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom %p (\"%s\") shape %p (%s: %d)\n",
|
||||||
js_CodeName[JSOp(*f.pc())], cs.executableAddress(), (void*)name, chars,
|
js_CodeName[JSOp(*f.pc())], cs.executableAddress(), (void*)name, latin1.get(),
|
||||||
(void*)holder->lastProperty(), cx->fp()->script()->filename,
|
(void*)holder->lastProperty(), cx->fp()->script()->filename,
|
||||||
CurrentLine(cx));
|
CurrentLine(cx));
|
||||||
js_free(chars);
|
JS_free(latin1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Update the inline guards, if needed.
|
// Update the inline guards, if needed.
|
||||||
|
@ -2440,47 +2440,6 @@ ToInt32(JSContext *cx, unsigned argc, jsval *vp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* badUTF8 = "...\xC0...";
|
|
||||||
static const char* bigUTF8 = "...\xFB\xBF\xBF\xBF\xBF...";
|
|
||||||
static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
TestUTF8(JSContext *cx, unsigned argc, jsval *vp)
|
|
||||||
{
|
|
||||||
int32_t mode = 1;
|
|
||||||
jschar chars[20];
|
|
||||||
size_t charsLength = 5;
|
|
||||||
char bytes[20];
|
|
||||||
size_t bytesLength = 20;
|
|
||||||
if (argc && !JS_ValueToInt32(cx, *JS_ARGV(cx, vp), &mode))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* The following throw errors if compiled with UTF-8. */
|
|
||||||
switch (mode) {
|
|
||||||
/* mode 1: malformed UTF-8 string. */
|
|
||||||
case 1:
|
|
||||||
JS_NewStringCopyZ(cx, badUTF8);
|
|
||||||
break;
|
|
||||||
/* mode 2: big UTF-8 character. */
|
|
||||||
case 2:
|
|
||||||
JS_NewStringCopyZ(cx, bigUTF8);
|
|
||||||
break;
|
|
||||||
/* mode 3: bad surrogate character. */
|
|
||||||
case 3:
|
|
||||||
DeflateStringToBuffer(cx, badSurrogate, 6, bytes, &bytesLength);
|
|
||||||
break;
|
|
||||||
/* mode 4: use a too small buffer. */
|
|
||||||
case 4:
|
|
||||||
JS_DecodeBytes(cx, "1234567890", 10, chars, &charsLength);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
JS_ReportError(cx, "invalid mode parameter");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
|
||||||
return !JS_IsExceptionPending (cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
ThrowError(JSContext *cx, unsigned argc, jsval *vp)
|
ThrowError(JSContext *cx, unsigned argc, jsval *vp)
|
||||||
{
|
{
|
||||||
@ -3740,10 +3699,6 @@ static JSFunctionSpecWithHelp shell_functions[] = {
|
|||||||
"pc2line(fun[, pc])",
|
"pc2line(fun[, pc])",
|
||||||
" Map PC to line number."),
|
" Map PC to line number."),
|
||||||
|
|
||||||
JS_FN_HELP("testUTF8", TestUTF8, 1, 0,
|
|
||||||
"testUTF8(mode)",
|
|
||||||
" Perform UTF-8 tests (modes are 1 to 4)."),
|
|
||||||
|
|
||||||
JS_FN_HELP("throwError", ThrowError, 0, 0,
|
JS_FN_HELP("throwError", ThrowError, 0, 0,
|
||||||
"throwError()",
|
"throwError()",
|
||||||
" Throw an error from JS_ReportError."),
|
" Throw an error from JS_ReportError."),
|
||||||
|
@ -1,122 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
var BUGNUMBER = 232182;
|
|
||||||
var summary = 'Display non-ascii characters in JS exceptions';
|
|
||||||
var actual = '';
|
|
||||||
var expect = 'no error';
|
|
||||||
|
|
||||||
printBugNumber(BUGNUMBER);
|
|
||||||
printStatus (summary);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This test accesses an undefined Unicode symbol. If the code has not been
|
|
||||||
* compiled with JS_C_STRINGS_ARE_UTF8, the thrown error truncates Unicode
|
|
||||||
* characters to bytes. Accessing \u0440\u0441, therefore, results in a
|
|
||||||
* message talking about an undefined variable 'AB' (\x41\x42).
|
|
||||||
*/
|
|
||||||
var utf8Enabled = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
\u0441\u0442;
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{
|
|
||||||
utf8Enabled = (e.message.charAt (0) == '\u0441');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the tests only if UTF-8 is enabled
|
|
||||||
|
|
||||||
printStatus('UTF-8 is ' + (utf8Enabled?'':'not ') + 'enabled');
|
|
||||||
|
|
||||||
if (!utf8Enabled)
|
|
||||||
{
|
|
||||||
reportCompare('Not run', 'Not run', 'utf8 is not enabled');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
status = summary + ': Throw Error with Unicode message';
|
|
||||||
expect = 'test \u0440\u0441';
|
|
||||||
try
|
|
||||||
{
|
|
||||||
throw Error (expect);
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{
|
|
||||||
actual = e.message;
|
|
||||||
}
|
|
||||||
reportCompare(expect, actual, status);
|
|
||||||
|
|
||||||
var inShell = (typeof stringsAreUTF8 == "function");
|
|
||||||
if (!inShell)
|
|
||||||
{
|
|
||||||
inShell = (typeof stringsAreUtf8 == "function");
|
|
||||||
if (inShell)
|
|
||||||
{
|
|
||||||
this.stringsAreUTF8 = stringsAreUtf8;
|
|
||||||
this.testUTF8 = testUtf8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inShell && stringsAreUTF8())
|
|
||||||
{
|
|
||||||
status = summary + ': UTF-8 test: bad UTF-08 sequence';
|
|
||||||
expect = 'Error';
|
|
||||||
actual = 'No error!';
|
|
||||||
try
|
|
||||||
{
|
|
||||||
testUTF8(1);
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{
|
|
||||||
actual = 'Error';
|
|
||||||
}
|
|
||||||
reportCompare(expect, actual, status);
|
|
||||||
|
|
||||||
status = summary + ': UTF-8 character too big to fit into Unicode surrogate pairs';
|
|
||||||
expect = 'Error';
|
|
||||||
actual = 'No error!';
|
|
||||||
try
|
|
||||||
{
|
|
||||||
testUTF8(2);
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{
|
|
||||||
actual = 'Error';
|
|
||||||
}
|
|
||||||
reportCompare(expect, actual, status);
|
|
||||||
|
|
||||||
status = summary + ': bad Unicode surrogate character';
|
|
||||||
expect = 'Error';
|
|
||||||
actual = 'No error!';
|
|
||||||
try
|
|
||||||
{
|
|
||||||
testUTF8(3);
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{
|
|
||||||
actual = 'Error';
|
|
||||||
}
|
|
||||||
reportCompare(expect, actual, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inShell)
|
|
||||||
{
|
|
||||||
status = summary + ': conversion target buffer overrun';
|
|
||||||
expect = 'Error';
|
|
||||||
actual = 'No error!';
|
|
||||||
try
|
|
||||||
{
|
|
||||||
testUTF8(4);
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{
|
|
||||||
actual = 'Error';
|
|
||||||
}
|
|
||||||
reportCompare(expect, actual, status);
|
|
||||||
}
|
|
||||||
}
|
|
28
js/src/vm/CharacterEncoding.cpp
Normal file
28
js/src/vm/CharacterEncoding.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=8 sw=4 et tw=78:
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "jscntxt.h"
|
||||||
|
|
||||||
|
#include "js/CharacterEncoding.h"
|
||||||
|
|
||||||
|
using namespace JS;
|
||||||
|
|
||||||
|
Latin1CharsZ
|
||||||
|
JS::LossyTwoByteCharsToNewLatin1CharsZ(JSContext *cx, TwoByteChars tbchars)
|
||||||
|
{
|
||||||
|
AutoAssertNoGC nogc;
|
||||||
|
JS_ASSERT(cx);
|
||||||
|
size_t len = tbchars.length();
|
||||||
|
unsigned char *latin1 = cx->pod_malloc<unsigned char>(len + 1);
|
||||||
|
if (!latin1)
|
||||||
|
return Latin1CharsZ();
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
latin1[i] = static_cast<unsigned char>(tbchars[i]);
|
||||||
|
latin1[len] = '\0';
|
||||||
|
return Latin1CharsZ(latin1, len);
|
||||||
|
}
|
||||||
|
|
@ -405,12 +405,6 @@ RegExpShared::~RegExpShared()
|
|||||||
js_delete<BytecodePattern>(bytecode);
|
js_delete<BytecodePattern>(bytecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
RegExpShared::trace(JSTracer *trc)
|
|
||||||
{
|
|
||||||
MarkStringUnbarriered(trc, &source, "regexpshared source");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RegExpShared::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
|
RegExpShared::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
|
||||||
{
|
{
|
||||||
@ -651,6 +645,18 @@ RegExpCompartment::RegExpCompartment(JSRuntime *rt)
|
|||||||
RegExpCompartment::~RegExpCompartment()
|
RegExpCompartment::~RegExpCompartment()
|
||||||
{
|
{
|
||||||
JS_ASSERT(map_.empty());
|
JS_ASSERT(map_.empty());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RegExpStatics may have prevented a single RegExpShared from
|
||||||
|
* being collected during RegExpCompartment::sweep().
|
||||||
|
*/
|
||||||
|
if (!inUse_.empty()) {
|
||||||
|
PendingSet::Enum e(inUse_);
|
||||||
|
RegExpShared *shared = e.front();
|
||||||
|
JS_ASSERT(shared->activeUseCount == 0);
|
||||||
|
js_delete(shared);
|
||||||
|
e.removeFront();
|
||||||
|
}
|
||||||
JS_ASSERT(inUse_.empty());
|
JS_ASSERT(inUse_.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include "jscntxt.h"
|
#include "jscntxt.h"
|
||||||
#include "jsobj.h"
|
#include "jsobj.h"
|
||||||
|
|
||||||
|
#include "gc/Barrier.h"
|
||||||
|
#include "gc/Marking.h"
|
||||||
#include "js/TemplateLib.h"
|
#include "js/TemplateLib.h"
|
||||||
#include "vm/MatchPairs.h"
|
#include "vm/MatchPairs.h"
|
||||||
|
|
||||||
@ -120,11 +122,12 @@ class RegExpShared
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Source to the RegExp. The RegExpShared must either be protected by a
|
* Source to the RegExp, for lazy compilation.
|
||||||
* RegExpGuard, which handles rooting for stacky RegExpShareds,
|
* The source must be rooted while activeUseCount is non-zero
|
||||||
* or trace() must be explicitly called during marking.
|
* via RegExpGuard, RegExpHeapGuard, or explicit calls to trace().
|
||||||
*/
|
*/
|
||||||
JSAtom * source;
|
JSAtom * source;
|
||||||
|
|
||||||
RegExpFlag flags;
|
RegExpFlag flags;
|
||||||
unsigned parenCount;
|
unsigned parenCount;
|
||||||
|
|
||||||
@ -149,7 +152,10 @@ class RegExpShared
|
|||||||
RegExpShared(JSRuntime *rt, JSAtom *source, RegExpFlag flags);
|
RegExpShared(JSRuntime *rt, JSAtom *source, RegExpFlag flags);
|
||||||
~RegExpShared();
|
~RegExpShared();
|
||||||
|
|
||||||
void trace(JSTracer *trc);
|
/* Explicit trace function for use by the RegExpStatics and JITs. */
|
||||||
|
void trace(JSTracer *trc) {
|
||||||
|
MarkStringUnbarriered(trc, &source, "regexpshared source");
|
||||||
|
}
|
||||||
|
|
||||||
/* Static functions to expose some Yarr logic. */
|
/* Static functions to expose some Yarr logic. */
|
||||||
static inline bool isJITRuntimeEnabled(JSContext *cx);
|
static inline bool isJITRuntimeEnabled(JSContext *cx);
|
||||||
@ -222,17 +228,58 @@ class RegExpGuard
|
|||||||
re_->incRef();
|
re_->incRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
~RegExpGuard() {
|
~RegExpGuard() { release(); }
|
||||||
if (re_)
|
|
||||||
re_->decRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init(RegExpShared &re) {
|
void init(RegExpShared &re) {
|
||||||
JS_ASSERT(!re_);
|
JS_ASSERT(!initialized());
|
||||||
re_ = &re;
|
re_ = &re;
|
||||||
re_->incRef();
|
re_->incRef();
|
||||||
source_ = re.source;
|
source_ = re_->source;
|
||||||
|
}
|
||||||
|
void release() {
|
||||||
|
if (re_) {
|
||||||
|
re_->decRef();
|
||||||
|
re_ = NULL;
|
||||||
|
source_ = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool initialized() const { return !!re_; }
|
||||||
|
RegExpShared *re() const { JS_ASSERT(initialized()); return re_; }
|
||||||
|
RegExpShared *operator->() { return re(); }
|
||||||
|
RegExpShared &operator*() { return *re(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Equivalent of RegExpGuard, heap-allocated, with explicit tracing. */
|
||||||
|
class RegExpHeapGuard
|
||||||
|
{
|
||||||
|
RegExpShared *re_;
|
||||||
|
|
||||||
|
RegExpHeapGuard(const RegExpGuard &) MOZ_DELETE;
|
||||||
|
void operator=(const RegExpHeapGuard &) MOZ_DELETE;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RegExpHeapGuard() : re_(NULL) { }
|
||||||
|
RegExpHeapGuard(RegExpShared &re) { init(re); }
|
||||||
|
~RegExpHeapGuard() { release(); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
void init(RegExpShared &re) {
|
||||||
|
JS_ASSERT(!initialized());
|
||||||
|
re_ = &re;
|
||||||
|
re_->incRef();
|
||||||
|
}
|
||||||
|
void release() {
|
||||||
|
if (re_) {
|
||||||
|
re_->decRef();
|
||||||
|
re_ = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void trace(JSTracer *trc) {
|
||||||
|
if (initialized())
|
||||||
|
re_->trace(trc);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool initialized() const { return !!re_; }
|
bool initialized() const { return !!re_; }
|
||||||
@ -246,9 +293,12 @@ class RegExpCompartment
|
|||||||
struct Key {
|
struct Key {
|
||||||
JSAtom *atom;
|
JSAtom *atom;
|
||||||
uint16_t flag;
|
uint16_t flag;
|
||||||
|
|
||||||
Key() {}
|
Key() {}
|
||||||
Key(JSAtom *atom, RegExpFlag flag)
|
Key(JSAtom *atom, RegExpFlag flag)
|
||||||
: atom(atom), flag(flag) {}
|
: atom(atom), flag(flag)
|
||||||
|
{ }
|
||||||
|
|
||||||
typedef Key Lookup;
|
typedef Key Lookup;
|
||||||
static HashNumber hash(const Lookup &l) {
|
static HashNumber hash(const Lookup &l) {
|
||||||
return DefaultHasher<JSAtom *>::hash(l.atom) ^ (l.flag << 1);
|
return DefaultHasher<JSAtom *>::hash(l.atom) ^ (l.flag << 1);
|
||||||
|
@ -27,15 +27,6 @@ SizeOfRegExpStaticsData(const JSObject *obj, JSMallocSizeOfFun mallocSizeOf)
|
|||||||
return mallocSizeOf(obj->getPrivate());
|
return mallocSizeOf(obj->getPrivate());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
|
||||||
RegExpStatics::RegExpStatics()
|
|
||||||
: pendingLazyEvaluation(false),
|
|
||||||
bufferLink(NULL),
|
|
||||||
copied(false)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
RegExpStatics::createDependent(JSContext *cx, size_t start, size_t end, Value *out)
|
RegExpStatics::createDependent(JSContext *cx, size_t start, size_t end, Value *out)
|
||||||
{
|
{
|
||||||
@ -231,15 +222,20 @@ RegExpStatics::copyTo(RegExpStatics &dst)
|
|||||||
if (!pendingLazyEvaluation)
|
if (!pendingLazyEvaluation)
|
||||||
dst.matches.initArrayFrom(matches);
|
dst.matches.initArrayFrom(matches);
|
||||||
|
|
||||||
|
if (regexp.initialized())
|
||||||
|
dst.regexp.init(*regexp);
|
||||||
|
else
|
||||||
|
dst.regexp.release();
|
||||||
|
|
||||||
dst.matchesInput = matchesInput;
|
dst.matchesInput = matchesInput;
|
||||||
dst.regexp = regexp;
|
|
||||||
dst.lastIndex = lastIndex;
|
dst.lastIndex = lastIndex;
|
||||||
dst.pendingInput = pendingInput;
|
dst.pendingInput = pendingInput;
|
||||||
dst.flags = flags;
|
dst.flags = flags;
|
||||||
dst.pendingLazyEvaluation = pendingLazyEvaluation;
|
dst.pendingLazyEvaluation = pendingLazyEvaluation;
|
||||||
|
|
||||||
JS_ASSERT_IF(pendingLazyEvaluation, regexp);
|
JS_ASSERT_IF(pendingLazyEvaluation, regexp.initialized());
|
||||||
JS_ASSERT_IF(pendingLazyEvaluation, matchesInput);
|
JS_ASSERT_IF(pendingLazyEvaluation, matchesInput);
|
||||||
|
JS_ASSERT(regexp.initialized() == dst.regexp.initialized());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -261,17 +257,20 @@ RegExpStatics::restore()
|
|||||||
|
|
||||||
inline void
|
inline void
|
||||||
RegExpStatics::updateLazily(JSContext *cx, JSLinearString *input,
|
RegExpStatics::updateLazily(JSContext *cx, JSLinearString *input,
|
||||||
RegExpObject *regexp, size_t lastIndex)
|
RegExpShared *shared, size_t lastIndex)
|
||||||
{
|
{
|
||||||
JS_ASSERT(input && regexp);
|
JS_ASSERT(input && shared);
|
||||||
aboutToWrite();
|
aboutToWrite();
|
||||||
|
|
||||||
BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
|
BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
|
||||||
pendingInput, input,
|
pendingInput, input,
|
||||||
matchesInput, input);
|
matchesInput, input);
|
||||||
pendingLazyEvaluation = true;
|
if (regexp.initialized())
|
||||||
this->regexp = regexp;
|
regexp.release();
|
||||||
|
regexp.init(*shared);
|
||||||
|
|
||||||
this->lastIndex = lastIndex;
|
this->lastIndex = lastIndex;
|
||||||
|
pendingLazyEvaluation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
@ -282,7 +281,7 @@ RegExpStatics::updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchP
|
|||||||
|
|
||||||
/* Unset all lazy state. */
|
/* Unset all lazy state. */
|
||||||
pendingLazyEvaluation = false;
|
pendingLazyEvaluation = false;
|
||||||
this->regexp = NULL;
|
this->regexp.release();
|
||||||
this->lastIndex = size_t(-1);
|
this->lastIndex = size_t(-1);
|
||||||
|
|
||||||
BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
|
BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
|
||||||
@ -301,11 +300,14 @@ inline void
|
|||||||
RegExpStatics::clear()
|
RegExpStatics::clear()
|
||||||
{
|
{
|
||||||
aboutToWrite();
|
aboutToWrite();
|
||||||
flags = RegExpFlag(0);
|
|
||||||
pendingInput = NULL;
|
|
||||||
pendingLazyEvaluation = false;
|
|
||||||
matchesInput = NULL;
|
|
||||||
matches.forgetArray();
|
matches.forgetArray();
|
||||||
|
matchesInput = NULL;
|
||||||
|
regexp.release();
|
||||||
|
lastIndex = size_t(-1);
|
||||||
|
pendingInput = NULL;
|
||||||
|
flags = RegExpFlag(0);
|
||||||
|
pendingLazyEvaluation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -363,8 +365,9 @@ RegExpStatics::checkInvariants()
|
|||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (pendingLazyEvaluation) {
|
if (pendingLazyEvaluation) {
|
||||||
JS_ASSERT(regexp);
|
JS_ASSERT(regexp.initialized());
|
||||||
JS_ASSERT(pendingInput);
|
JS_ASSERT(pendingInput);
|
||||||
|
JS_ASSERT(lastIndex != size_t(-1));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ RegExpStatics::executeLazy(JSContext *cx)
|
|||||||
if (!pendingLazyEvaluation)
|
if (!pendingLazyEvaluation)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
JS_ASSERT(regexp);
|
JS_ASSERT(regexp.initialized());
|
||||||
JS_ASSERT(matchesInput);
|
JS_ASSERT(matchesInput);
|
||||||
JS_ASSERT(lastIndex != size_t(-1));
|
JS_ASSERT(lastIndex != size_t(-1));
|
||||||
|
|
||||||
@ -87,17 +87,20 @@ RegExpStatics::executeLazy(JSContext *cx)
|
|||||||
StableCharPtr chars(matchesInput->chars(), length);
|
StableCharPtr chars(matchesInput->chars(), length);
|
||||||
|
|
||||||
/* Execute the full regular expression. */
|
/* Execute the full regular expression. */
|
||||||
RegExpGuard shared(cx);
|
RegExpRunStatus status = regexp->execute(cx, chars, length, &this->lastIndex, this->matches);
|
||||||
if (!regexp->getShared(cx, &shared))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
RegExpRunStatus status = shared->execute(cx, chars, length, &this->lastIndex, this->matches);
|
|
||||||
if (status == RegExpRunStatus_Error)
|
if (status == RegExpRunStatus_Error)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RegExpStatics are only updated on successful (matching) execution.
|
||||||
|
* Re-running the same expression must therefore produce a matching result.
|
||||||
|
*/
|
||||||
|
JS_ASSERT(status == RegExpRunStatus_Success);
|
||||||
|
|
||||||
/* Unset lazy state and remove rooted values that now have no use. */
|
/* Unset lazy state and remove rooted values that now have no use. */
|
||||||
pendingLazyEvaluation = false;
|
pendingLazyEvaluation = false;
|
||||||
regexp = NULL;
|
regexp.release();
|
||||||
|
lastIndex = size_t(-1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "js/Vector.h"
|
#include "js/Vector.h"
|
||||||
|
|
||||||
#include "vm/MatchPairs.h"
|
#include "vm/MatchPairs.h"
|
||||||
|
#include "vm/RegExpObject.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ class RegExpStatics
|
|||||||
HeapPtr<JSLinearString> matchesInput;
|
HeapPtr<JSLinearString> matchesInput;
|
||||||
|
|
||||||
/* The previous RegExp input, used to resolve lazy state. */
|
/* The previous RegExp input, used to resolve lazy state. */
|
||||||
HeapPtr<RegExpObject> regexp;
|
RegExpHeapGuard regexp;
|
||||||
size_t lastIndex;
|
size_t lastIndex;
|
||||||
|
|
||||||
/* The latest RegExp input, set before execution. */
|
/* The latest RegExp input, set before execution. */
|
||||||
@ -44,6 +45,10 @@ class RegExpStatics
|
|||||||
RegExpStatics *bufferLink;
|
RegExpStatics *bufferLink;
|
||||||
bool copied;
|
bool copied;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RegExpStatics() : bufferLink(NULL), copied(false) { clear(); }
|
||||||
|
static JSObject *create(JSContext *cx, GlobalObject *parent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool executeLazy(JSContext *cx);
|
bool executeLazy(JSContext *cx);
|
||||||
|
|
||||||
@ -80,14 +85,9 @@ class RegExpStatics
|
|||||||
friend class PreserveRegExpStatics;
|
friend class PreserveRegExpStatics;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline RegExpStatics();
|
|
||||||
|
|
||||||
static JSObject *create(JSContext *cx, GlobalObject *parent);
|
|
||||||
|
|
||||||
/* Mutators. */
|
/* Mutators. */
|
||||||
|
|
||||||
inline void updateLazily(JSContext *cx, JSLinearString *input,
|
inline void updateLazily(JSContext *cx, JSLinearString *input,
|
||||||
RegExpObject *regexp, size_t lastIndex);
|
RegExpShared *shared, size_t lastIndex);
|
||||||
inline bool updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchPairs &newPairs);
|
inline bool updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchPairs &newPairs);
|
||||||
inline void setMultiline(JSContext *cx, bool enabled);
|
inline void setMultiline(JSContext *cx, bool enabled);
|
||||||
|
|
||||||
@ -120,12 +120,16 @@ class RegExpStatics
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mark(JSTracer *trc) {
|
void mark(JSTracer *trc) {
|
||||||
if (regexp)
|
/*
|
||||||
gc::MarkObject(trc, ®exp, "res->regexp");
|
* Changes to this function must also be reflected in
|
||||||
|
* RegExpStatics::AutoRooter::trace().
|
||||||
|
*/
|
||||||
if (pendingInput)
|
if (pendingInput)
|
||||||
MarkString(trc, &pendingInput, "res->pendingInput");
|
MarkString(trc, &pendingInput, "res->pendingInput");
|
||||||
if (matchesInput)
|
if (matchesInput)
|
||||||
MarkString(trc, &matchesInput, "res->matchesInput");
|
MarkString(trc, &matchesInput, "res->matchesInput");
|
||||||
|
if (regexp.initialized())
|
||||||
|
regexp->trace(trc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Value creators. */
|
/* Value creators. */
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/GuardObjects.h"
|
#include "mozilla/GuardObjects.h"
|
||||||
|
|
||||||
|
#include "js/CharacterEncoding.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jsatom.h"
|
#include "jsatom.h"
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
@ -477,6 +479,11 @@ class JSLinearString : public JSString
|
|||||||
JS_ASSERT(JSString::isLinear());
|
JS_ASSERT(JSString::isLinear());
|
||||||
return d.u1.chars;
|
return d.u1.chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS::TwoByteChars range() const {
|
||||||
|
JS_ASSERT(JSString::isLinear());
|
||||||
|
return JS::TwoByteChars(d.u1.chars, length());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
JS_STATIC_ASSERT(sizeof(JSLinearString) == sizeof(JSString));
|
JS_STATIC_ASSERT(sizeof(JSLinearString) == sizeof(JSString));
|
||||||
|
@ -575,7 +575,7 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
|||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
JS_EncodeStringToBuffer(str, buffer, length);
|
JS_EncodeStringToBuffer(cx, str, buffer, length);
|
||||||
buffer[length] = '\0';
|
buffer[length] = '\0';
|
||||||
*((void**)d) = buffer;
|
*((void**)d) = buffer;
|
||||||
return true;
|
return true;
|
||||||
@ -701,7 +701,7 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
|||||||
if (rs->Length() != uint32_t(length)) {
|
if (rs->Length() != uint32_t(length)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
JS_EncodeStringToBuffer(str, rs->BeginWriting(), length);
|
JS_EncodeStringToBuffer(cx, str, rs->BeginWriting(), length);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1875,7 +1875,7 @@ XPCConvert::JSStringWithSize2Native(XPCCallContext& ccx, void* d, jsval s,
|
|||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
JS_EncodeStringToBuffer(str, buffer, len);
|
JS_EncodeStringToBuffer(cx, str, buffer, len);
|
||||||
buffer[len] = '\0';
|
buffer[len] = '\0';
|
||||||
*((char**)d) = buffer;
|
*((char**)d) = buffer;
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ XPCJSStackFrame::CreateStack(JSContext* cx, XPCJSStackFrame** stack)
|
|||||||
if (length != size_t(-1)) {
|
if (length != size_t(-1)) {
|
||||||
self->mFunname = static_cast<char *>(nsMemory::Alloc(length + 1));
|
self->mFunname = static_cast<char *>(nsMemory::Alloc(length + 1));
|
||||||
if (self->mFunname) {
|
if (self->mFunname) {
|
||||||
JS_EncodeStringToBuffer(funid, self->mFunname, length);
|
JS_EncodeStringToBuffer(cx, funid, self->mFunname, length);
|
||||||
self->mFunname[length] = '\0';
|
self->mFunname[length] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
layout/reftests/bugs/817019-1.html
Normal file
33
layout/reftests/bugs/817019-1.html
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title></title>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function paintCanvas() {
|
||||||
|
var elem = document.getElementById("mycanv");
|
||||||
|
var ctx = elem.getContext('2d');
|
||||||
|
|
||||||
|
ctx.fillStyle = 'white';
|
||||||
|
ctx.fillRect(0, 0, 200, 200);
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(150, 150, 100, 0, Math.PI * 2, true);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.clip();
|
||||||
|
|
||||||
|
// create radial gradient
|
||||||
|
var grd = ctx.createRadialGradient(110, 110, 42, 110, 110, 121);
|
||||||
|
grd.addColorStop(0, '#FFFFFF');
|
||||||
|
grd.addColorStop(1, '#E5E5E5');
|
||||||
|
|
||||||
|
ctx.fillStyle = grd;
|
||||||
|
// This should be completely clipped out!
|
||||||
|
ctx.fillRect(0, 0, 1, 1);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="paintCanvas();">
|
||||||
|
<canvas width=200 height=200 moz-opaque="true" id="mycanv"></canvas>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1740,3 +1740,4 @@ skip-if(B2G) == 814952-1.html 814952-1-ref.html
|
|||||||
skip-if(B2G) == 818276-1.html 818276-1-ref.html
|
skip-if(B2G) == 818276-1.html 818276-1-ref.html
|
||||||
== 827577-1a.html 827577-1-ref.html
|
== 827577-1a.html 827577-1-ref.html
|
||||||
== 827577-1b.html 827577-1-ref.html
|
== 827577-1b.html 827577-1-ref.html
|
||||||
|
== 817019-1.html about:blank
|
||||||
|
@ -2,5 +2,4 @@ This source is from the Speex library (http://git.xiph.org/speex.git/), from
|
|||||||
commit a6d05eb5.
|
commit a6d05eb5.
|
||||||
|
|
||||||
It consists in the audio resampling code (resampler.c) and its header files
|
It consists in the audio resampling code (resampler.c) and its header files
|
||||||
dependancies. No changes have been made to those files, imported in the tree
|
dependancies, imported into the tree using the update.sh script.
|
||||||
using the update.sh script.
|
|
||||||
|
@ -960,13 +960,15 @@ EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, co
|
|||||||
{
|
{
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
int istride_save, ostride_save;
|
int istride_save, ostride_save;
|
||||||
spx_uint32_t bak_len = *out_len;
|
spx_uint32_t bak_out_len = *out_len;
|
||||||
|
spx_uint32_t bak_in_len = *in_len;
|
||||||
istride_save = st->in_stride;
|
istride_save = st->in_stride;
|
||||||
ostride_save = st->out_stride;
|
ostride_save = st->out_stride;
|
||||||
st->in_stride = st->out_stride = st->nb_channels;
|
st->in_stride = st->out_stride = st->nb_channels;
|
||||||
for (i=0;i<st->nb_channels;i++)
|
for (i=0;i<st->nb_channels;i++)
|
||||||
{
|
{
|
||||||
*out_len = bak_len;
|
*out_len = bak_out_len;
|
||||||
|
*in_len = bak_in_len;
|
||||||
if (in != NULL)
|
if (in != NULL)
|
||||||
speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
|
speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
|
||||||
else
|
else
|
||||||
@ -981,13 +983,15 @@ EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, cons
|
|||||||
{
|
{
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
int istride_save, ostride_save;
|
int istride_save, ostride_save;
|
||||||
spx_uint32_t bak_len = *out_len;
|
spx_uint32_t bak_out_len = *out_len;
|
||||||
|
spx_uint32_t bak_in_len = *in_len;
|
||||||
istride_save = st->in_stride;
|
istride_save = st->in_stride;
|
||||||
ostride_save = st->out_stride;
|
ostride_save = st->out_stride;
|
||||||
st->in_stride = st->out_stride = st->nb_channels;
|
st->in_stride = st->out_stride = st->nb_channels;
|
||||||
for (i=0;i<st->nb_channels;i++)
|
for (i=0;i<st->nb_channels;i++)
|
||||||
{
|
{
|
||||||
*out_len = bak_len;
|
*out_len = bak_out_len;
|
||||||
|
*in_len = bak_in_len;
|
||||||
if (in != NULL)
|
if (in != NULL)
|
||||||
speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
|
speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
|
||||||
else
|
else
|
||||||
|
54
media/libspeex_resampler/truncation.patch
Normal file
54
media/libspeex_resampler/truncation.patch
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
From 5adadc5626ee2d5d3a3ca21e70fd195b9d002a0b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jean-Marc Valin <jmvalin@jmvalin.ca>
|
||||||
|
Date: Wed, 1 Aug 2012 13:19:38 -0400
|
||||||
|
Subject: [PATCH] Properly save in_len for multiple channels in the resampler.
|
||||||
|
|
||||||
|
This fixes issues with clicking in one channel and/or truncation
|
||||||
|
with some unusual sample rates.
|
||||||
|
---
|
||||||
|
src/resample.c | 12 ++++++++----
|
||||||
|
1 files changed, 8 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/resample.c b/src/resample.c
|
||||||
|
index 84aaf59..6e92bd0 100644
|
||||||
|
--- a/src/resample.c
|
||||||
|
+++ b/src/resample.c
|
||||||
|
@@ -966,13 +966,15 @@ SPX_RESAMPLE_EXPORT int speex_resampler_process_interleaved_float(SpeexResampler
|
||||||
|
{
|
||||||
|
spx_uint32_t i;
|
||||||
|
int istride_save, ostride_save;
|
||||||
|
- spx_uint32_t bak_len = *out_len;
|
||||||
|
+ spx_uint32_t bak_out_len = *out_len;
|
||||||
|
+ spx_uint32_t bak_in_len = *in_len;
|
||||||
|
istride_save = st->in_stride;
|
||||||
|
ostride_save = st->out_stride;
|
||||||
|
st->in_stride = st->out_stride = st->nb_channels;
|
||||||
|
for (i=0;i<st->nb_channels;i++)
|
||||||
|
{
|
||||||
|
- *out_len = bak_len;
|
||||||
|
+ *out_len = bak_out_len;
|
||||||
|
+ *in_len = bak_in_len;
|
||||||
|
if (in != NULL)
|
||||||
|
speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
|
||||||
|
else
|
||||||
|
@@ -987,13 +989,15 @@ SPX_RESAMPLE_EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerSt
|
||||||
|
{
|
||||||
|
spx_uint32_t i;
|
||||||
|
int istride_save, ostride_save;
|
||||||
|
- spx_uint32_t bak_len = *out_len;
|
||||||
|
+ spx_uint32_t bak_out_len = *out_len;
|
||||||
|
+ spx_uint32_t bak_in_len = *in_len;
|
||||||
|
istride_save = st->in_stride;
|
||||||
|
ostride_save = st->out_stride;
|
||||||
|
st->in_stride = st->out_stride = st->nb_channels;
|
||||||
|
for (i=0;i<st->nb_channels;i++)
|
||||||
|
{
|
||||||
|
- *out_len = bak_len;
|
||||||
|
+ *out_len = bak_out_len;
|
||||||
|
+ *in_len = bak_in_len;
|
||||||
|
if (in != NULL)
|
||||||
|
speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
|
||||||
|
else
|
||||||
|
--
|
||||||
|
1.7.2.5
|
||||||
|
|
@ -6,6 +6,7 @@
|
|||||||
#
|
#
|
||||||
# Copies the needed files from a directory containing the original
|
# Copies the needed files from a directory containing the original
|
||||||
# libspeex sources that we need for HTML5 media playback rate change.
|
# libspeex sources that we need for HTML5 media playback rate change.
|
||||||
|
|
||||||
cp $1/libspeex/resample.c src
|
cp $1/libspeex/resample.c src
|
||||||
cp $1/libspeex/arch.h src
|
cp $1/libspeex/arch.h src
|
||||||
cp $1/libspeex/stack_alloc.h src
|
cp $1/libspeex/stack_alloc.h src
|
||||||
@ -15,3 +16,6 @@ cp $1/include/speex/speex_types.h src
|
|||||||
sed -e 's/unsigned @SIZE16@/uint16_t/g' -e 's/unsigned @SIZE32@/uint32_t/g' -e 's/@SIZE16@/int16_t/g' -e 's/@SIZE32@/int32_t/g' < $1/include/speex/speex_config_types.h.in > src/speex_config_types.h
|
sed -e 's/unsigned @SIZE16@/uint16_t/g' -e 's/unsigned @SIZE32@/uint32_t/g' -e 's/@SIZE16@/int16_t/g' -e 's/@SIZE32@/int32_t/g' < $1/include/speex/speex_config_types.h.in > src/speex_config_types.h
|
||||||
cp $1/AUTHORS .
|
cp $1/AUTHORS .
|
||||||
cp $1/COPYING .
|
cp $1/COPYING .
|
||||||
|
|
||||||
|
# apply outstanding local patches
|
||||||
|
patch -p1 < truncation.patch
|
||||||
|
@ -41,10 +41,14 @@ public:
|
|||||||
if (!observerService)
|
if (!observerService)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nsresult rv = observerService->AddObserver(this,
|
nsresult rv = NS_OK;
|
||||||
NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
|
||||||
false);
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
MOZ_ASSERT(rv == NS_OK);
|
rv = observerService->AddObserver(this,
|
||||||
|
NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
||||||
|
false);
|
||||||
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
|
||||||
|
#endif
|
||||||
(void) rv;
|
(void) rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +222,9 @@ PeerConnectionImpl::PeerConnectionImpl()
|
|||||||
, mIdentity(NULL)
|
, mIdentity(NULL)
|
||||||
, mSTSThread(NULL)
|
, mSTSThread(NULL)
|
||||||
, mMedia(new PeerConnectionMedia(this)) {
|
, mMedia(new PeerConnectionMedia(this)) {
|
||||||
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerConnectionImpl::~PeerConnectionImpl()
|
PeerConnectionImpl::~PeerConnectionImpl()
|
||||||
@ -288,10 +290,13 @@ NS_IMETHODIMP
|
|||||||
PeerConnectionImpl::Initialize(IPeerConnectionObserver* aObserver,
|
PeerConnectionImpl::Initialize(IPeerConnectionObserver* aObserver,
|
||||||
nsIDOMWindow* aWindow,
|
nsIDOMWindow* aWindow,
|
||||||
nsIThread* aThread) {
|
nsIThread* aThread) {
|
||||||
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
#endif
|
||||||
MOZ_ASSERT(aObserver);
|
MOZ_ASSERT(aObserver);
|
||||||
MOZ_ASSERT(aThread);
|
MOZ_ASSERT(aThread);
|
||||||
mPCObserver = aObserver;
|
|
||||||
|
mPCObserver = do_GetWeakReference(aObserver);
|
||||||
|
|
||||||
nsresult res;
|
nsresult res;
|
||||||
|
|
||||||
@ -521,8 +526,12 @@ PeerConnectionImpl::NotifyConnection()
|
|||||||
CSFLogDebugS(logTag, __FUNCTION__);
|
CSFLogDebugS(logTag, __FUNCTION__);
|
||||||
|
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
|
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||||
|
if (!pco) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
RUN_ON_THREAD(mThread,
|
RUN_ON_THREAD(mThread,
|
||||||
WrapRunnable(mPCObserver,
|
WrapRunnable(pco,
|
||||||
&IPeerConnectionObserver::NotifyConnection),
|
&IPeerConnectionObserver::NotifyConnection),
|
||||||
NS_DISPATCH_NORMAL);
|
NS_DISPATCH_NORMAL);
|
||||||
#endif
|
#endif
|
||||||
@ -536,10 +545,13 @@ PeerConnectionImpl::NotifyClosedConnection()
|
|||||||
CSFLogDebugS(logTag, __FUNCTION__);
|
CSFLogDebugS(logTag, __FUNCTION__);
|
||||||
|
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
|
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||||
|
if (!pco) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
RUN_ON_THREAD(mThread,
|
RUN_ON_THREAD(mThread,
|
||||||
WrapRunnable(mPCObserver,
|
WrapRunnable(pco, &IPeerConnectionObserver::NotifyClosedConnection),
|
||||||
&IPeerConnectionObserver::NotifyClosedConnection),
|
NS_DISPATCH_NORMAL);
|
||||||
NS_DISPATCH_NORMAL);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,15 +577,20 @@ PeerConnectionImpl::NotifyDataChannel(already_AddRefed<mozilla::DataChannel> aCh
|
|||||||
CSFLogDebugS(logTag, __FUNCTION__ << ": channel: " << static_cast<void*>(aChannel.get()));
|
CSFLogDebugS(logTag, __FUNCTION__ << ": channel: " << static_cast<void*>(aChannel.get()));
|
||||||
|
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
nsCOMPtr<nsIDOMDataChannel> domchannel;
|
nsCOMPtr<nsIDOMDataChannel> domchannel;
|
||||||
nsresult rv = NS_NewDOMDataChannel(aChannel, mWindow,
|
nsresult rv = NS_NewDOMDataChannel(aChannel, mWindow,
|
||||||
getter_AddRefs(domchannel));
|
getter_AddRefs(domchannel));
|
||||||
NS_ENSURE_SUCCESS_VOID(rv);
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
|
||||||
|
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||||
|
if (!pco) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RUN_ON_THREAD(mThread,
|
RUN_ON_THREAD(mThread,
|
||||||
WrapRunnableNM(NotifyDataChannel_m,
|
WrapRunnableNM(NotifyDataChannel_m,
|
||||||
domchannel.get(),
|
domchannel.get(),
|
||||||
mPCObserver),
|
pco),
|
||||||
NS_DISPATCH_NORMAL);
|
NS_DISPATCH_NORMAL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -996,16 +1013,20 @@ PeerConnectionImpl::onCallEvent(ccapi_call_event_e aCallEvent,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPCObserver) {
|
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||||
PeerConnectionObserverDispatch* runnable =
|
if (!pco) {
|
||||||
new PeerConnectionObserverDispatch(aInfo, this, mPCObserver);
|
return;
|
||||||
|
|
||||||
if (mThread) {
|
|
||||||
mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runnable->Run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PeerConnectionObserverDispatch* runnable =
|
||||||
|
new PeerConnectionObserverDispatch(aInfo, this, pco);
|
||||||
|
|
||||||
|
if (mThread) {
|
||||||
|
mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
runnable->Run();
|
||||||
|
delete runnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1016,7 +1037,11 @@ PeerConnectionImpl::ChangeReadyState(PeerConnectionImpl::ReadyState aReadyState)
|
|||||||
|
|
||||||
// Note that we are passing an nsRefPtr<IPeerConnectionObserver> which
|
// Note that we are passing an nsRefPtr<IPeerConnectionObserver> which
|
||||||
// keeps the observer live.
|
// keeps the observer live.
|
||||||
RUN_ON_THREAD(mThread, WrapRunnable(mPCObserver,
|
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||||
|
if (!pco) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RUN_ON_THREAD(mThread, WrapRunnable(pco,
|
||||||
&IPeerConnectionObserver::OnStateChange,
|
&IPeerConnectionObserver::OnStateChange,
|
||||||
// static_cast needed to work around old Android NDK r5c compiler
|
// static_cast needed to work around old Android NDK r5c compiler
|
||||||
static_cast<int>(IPeerConnectionObserver::kReadyState)),
|
static_cast<int>(IPeerConnectionObserver::kReadyState)),
|
||||||
@ -1070,14 +1095,16 @@ PeerConnectionImpl::IceGatheringCompleted_m(NrIceCtx *aCtx)
|
|||||||
mIceState = kIceWaiting;
|
mIceState = kIceWaiting;
|
||||||
|
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
if (mPCObserver) {
|
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||||
RUN_ON_THREAD(mThread,
|
if (!pco) {
|
||||||
WrapRunnable(mPCObserver,
|
return NS_OK;
|
||||||
&IPeerConnectionObserver::OnStateChange,
|
|
||||||
// static_cast required to work around old C++ compiler on Android NDK r5c
|
|
||||||
static_cast<int>(IPeerConnectionObserver::kIceState)),
|
|
||||||
NS_DISPATCH_NORMAL);
|
|
||||||
}
|
}
|
||||||
|
RUN_ON_THREAD(mThread,
|
||||||
|
WrapRunnable(pco,
|
||||||
|
&IPeerConnectionObserver::OnStateChange,
|
||||||
|
// static_cast required to work around old C++ compiler on Android NDK r5c
|
||||||
|
static_cast<int>(IPeerConnectionObserver::kIceState)),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
#endif
|
#endif
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -1105,14 +1132,16 @@ PeerConnectionImpl::IceCompleted_m(NrIceCtx *aCtx)
|
|||||||
mIceState = kIceConnected;
|
mIceState = kIceConnected;
|
||||||
|
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
if (mPCObserver) {
|
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||||
RUN_ON_THREAD(mThread,
|
if (!pco) {
|
||||||
WrapRunnable(mPCObserver,
|
return NS_OK;
|
||||||
&IPeerConnectionObserver::OnStateChange,
|
|
||||||
// static_cast required to work around old C++ compiler on Android NDK r5c
|
|
||||||
static_cast<int>(IPeerConnectionObserver::kIceState)),
|
|
||||||
NS_DISPATCH_NORMAL);
|
|
||||||
}
|
}
|
||||||
|
RUN_ON_THREAD(mThread,
|
||||||
|
WrapRunnable(pco,
|
||||||
|
&IPeerConnectionObserver::OnStateChange,
|
||||||
|
// static_cast required to work around old C++ compiler on Android NDK r5c
|
||||||
|
static_cast<int>(IPeerConnectionObserver::kIceState)),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
#endif
|
#endif
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
#include "prlock.h"
|
#include "prlock.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "nsWeakPtr.h"
|
||||||
|
#include "nsIWeakReferenceUtils.h" // for the definition of nsWeakPtr
|
||||||
#include "IPeerConnection.h"
|
#include "IPeerConnection.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
@ -230,7 +232,9 @@ private:
|
|||||||
IceState mIceState;
|
IceState mIceState;
|
||||||
|
|
||||||
nsCOMPtr<nsIThread> mThread;
|
nsCOMPtr<nsIThread> mThread;
|
||||||
nsCOMPtr<IPeerConnectionObserver> mPCObserver;
|
// Weak pointer to IPeerConnectionObserver
|
||||||
|
// This is only safe to use on the main thread
|
||||||
|
nsWeakPtr mPCObserver;
|
||||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||||
|
|
||||||
// The SDP sent in from JS - here for debugging.
|
// The SDP sent in from JS - here for debugging.
|
||||||
|
@ -1779,6 +1779,8 @@ gsmsdp_get_remote_sdp_direction (fsmdef_dcb_t *dcb_p, uint16_t level,
|
|||||||
cc_sdp_t *sdp_p = dcb_p->sdp;
|
cc_sdp_t *sdp_p = dcb_p->sdp;
|
||||||
uint16_t media_attr;
|
uint16_t media_attr;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
uint32 port;
|
||||||
|
int sdpmode = 0;
|
||||||
static const sdp_attr_e dir_attr_array[] = {
|
static const sdp_attr_e dir_attr_array[] = {
|
||||||
SDP_ATTR_INACTIVE,
|
SDP_ATTR_INACTIVE,
|
||||||
SDP_ATTR_RECVONLY,
|
SDP_ATTR_RECVONLY,
|
||||||
@ -1791,6 +1793,8 @@ gsmsdp_get_remote_sdp_direction (fsmdef_dcb_t *dcb_p, uint16_t level,
|
|||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||||
|
|
||||||
media_attr = 0; /* media level attr. count */
|
media_attr = 0; /* media level attr. count */
|
||||||
/*
|
/*
|
||||||
* Now check for direction as a media attribute. If found, the
|
* Now check for direction as a media attribute. If found, the
|
||||||
@ -1842,6 +1846,17 @@ gsmsdp_get_remote_sdp_direction (fsmdef_dcb_t *dcb_p, uint16_t level,
|
|||||||
if (dest_addr->type == CPR_IP_ADDR_IPV4 &&
|
if (dest_addr->type == CPR_IP_ADDR_IPV4 &&
|
||||||
dest_addr->u.ip4 == 0) {
|
dest_addr->u.ip4 == 0) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For WebRTC, we allow active media sections with IP=0.0.0.0, iff
|
||||||
|
* port != 0. This is to allow interop with existing Trickle ICE
|
||||||
|
* implementations. TODO: This may need to be updated to match the
|
||||||
|
* spec once the Trickle ICE spec is finalized.
|
||||||
|
*/
|
||||||
|
port = sdp_get_media_portnum(sdp_p->dest_sdp, level);
|
||||||
|
if (sdpmode && port != 0) {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
direction = SDP_DIRECTION_INACTIVE;
|
direction = SDP_DIRECTION_INACTIVE;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -133,6 +133,7 @@ LOCAL_INCLUDES += \
|
|||||||
-I$(topsrcdir)/media/webrtc/signaling/src/peerconnection \
|
-I$(topsrcdir)/media/webrtc/signaling/src/peerconnection \
|
||||||
-I$(topsrcdir)/media/webrtc/signaling/media-conduit\
|
-I$(topsrcdir)/media/webrtc/signaling/media-conduit\
|
||||||
-I$(topsrcdir)/media/webrtc/trunk/third_party/libjingle/source/ \
|
-I$(topsrcdir)/media/webrtc/trunk/third_party/libjingle/source/ \
|
||||||
|
-I$(topsrcdir)/xpcom/base/ \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifneq ($(OS_TARGET),WINNT)
|
ifneq ($(OS_TARGET),WINNT)
|
||||||
|
@ -23,9 +23,11 @@ using namespace std;
|
|||||||
#include "FakeMediaStreams.h"
|
#include "FakeMediaStreams.h"
|
||||||
#include "FakeMediaStreamsImpl.h"
|
#include "FakeMediaStreamsImpl.h"
|
||||||
#include "PeerConnectionImpl.h"
|
#include "PeerConnectionImpl.h"
|
||||||
|
#include "PeerConnectionCtx.h"
|
||||||
#include "runnable_utils.h"
|
#include "runnable_utils.h"
|
||||||
#include "nsStaticComponents.h"
|
#include "nsStaticComponents.h"
|
||||||
#include "nsIDOMRTCPeerConnection.h"
|
#include "nsIDOMRTCPeerConnection.h"
|
||||||
|
#include "nsWeakReference.h"
|
||||||
|
|
||||||
#include "mtransport_test_utils.h"
|
#include "mtransport_test_utils.h"
|
||||||
MtransportTestUtils *test_utils;
|
MtransportTestUtils *test_utils;
|
||||||
@ -118,7 +120,8 @@ enum offerAnswerFlags
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TestObserver : public IPeerConnectionObserver
|
class TestObserver : public IPeerConnectionObserver,
|
||||||
|
public nsSupportsWeakReference
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Action {
|
enum Action {
|
||||||
@ -163,7 +166,9 @@ private:
|
|||||||
std::vector<nsDOMMediaStream *> streams;
|
std::vector<nsDOMMediaStream *> streams;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_THREADSAFE_ISUPPORTS1(TestObserver, IPeerConnectionObserver)
|
NS_IMPL_THREADSAFE_ISUPPORTS2(TestObserver,
|
||||||
|
IPeerConnectionObserver,
|
||||||
|
nsISupportsWeakReference)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
TestObserver::OnCreateOfferSuccess(const char* offer)
|
TestObserver::OnCreateOfferSuccess(const char* offer)
|
||||||
@ -489,7 +494,7 @@ class SignalingAgent {
|
|||||||
NS_DISPATCH_SYNC);
|
NS_DISPATCH_SYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(nsCOMPtr<nsIThread> thread)
|
void Init_m(nsCOMPtr<nsIThread> thread)
|
||||||
{
|
{
|
||||||
size_t found = 2;
|
size_t found = 2;
|
||||||
ASSERT_TRUE(found > 0);
|
ASSERT_TRUE(found > 0);
|
||||||
@ -502,6 +507,14 @@ class SignalingAgent {
|
|||||||
|
|
||||||
ASSERT_EQ(pc->Initialize(pObserver, nullptr, thread), NS_OK);
|
ASSERT_EQ(pc->Initialize(pObserver, nullptr, thread), NS_OK);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init(nsCOMPtr<nsIThread> thread)
|
||||||
|
{
|
||||||
|
thread->Dispatch(
|
||||||
|
WrapRunnable(this, &SignalingAgent::Init_m, thread),
|
||||||
|
NS_DISPATCH_SYNC);
|
||||||
|
|
||||||
ASSERT_TRUE_WAIT(sipcc_state() == sipcc::PeerConnectionImpl::kStarted,
|
ASSERT_TRUE_WAIT(sipcc_state() == sipcc::PeerConnectionImpl::kStarted,
|
||||||
kDefaultTimeout);
|
kDefaultTimeout);
|
||||||
ASSERT_TRUE_WAIT(ice_state() == sipcc::PeerConnectionImpl::kIceWaiting, 5000);
|
ASSERT_TRUE_WAIT(ice_state() == sipcc::PeerConnectionImpl::kIceWaiting, 5000);
|
||||||
@ -592,14 +605,18 @@ class SignalingAgent {
|
|||||||
// Now call CreateOffer as JS would
|
// Now call CreateOffer as JS would
|
||||||
pObserver->state = TestObserver::stateNoResponse;
|
pObserver->state = TestObserver::stateNoResponse;
|
||||||
ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
|
ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
|
||||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateSuccess, kDefaultTimeout);
|
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||||
|
kDefaultTimeout);
|
||||||
|
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||||
SDPSanityCheck(pObserver->lastString, sdpCheck, true);
|
SDPSanityCheck(pObserver->lastString, sdpCheck, true);
|
||||||
offer_ = pObserver->lastString;
|
offer_ = pObserver->lastString;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateOfferExpectError(sipcc::MediaConstraints& constraints) {
|
void CreateOfferExpectError(sipcc::MediaConstraints& constraints) {
|
||||||
ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
|
ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
|
||||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateError, kDefaultTimeout);
|
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||||
|
kDefaultTimeout);
|
||||||
|
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
||||||
@ -628,7 +645,9 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
|||||||
|
|
||||||
pObserver->state = TestObserver::stateNoResponse;
|
pObserver->state = TestObserver::stateNoResponse;
|
||||||
ASSERT_EQ(pc->CreateAnswer(constraints), NS_OK);
|
ASSERT_EQ(pc->CreateAnswer(constraints), NS_OK);
|
||||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateSuccess, kDefaultTimeout);
|
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||||
|
kDefaultTimeout);
|
||||||
|
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||||
SDPSanityCheck(pObserver->lastString, sdpCheck, false);
|
SDPSanityCheck(pObserver->lastString, sdpCheck, false);
|
||||||
|
|
||||||
answer_ = pObserver->lastString;
|
answer_ = pObserver->lastString;
|
||||||
@ -653,7 +672,9 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
|||||||
// Now call CreateOffer as JS would
|
// Now call CreateOffer as JS would
|
||||||
pObserver->state = TestObserver::stateNoResponse;
|
pObserver->state = TestObserver::stateNoResponse;
|
||||||
ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
|
ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
|
||||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateSuccess, kDefaultTimeout);
|
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||||
|
kDefaultTimeout);
|
||||||
|
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||||
SDPSanityCheck(pObserver->lastString, sdpCheck, true);
|
SDPSanityCheck(pObserver->lastString, sdpCheck, true);
|
||||||
offer_ = pObserver->lastString;
|
offer_ = pObserver->lastString;
|
||||||
}
|
}
|
||||||
@ -661,13 +682,17 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
|||||||
void SetRemote(TestObserver::Action action, std::string remote) {
|
void SetRemote(TestObserver::Action action, std::string remote) {
|
||||||
pObserver->state = TestObserver::stateNoResponse;
|
pObserver->state = TestObserver::stateNoResponse;
|
||||||
ASSERT_EQ(pc->SetRemoteDescription(action, remote.c_str()), NS_OK);
|
ASSERT_EQ(pc->SetRemoteDescription(action, remote.c_str()), NS_OK);
|
||||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateSuccess, kDefaultTimeout);
|
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||||
|
kDefaultTimeout);
|
||||||
|
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLocal(TestObserver::Action action, std::string local) {
|
void SetLocal(TestObserver::Action action, std::string local) {
|
||||||
pObserver->state = TestObserver::stateNoResponse;
|
pObserver->state = TestObserver::stateNoResponse;
|
||||||
ASSERT_EQ(pc->SetLocalDescription(action, local.c_str()), NS_OK);
|
ASSERT_EQ(pc->SetLocalDescription(action, local.c_str()), NS_OK);
|
||||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateSuccess, kDefaultTimeout);
|
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||||
|
kDefaultTimeout);
|
||||||
|
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoTrickleIce(ParsedSDP &sdp) {
|
void DoTrickleIce(ParsedSDP &sdp) {
|
||||||
@ -734,6 +759,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void SDPSanityCheck(std::string sdp, uint32_t flags, bool offer)
|
void SDPSanityCheck(std::string sdp, uint32_t flags, bool offer)
|
||||||
{
|
{
|
||||||
|
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||||
ASSERT_NE(sdp.find("v=0"), std::string::npos);
|
ASSERT_NE(sdp.find("v=0"), std::string::npos);
|
||||||
ASSERT_NE(sdp.find("c=IN IP4"), std::string::npos);
|
ASSERT_NE(sdp.find("c=IN IP4"), std::string::npos);
|
||||||
ASSERT_NE(sdp.find("a=fingerprint:sha-256"), std::string::npos);
|
ASSERT_NE(sdp.find("a=fingerprint:sha-256"), std::string::npos);
|
||||||
@ -1700,6 +1726,32 @@ TEST_F(SignalingTest, CheckTrickleSdpChange)
|
|||||||
ASSERT_EQ(a2_.getLocalDescription(),a1_.getRemoteDescription());
|
ASSERT_EQ(a2_.getLocalDescription(),a1_.getRemoteDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SignalingTest, ipAddrAnyOffer)
|
||||||
|
{
|
||||||
|
sipcc::MediaConstraints constraints;
|
||||||
|
std::string offer =
|
||||||
|
"v=0\r\n"
|
||||||
|
"o=- 1 1 IN IP4 127.0.0.1\r\n"
|
||||||
|
"s=-\r\n"
|
||||||
|
"b=AS:64\r\n"
|
||||||
|
"t=0 0\r\n"
|
||||||
|
"a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:"
|
||||||
|
"7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n"
|
||||||
|
"m=audio 9000 RTP/AVP 99\r\n"
|
||||||
|
"c=IN IP4 0.0.0.0\r\n"
|
||||||
|
"a=rtpmap:99 opus/48000/2\r\n"
|
||||||
|
"a=ice-ufrag:cYuakxkEKH+RApYE\r\n"
|
||||||
|
"a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n"
|
||||||
|
"a=sendrecv\r\n";
|
||||||
|
|
||||||
|
a2_.SetRemote(TestObserver::OFFER, offer);
|
||||||
|
ASSERT_TRUE(a2_.pObserver->state == TestObserver::stateSuccess);
|
||||||
|
a2_.CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO);
|
||||||
|
ASSERT_TRUE(a2_.pObserver->state == TestObserver::stateSuccess);
|
||||||
|
std::string answer = a2_.answer();
|
||||||
|
ASSERT_NE(answer.find("a=sendrecv"), std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
} // End namespace test.
|
} // End namespace test.
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
@ -1720,6 +1772,13 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
::testing::AddGlobalTestEnvironment(new test::SignalingEnvironment);
|
::testing::AddGlobalTestEnvironment(new test::SignalingEnvironment);
|
||||||
int result = RUN_ALL_TESTS();
|
int result = RUN_ALL_TESTS();
|
||||||
|
|
||||||
|
// Because we don't initialize on the main thread, we can't register for
|
||||||
|
// XPCOM shutdown callbacks (where the context is usually shut down) --
|
||||||
|
// so we need to explictly destroy the context.
|
||||||
|
sipcc::PeerConnectionCtx::Destroy();
|
||||||
delete test_utils;
|
delete test_utils;
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
49
mfbt/Range.h
Normal file
49
mfbt/Range.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=8 sw=4 et tw=78:
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_Range_h_
|
||||||
|
#define mozilla_Range_h_
|
||||||
|
|
||||||
|
#include "mozilla/NullPtr.h"
|
||||||
|
#include "mozilla/RangedPtr.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
// Range<T> is a tuple containing a pointer and a length.
|
||||||
|
template <typename T>
|
||||||
|
class Range
|
||||||
|
{
|
||||||
|
RangedPtr<T> mStart;
|
||||||
|
RangedPtr<T> mEnd;
|
||||||
|
|
||||||
|
typedef void (Range::* ConvertibleToBool)();
|
||||||
|
void nonNull() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Range() : mStart(nullptr, 0), mEnd(nullptr, 0) {}
|
||||||
|
Range(T* p, size_t len)
|
||||||
|
: mStart(p, p, p + len),
|
||||||
|
mEnd(p + len, p, p + len)
|
||||||
|
{}
|
||||||
|
|
||||||
|
RangedPtr<T> start() const { return mStart; }
|
||||||
|
RangedPtr<T> end() const { return mEnd; }
|
||||||
|
size_t length() const { return mEnd - mStart; }
|
||||||
|
|
||||||
|
T& operator[](size_t offset) {
|
||||||
|
return mStart[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
operator ConvertibleToBool() const { return mStart ? &Range::nonNull : 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_Range_h_
|
||||||
|
|
@ -46,6 +46,9 @@ class RangedPtr
|
|||||||
T* const rangeEnd;
|
T* const rangeEnd;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef void (RangedPtr::* ConvertibleToBool)();
|
||||||
|
void nonNull() {}
|
||||||
|
|
||||||
void checkSanity() {
|
void checkSanity() {
|
||||||
MOZ_ASSERT(rangeStart <= ptr);
|
MOZ_ASSERT(rangeStart <= ptr);
|
||||||
MOZ_ASSERT(ptr <= rangeEnd);
|
MOZ_ASSERT(ptr <= rangeEnd);
|
||||||
@ -97,7 +100,7 @@ class RangedPtr
|
|||||||
|
|
||||||
/* Equivalent to RangedPtr(arr, arr, N). */
|
/* Equivalent to RangedPtr(arr, arr, N). */
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
RangedPtr(T arr[N])
|
RangedPtr(T (&arr)[N])
|
||||||
: ptr(arr)
|
: ptr(arr)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
, rangeStart(arr), rangeEnd(arr + N)
|
, rangeStart(arr), rangeEnd(arr + N)
|
||||||
@ -110,6 +113,8 @@ class RangedPtr
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator ConvertibleToBool() const { return ptr ? &RangedPtr::nonNull : 0; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* You can only assign one RangedPtr into another if the two pointers have
|
* You can only assign one RangedPtr into another if the two pointers have
|
||||||
* the same valid range:
|
* the same valid range:
|
||||||
@ -242,7 +247,6 @@ class RangedPtr
|
|||||||
private:
|
private:
|
||||||
RangedPtr() MOZ_DELETE;
|
RangedPtr() MOZ_DELETE;
|
||||||
T* operator&() MOZ_DELETE;
|
T* operator&() MOZ_DELETE;
|
||||||
operator T*() const MOZ_DELETE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace mozilla */
|
} /* namespace mozilla */
|
||||||
|
@ -25,6 +25,7 @@ EXPORTS_mozilla += \
|
|||||||
MathAlgorithms.h \
|
MathAlgorithms.h \
|
||||||
MSStdInt.h \
|
MSStdInt.h \
|
||||||
NullPtr.h \
|
NullPtr.h \
|
||||||
|
Range.h \
|
||||||
RangedPtr.h \
|
RangedPtr.h \
|
||||||
RefPtr.h \
|
RefPtr.h \
|
||||||
Scoped.h \
|
Scoped.h \
|
||||||
|
@ -46,7 +46,6 @@ DEFINES += \
|
|||||||
-DAPP_NAME=$(MOZ_APP_NAME) \
|
-DAPP_NAME=$(MOZ_APP_NAME) \
|
||||||
-DAPP_VERSION=$(MOZ_APP_VERSION) \
|
-DAPP_VERSION=$(MOZ_APP_VERSION) \
|
||||||
-DMOZ_UPDATER=$(MOZ_UPDATER) \
|
-DMOZ_UPDATER=$(MOZ_UPDATER) \
|
||||||
-DMOZ_APP_UA_NAME=$(MOZ_APP_UA_NAME) \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifdef MOZ_PKG_SPECIAL
|
ifdef MOZ_PKG_SPECIAL
|
||||||
|
@ -573,8 +573,6 @@ pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-erro
|
|||||||
pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
|
pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
|
||||||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||||
|
|
||||||
pref("browser.safebrowsing.id", "@MOZ_APP_UA_NAME@");
|
|
||||||
|
|
||||||
// Name of the about: page contributed by safebrowsing to handle display of error
|
// Name of the about: page contributed by safebrowsing to handle display of error
|
||||||
// pages on phishing/malware hits. (bug 399233)
|
// pages on phishing/malware hits. (bug 399233)
|
||||||
pref("urlclassifier.alternate_error_page", "blocked");
|
pref("urlclassifier.alternate_error_page", "blocked");
|
||||||
|
@ -39,4 +39,14 @@ EXTRA_COMPONENTS = \
|
|||||||
BlocklistPrompt.js \
|
BlocklistPrompt.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
ifdef MOZ_SAFE_BROWSING
|
||||||
|
DEFINES += \
|
||||||
|
-DMOZ_APP_UA_NAME=$(MOZ_APP_UA_NAME) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
EXTRA_PP_JS_MODULES = \
|
||||||
|
SafeBrowsing.jsm \
|
||||||
|
$(NULL)
|
||||||
|
endif
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
182
mobile/android/components/SafeBrowsing.jsm
Normal file
182
mobile/android/components/SafeBrowsing.jsm
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
this.EXPORTED_SYMBOLS = ["SafeBrowsing"];
|
||||||
|
|
||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
const phishingList = "goog-phish-shavar";
|
||||||
|
const malwareList = "goog-malware-shavar";
|
||||||
|
|
||||||
|
var debug = false;
|
||||||
|
|
||||||
|
function log(...stuff) {
|
||||||
|
if (!debug)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let msg = "SafeBrowsing: " + stuff.join(" ");
|
||||||
|
Services.console.logStringMessage(msg);
|
||||||
|
dump(msg + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.SafeBrowsing = {
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
if (this.initialized) {
|
||||||
|
log("Already initialized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.prefs.addObserver("browser.safebrowsing", this.readPrefs, false);
|
||||||
|
this.readPrefs();
|
||||||
|
|
||||||
|
// Register our two types of tables, and add custom Mozilla entries
|
||||||
|
let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
|
||||||
|
getService(Ci.nsIUrlListManager);
|
||||||
|
listManager.registerTable(phishingList, false);
|
||||||
|
listManager.registerTable(malwareList, false);
|
||||||
|
this.addMozEntries();
|
||||||
|
|
||||||
|
this.controlUpdateChecking();
|
||||||
|
this.initialized = true;
|
||||||
|
|
||||||
|
log("init() finished");
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
initialized: false,
|
||||||
|
phishingEnabled: false,
|
||||||
|
malwareEnabled: false,
|
||||||
|
|
||||||
|
updateURL: null,
|
||||||
|
keyURL: null,
|
||||||
|
gethashURL: null,
|
||||||
|
|
||||||
|
reportURL: null,
|
||||||
|
reportGenericURL: null,
|
||||||
|
reportErrorURL: null,
|
||||||
|
reportPhishURL: null,
|
||||||
|
reportMalwareURL: null,
|
||||||
|
reportMalwareErrorURL: null,
|
||||||
|
|
||||||
|
|
||||||
|
getReportURL: function(kind) {
|
||||||
|
return this["report" + kind + "URL"];
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
readPrefs: function() {
|
||||||
|
log("reading prefs");
|
||||||
|
|
||||||
|
debug = Services.prefs.getBoolPref("browser.safebrowsing.debug");
|
||||||
|
this.phishingEnabled = Services.prefs.getBoolPref("browser.safebrowsing.enabled");
|
||||||
|
this.malwareEnabled = Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled");
|
||||||
|
this.updateProviderURLs();
|
||||||
|
|
||||||
|
// XXX The listManager backend gets confused if this is called before the
|
||||||
|
// lists are registered. So only call it here when a pref changes, and not
|
||||||
|
// when doing initialization. I expect to refactor this later, so pardon the hack.
|
||||||
|
if (this.initialized)
|
||||||
|
this.controlUpdateChecking();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
updateProviderURLs: function() {
|
||||||
|
#ifdef USE_HISTORIC_SAFEBROWSING_ID
|
||||||
|
let clientID = "navclient-auto-ffox";
|
||||||
|
#else
|
||||||
|
#expand let clientID = __MOZ_APP_UA_NAME__;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
log("initializing safe browsing URLs");
|
||||||
|
let basePref = "browser.safebrowsing.";
|
||||||
|
|
||||||
|
// Urls to HTML report pages
|
||||||
|
this.reportURL = Services.urlFormatter.formatURLPref(basePref + "reportURL");
|
||||||
|
this.reportGenericURL = Services.urlFormatter.formatURLPref(basePref + "reportGenericURL");
|
||||||
|
this.reportErrorURL = Services.urlFormatter.formatURLPref(basePref + "reportErrorURL");
|
||||||
|
this.reportPhishURL = Services.urlFormatter.formatURLPref(basePref + "reportPhishURL");
|
||||||
|
this.reportMalwareURL = Services.urlFormatter.formatURLPref(basePref + "reportMalwareURL");
|
||||||
|
this.reportMalwareErrorURL = Services.urlFormatter.formatURLPref(basePref + "reportMalwareErrorURL");
|
||||||
|
|
||||||
|
// Urls used to update DB
|
||||||
|
this.updateURL = Services.urlFormatter.formatURLPref(basePref + "updateURL");
|
||||||
|
this.keyURL = Services.urlFormatter.formatURLPref(basePref + "keyURL");
|
||||||
|
this.gethashURL = Services.urlFormatter.formatURLPref(basePref + "gethashURL");
|
||||||
|
|
||||||
|
this.updateURL = this.updateURL.replace("SAFEBROWSING_ID", clientID);
|
||||||
|
this.keyURL = this.keyURL.replace("SAFEBROWSING_ID", clientID);
|
||||||
|
this.gethashURL = this.gethashURL.replace("SAFEBROWSING_ID", clientID);
|
||||||
|
|
||||||
|
let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
|
||||||
|
getService(Ci.nsIUrlListManager);
|
||||||
|
|
||||||
|
listManager.setUpdateUrl(this.updateURL);
|
||||||
|
// XXX Bug 779317 - setKeyUrl has the side effect of fetching a key from the server.
|
||||||
|
// This shouldn't happen if anti-phishing/anti-malware is disabled.
|
||||||
|
if (this.phishingEnabled || this.malwareEnabled)
|
||||||
|
listManager.setKeyUrl(this.keyURL);
|
||||||
|
listManager.setGethashUrl(this.gethashURL);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
controlUpdateChecking: function() {
|
||||||
|
log("phishingEnabled:", this.phishingEnabled, "malwareEnabled:", this.malwareEnabled);
|
||||||
|
|
||||||
|
let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
|
||||||
|
getService(Ci.nsIUrlListManager);
|
||||||
|
|
||||||
|
if (this.phishingEnabled)
|
||||||
|
listManager.enableUpdate(phishingList);
|
||||||
|
else
|
||||||
|
listManager.disableUpdate(phishingList);
|
||||||
|
|
||||||
|
if (this.malwareEnabled)
|
||||||
|
listManager.enableUpdate(malwareList);
|
||||||
|
else
|
||||||
|
listManager.disableUpdate(malwareList);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
addMozEntries: function() {
|
||||||
|
// Add test entries to the DB.
|
||||||
|
// XXX bug 779008 - this could be done by DB itself?
|
||||||
|
const phishURL = "mozilla.org/firefox/its-a-trap.html";
|
||||||
|
const malwareURL = "mozilla.org/firefox/its-an-attack.html";
|
||||||
|
|
||||||
|
let update = "n:1000\ni:test-malware-simple\nad:1\n" +
|
||||||
|
"a:1:32:" + malwareURL.length + "\n" +
|
||||||
|
malwareURL;
|
||||||
|
update += "n:1000\ni:test-phish-simple\nad:1\n" +
|
||||||
|
"a:1:32:" + phishURL.length + "\n" +
|
||||||
|
phishURL;
|
||||||
|
log("addMozEntries:", update);
|
||||||
|
|
||||||
|
let db = Cc["@mozilla.org/url-classifier/dbservice;1"].
|
||||||
|
getService(Ci.nsIUrlClassifierDBService);
|
||||||
|
|
||||||
|
// nsIUrlClassifierUpdateObserver
|
||||||
|
let dummyListener = {
|
||||||
|
updateUrlRequested: function() { },
|
||||||
|
streamFinished: function() { },
|
||||||
|
updateError: function() { },
|
||||||
|
updateSuccess: function() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
db.beginUpdate(dummyListener, "test-malware-simple,test-phish-simple", "");
|
||||||
|
db.beginStream("", "");
|
||||||
|
db.updateStream(update);
|
||||||
|
db.finishStream();
|
||||||
|
db.finishUpdate();
|
||||||
|
} catch(ex) {
|
||||||
|
// beginUpdate will throw harmlessly if there's an existing update in progress, ignore failures.
|
||||||
|
log("addMozEntries failed!", ex);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
@ -297,8 +297,6 @@
|
|||||||
@BINPATH@/components/nsDownloadManagerUI.js
|
@BINPATH@/components/nsDownloadManagerUI.js
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
|
||||||
@BINPATH@/components/GPSDGeolocationProvider.js
|
|
||||||
@BINPATH@/components/nsSidebar.manifest
|
@BINPATH@/components/nsSidebar.manifest
|
||||||
@BINPATH@/components/nsSidebar.js
|
@BINPATH@/components/nsSidebar.js
|
||||||
@BINPATH@/components/extensions.manifest
|
@BINPATH@/components/extensions.manifest
|
||||||
|
@ -345,8 +345,6 @@
|
|||||||
@BINPATH@/components/nsDownloadManagerUI.js
|
@BINPATH@/components/nsDownloadManagerUI.js
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
|
||||||
@BINPATH@/components/GPSDGeolocationProvider.js
|
|
||||||
@BINPATH@/components/nsSidebar.manifest
|
@BINPATH@/components/nsSidebar.manifest
|
||||||
@BINPATH@/components/nsSidebar.js
|
@BINPATH@/components/nsSidebar.js
|
||||||
@BINPATH@/components/extensions.manifest
|
@BINPATH@/components/extensions.manifest
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user