Merge m-c to m-i.

This commit is contained in:
Ms2ger 2012-05-25 11:15:32 +02:00
commit 65aa2a4593
583 changed files with 12249 additions and 4914 deletions

View File

@ -343,10 +343,10 @@ nsAccessiblePivot::MovePivotInternal(nsAccessible* aPosition)
nsAccessible*
nsAccessiblePivot::SearchBackward(nsAccessible* aAccessible,
nsIAccessibleTraversalRule* aRule,
bool searchCurrent,
nsresult* rv)
bool aSearchCurrent,
nsresult* aResult)
{
*rv = NS_OK;
*aResult = NS_OK;
// Initial position could be unset, in that case return null.
if (!aAccessible)
@ -357,9 +357,9 @@ nsAccessiblePivot::SearchBackward(nsAccessible* aAccessible,
PRUint16 filtered = nsIAccessibleTraversalRule::FILTER_IGNORE;
if (searchCurrent) {
*rv = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*rv, nsnull);
if (aSearchCurrent) {
*aResult = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*aResult, nsnull);
if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH)
return accessible;
}
@ -371,16 +371,17 @@ nsAccessiblePivot::SearchBackward(nsAccessible* aAccessible,
if (!(accessible = parent->GetChildAt(--idxInParent)))
continue;
*rv = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*rv, nsnull);
*aResult = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*aResult, nsnull);
nsAccessible* lastChild;
while (!(filtered & nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE) &&
(lastChild = accessible->LastChild())) {
parent = accessible;
accessible = lastChild;
*rv = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*rv, nsnull);
idxInParent = accessible->IndexInParent();
*aResult = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*aResult, nsnull);
}
if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH)
@ -390,8 +391,8 @@ nsAccessiblePivot::SearchBackward(nsAccessible* aAccessible,
if (!(accessible = parent))
break;
*rv = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*rv, nsnull);
*aResult = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*aResult, nsnull);
if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH)
return accessible;
@ -403,10 +404,10 @@ nsAccessiblePivot::SearchBackward(nsAccessible* aAccessible,
nsAccessible*
nsAccessiblePivot::SearchForward(nsAccessible* aAccessible,
nsIAccessibleTraversalRule* aRule,
bool searchCurrent,
nsresult* rv)
bool aSearchCurrent,
nsresult* aResult)
{
*rv = NS_OK;
*aResult = NS_OK;
// Initial position could be not set, in that case begin search from root.
nsAccessible *accessible = (!aAccessible) ? mRoot.get() : aAccessible;
@ -414,9 +415,9 @@ nsAccessiblePivot::SearchForward(nsAccessible* aAccessible,
RuleCache cache(aRule);
PRUint16 filtered = nsIAccessibleTraversalRule::FILTER_IGNORE;
*rv = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*rv, nsnull);
if (searchCurrent && (filtered & nsIAccessibleTraversalRule::FILTER_MATCH))
*aResult = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*aResult, nsnull);
if (aSearchCurrent && (filtered & nsIAccessibleTraversalRule::FILTER_MATCH))
return accessible;
while (true) {
@ -424,8 +425,8 @@ nsAccessiblePivot::SearchForward(nsAccessible* aAccessible,
while (!(filtered & nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE) &&
(firstChild = accessible->FirstChild())) {
accessible = firstChild;
*rv = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*rv, nsnull);
*aResult = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*aResult, nsnull);
if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH)
return accessible;
@ -447,8 +448,8 @@ nsAccessiblePivot::SearchForward(nsAccessible* aAccessible,
break;
accessible = sibling;
*rv = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*rv, nsnull);
*aResult = cache.ApplyFilter(accessible, &filtered);
NS_ENSURE_SUCCESS(*aResult, nsnull);
if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH)
return accessible;

View File

@ -60,16 +60,16 @@ private:
*/
nsAccessible* SearchForward(nsAccessible* aAccessible,
nsIAccessibleTraversalRule* aRule,
bool searchCurrent,
nsresult* rv);
bool aSearchCurrent,
nsresult* aResult);
/*
* Reverse search in preorder for the first accessible to match the rule.
*/
nsAccessible* SearchBackward(nsAccessible* aAccessible,
nsIAccessibleTraversalRule* aRule,
bool searchCurrent,
nsresult* rv);
bool aSearchCurrent,
nsresult* aResult);
/*
* Update the pivot, and notify observers.

View File

@ -9,7 +9,7 @@ const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
const INCLUDE_ROLE = 0x01;
const INCLUDE_DESC = 0x01;
const INCLUDE_NAME = 0x02;
const INCLUDE_CUSTOM = 0x04;
@ -79,7 +79,12 @@ var UtteranceGenerator = {
if (aForceName)
flags |= INCLUDE_NAME;
return func.apply(this, [aAccessible, roleString, flags]);
let state = {};
let extState = {};
aAccessible.getState(state, extState);
let states = {base: state.value, ext: extState.value};
return func.apply(this, [aAccessible, roleString, states, flags]);
},
/**
@ -122,93 +127,78 @@ var UtteranceGenerator = {
},
verbosityRoleMap: {
'menubar': INCLUDE_ROLE,
'scrollbar': INCLUDE_ROLE,
'grip': INCLUDE_ROLE,
'alert': INCLUDE_ROLE,
'menupopup': INCLUDE_ROLE,
'menuitem': INCLUDE_ROLE,
'tooltip': INCLUDE_ROLE,
'menubar': INCLUDE_DESC,
'scrollbar': INCLUDE_DESC,
'grip': INCLUDE_DESC,
'alert': INCLUDE_DESC,
'menupopup': INCLUDE_DESC,
'menuitem': INCLUDE_DESC,
'tooltip': INCLUDE_DESC,
'application': INCLUDE_NAME,
'document': INCLUDE_NAME,
'toolbar': INCLUDE_ROLE,
'link': INCLUDE_ROLE,
'list': INCLUDE_ROLE,
'listitem': INCLUDE_ROLE,
'outline': INCLUDE_ROLE,
'outlineitem': INCLUDE_ROLE,
'pagetab': INCLUDE_ROLE,
'graphic': INCLUDE_ROLE | INCLUDE_NAME,
'toolbar': INCLUDE_DESC,
'link': INCLUDE_DESC,
'list': INCLUDE_DESC,
'listitem': INCLUDE_DESC,
'outline': INCLUDE_DESC,
'outlineitem': INCLUDE_DESC,
'pagetab': INCLUDE_DESC,
'graphic': INCLUDE_DESC | INCLUDE_NAME,
'statictext': INCLUDE_NAME,
'text leaf': INCLUDE_NAME,
'pushbutton': INCLUDE_ROLE,
'checkbutton': INCLUDE_ROLE | INCLUDE_NAME,
'radiobutton': INCLUDE_ROLE | INCLUDE_NAME,
'combobox': INCLUDE_ROLE,
'droplist': INCLUDE_ROLE,
'progressbar': INCLUDE_ROLE,
'slider': INCLUDE_ROLE,
'spinbutton': INCLUDE_ROLE,
'diagram': INCLUDE_ROLE,
'animation': INCLUDE_ROLE,
'equation': INCLUDE_ROLE,
'buttonmenu': INCLUDE_ROLE,
'pagetablist': INCLUDE_ROLE,
'canvas': INCLUDE_ROLE,
'check menu item': INCLUDE_ROLE,
'label': INCLUDE_ROLE,
'password text': INCLUDE_ROLE,
'popup menu': INCLUDE_ROLE,
'radio menu item': INCLUDE_ROLE,
'toggle button': INCLUDE_ROLE,
'header': INCLUDE_ROLE,
'footer': INCLUDE_ROLE,
'entry': INCLUDE_ROLE,
'caption': INCLUDE_ROLE,
'document frame': INCLUDE_ROLE,
'heading': INCLUDE_ROLE,
'calendar': INCLUDE_ROLE,
'combobox list': INCLUDE_ROLE,
'combobox option': INCLUDE_ROLE,
'image map': INCLUDE_ROLE,
'option': INCLUDE_ROLE,
'listbox': INCLUDE_ROLE},
'pushbutton': INCLUDE_DESC,
'checkbutton': INCLUDE_DESC | INCLUDE_NAME,
'radiobutton': INCLUDE_DESC | INCLUDE_NAME,
'combobox': INCLUDE_DESC,
'droplist': INCLUDE_DESC,
'progressbar': INCLUDE_DESC,
'slider': INCLUDE_DESC,
'spinbutton': INCLUDE_DESC,
'diagram': INCLUDE_DESC,
'animation': INCLUDE_DESC,
'equation': INCLUDE_DESC,
'buttonmenu': INCLUDE_DESC,
'pagetablist': INCLUDE_DESC,
'canvas': INCLUDE_DESC,
'check menu item': INCLUDE_DESC,
'label': INCLUDE_DESC,
'password text': INCLUDE_DESC,
'popup menu': INCLUDE_DESC,
'radio menu item': INCLUDE_DESC,
'toggle button': INCLUDE_DESC,
'header': INCLUDE_DESC,
'footer': INCLUDE_DESC,
'entry': INCLUDE_DESC,
'caption': INCLUDE_DESC,
'document frame': INCLUDE_DESC,
'heading': INCLUDE_DESC,
'calendar': INCLUDE_DESC,
'combobox list': INCLUDE_DESC,
'combobox option': INCLUDE_DESC,
'image map': INCLUDE_DESC,
'option': INCLUDE_DESC,
'listbox': INCLUDE_DESC},
objectUtteranceFunctions: {
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aFlags) {
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
let desc = (aFlags & INCLUDE_ROLE) ?
this._getLocalizedRole(aRoleStr) : '';
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
let utterance = [];
if (desc) {
let state = {};
let extState = {};
aAccessible.getState(state, extState);
if (state.value & Ci.nsIAccessibleStates.STATE_CHECKABLE) {
let stateStr = (state.value & Ci.nsIAccessibleStates.STATE_CHECKED) ?
'objChecked' : 'objNotChecked';
desc = gStringBundle.formatStringFromName(stateStr, [desc], 1);
}
if (extState.value & Ci.nsIAccessibleStates.EXT_STATE_EXPANDABLE) {
let stateStr = (state.value & Ci.nsIAccessibleStates.STATE_EXPANDED) ?
'objExpanded' : 'objCollapsed';
desc = gStringBundle.formatStringFromName(stateStr, [desc], 1);
}
utterance.push(desc);
if (aFlags & INCLUDE_DESC) {
let desc = this._getLocalizedStates(aStates);
let roleStr = this._getLocalizedRole(aRoleStr);
if (roleStr)
desc.push(roleStr);
utterance.push(desc.join(' '));
}
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
if (name)
utterance.push(name);
return utterance;
},
heading: function heading(aAccessible, aRoleStr, aFlags) {
heading: function heading(aAccessible, aRoleStr, aStates, aFlags) {
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
let level = {};
aAccessible.groupPosition(level, {}, {});
@ -221,7 +211,7 @@ var UtteranceGenerator = {
return utterance;
},
listitem: function listitem(aAccessible, aRoleStr, aFlags) {
listitem: function listitem(aAccessible, aRoleStr, aStates, aFlags) {
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
let localizedRole = this._getLocalizedRole(aRoleStr);
let itemno = {};
@ -244,5 +234,35 @@ var UtteranceGenerator = {
} catch (x) {
return '';
}
},
_getLocalizedStates: function _getLocalizedStates(aStates) {
let stateUtterances = [];
if (aStates.base & Ci.nsIAccessibleStates.STATE_UNAVAILABLE) {
stateUtterances.push(gStringBundle.GetStringFromName('stateUnavailable'));
}
if (aStates.base & Ci.nsIAccessibleStates.STATE_CHECKABLE) {
let stateStr = (aStates.base & Ci.nsIAccessibleStates.STATE_CHECKED) ?
'stateChecked' : 'stateNotChecked';
stateUtterances.push(gStringBundle.GetStringFromName(stateStr));
}
if (aStates.ext & Ci.nsIAccessibleStates.EXT_STATE_EXPANDABLE) {
let stateStr = (aStates.base & Ci.nsIAccessibleStates.STATE_EXPANDED) ?
'stateExpanded' : 'stateCollapsed';
stateUtterances.push(gStringBundle.GetStringFromName(stateStr));
}
if (aStates.base & Ci.nsIAccessibleStates.STATE_REQUIRED) {
stateUtterances.push(gStringBundle.GetStringFromName('stateRequired'));
}
if (aStates.base & Ci.nsIAccessibleStates.STATE_TRAVERSED) {
stateUtterances.push(gStringBundle.GetStringFromName('stateTraversed'));
}
return stateUtterances;
}
};

View File

@ -136,8 +136,28 @@ var VirtualCursorController = {
let virtualCursor = this.getVirtualCursor(document);
let acc = virtualCursor.position;
if (acc.numActions > 0)
if (acc.numActions > 0) {
acc.doAction(0);
} else {
// XXX Some mobile widget sets do not expose actions properly
// (via ARIA roles, etc.), so we need to generate a click.
// Could possibly be made simpler in the future. Maybe core
// engine could expose nsCoreUtiles::DispatchMouseEvent()?
let docAcc = gAccRetrieval.getAccessibleFor(this.chromeWin.document);
let docX = {}, docY = {}, docW = {}, docH = {};
docAcc.getBounds(docX, docY, docW, docH);
let objX = {}, objY = {}, objW = {}, objH = {};
acc.getBounds(objX, objY, objW, objH);
let x = Math.round((objX.value - docX.value) + objW.value/2);
let y = Math.round((objY.value - docY.value) + objH.value/2);
let cwu = this.chromeWin.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
cwu.sendMouseEventToWindow('mousedown', x, y, 0, 1, 0, false);
cwu.sendMouseEventToWindow('mouseup', x, y, 0, 1, 0, false);
}
},
getVirtualCursor: function getVirtualCursor(document) {

View File

@ -420,6 +420,9 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
- (NSString*)role
{
if (mIsExpired)
return nil;
#ifdef DEBUG
NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(mGeckoAccessible),
"Does not support nsIAccessibleText when it should");
@ -633,8 +636,14 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[self invalidateChildren];
mIsExpired = YES;
id parent = [self parent];
if ([parent isKindOfClass:[mozAccessible class]])
[parent invalidateChildren];
mIsExpired = YES;
mGeckoAccessible = nsnull;
NS_OBJC_END_TRY_ABORT_BLOCK;
}

View File

@ -23,5 +23,9 @@
<a href="http://mozilla.org" title="Link 2 title">Link 2</a>
<a href="http://mozilla.org" title="Link 3 title">Link 3</a>
</p>
<ul>
<li>Hello<span> </span></li>
<li>World</li>
</ul>
</body>
</html>

View File

@ -61,7 +61,7 @@
'semper', ' nulla. ', 'Second Section Title',
'Sed accumsan luctus lacus, vitae mollis arcu tristique vulputate.',
'An ', 'embedded', ' document.', 'Hide me', 'Link 1', 'Link 2',
'Link 3']);
'Link 3', 'Hello', 'World']);
// Just a random smoke test to see if our setTextRange works.
gQueue.push(

View File

@ -30,6 +30,7 @@ build/Makefile
build/pgo/Makefile
build/pgo/blueprint/Makefile
build/pgo/js-input/Makefile
build/virtualenv/Makefile
config/Makefile
config/autoconf.mk
config/nspr/Makefile

View File

@ -1,14 +1,14 @@
[
{
"size": 195,
"digest": "ff960e3cb9e07865bde6fdb0d4127a11205d4cb70ee527e30ccc38f6370a9d750eb5da8993cb3c5de28b45836a3a20b8c25c4adcc68b1945a59dbe1c8b28cc23",
"algorithm": "sha512",
"size": 195,
"digest": "da2edcb1ec9b169f6c685d02ebd0bd4ad53ace2df58598f15e1bde43dd74bcb816620601587c97e636bda3327045b43c8f5e973672ebd904e06036f70466908f",
"algorithm": "sha512",
"filename": "setup.sh"
},
},
{
"size": 121135598,
"digest": "e182eb95105f186ec81546c373752c3af5b8fbc520fd14d37fcb1bb40efac76b96befe868b5a5a17f967bd04390122b7911d167dda1516225709cbd3a00e2c78",
"algorithm": "sha512",
"filename": "gonk-toolchain-1.tar.bz2"
"size": 121166734,
"digest": "10da1d28d49ff1aa9ad3d84e52235dc8ed7df6721530b896a53424480ec23a2e9f28cadd631f562342325611ecb72152be51f9b62616356f33005f6cc0fb82fe",
"algorithm": "sha512",
"filename": "gonk-toolchain-3.tar.bz2"
}
]

View File

@ -147,7 +147,7 @@ pref("app.update.silent", false);
// If set to true, the Update Service will apply updates in the background
// when it finishes downloading them.
pref("app.update.stage.enabled", false);
pref("app.update.stage.enabled", true);
// Update service URL:
pref("app.update.url", "https://aus3.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");

View File

@ -61,12 +61,6 @@ let (XULAppInfo = {
XULAppInfoFactory);
}
const FILENAME_BOOKMARKS_HTML = "bookmarks.html";
let (backup_date = new Date().toLocaleFormat("%Y-%m-%d")) {
const FILENAME_BOOKMARKS_JSON = "bookmarks-" + backup_date + ".json";
}
// Smart bookmarks constants.
const SMART_BOOKMARKS_VERSION = 4;
const SMART_BOOKMARKS_ON_TOOLBAR = 1;

View File

@ -2,12 +2,7 @@
head = head_bookmarks.js
tail =
[test_384370.js]
[test_398914.js]
[test_421483.js]
[test_457441-import-export-corrupt-bookmarks-html.js]
[test_bookmarksRestoreNotification.js]
[test_bookmarks_html.js]
[test_browserGlue_corrupt.js]
[test_browserGlue_corrupt_nobackup.js]
[test_browserGlue_corrupt_nobackup_default.js]

View File

@ -32,8 +32,7 @@ var gConnectionsDialog = {
}
}
var noProxiesPref = document.getElementById("network.proxy.no_proxies_on");
noProxiesPref.value = noProxiesPref.value.replace(/[;]/g,',');
this.sanitizeNoProxiesPref();
return true;
},
@ -159,6 +158,16 @@ var gConnectionsDialog = {
autoURLPref.value = autoURL.value = URIFixup.createFixupURI(autoURL.value, 0).spec;
} catch(ex) {}
},
sanitizeNoProxiesPref: function()
{
var noProxiesPref = document.getElementById("network.proxy.no_proxies_on");
// replace substrings of ; and \n with commas if they're neither immediately
// preceded nor followed by a valid separator character
noProxiesPref.value = noProxiesPref.value.replace(/([^, \n;])[;\n]+(?![,\n;])/g, '$1,');
// replace any remaining ; and \n since some may follow commas, etc.
noProxiesPref.value = noProxiesPref.value.replace(/[;\n]/g, '');
},
readHTTPProxyServer: function ()
{

View File

@ -139,17 +139,9 @@
<radio id="networkProxySOCKSVersion5" value="5" label="&socks5.label;" accesskey="&socks5.accesskey;" />
</radiogroup>
</row>
<row align="center">
<hbox align="center" pack="end">
<label value="&noproxy.label;" accesskey="&noproxy.accesskey;" control="networkProxyNone"/>
</hbox>
<textbox id="networkProxyNone" preference="network.proxy.no_proxies_on"/>
</row>
<row>
<spacer/>
<label value="&noproxyExplain.label;" control="networkProxyNone"/>
</row>
<label value="&noproxy.label;" accesskey="&noproxy.accesskey;" control="networkProxyNone"/>
<textbox id="networkProxyNone" preference="network.proxy.no_proxies_on" multiline="true" rows="2"/>
<label value="&noproxyExplain.label;" control="networkProxyNone"/>
</rows>
</grid>
<radio value="2" label="&autoTypeRadio.label;" accesskey="&autoTypeRadio.accesskey;"/>

View File

@ -16,6 +16,7 @@ _BROWSER_FILES = \
browser_bug410900.js \
browser_bug567487.js \
browser_bug731866.js \
browser_connection.js \
privacypane_tests.js \
browser_privacypane_1.js \
browser_privacypane_2.js \

View File

@ -0,0 +1,128 @@
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* 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/Services.jsm");
function test() {
waitForExplicitFinish();
// network.proxy.type needs to be backed up and restored because mochitest
// changes this setting from the default
let oldNetworkProxyType = Services.prefs.getIntPref("network.proxy.type");
registerCleanupFunction(function() {
Services.prefs.setIntPref("network.proxy.type", oldNetworkProxyType);
Services.prefs.clearUserPref("network.proxy.no_proxies_on");
Services.prefs.clearUserPref("browser.preferences.instantApply");
});
let connectionURI = "chrome://browser/content/preferences/connection.xul";
let windowWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
// instantApply must be true, otherwise connection dialog won't save
// when opened from in-content prefs
Services.prefs.setBoolPref("browser.preferences.instantApply", true);
// this observer is registered after the pref tab loads
let observer = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
// when connection window loads, run tests and acceptDialog()
let win = aSubject.QueryInterface(Components.interfaces.nsIDOMWindow);
win.addEventListener("load", function winLoadListener() {
win.removeEventListener("load", winLoadListener, false);
if (win.location.href == connectionURI) {
ok(true, "connection window opened");
runConnectionTests(win);
win.document.documentElement.acceptDialog();
}
}, false);
} else if (aTopic == "domwindowclosed") {
// finish up when connection window closes
let win = aSubject.QueryInterface(Components.interfaces.nsIDOMWindow);
if (win.location.href == connectionURI) {
windowWatcher.unregisterNotification(observer);
ok(true, "connection window closed");
// runConnectionTests will have changed this pref - make sure it was
// sanitized correctly when the dialog was accepted
is(Services.prefs.getCharPref("network.proxy.no_proxies_on"),
".a.com,.b.com,.c.com", "no_proxies_on pref has correct value");
gBrowser.removeCurrentTab();
finish();
}
}
}
}
/*
The connection dialog alone won't save onaccept since it uses type="child",
so it has to be opened as a sub dialog of the main pref tab.
Open the main tab here.
*/
gBrowser.selectedTab = gBrowser.addTab("about:preferences");
let newTabBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab);
newTabBrowser.addEventListener("load", function tabLoadListener() {
newTabBrowser.removeEventListener("load", tabLoadListener, true);
is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
windowWatcher.registerNotification(observer);
gBrowser.contentWindow.gAdvancedPane.showConnections();
}, true);
}
// run a bunch of tests on the window containing connection.xul
function runConnectionTests(win) {
let doc = win.document;
let networkProxyNone = doc.getElementById("networkProxyNone");
let networkProxyNonePref = doc.getElementById("network.proxy.no_proxies_on");
let networkProxyTypePref = doc.getElementById("network.proxy.type");
// make sure the networkProxyNone textbox is formatted properly
is(networkProxyNone.getAttribute("multiline"), "true",
"networkProxyNone textbox is multiline");
is(networkProxyNone.getAttribute("rows"), "2",
"networkProxyNone textbox has two rows");
// check if sanitizing the given input for the no_proxies_on pref results in
// expected string
function testSanitize(input, expected, errorMessage) {
networkProxyNonePref.value = input;
win.gConnectionsDialog.sanitizeNoProxiesPref();
is(networkProxyNonePref.value, expected, errorMessage);
}
// change this pref so proxy exceptions are actually configurable
networkProxyTypePref.value = 1;
is(networkProxyNone.disabled, false, "networkProxyNone textbox is enabled");
testSanitize(".a.com", ".a.com",
"sanitize doesn't mess up single filter");
testSanitize(".a.com, .b.com, .c.com", ".a.com, .b.com, .c.com",
"sanitize doesn't mess up multiple comma/space sep filters");
testSanitize(".a.com\n.b.com", ".a.com,.b.com",
"sanitize turns line break into comma");
testSanitize(".a.com,\n.b.com", ".a.com,.b.com",
"sanitize doesn't add duplicate comma after comma");
testSanitize(".a.com\n,.b.com", ".a.com,.b.com",
"sanitize doesn't add duplicate comma before comma");
testSanitize(".a.com,\n,.b.com", ".a.com,,.b.com",
"sanitize doesn't add duplicate comma surrounded by commas");
testSanitize(".a.com, \n.b.com", ".a.com, .b.com",
"sanitize doesn't add comma after comma/space");
testSanitize(".a.com\n .b.com", ".a.com, .b.com",
"sanitize adds comma before space");
testSanitize(".a.com\n\n\n;;\n;\n.b.com", ".a.com,.b.com",
"sanitize only adds one comma per substring of bad chars");
testSanitize(".a.com,,.b.com", ".a.com,,.b.com",
"duplicate commas from user are untouched");
testSanitize(".a.com\n.b.com\n.c.com,\n.d.com,\n.e.com",
".a.com,.b.com,.c.com,.d.com,.e.com",
"sanitize replaces things globally");
// will check that this was sanitized properly after window closes
networkProxyNonePref.value = ".a.com;.b.com\n.c.com";
}

View File

@ -8,27 +8,21 @@ function test() {
let newWin = window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
let notificationCount = 0;
let expected = false;
let observer = {
observe: function(aSubject, aTopic, aData) {
is(aTopic, "last-pb-context-exited", "Correct topic should be dispatched");
++notificationCount;
is(expected, true, "notification not expected yet");
Services.obs.removeObserver(observer, "last-pb-context-exited", false);
gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
finish();
}
};
Services.obs.addObserver(observer, "last-pb-context-exited", false);
newWin.gPrivateBrowsingUI.privateWindow = true;
SimpleTest.is(notificationCount, 0, "last-pb-context-exited should not be fired yet");
newWin.gPrivateBrowsingUI.privateWindow = false;
newWin.close();
expected = true;
newWin.close(); // this will cause the docshells to leave PB mode
newWin = null;
window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.garbageCollect(); // Make sure that the docshell is destroyed
SimpleTest.is(notificationCount, 1, "last-pb-context-exited should be fired once");
Services.obs.removeObserver(observer, "last-pb-context-exited", false);
// cleanup
gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
finish();
SpecialPowers.forceGC();
}, newWin);
}

View File

@ -0,0 +1,34 @@
# 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/.
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
# Paths here are topsrcdir-relative, and
# must be in dependency-order.
setuptools_packages := \
other-licenses/simplejson-2.1.1 \
testing/mozbase/manifestdestiny \
testing/mozbase/mozinfo \
testing/mozbase/mozinstall \
testing/mozbase/mozlog \
testing/mozbase/mozprocess \
testing/mozbase/mozprofile \
testing/mozbase/mozrunner \
$(NULL)
define install_setuptools_package
cd $(topsrcdir)/$(1)/; $(PYTHON) setup.py develop
endef
default::
$(foreach package,$(setuptools_packages),$(call install_setuptools_package,$(package)))
include $(topsrcdir)/config/rules.mk

View File

@ -212,6 +212,7 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI,
// and with startupcache not at all), but this is where we would start
// if we need to re-add.
// See bug 531886, bug 533038.
result->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
*aResult = result;
NS_ADDREF(*aResult);

View File

@ -308,6 +308,8 @@ MOZ_PGO_OPTIMIZE_FLAGS = @MOZ_PGO_OPTIMIZE_FLAGS@
MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@
MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@
MOZ_ALLOW_HEAP_EXECUTE_FLAGS = @MOZ_ALLOW_HEAP_EXECUTE_FLAGS@
MOZ_RTTI_FLAGS_ON = @_MOZ_RTTI_FLAGS_ON@
PROFILE_GEN_CFLAGS = @PROFILE_GEN_CFLAGS@

View File

@ -10,7 +10,7 @@
// For some reason, Apple's GCC refuses to honor -fno-exceptions when
// compiling ObjC.
#if __EXCEPTIONS && !(__OBJC__ && __GNUC__ && XP_IOS)
#if __EXCEPTIONS && !(__OBJC__ && __APPLE_CC__)
# error "STL code can only be used with -fno-exceptions"
#endif

View File

@ -594,6 +594,7 @@ proto/exec.h
psap.h
Pt.h
pthread.h
pthread_np.h
pwd.h
Python.h
QDOffscreen.h

View File

@ -239,7 +239,7 @@ if test -n "$gonkdir" ; then
;;
esac
CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/hardware/libhardware_legacy/include -I$gonkdir/system/core/include -isystem $gonkdir/bionic -I$gonkdir/frameworks/base/include -I$gonkdir/external/dbus $CPPFLAGS -I$gonkdir/frameworks/base/services/sensorservice"
CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/hardware/libhardware_legacy/include -I$gonkdir/system -I$gonkdir/system/core/include -isystem $gonkdir/bionic -I$gonkdir/frameworks/base/include -I$gonkdir/external/dbus $CPPFLAGS -I$gonkdir/frameworks/base/services/sensorservice"
CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS $STLPORT_CPPFLAGS"
LIBS="$LIBS $STLPORT_LIBS"
@ -369,6 +369,7 @@ case "$target" in
CPPFLAGS="-isystem $android_platform/usr/include $CPPFLAGS"
CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS"
ASFLAGS="-isystem $android_platform/usr/include -DANDROID $ASFLAGS"
dnl Add -llog by default, since we use it all over the place.
dnl Add --allow-shlib-undefined, because libGLESv2 links to an
@ -2267,6 +2268,22 @@ case "$target" in
LDFLAGS=$_SAVE_LDFLAGS
fi
dnl With newer linkers we need to pass -allow_heap_execute because of
dnl Microsoft Silverlight (5.1.10411.0 at least).
AC_MSG_CHECKING([for -allow_heap_execute option to ld])
_SAVE_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,-allow_heap_execute"
AC_TRY_LINK(,[return 0;],_HAVE_ALLOW_HEAP_EXECUTE=1,
_HAVE_ALLOW_HEAP_EXECUTE=)
if test -n "$_HAVE_ALLOW_HEAP_EXECUTE" ; then
AC_MSG_RESULT([yes])
MOZ_ALLOW_HEAP_EXECUTE_FLAGS="-Wl,-allow_heap_execute"
else
AC_MSG_RESULT([no])
fi
LDFLAGS=$_SAVE_LDFLAGS
MOZ_FIX_LINK_PATHS='-Wl,-executable_path,$(LIBXUL_DIST)/bin'
;;
@ -3182,11 +3199,11 @@ EOF
"$ac_cv_have_visibility_class_bug" = "no"; then
VISIBILITY_FLAGS='-I$(DIST)/system_wrappers -include $(topsrcdir)/config/gcc_hidden.h'
WRAP_SYSTEM_INCLUDES=1
STL_FLAGS='-I$(DIST)/stl_wrappers'
WRAP_STL_INCLUDES=1
else
VISIBILITY_FLAGS='-fvisibility=hidden'
fi # have visibility pragma bug
STL_FLAGS='-I$(DIST)/stl_wrappers'
WRAP_STL_INCLUDES=1
fi # have visibility pragma
fi # have visibility(default) attribute
fi # have visibility(hidden) attribute
@ -7014,6 +7031,7 @@ AC_SUBST(MOZ_OPTIMIZE)
AC_SUBST(MOZ_FRAMEPTR_FLAGS)
AC_SUBST(MOZ_OPTIMIZE_FLAGS)
AC_SUBST(MOZ_OPTIMIZE_LDFLAGS)
AC_SUBST(MOZ_ALLOW_HEAP_EXECUTE_FLAGS)
AC_SUBST(MOZ_OPTIMIZE_SIZE_TWEAK)
AC_SUBST(MOZ_PGO_OPTIMIZE_FLAGS)
@ -7920,10 +7938,9 @@ else
fi
AC_SUBST(CL_INCLUDES_PREFIX)
rm -f dummy-hello.c
_topsrcdirwin=`cd \`dirname $0\`; pwd -W`
dnl cl.py provides dependency generation for MSVC
CC_WRAPPER="$PYTHON -O $_topsrcdirwin/build/cl.py"
CXX_WRAPPER="$PYTHON -O $_topsrcdirwin/build/cl.py"
CC_WRAPPER='$(PYTHON) -O $(topsrcdir)/build/cl.py'
CXX_WRAPPER='$(PYTHON) -O $(topsrcdir)/build/cl.py'
COMPILER_DEPEND=1
fi
fi
@ -8565,7 +8582,6 @@ AC_SUBST(MOZ_MAPINFO)
AC_SUBST(MOZ_BROWSE_INFO)
AC_SUBST(MOZ_TOOLS_DIR)
AC_SUBST(WIN32_REDIST_DIR)
AC_SUBST(PYTHON)
AC_SUBST(MAKENSISU)
dnl Echo the CFLAGS to remove extra whitespace.
@ -8947,6 +8963,22 @@ AC_SUBST(MOZ_DEFINES)
rm -f confdefs.h
mv confdefs.h.save confdefs.h
dnl Create a virtualenv where we can install local Python packages
AC_MSG_RESULT([Creating Python virtualenv])
rm -rf _virtualenv
mkdir -p _virtualenv
MACOSX_DEPLOYMENT_TARGET= PYTHONDONTWRITEBYTECODE= $PYTHON $_topsrcdir/other-licenses/virtualenv/virtualenv.py ./_virtualenv
case "$host_os" in
mingw*)
PYTHON=`pwd`/_virtualenv/Scripts/python.exe
;;
*)
PYTHON=`pwd`/_virtualenv/bin/python
;;
esac
AC_SUBST(PYTHON)
dnl Load the list of Makefiles to generate.
dnl To add new Makefiles, edit allmakefiles.sh.
dnl allmakefiles.sh sets the variable, MAKEFILES.
@ -8970,6 +9002,10 @@ mv -f config/autoconf.mk config/autoconf.mk.orig 2> /dev/null
AC_OUTPUT($MAKEFILES)
# Populate the virtualenv
AC_MSG_RESULT([Populating Python virtualenv])
$MAKE -C build/virtualenv MACOSX_DEPLOYMENT_TARGET= || exit 1
# Generate a JSON config file for unittest harnesses etc to read
# build configuration details from in a standardized way.
OS_TARGET=${OS_TARGET} TARGET_CPU=${TARGET_CPU} MOZ_DEBUG=${MOZ_DEBUG} \

View File

@ -18,6 +18,7 @@
#include "nsStyleLinkElement.h"
#include "nsINodeInfo.h"
#include "nsIDocShell.h"
#include "nsILoadContext.h"
#include "nsIDocShellTreeItem.h"
#include "nsCPrefetchService.h"
#include "nsIURI.h"
@ -1032,6 +1033,13 @@ nsContentSink::ProcessOfflineManifest(const nsAString& aManifestSpec)
return;
}
// If the docshell's in private browsing mode, we don't want to do any
// manifest processing.
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(mDocShell);
if (loadContext->UsePrivateBrowsing()) {
return;
}
nsresult rv;
// Grab the application cache the document was loaded from, if any.

View File

@ -1478,7 +1478,12 @@ nsIContent::IMEState
nsIContent::GetDesiredIMEState()
{
if (!IsEditableInternal()) {
return IMEState(IMEState::DISABLED);
// Check for the special case where we're dealing with elements which don't
// have the editable flag set, but are readwrite (such as text controls).
if (!IsElement() ||
!AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
return IMEState(IMEState::DISABLED);
}
}
// NOTE: The content for independent editors (e.g., input[type=text],
// textarea) must override this method, so, we don't need to worry about

View File

@ -660,13 +660,24 @@ nsTextStateManager::ContentRemoved(nsIDocument* aDocument,
new TextChangeEvent(mWidget, offset, offset + childOffset, offset));
}
static bool IsEditable(nsINode* node) {
if (node->IsEditable()) {
return true;
}
// |node| might be readwrite (for example, a text control)
if (node->IsElement() && node->AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
return true;
}
return false;
}
static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
nsIContent* aContent)
{
if (aContent) {
nsINode* root = nsnull;
nsINode* node = aContent;
while (node && node->IsEditable()) {
while (node && IsEditable(node)) {
root = node;
node = node->GetNodeParent();
}

View File

@ -57,12 +57,19 @@ function runTest() {
scrollDown15PxWithPixelScrolling(scrollbox);
setTimeout(function checkThatScrollIsFinishedAlmostInstantly() {
is(scrollbox.scrollTop, scrollTopBefore + 15, "Pixel scrolling should have finished after waiting for one 0-interval timer. We shouldn't be scrolling smoothly, even though the pref is set.")
win.close();
clearPrefs();
SimpleTest.finish();
}, 0);
// wait for the next refresh driver run
window.mozRequestAnimationFrame(function() {
// actually, wait for the next one before checking results, since
// scrolling might not be flushed until after this code has run
window.mozRequestAnimationFrame(function() {
is(scrollbox.scrollTop, scrollTopBefore + 15,
"Pixel scrolling should have finished after one refresh driver iteration. " +
"We shouldn't be scrolling smoothly, even though the pref is set.");
win.close();
clearPrefs();
SimpleTest.finish();
});
});
}, win);
}

View File

@ -1285,22 +1285,22 @@ nsHTMLInputElement::AfterSetFiles(bool aSetValueChanged)
UpdateAllValidityStates(true);
}
void
nsHTMLInputElement::FireChangeEventIfNeeded()
{
nsString value;
GetValueInternal(value);
if (!IsSingleLineTextControl(false) || mFocusedValue.Equals(value)) {
return;
}
// Dispatch the change event.
mFocusedValue = value;
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
static_cast<nsIContent*>(this),
NS_LITERAL_STRING("change"), true,
false);
void
nsHTMLInputElement::FireChangeEventIfNeeded()
{
nsString value;
GetValueInternal(value);
if (!IsSingleLineTextControl(false) || mFocusedValue.Equals(value)) {
return;
}
// Dispatch the change event.
mFocusedValue = value;
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
static_cast<nsIContent*>(this),
NS_LITERAL_STRING("change"), true,
false);
}
const nsCOMArray<nsIDOMFile>&
@ -3203,7 +3203,6 @@ nsHTMLInputElement::IntrinsicState() const
}
if (PlaceholderApplies() && HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
!nsContentUtils::IsFocusedContent((nsIContent*)(this)) &&
IsValueEmpty()) {
state |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
}
@ -4075,8 +4074,7 @@ nsHTMLInputElement::OnValueChanged(bool aNotify)
// :-moz-placeholder pseudo-class may change when the value changes.
// However, we don't want to waste cycles if the state doesn't apply.
if (PlaceholderApplies() &&
HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
!nsContentUtils::IsFocusedContent(this)) {
HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
UpdateState(aNotify);
}
}

View File

@ -2645,7 +2645,11 @@ void nsHTMLMediaElement::ResourceLoaded()
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
AddRemoveSelfReference();
if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA) {
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
// MediaStream sources are put into HAVE_CURRENT_DATA state here on setup. If the
// stream is not blocked, we will receive a notification that will put it
// into HAVE_ENOUGH_DATA state.
ChangeReadyState(mStream ? nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA
: nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
}
// Ensure a progress event is dispatched at the end of download.
DispatchAsyncEvent(NS_LITERAL_STRING("progress"));

View File

@ -699,22 +699,22 @@ nsHTMLTextAreaElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
}
void
nsHTMLTextAreaElement::FireChangeEventIfNeeded()
{
nsString value;
GetValueInternal(value, true);
if (mFocusedValue.Equals(value)) {
return;
}
// Dispatch the change event.
mFocusedValue = value;
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
static_cast<nsIContent*>(this),
NS_LITERAL_STRING("change"), true,
false);
void
nsHTMLTextAreaElement::FireChangeEventIfNeeded()
{
nsString value;
GetValueInternal(value, true);
if (mFocusedValue.Equals(value)) {
return;
}
// Dispatch the change event.
mFocusedValue = value;
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
static_cast<nsIContent*>(this),
NS_LITERAL_STRING("change"), true,
false);
}
nsresult
@ -1146,7 +1146,6 @@ nsHTMLTextAreaElement::IntrinsicState() const
}
if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
!nsContentUtils::IsFocusedContent((nsIContent*)(this)) &&
IsValueEmpty()) {
state |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
}
@ -1515,8 +1514,7 @@ nsHTMLTextAreaElement::OnValueChanged(bool aNotify)
UpdateValueMissingValidityState();
if (validBefore != IsValid() ||
(HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)
&& !nsContentUtils::IsFocusedContent((nsIContent*)(this)))) {
HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
UpdateState(aNotify);
}
}

View File

@ -1934,16 +1934,9 @@ nsTextEditorState::ValueWasChanged(bool aNotify)
return;
}
bool showPlaceholder = false;
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
if (!nsContentUtils::IsFocusedContent(content)) {
// If the content is focused, we don't care about the changes because
// the placeholder is going to be hidden/shown on blur.
nsAutoString valueString;
GetValue(valueString, true);
showPlaceholder = valueString.IsEmpty();
}
SetPlaceholderClass(showPlaceholder, aNotify);
nsAutoString valueString;
GetValue(valueString, true);
SetPlaceholderClass(valueString.IsEmpty(), aNotify);
}
void

View File

@ -1761,6 +1761,17 @@ MediaStream::ChangeExplicitBlockerCount(PRInt32 aDelta)
GraphImpl()->AppendMessage(new Message(this, aDelta));
}
void
MediaStream::AddListenerImpl(already_AddRefed<MediaStreamListener> aListener)
{
MediaStreamListener* listener = *mListeners.AppendElement() = aListener;
listener->NotifyBlockingChanged(GraphImpl(),
mBlocked.GetAt(GraphImpl()->mCurrentTime) ? MediaStreamListener::BLOCKED : MediaStreamListener::UNBLOCKED);
if (mNotifiedFinished) {
listener->NotifyFinished(GraphImpl());
}
}
void
MediaStream::AddListener(MediaStreamListener* aListener)
{

View File

@ -83,6 +83,10 @@ class MediaStreamGraph;
* reentry into media graph methods is possible, although very much discouraged!
* You should do something non-blocking and non-reentrant (e.g. dispatch an
* event to some thread) and return.
*
* When a listener is first attached, we guarantee to send a NotifyBlockingChanged
* callback to notify of the initial blocking state. Also, if a listener is
* attached to a stream that has already finished, we'll call NotifyFinished.
*/
class MediaStreamListener {
public:
@ -263,10 +267,7 @@ public:
{
mExplicitBlockerCount.SetAtAndAfter(aTime, mExplicitBlockerCount.GetAt(aTime) + aDelta);
}
void AddListenerImpl(already_AddRefed<MediaStreamListener> aListener)
{
*mListeners.AppendElement() = aListener;
}
void AddListenerImpl(already_AddRefed<MediaStreamListener> aListener);
void RemoveListenerImpl(MediaStreamListener* aListener)
{
mListeners.RemoveElement(aListener);

View File

@ -1206,9 +1206,7 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
jsval val;
JSObject* proto = NULL;
if ((!::JS_LookupPropertyWithFlags(cx, global, className.get(),
JSRESOLVE_CLASSNAME,
&val)) ||
if ((!::JS_LookupPropertyWithFlags(cx, global, className.get(), 0, &val)) ||
JSVAL_IS_PRIMITIVE(val)) {
// We need to initialize the class.

View File

@ -2374,9 +2374,10 @@ nsXULDocument::PrepareToWalk()
PRUint32 piInsertionPoint = 0;
if (mState != eState_Master) {
piInsertionPoint = IndexOf(GetRootElement());
NS_ASSERTION(piInsertionPoint >= 0,
PRInt32 indexOfRoot = IndexOf(GetRootElement());
NS_ASSERTION(indexOfRoot >= 0,
"No root content when preparing to walk overlay!");
piInsertionPoint = indexOfRoot;
}
const nsTArray<nsRefPtr<nsXULPrototypePI> >& processingInstructions =

View File

@ -8794,6 +8794,10 @@ nsDocShell::GetInheritedPrincipal(bool aConsiderCurrentDocument)
bool
nsDocShell::ShouldCheckAppCache(nsIURI *aURI)
{
if (mInPrivateBrowsing) {
return false;
}
nsCOMPtr<nsIOfflineCacheUpdateService> offlineService =
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
if (!offlineService) {

View File

@ -1,3 +1,7 @@
/* The test text as octets for reference
* %83%86%83%6a%83%52%81%5b%83%68%82%cd%81%41%82%b7%82%d7%82%c4%82%cc%95%b6%8e%9a%82%c9%8c%c5%97%4c%82%cc%94%d4%8d%86%82%f0%95%74%97%5e%82%b5%82%dc%82%b7
*/
/* The test text decoded correctly as Shift_JIS */
const rightText="\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059";
@ -37,7 +41,15 @@ function afterChangeCharset() {
function test() {
waitForExplicitFinish();
var rootDir = getRootDirectory(gTestPath);
// Get the local directory. This needs to be a file: URI because chrome: URIs
// are always UTF-8 (bug 617339) and we are testing decoding from other
// charsets.
var jar = getJar(getRootDirectory(gTestPath));
var dir = jar ?
extractJarToTmp(jar) :
getChromeDir(getResolvedURI(gTestPath));
var rootDir = Services.io.newFileURI(dir).spec;
gBrowser.selectedTab = gBrowser.addTab(rootDir + "test-form_sjis.html");
gBrowser.selectedBrowser.addEventListener("load", afterOpen, true);
}

View File

@ -201,6 +201,15 @@ WebappsApplication.prototype = {
_receipts: [],
_installOrigin: null,
_installTime: 0,
__exposedProps__: {
origin: 'r',
manifest: 'r',
manifestURL: 'r',
installOrigin: 'r',
installTime: 'r',
launch: 'r',
uninstall: 'r'
},
get origin() {
return this._origin;

View File

@ -5306,11 +5306,10 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
JSObject **objp)
{
if (flags & (JSRESOLVE_ASSIGNING | JSRESOLVE_DECLARING |
JSRESOLVE_CLASSNAME | JSRESOLVE_QUALIFIED) ||
JSRESOLVE_QUALIFIED) ||
!JSID_IS_STRING(id)) {
// Nothing to do here if we're either assigning or declaring,
// resolving a class name, doing a qualified resolve, or
// resolving a number.
// doing a qualified resolve, or resolving a number.
return JS_TRUE;
}
@ -6944,7 +6943,7 @@ static JSBool
LocationSetterUnwrapper(JSContext *cx, JSHandleObject obj_, JSHandleId id, JSBool strict,
jsval *vp)
{
JS::RootedVarObject obj(cx, obj_);
JS::RootedObject obj(cx, obj_);
JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj);
if (wrapped) {
@ -6959,8 +6958,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj_, jsid id_, PRUint32 flags,
JSObject **objp, bool *_retval)
{
JS::RootedVarObject obj(cx, obj_);
JS::RootedVarId id(cx, id_);
JS::RootedObject obj(cx, obj_);
JS::RootedId id(cx, id_);
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);

View File

@ -1822,7 +1822,7 @@ nsDOMWindowUtils::GetParent(const JS::Value& aObject,
// Outerize if necessary.
if (parent) {
if (JSObjectOp outerize = js::GetObjectClass(parent)->ext.outerObject) {
*aParent = OBJECT_TO_JSVAL(outerize(aCx, JS::RootedVarObject(aCx, parent)));
*aParent = OBJECT_TO_JSVAL(outerize(aCx, JS::RootedObject(aCx, parent)));
}
}

View File

@ -1,523 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "domstubs.idl"
interface nsIFrameRequestCallback;
interface nsIControllers;
interface nsIDOMBlob;
interface nsIDOMLocation;
interface nsIDOMMediaQueryList;
interface nsIDOMOfflineResourceList;
interface nsIDOMPerformance;
interface nsIDOMStorage;
interface nsIPrompt;
interface nsISelection;
interface nsIVariant;
[scriptable, uuid(8fc58f56-f769-4368-a098-edd08550cf1a)]
interface nsIDOMMozURLProperty : nsISupports
{
DOMString createObjectURL(in nsIDOMBlob blob);
void revokeObjectURL(in DOMString URL);
};
/**
* The nsIDOMWindow interface is the primary interface for a DOM
* window object. It represents a single window object that may
* contain child windows if the document in the window contains a
* HTML frameset document or if the document contains iframe elements.
*
* @see <http://www.whatwg.org/html/#window>
*/
<<<<<<< HEAD
[scriptable, uuid(a89569e6-4fef-49a5-a19b-612ac481fa2e)]
=======
[scriptable, uuid(A1AF6CD9-C6E7-4037-99F8-DBCA1B03E345)]
>>>>>>> Bug 754997 - For <iframe mozbrowser>, override window.{top,parent,frameElement} in C++.
interface nsIDOMWindow : nsISupports
{
// the current browsing context
readonly attribute nsIDOMWindow window;
/* [replaceable] self */
readonly attribute nsIDOMWindow self;
/**
* Accessor for the document in this window.
*/
readonly attribute nsIDOMDocument document;
/**
* Set/Get the name of this window.
*
* This attribute is "replaceable" in JavaScript
*/
attribute DOMString name;
/* The setter that takes a string argument needs to be special cased! */
readonly attribute nsIDOMLocation location;
readonly attribute nsIDOMHistory history;
/* [replaceable] locationbar */
readonly attribute nsIDOMBarProp locationbar;
/* [replaceable] menubar */
readonly attribute nsIDOMBarProp menubar;
/* [replaceable] personalbar */
readonly attribute nsIDOMBarProp personalbar;
/**
* Accessor for the object that controls whether or not scrollbars
* are shown in this window.
*
* This attribute is "replaceable" in JavaScript
*/
readonly attribute nsIDOMBarProp scrollbars;
/* [replaceable] statusbar */
readonly attribute nsIDOMBarProp statusbar;
/* [replaceable] toolbar */
readonly attribute nsIDOMBarProp toolbar;
/* [replaceable] */
attribute DOMString status;
void close();
void stop();
void focus();
void blur();
// other browsing contexts
/* [replaceable] length */
readonly attribute unsigned long length;
/**
* |top| gets the root of the window hierarchy.
*
* This function does not cross chrome-content boundaries, so if this
* window's parent is of a different type, |top| will return this window.
*
* When script reads the top property, we run GetScriptableTop, which
* will not cross an <iframe mozbrowser> boundary.
*
* In contrast, C++ calls to GetTop are forwarded to GetRealTop, which
* ignores <iframe mozbrowser> boundaries.
*
* This property is "replaceable" in JavaScript.
*/
[binaryname(ScriptableTop)]
readonly attribute nsIDOMWindow top;
/**
* You shouldn't need to call this function directly; call GetTop instead.
*/
[noscript]
readonly attribute nsIDOMWindow realTop;
%{C++
nsresult GetTop(nsIDOMWindow **aWindow)
{
return GetRealTop(aWindow);
}
%}
/**
* |parent| gets this window's parent window. If this window has no parent,
* we return the window itself.
*
* This property does not cross chrome-content boundaries, so if this
* window's parent is of a different type, we return the window itself as its
* parent.
*
* When script reads the property (or when C++ calls ScriptableTop), this
* property does not cross <iframe mozbrowser> boundaries. In contrast, when
* C++ calls GetParent, we ignore the mozbrowser attribute.
*/
[binaryname(ScriptableParent)]
readonly attribute nsIDOMWindow parent;
/**
* You shouldn't need to read this property directly; call GetParent instead.
*/
[noscript]
readonly attribute nsIDOMWindow realParent;
%{C++
inline nsresult GetParent(nsIDOMWindow **aWindow)
{
return GetRealParent(aWindow);
}
%}
attribute nsIDOMWindow opener;
/**
* |frameElement| gets this window's <iframe> or <frame> element, if it has
* one.
*
* When script reads this property (or when C++ calls
* ScriptableFrameElement), we return |null| if the window is inside an
* <iframe mozbrowser>. In contrast, when C++ calls GetFrameElement, we
* ignore the mozbrowser attribute.
*/
[binaryname(ScriptableFrameElement)]
readonly attribute nsIDOMElement frameElement;
/**
* You shouldn't need to read this property directly; call GetFrameElement
* instead.
*/
[noscript]
readonly attribute nsIDOMElement realFrameElement;
%{C++
inline nsresult GetFrameElement(nsIDOMElement **aElement)
{
return GetRealFrameElement(aElement);
}
%}
// the user agent
readonly attribute nsIDOMNavigator navigator;
/**
* Get the application cache object for this window.
*/
readonly attribute nsIDOMOfflineResourceList applicationCache;
// user prompts
void alert(in DOMString text);
boolean confirm(in DOMString text);
// prompt() should return a null string if cancel is pressed
DOMString prompt([optional] in DOMString aMessage,
[optional] in DOMString aInitial);
void print();
nsIVariant showModalDialog(in DOMString aURI,
[optional] in nsIVariant aArgs,
[optional] in DOMString aOptions);
// cross-document messaging
/**
* Implements a safe message-passing system which can cross same-origin
* boundaries.
*
* This method, when called, causes a MessageEvent to be asynchronously
* dispatched at the primary document for the window upon which this method is
* called. (Note that the postMessage property on windows is allAccess and
* thus is readable cross-origin.) The dispatched event will have message as
* its data, the calling context's window as its source, and an origin
* determined by the calling context's main document URI. The targetOrigin
* argument specifies a URI and is used to restrict the message to be sent
* only when the target window has the same origin as targetOrigin (since,
* when the sender and the target have different origins, neither can read the
* location of the other).
*
* @see <http://www.whatwg.org/html/#dom-window-postmessage>
*/
[implicit_jscontext, binaryname(PostMessageMoz)]
void postMessage(in jsval message, in DOMString targetOrigin);
// WindowBase64
// Ascii base64 data to binary data and vice versa...
DOMString atob(in DOMString aAsciiString);
DOMString btoa(in DOMString aBase64Data);
// WindowSessionStorage
/**
* Session storage for the current browsing context.
*/
readonly attribute nsIDOMStorage sessionStorage;
// WindowLocalStorage
/**
* Local storage for the current browsing context.
*/
readonly attribute nsIDOMStorage localStorage;
// DOM Range
/**
* Method for accessing this window's selection object.
*/
nsISelection getSelection();
// CSSOM-View
// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface
nsIDOMMediaQueryList matchMedia(in DOMString media_query_list);
readonly attribute nsIDOMScreen screen;
// viewport
attribute long innerWidth;
attribute long innerHeight;
// viewport scrolling
/**
* Accessor for the current x scroll position in this window in
* pixels.
*
* This attribute is "replaceable" in JavaScript
*/
readonly attribute long scrollX;
/* The offset in pixels by which the window is scrolled */
readonly attribute long pageXOffset;
/**
* Accessor for the current y scroll position in this window in
* pixels.
*
* This attribute is "replaceable" in JavaScript
*/
readonly attribute long scrollY;
/* The offset in pixels by which the window is scrolled */
readonly attribute long pageYOffset;
void scroll(in long xScroll, in long yScroll);
/**
* Method for scrolling this window to an absolute pixel offset.
*/
void scrollTo(in long xScroll, in long yScroll);
/**
* Method for scrolling this window to a pixel offset relative to
* the current scroll position.
*/
void scrollBy(in long xScrollDif, in long yScrollDif);
// client
attribute long screenX;
attribute long screenY;
attribute long outerWidth;
attribute long outerHeight;
// CSSOM
/**
* @see <http://dev.w3.org/csswg/cssom/#dom-window-getcomputedstyle>
*/
nsIDOMCSSStyleDeclaration getComputedStyle(in nsIDOMElement elt,
[optional] in DOMString pseudoElt);
// Mozilla extensions
/**
* Get the window root for this window. This is useful for hooking
* up event listeners to this window and every other window nested
* in the window root.
*/
[noscript] readonly attribute nsIDOMEventTarget windowRoot;
/**
* Accessor for the child windows in this window.
*/
[noscript] readonly attribute nsIDOMWindowCollection frames;
/**
* Set/Get the document scale factor as a multiplier on the default
* size. When setting this attribute, a NS_ERROR_NOT_IMPLEMENTED
* error may be returned by implementations not supporting
* zoom. Implementations not supporting zoom should return 1.0 all
* the time for the Get operation. 1.0 is equals normal size,
* i.e. no zoom.
*/
[noscript] attribute float textZoom;
/**
* Method for scrolling this window by a number of lines.
*/
void scrollByLines(in long numLines);
/**
* Method for scrolling this window by a number of pages.
*/
void scrollByPages(in long numPages);
/**
* Method for sizing this window to the content in the window.
*/
void sizeToContent();
/* [replaceable] content */
readonly attribute nsIDOMWindow content;
/* [replaceable] prompter */
[noscript] readonly attribute nsIPrompt prompter;
readonly attribute boolean closed;
// http://wiki.whatwg.org/wiki/Crypto
readonly attribute nsIDOMCrypto crypto;
readonly attribute nsIDOMPkcs11 pkcs11;
// XXX Shouldn't this be in nsIDOMChromeWindow?
/* [replaceable] controllers */
readonly attribute nsIControllers controllers;
attribute DOMString defaultStatus;
readonly attribute float mozInnerScreenX;
readonly attribute float mozInnerScreenY;
/* The maximum offset that the window can be scrolled to
(i.e., the document width/height minus the scrollport width/height) */
readonly attribute long scrollMaxX;
readonly attribute long scrollMaxY;
attribute boolean fullScreen;
void back();
void forward();
void home();
void moveTo(in long xPos, in long yPos);
void moveBy(in long xDif, in long yDif);
void resizeTo(in long width, in long height);
void resizeBy(in long widthDif, in long heightDif);
/**
* Open a new window with this one as the parent. This method will
* NOT examine the JS stack for purposes of determining a caller.
* This window will be used for security checks during the search by
* name and the default character set on the newly opened window
* will just be the default character set of this window.
*/
[noscript] nsIDOMWindow open(in DOMString url, in DOMString name,
in DOMString options);
/**
* This method works like open except that aExtraArgument gets
* converted into the array window.arguments in JS, if
* aExtraArgument is a nsISupportsArray then the individual items in
* the array are inserted into window.arguments, and primitive
* nsISupports (nsISupportsPrimitives) types are converted to native
* JS types when possible.
*/
[noscript] nsIDOMWindow openDialog(in DOMString url, in DOMString name,
in DOMString options,
in nsISupports aExtraArgument);
// XXX Should this be in nsIDOMChromeWindow?
void updateCommands(in DOMString action);
/* Find in page.
* @param str: the search pattern
* @param caseSensitive: is the search caseSensitive
* @param backwards: should we search backwards
* @param wrapAround: should we wrap the search
* @param wholeWord: should we search only for whole words
* @param searchInFrames: should we search through all frames
* @param showDialog: should we show the Find dialog
*/
boolean find([optional] in DOMString str,
[optional] in boolean caseSensitive,
[optional] in boolean backwards,
[optional] in boolean wrapAround,
[optional] in boolean wholeWord,
[optional] in boolean searchInFrames,
[optional] in boolean showDialog);
/**
* Returns the number of times this document for this window has
* been painted to the screen.
*/
readonly attribute unsigned long long mozPaintCount;
/**
* Request a refresh of this browser window.
*
* @see <http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html>
*/
// Argument is optional only so we can warn when it's null
long
mozRequestAnimationFrame([optional] in nsIFrameRequestCallback aCallback);
/**
* Cancel a refresh callback.
*/
void mozCancelAnimationFrame(in long aHandle);
// Backwards-compat shim for now to make Google maps work
void mozCancelRequestAnimationFrame(in long aHandle);
/**
* The current animation start time in milliseconds since the epoch.
*/
readonly attribute long long mozAnimationStartTime;
/**
* @see <http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking>
*/
readonly attribute nsIDOMMozURLProperty URL;
/**
* HTML5 event attributes that only apply to windows and <body>/<frameset>
*/
[implicit_jscontext] attribute jsval onafterprint;
[implicit_jscontext] attribute jsval onbeforeprint;
[implicit_jscontext] attribute jsval onbeforeunload;
[implicit_jscontext] attribute jsval onhashchange;
[implicit_jscontext] attribute jsval onmessage;
[implicit_jscontext] attribute jsval onoffline;
[implicit_jscontext] attribute jsval ononline;
[implicit_jscontext] attribute jsval onpopstate;
[implicit_jscontext] attribute jsval onpagehide;
[implicit_jscontext] attribute jsval onpageshow;
// Not supported yet
// [implicit_jscontext] attribute jsval onredo;
[implicit_jscontext] attribute jsval onresize;
// Not supported yet
// [implicit_jscontext] attribute jsval onstorage;
// Not supported yet
// [implicit_jscontext] attribute jsval onundo;
[implicit_jscontext] attribute jsval onunload;
/**
* Non-HTML5 window-specific event attributes
*/
[implicit_jscontext] attribute jsval ondevicemotion;
[implicit_jscontext] attribute jsval ondeviceorientation;
[implicit_jscontext] attribute jsval ondeviceproximity;
[implicit_jscontext] attribute jsval onuserproximity;
[implicit_jscontext] attribute jsval ondevicelight;
[implicit_jscontext] attribute jsval onmouseenter;
[implicit_jscontext] attribute jsval onmouseleave;
};
[scriptable, uuid(2146c906-57f7-486c-a1b4-8cdb57ef577f)]
interface nsIDOMWindowPerformance : nsISupports
{
/**
* A namespace to hold performance related data and statistics.
*/
readonly attribute nsIDOMPerformance performance;
};
/**
* Empty interface for compatibility with older versions.
* @deprecated Use nsIDOMWindow instead
*/
[scriptable, uuid(8da641ab-906a-456e-97f2-b77df4ca2d95)]
interface nsIDOMWindowInternal : nsIDOMWindow {};

View File

@ -73,10 +73,6 @@ definition = definition
headingLevel = heading level %S
# LOCALIZATION NOTE: %1$S is the item's role name (e.g. "List item" or "Page tab"), %2$S is the position of the item n the set. %3$S is the total number of such items in the set. An expanded example would read "List item 2 of 5".
objItemOf = %1$S %2$S of %3$S
objChecked = checked %S
objNotChecked = not checked %S
objExpanded = expanded %S
objCollapsed = collapsed %S
# Invoked actions
jumpAction = jumped
@ -99,3 +95,12 @@ tabLoaded = loaded
tabNew = new tab
tabLoadStopped = loading stopped
tabReload = reloading
# Object states
stateChecked = checked
stateNotChecked = not checked
stateExpanded = expanded
stateCollapsed = collapsed
stateUnavailable = unavailable
stateRequired = required
stateTraversed = visited

View File

@ -299,7 +299,7 @@ nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer()
#endif
if (mPStreamListener) {
mPStreamListener->SetStreamListenerPeer(this);
mPStreamListener->SetStreamListenerPeer(nsnull);
}
// close FD of mFileCacheOutputStream if it's still open

View File

@ -0,0 +1,490 @@
/* 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 <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <android/log.h>
#include "AutoMounter.h"
#include "AutoMounterSetting.h"
#include "base/message_loop.h"
#include "mozilla/FileUtils.h"
#include "mozilla/Hal.h"
#include "nsAutoPtr.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include "Volume.h"
#include "VolumeManager.h"
using namespace mozilla::hal;
/**************************************************************************
*
* The following "switch" files are available for monitoring usb
* connections:
*
* /sys/devices/virtual/switch/usb_connected/state
* /sys/devices/virtual/switch/usb_configuration/state
*
* Under gingerbread, only the usb_configuration seems to be available.
* Starting with honeycomb, usb_connected was also added.
*
* When a cable insertion/removal occurs, then a uevent similar to the
* following will be generted:
*
* change@/devices/virtual/switch/usb_configuration
* ACTION=change
* DEVPATH=/devices/virtual/switch/usb_configuration
* SUBSYSTEM=switch
* SWITCH_NAME=usb_configuration
* SWITCH_STATE=0
* SEQNUM=5038
*
* SWITCH_STATE will be 0 after a removal and 1 after an insertion
*
**************************************************************************/
#define USB_CONFIGURATION_SWITCH_NAME NS_LITERAL_STRING("usb_configuration")
#define GB_SYS_UMS_ENABLE "/sys/devices/virtual/usb_composite/usb_mass_storage/enable"
#define GB_SYS_USB_CONFIGURED "/sys/devices/virtual/switch/usb_configuration/state"
#define ICS_SYS_USB_FUNCTIONS "/sys/devices/virtual/android_usb/android0/functions"
#define ICS_SYS_UMS_DIRECTORY "/sys/devices/virtual/android_usb/android0/f_mass_storage"
#define ICS_SYS_USB_STATE "/sys/devices/virtual/android_usb/android0/state"
#define USE_DEBUG 0
#undef LOG
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AutoMounter" , ## args)
#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "AutoMounter" , ## args)
#if USE_DEBUG
#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "AutoMounter" , ## args)
#else
#define DBG(args...)
#endif
namespace mozilla {
namespace system {
class AutoMounter;
/**************************************************************************
*
* Some helper functions for reading/writing files in /sys
*
**************************************************************************/
static bool
ReadSysFile(const char *aFilename, char *aBuf, size_t aBufSize)
{
int fd = open(aFilename, O_RDONLY);
if (fd < 0) {
ERR("Unable to open file '%s' for reading", aFilename);
return false;
}
ScopedClose autoClose(fd);
ssize_t bytesRead = read(fd, aBuf, aBufSize - 1);
if (bytesRead < 0) {
ERR("Unable to read from file '%s'", aFilename);
return false;
}
if (aBuf[bytesRead - 1] == '\n') {
bytesRead--;
}
aBuf[bytesRead] = '\0';
return true;
}
static bool
ReadSysFile(const char *aFilename, bool *aVal)
{
char valBuf[20];
if (!ReadSysFile(aFilename, valBuf, sizeof(valBuf))) {
return false;
}
int intVal;
if (sscanf(valBuf, "%d", &intVal) != 1) {
return false;
}
*aVal = (intVal != 0);
return true;
}
/***************************************************************************/
inline const char *SwitchStateStr(const SwitchEvent &aEvent)
{
return aEvent.status() == SWITCH_STATE_ON ? "plugged" : "unplugged";
}
/***************************************************************************/
static bool
IsUsbCablePluggedIn()
{
#if 0
// Use this code when bug 745078 gets fixed (or use whatever the
// appropriate method is)
return GetCurrentSwitchEvent(SWITCH_USB) == SWITCH_STATE_ON;
#else
// Until then, just go read the file directly
if (access(ICS_SYS_USB_STATE, F_OK) == 0) {
char usbState[20];
return ReadSysFile(ICS_SYS_USB_STATE,
usbState, sizeof(usbState)) &&
(strcmp(usbState, "CONFIGURED") == 0);
}
bool configured;
return ReadSysFile(GB_SYS_USB_CONFIGURED, &configured) &&
configured;
#endif
}
/***************************************************************************/
class VolumeManagerStateObserver : public VolumeManager::StateObserver
{
public:
virtual void Notify(const VolumeManager::StateChangedEvent &aEvent);
};
class AutoMounterResponseCallback : public VolumeResponseCallback
{
public:
AutoMounterResponseCallback()
: mErrorCount(0)
{
}
protected:
virtual void ResponseReceived(const VolumeCommand *aCommand);
private:
const static int kMaxErrorCount = 3; // Max number of errors before we give up
int mErrorCount;
};
/***************************************************************************/
class AutoMounter : public RefCounted<AutoMounter>
{
public:
AutoMounter()
: mResponseCallback(new AutoMounterResponseCallback),
mMode(AUTOMOUNTER_DISABLE)
{
VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver);
DBG("Calling UpdateState from constructor");
UpdateState();
}
~AutoMounter()
{
VolumeManager::UnregisterStateObserver(&mVolumeManagerStateObserver);
}
void UpdateState();
void SetMode(int32_t aMode)
{
if ((aMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) &&
(mMode == AUTOMOUNTER_DISABLE)) {
// If it's already disabled, then leave it as disabled.
// AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED implies "enabled until unplugged"
aMode = AUTOMOUNTER_DISABLE;
}
mMode = aMode;
DBG("Calling UpdateState due to mode set to %d", mMode);
UpdateState();
}
private:
VolumeManagerStateObserver mVolumeManagerStateObserver;
RefPtr<VolumeResponseCallback> mResponseCallback;
int32_t mMode;
};
static RefPtr<AutoMounter> sAutoMounter;
/***************************************************************************/
void
VolumeManagerStateObserver::Notify(const VolumeManager::StateChangedEvent &)
{
LOG("VolumeManager state changed event: %s", VolumeManager::StateStr());
if (!sAutoMounter) {
return;
}
DBG("Calling UpdateState due to VolumeManagerStateObserver");
sAutoMounter->UpdateState();
}
void
AutoMounterResponseCallback::ResponseReceived(const VolumeCommand *aCommand)
{
if (WasSuccessful()) {
DBG("Calling UpdateState due to Volume::OnSuccess");
mErrorCount = 0;
sAutoMounter->UpdateState();
return;
}
ERR("Command '%s' failed: %d '%s'",
aCommand->CmdStr(), ResponseCode(), ResponseStr().get());
if (++mErrorCount < kMaxErrorCount) {
DBG("Calling UpdateState due to VolumeResponseCallback::OnError");
sAutoMounter->UpdateState();
}
}
/***************************************************************************/
void
AutoMounter::UpdateState()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
// If the following preconditions are met:
// - UMS is available (i.e. compiled into the kernel)
// - UMS is enabled
// - AutoMounter is enabled
// - USB cable is plugged in
// then we will try to unmount and share
// otherwise we will try to unshare and mount.
if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
// The volume manager isn't in a ready state, so there
// isn't anything else that we can do.
LOG("UpdateState: VolumeManager not ready yet");
return;
}
if (mResponseCallback->IsPending()) {
// We only deal with one outstanding volume command at a time,
// so we need to wait for it to finish.
return;
}
std::vector<RefPtr<Volume> > volumeArray;
RefPtr<Volume> vol = VolumeManager::FindVolumeByName(NS_LITERAL_CSTRING("sdcard"));
if (vol != NULL) {
volumeArray.push_back(vol);
}
if (volumeArray.size() == 0) {
// No volumes of interest, nothing to do
LOG("UpdateState: No volumes found");
return;
}
bool umsAvail = false;
bool umsEnabled = false;
if (access(ICS_SYS_USB_FUNCTIONS, F_OK) == 0) {
umsAvail = (access(ICS_SYS_UMS_DIRECTORY, F_OK) == 0);
char functionsStr[60];
umsEnabled = umsAvail &&
ReadSysFile(ICS_SYS_USB_FUNCTIONS, functionsStr, sizeof(functionsStr)) &&
!!strstr(functionsStr, "mass_storage");
} else {
umsAvail = ReadSysFile(GB_SYS_UMS_ENABLE, &umsEnabled);
}
bool usbCablePluggedIn = IsUsbCablePluggedIn();
bool enabled = (mMode == AUTOMOUNTER_ENABLE);
if (mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) {
enabled = usbCablePluggedIn;
if (!usbCablePluggedIn) {
mMode = AUTOMOUNTER_DISABLE;
}
}
bool tryToShare = (umsAvail && umsEnabled && enabled && usbCablePluggedIn);
LOG("UpdateState: umsAvail:%d umsEnabled:%d mode:%d usbCablePluggedIn:%d tryToShare:%d",
umsAvail, umsEnabled, mMode, usbCablePluggedIn, tryToShare);
VolumeManager::VolumeArray::iterator volIter;
for (volIter = volumeArray.begin(); volIter != volumeArray.end(); volIter++) {
RefPtr<Volume> vol = *volIter;
Volume::STATE volState = vol->State();
LOG("UpdateState: Volume %s is %s", vol->NameStr(), vol->StateStr());
if (tryToShare) {
// We're going to try to unmount and share the volumes
switch (volState) {
case Volume::STATE_MOUNTED: {
// Volume is mounted, we need to unmount before
// we can share.
DBG("UpdateState: Unmounting %s", vol->NameStr());
vol->StartUnmount(mResponseCallback);
return;
}
case Volume::STATE_IDLE: {
// Volume is unmounted. We can go ahead and share.
DBG("UpdateState: Sharing %s", vol->NameStr());
vol->StartShare(mResponseCallback);
return;
}
default: {
// Not in a state that we can do anything about.
break;
}
}
} else {
// We're going to try and unshare and remount the volumes
switch (volState) {
case Volume::STATE_SHARED: {
// Volume is shared. We can go ahead and unshare.
DBG("UpdateState: Unsharing %s", vol->NameStr());
vol->StartUnshare(mResponseCallback);
return;
}
case Volume::STATE_IDLE: {
// Volume is unmounted, try to mount.
DBG("UpdateState: Mounting %s", vol->NameStr());
vol->StartMount(mResponseCallback);
return;
}
default: {
// Not in a state that we can do anything about.
break;
}
}
}
}
}
/***************************************************************************/
static void
InitAutoMounterIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
MOZ_ASSERT(!sAutoMounter);
sAutoMounter = new AutoMounter();
}
static void
ShutdownAutoMounterIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
sAutoMounter = NULL;
ShutdownVolumeManager();
}
static void
SetAutoMounterModeIOThread(const int32_t &aMode)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
MOZ_ASSERT(sAutoMounter);
sAutoMounter->SetMode(aMode);
}
static void
UsbCableEventIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
if (!sAutoMounter) {
return;
}
DBG("Calling UpdateState due to USBCableEvent");
sAutoMounter->UpdateState();
}
/**************************************************************************
*
* Public API
*
* Since the AutoMounter runs in IO Thread context, we need to switch
* to IOThread context before we can do anything.
*
**************************************************************************/
class UsbCableObserver : public SwitchObserver,
public RefCounted<UsbCableObserver>
{
public:
UsbCableObserver()
{
RegisterSwitchObserver(SWITCH_USB, this);
}
~UsbCableObserver()
{
UnregisterSwitchObserver(SWITCH_USB, this);
}
virtual void Notify(const SwitchEvent &aEvent)
{
DBG("UsbCable switch device: %d state: %s\n",
aEvent.device(), SwitchStateStr(aEvent));
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(UsbCableEventIOThread));
}
};
static RefPtr<UsbCableObserver> sUsbCableObserver;
static RefPtr<AutoMounterSetting> sAutoMounterSetting;
void
InitAutoMounter()
{
InitVolumeManager();
sAutoMounterSetting = new AutoMounterSetting();
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(InitAutoMounterIOThread));
// Switch Observers need to run on the main thread, so we need to
// start it here and have it send events to the AutoMounter running
// on the IO Thread.
sUsbCableObserver = new UsbCableObserver();
}
void
SetAutoMounterMode(int32_t aMode)
{
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(SetAutoMounterModeIOThread, aMode));
}
void
ShutdownAutoMounter()
{
sAutoMounterSetting = NULL;
sUsbCableObserver = NULL;
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(ShutdownAutoMounterIOThread));
}
} // system
} // mozilla

View File

@ -0,0 +1,47 @@
/* 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_system_automounter_h__
#define mozilla_system_automounter_h__
#include "mozilla/StandardInteger.h"
namespace mozilla {
namespace system {
// AutoMounter modes
#define AUTOMOUNTER_DISABLE 0
#define AUTOMOUNTER_ENABLE 1
#define AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED 2
/**
* Initialize the automounter. This causes some of the phone's
* directories to show up on the host when the phone is plugged
* into the host via USB.
*
* When the AutoMounter starts, it will poll the current state
* of affairs (usb cable plugged in, automounter enabled, etc)
* and try to make the state of the volumes match.
*/
void InitAutoMounter();
/**
* Sets the enabled state of the automounter.
*
* This will in turn cause the automounter to re-evaluate
* whether it should mount/unmount/share/unshare volumes.
*/
void SetAutoMounterMode(int32_t aMode);
/**
* Shuts down the automounter.
*
* This leaves the volumes in whatever state they're in.
*/
void ShutdownAutoMounter();
} // system
} // mozilla
#endif // mozilla_system_automounter_h__

View File

@ -0,0 +1,150 @@
/* 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 "AutoMounter.h"
#include "AutoMounterSetting.h"
#include "base/message_loop.h"
#include "jsapi.h"
#include "mozilla/Services.h"
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsIObserverService.h"
#include "nsIJSContextStack.h"
#include "nsISettingsService.h"
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "xpcpublic.h"
#undef LOG
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AutoMounterSetting" , ## args)
#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "AutoMounterSetting" , ## args)
#define UMS_MODE "ums.mode"
#define MOZSETTINGS_CHANGED "mozsettings-changed"
namespace mozilla {
namespace system {
class SettingsServiceCallback : public nsISettingsServiceCallback
{
public:
NS_DECL_ISUPPORTS
SettingsServiceCallback() {}
NS_IMETHOD Handle(const nsAString &aName, const JS::Value &aResult, JSContext *aContext) {
if (JSVAL_IS_INT(aResult)) {
int32_t mode = JSVAL_TO_INT(aResult);
SetAutoMounterMode(mode);
}
return NS_OK;
}
NS_IMETHOD HandleError(const nsAString &aName, JSContext *aContext) {
ERR("SettingsCallback::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
return NS_OK;
}
};
NS_IMPL_THREADSAFE_ISUPPORTS1(SettingsServiceCallback, nsISettingsServiceCallback)
AutoMounterSetting::AutoMounterSetting()
{
// Setup an observer to watch changes to the setting
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (!observerService) {
ERR("GetObserverService failed");
return;
}
nsresult rv;
rv = observerService->AddObserver(this, MOZSETTINGS_CHANGED, false);
if (NS_FAILED(rv)) {
ERR("AddObserver failed");
return;
}
// Get the initial value of the setting.
nsCOMPtr<nsISettingsService> settingsService =
do_GetService("@mozilla.org/settingsService;1");
if (!settingsService) {
ERR("Failed to get settingsLock service!");
return;
}
nsCOMPtr<nsISettingsServiceLock> lock;
settingsService->GetLock(getter_AddRefs(lock));
nsCOMPtr<nsISettingsServiceCallback> callback = new SettingsServiceCallback();
lock->Get(UMS_MODE, callback);
}
AutoMounterSetting::~AutoMounterSetting()
{
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
observerService->RemoveObserver(this, MOZSETTINGS_CHANGED);
}
}
NS_IMPL_ISUPPORTS1(AutoMounterSetting, nsIObserver)
NS_IMETHODIMP
AutoMounterSetting::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
return NS_OK;
}
LOG("%s: detected %s data = '%s'", __FUNCTION__, aTopic,
NS_LossyConvertUTF16toASCII(aData).get());
// Note that this function gets called for any and all settings changes,
// so we need to carefully check if we have the one we're interested in.
//
// The string that we're interested in will be a JSON string that looks like:
// {"key":"ums.autoMount","value":true}
nsCOMPtr<nsIThreadJSContextStack> stack =
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
if (!stack) {
ERR("Failed to get JSContextStack");
return NS_OK;
}
JSContext *cx = stack->GetSafeJSContext();
if (!cx) {
ERR("Failed to GetSafeJSContext");
return NS_OK;
}
nsDependentString dataStr(aData);
JS::Value val;
if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) ||
!val.isObject()) {
return NS_OK;
}
JSObject &obj(val.toObject());
JS::Value key;
if (!JS_GetProperty(cx, &obj, "key", &key) ||
!key.isString()) {
return NS_OK;
}
JSBool match;
if (!JS_StringEqualsAscii(cx, key.toString(), UMS_MODE, &match) ||
(match != JS_TRUE)) {
return NS_OK;
}
JS::Value value;
if (!JS_GetProperty(cx, &obj, "value", &value) ||
!value.isInt32()) {
return NS_OK;
}
int32_t mode = value.toInt32();
SetAutoMounterMode(mode);
return NS_OK;
}
} // namespace system
} // namespace mozilla

View File

@ -0,0 +1,29 @@
/* 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_system_automountersetting_h__
#define mozilla_system_automountersetting_h__
#include "nsIObserver.h"
namespace mozilla {
namespace system {
class ResultListener;
class AutoMounterSetting : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
AutoMounterSetting();
virtual ~AutoMounterSetting();
};
} // namespace system
} // namespace mozilla
#endif // mozilla_system_automountersetting_h__

View File

@ -42,7 +42,12 @@ LOCAL_INCLUDES = \
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
CPPSRCS += \
AudioManager.cpp \
AutoMounter.cpp \
AutoMounterSetting.cpp \
GonkGPSGeolocationProvider.cpp \
Volume.cpp \
VolumeCommand.cpp \
VolumeManager.cpp \
$(NULL)
# for our local copy of AudioSystem.h
LOCAL_INCLUDES += -I$(topsrcdir)/media/libsydneyaudio/src

View File

@ -15,6 +15,9 @@
#include "jsfriendapi.h"
#include "mozilla/dom/workers/Workers.h"
#ifdef MOZ_WIDGET_GONK
#include "AutoMounter.h"
#endif
#include "mozilla/ipc/Ril.h"
#ifdef MOZ_B2G_BT
#include "mozilla/ipc/DBusThread.h"
@ -39,6 +42,9 @@
USING_WORKERS_NAMESPACE
using namespace mozilla::dom::gonk;
using namespace mozilla::ipc;
#ifdef MOZ_WIDGET_GONK
using namespace mozilla::system;
#endif
#ifdef MOZ_B2G_BT
using namespace mozilla::dom::bluetooth;
#endif
@ -230,6 +236,10 @@ SystemWorkerManager::Init()
}
#endif
#ifdef MOZ_WIDGET_GONK
InitAutoMounter();
#endif
nsCOMPtr<nsIObserverService> obs =
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
if (!obs) {
@ -253,6 +263,10 @@ SystemWorkerManager::Shutdown()
mShutdown = true;
#ifdef MOZ_WIDGET_GONK
ShutdownAutoMounter();
#endif
StopRil();
#ifdef MOZ_B2G_BT
StopDBus();

View File

@ -0,0 +1,71 @@
/* 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 "Volume.h"
#include "VolumeCommand.h"
#include "VolumeManager.h"
#include "VolumeManagerLog.h"
namespace mozilla {
namespace system {
Volume::Volume(const nsCSubstring &aName)
: mState(STATE_INIT),
mName(aName)
{
DBG("Volume %s: created", NameStr());
}
void
Volume::SetState(Volume::STATE aNewState)
{
if (aNewState != mState) {
LOG("Volume %s: changing state from %s to %s",
NameStr(), StateStr(mState), StateStr(aNewState));
mState = aNewState;
}
}
void
Volume::SetMountPoint(const nsCSubstring &aMountPoint)
{
if (!mMountPoint.Equals(aMountPoint)) {
mMountPoint = aMountPoint;
DBG("Volume %s: Setting mountpoint to '%s'", NameStr(), mMountPoint.get());
}
}
void
Volume::StartMount(VolumeResponseCallback *aCallback)
{
StartCommand(new VolumeActionCommand(this, "mount", "", aCallback));
}
void
Volume::StartUnmount(VolumeResponseCallback *aCallback)
{
StartCommand(new VolumeActionCommand(this, "unmount", "force", aCallback));
}
void
Volume::StartShare(VolumeResponseCallback *aCallback)
{
StartCommand(new VolumeActionCommand(this, "share", "ums", aCallback));
}
void
Volume::StartUnshare(VolumeResponseCallback *aCallback)
{
StartCommand(new VolumeActionCommand(this, "unshare", "ums", aCallback));
}
void
Volume::StartCommand(VolumeCommand *aCommand)
{
VolumeManager::PostCommand(aCommand);
}
} // namespace system
} // namespace mozilla

95
dom/system/gonk/Volume.h Normal file
View File

@ -0,0 +1,95 @@
/* 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_system_volume_h__
#define mozilla_system_volume_h__
#include "mozilla/RefPtr.h"
#include "nsString.h"
#include "VolumeCommand.h"
namespace mozilla {
namespace system {
/***************************************************************************
*
* There is an instance of the Volume class for each volume reported
* from vold.
*
* Each volume originates from the /system/etv/vold.fstab file.
*
***************************************************************************/
class Volume : public RefCounted<Volume>
{
public:
// These MUST match the states from android's system/vold/Volume.h header
enum STATE
{
STATE_INIT = -1,
STATE_NOMEDIA = 0,
STATE_IDLE = 1,
STATE_PENDING = 2,
STATE_CHECKING = 3,
STATE_MOUNTED = 4,
STATE_UNMOUNTING = 5,
STATE_FORMATTING = 6,
STATE_SHARED = 7,
STATE_SHAREDMNT = 8
};
Volume(const nsCSubstring &aVolumeName);
const char *StateStr(STATE aState) const
{
switch (aState) {
case STATE_INIT: return "Init";
case STATE_NOMEDIA: return "NoMedia";
case STATE_IDLE: return "Idle";
case STATE_PENDING: return "Pending";
case STATE_CHECKING: return "Checking";
case STATE_MOUNTED: return "Mounted";
case STATE_UNMOUNTING: return "Unmounting";
case STATE_FORMATTING: return "Formatting";
case STATE_SHARED: return "Shared";
case STATE_SHAREDMNT: return "Shared-Mounted";
}
return "???";
}
const char *StateStr() const { return StateStr(mState); }
STATE State() const { return mState; }
const nsCString &Name() const { return mName; }
const char *NameStr() const { return mName.get(); }
// The mount point is the name of the directory where the volume is mounted.
// (i.e. path that leads to the files stored on the volume).
const nsCString &MountPoint() const { return mMountPoint; }
// The StartXxx functions will queue up a command to the VolumeManager.
// You can queue up as many commands as you like, and aCallback will
// be called as each one completes.
void StartMount(VolumeResponseCallback *aCallback);
void StartUnmount(VolumeResponseCallback *aCallback);
void StartShare(VolumeResponseCallback *aCallback);
void StartUnshare(VolumeResponseCallback *aCallback);
private:
friend class VolumeManager; // Calls SetState
friend class VolumeListCallback; // Calls SetMountPoint, SetState
void SetState(STATE aNewState);
void SetMountPoint(const nsCSubstring &aMountPoint);
void StartCommand(VolumeCommand *aCommand);
STATE mState;
const nsCString mName;
nsCString mMountPoint;
};
} // system
} // mozilla
#endif // mozilla_system_volumemanager_h__

View File

@ -0,0 +1,85 @@
/* 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 "nsString.h"
#include "nsWhitespaceTokenizer.h"
#include "Volume.h"
#include "VolumeCommand.h"
#include "VolumeManager.h"
#include "VolumeManagerLog.h"
namespace mozilla {
namespace system {
/***************************************************************************
*
* The VolumeActionCommand class is used to send commands which apply
* to a particular volume.
*
* The following commands would fit into this category:
*
* volume mount <volname>
* volume unmount <volname> [force]
* volume format <volname>
* volume share <volname> <method>
* volume unshare <volname> <method>
* volume shared <volname> <method>
*
* A typical response looks like:
*
* # vdc volume unshare sdcard ums
* 605 Volume sdcard /mnt/sdcard state changed from 7 (Shared-Unmounted) to 1 (Idle-Unmounted)
* 200 volume operation succeeded
*
* Note that the 600 series of responses are considered unsolicited and
* are dealt with directly by the VolumeManager. This command will only
* see the terminating response code (200 in the example above).
*
***************************************************************************/
VolumeActionCommand::VolumeActionCommand(Volume *aVolume,
const char *aAction,
const char *aExtraArgs,
VolumeResponseCallback *aCallback)
: VolumeCommand(aCallback),
mVolume(aVolume)
{
nsCAutoString cmd;
cmd = "volume ";
cmd += aAction;
cmd += " ";
cmd += aVolume->Name().get();
// vold doesn't like trailing white space, so only add it if we really need to.
if (aExtraArgs && (*aExtraArgs != '\0')) {
cmd += " ";
cmd += aExtraArgs;
}
SetCmd(cmd);
}
/***************************************************************************
*
* The VolumeListCommand class is used to send the "volume list" command to
* vold.
*
* A typical response looks like:
*
* # vdc volume list
* 110 sdcard /mnt/sdcard 4
* 110 sdcard1 /mnt/sdcard/external_sd 4
* 200 Volumes listed.
*
***************************************************************************/
VolumeListCommand::VolumeListCommand(VolumeResponseCallback *aCallback)
: VolumeCommand(NS_LITERAL_CSTRING("volume list"), aCallback)
{
}
} // system
} // mozilla

View File

@ -0,0 +1,185 @@
/* 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_system_volumecommand_h__
#define mozilla_system_volumecommand_h__
#include "mozilla/RefPtr.h"
#include <algorithm>
#include <vold/ResponseCode.h>
namespace mozilla {
namespace system {
class Volume;
class VolumeCommand;
/***************************************************************************
*
* The VolumeResponseCallback class is an abstract base class. The ResponseReceived
* method will be called for each response received.
*
* Depending on the command, there may be multiple responses for the
* command. Done() will return true if this is the last response.
*
* The responses from vold are all of the form:
*
* <ResponseCode> <String>
*
* Valid Response codes can be found in the vold/ResponseCode.h header.
*
***************************************************************************/
class VolumeResponseCallback : public RefCounted<VolumeResponseCallback>
{
public:
VolumeResponseCallback()
: mResponseCode(0), mPending(false) {}
virtual ~VolumeResponseCallback() {}
bool Done() const
{
// Response codes from the 200, 400, and 500 series all indicated that
// the command has completed.
return (mResponseCode >= ResponseCode::CommandOkay)
&& (mResponseCode < ResponseCode::UnsolicitedInformational);
}
bool WasSuccessful() const
{
return mResponseCode == ResponseCode::CommandOkay;
}
bool IsPending() const { return mPending; }
int ResponseCode() const { return mResponseCode; }
const nsCString &ResponseStr() const { return mResponseStr; }
protected:
virtual void ResponseReceived(const VolumeCommand *aCommand) = 0;
private:
friend class VolumeCommand; // Calls HandleResponse and SetPending
void HandleResponse(const VolumeCommand *aCommand,
int aResponseCode,
nsACString &aResponseStr)
{
mResponseCode = aResponseCode;
mResponseStr = aResponseStr;
if (mResponseCode >= ResponseCode::CommandOkay) {
// This is a final response.
mPending = false;
}
ResponseReceived(aCommand);
}
void SetPending(bool aPending) { mPending = aPending; }
int mResponseCode; // The response code parsed from vold
nsCString mResponseStr; // The rest of the line.
bool mPending; // Waiting for response?
};
/***************************************************************************
*
* The VolumeCommand class is an abstract base class used to encapsulate
* volume commands send to vold.
*
* See VolumeManager.h for a list of the volume commands.
*
* Commands sent to vold need an explicit null character so we add one
* to the command to ensure that it's included in the length.
*
* All of these commands are asynchronous in nature, and the
* ResponseReceived callback will be called when a response is available.
*
***************************************************************************/
class VolumeCommand : public RefCounted<VolumeCommand>
{
public:
VolumeCommand(VolumeResponseCallback *aCallback)
: mBytesConsumed(0),
mCallback(aCallback)
{
SetCmd(NS_LITERAL_CSTRING(""));
}
VolumeCommand(const nsACString &aCommand, VolumeResponseCallback *aCallback)
: mBytesConsumed(0),
mCallback(aCallback)
{
SetCmd(aCommand);
}
virtual ~VolumeCommand() {}
void SetCmd(const nsACString &aCommand)
{
mCmd = aCommand;
// Add a null character. We want this to be included in the length since
// vold uses it to determine the end of the command.
mCmd.Append('\0');
}
const char *CmdStr() const { return mCmd.get(); }
const char *Data() const { return mCmd.Data() + mBytesConsumed; }
size_t BytesConsumed() const { return mBytesConsumed; }
size_t BytesRemaining() const
{
return mCmd.Length() - std::min(mCmd.Length(), mBytesConsumed);
}
void ConsumeBytes(size_t aNumBytes)
{
mBytesConsumed += std::min(BytesRemaining(), aNumBytes);
}
private:
friend class VolumeManager; // Calls SetPending & HandleResponse
void SetPending(bool aPending)
{
if (mCallback) {
mCallback->SetPending(aPending);
}
}
void HandleResponse(int aResponseCode, nsACString &aResponseStr)
{
if (mCallback) {
mCallback->HandleResponse(this, aResponseCode, aResponseStr);
}
}
nsCString mCmd; // Command being sent
size_t mBytesConsumed; // How many bytes have been sent
// Called when a response to the command is received.
RefPtr<VolumeResponseCallback> mCallback;
};
class VolumeActionCommand : public VolumeCommand
{
public:
VolumeActionCommand(Volume *aVolume, const char *aAction,
const char *aExtraArgs, VolumeResponseCallback *aCallback);
private:
RefPtr<Volume> mVolume;
};
class VolumeListCommand : public VolumeCommand
{
public:
VolumeListCommand(VolumeResponseCallback *aCallback);
};
} // system
} // mozilla
#endif // mozilla_system_volumecommand_h__

View File

@ -0,0 +1,448 @@
/* 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 <android/log.h>
#include <cutils/sockets.h>
#include <fcntl.h>
#include <sys/socket.h>
#include "base/message_loop.h"
#include "nsWhitespaceTokenizer.h"
#include "nsXULAppAPI.h"
#include "Volume.h"
#include "VolumeCommand.h"
#include "VolumeManager.h"
#include "VolumeManagerLog.h"
//using namespace mozilla::dom::gonk;
namespace mozilla {
namespace system {
static RefPtr<VolumeManager> sVolumeManager;
/***************************************************************************/
VolumeManager::VolumeManager()
: mState(VolumeManager::STARTING),
mSocket(-1),
mCommandPending(false),
mRcvIdx(0)
{
DBG("VolumeManager constructor called");
}
VolumeManager::~VolumeManager()
{
}
//static
VolumeManager::STATE
VolumeManager::State()
{
if (!sVolumeManager) {
return VolumeManager::UNINITIALIZED;
}
return sVolumeManager->mState;
}
//static
const char *
VolumeManager::StateStr()
{
switch (State()) {
case UNINITIALIZED: return "Uninitialized";
case STARTING: return "Starting";
case VOLUMES_READY: return "Volumes Ready";
}
return "???";
}
//static
void
VolumeManager::SetState(STATE aNewState)
{
if (!sVolumeManager) {
return;
}
if (sVolumeManager->mState != aNewState) {
sVolumeManager->mState = aNewState;
sVolumeManager->mStateObserverList.Broadcast(StateChangedEvent());
}
}
//static
void
VolumeManager::RegisterStateObserver(StateObserver *aObserver)
{
sVolumeManager->mStateObserverList.AddObserver(aObserver);
}
//static
void VolumeManager::UnregisterStateObserver(StateObserver *aObserver)
{
sVolumeManager->mStateObserverList.RemoveObserver(aObserver);
}
//static
TemporaryRef<Volume>
VolumeManager::FindVolumeByName(const nsCSubstring &aName)
{
if (!sVolumeManager) {
return NULL;
}
for (VolumeArray::iterator volIter = sVolumeManager->mVolumeArray.begin();
volIter != sVolumeManager->mVolumeArray.end();
volIter++) {
if ((*volIter)->Name().Equals(aName)) {
return *volIter;
}
}
return NULL;
}
//static
TemporaryRef<Volume>
VolumeManager::FindAddVolumeByName(const nsCSubstring &aName)
{
RefPtr<Volume> vol = FindVolumeByName(aName);
if (vol) {
return vol;
}
// No volume found, create and add a new one.
vol = new Volume(aName);
sVolumeManager->mVolumeArray.push_back(vol);
return vol;
}
class VolumeListCallback : public VolumeResponseCallback
{
virtual void ResponseReceived(const VolumeCommand *aCommand)
{
switch (ResponseCode()) {
case ResponseCode::VolumeListResult: {
// Each line will look something like:
//
// sdcard /mnt/sdcard 1
//
// So for each volume that we get back, we update any volumes that
// we have of the same name, or add new ones if they don't exist.
nsCWhitespaceTokenizer tokenizer(ResponseStr());
nsDependentCSubstring volName(tokenizer.nextToken());
nsDependentCSubstring mntPoint(tokenizer.nextToken());
nsCString state(tokenizer.nextToken());
RefPtr<Volume> vol = VolumeManager::FindAddVolumeByName(volName);
vol->SetMountPoint(mntPoint);
PRInt32 errCode;
vol->SetState((Volume::STATE)state.ToInteger(&errCode));
break;
}
case ResponseCode::CommandOkay: {
// We've received the list of volumes. Tell anybody who
// is listening that we're open for business.
VolumeManager::SetState(VolumeManager::VOLUMES_READY);
break;
}
}
}
};
bool
VolumeManager::OpenSocket()
{
SetState(STARTING);
if ((mSocket.rwget() = socket_local_client("vold",
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM)) < 0) {
ERR("Error connecting to vold: (%s) - will retry", strerror(errno));
return false;
}
// add FD_CLOEXEC flag
int flags = fcntl(mSocket.get(), F_GETFD);
if (flags == -1) {
return false;
}
flags |= FD_CLOEXEC;
if (fcntl(mSocket.get(), F_SETFD, flags) == -1) {
return false;
}
// set non-blocking
if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1) {
return false;
}
if (!MessageLoopForIO::current()->
WatchFileDescriptor(mSocket.get(),
true,
MessageLoopForIO::WATCH_READ,
&mReadWatcher,
this)) {
return false;
}
LOG("Connected to vold");
PostCommand(new VolumeListCommand(new VolumeListCallback));
return true;
}
//static
void
VolumeManager::PostCommand(VolumeCommand *aCommand)
{
if (!sVolumeManager) {
ERR("VolumeManager not initialized. Dropping command '%s'", aCommand->Data());
return;
}
aCommand->SetPending(true);
DBG("Sending command '%s'", aCommand->Data());
// vold can only process one command at a time, so add our command
// to the end of the command queue.
sVolumeManager->mCommands.push(aCommand);
if (!sVolumeManager->mCommandPending) {
// There aren't any commands currently being processed, so go
// ahead and kick this one off.
sVolumeManager->mCommandPending = true;
sVolumeManager->WriteCommandData();
}
}
/***************************************************************************
* The WriteCommandData initiates sending of a command to vold. Since
* we're running on the IOThread and not allowed to block, WriteCommandData
* will write as much data as it can, and if not all of the data can be
* written then it will setup a file descriptor watcher and
* OnFileCanWriteWithoutBlocking will call WriteCommandData to write out
* more of the command data.
*/
void
VolumeManager::WriteCommandData()
{
if (mCommands.size() == 0) {
return;
}
VolumeCommand *cmd = mCommands.front();
if (cmd->BytesRemaining() == 0) {
// All bytes have been written. We're waiting for a response.
return;
}
// There are more bytes left to write. Try to write them all.
ssize_t bytesWritten = write(mSocket.get(), cmd->Data(), cmd->BytesRemaining());
if (bytesWritten < 0) {
ERR("Failed to write %d bytes to vold socket", cmd->BytesRemaining());
Restart();
return;
}
DBG("Wrote %ld bytes (of %d)", bytesWritten, cmd->BytesRemaining());
cmd->ConsumeBytes(bytesWritten);
if (cmd->BytesRemaining() == 0) {
return;
}
// We were unable to write all of the command bytes. Setup a watcher
// so we'll get called again when we can write without blocking.
if (!MessageLoopForIO::current()->
WatchFileDescriptor(mSocket.get(),
false, // one-shot
MessageLoopForIO::WATCH_WRITE,
&mWriteWatcher,
this)) {
ERR("Failed to setup write watcher for vold socket");
Restart();
}
}
void
VolumeManager::OnFileCanReadWithoutBlocking(int aFd)
{
MOZ_ASSERT(aFd == mSocket.get());
while (true) {
ssize_t bytesRemaining = read(aFd, &mRcvBuf[mRcvIdx], sizeof(mRcvBuf) - mRcvIdx);
if (bytesRemaining < 0) {
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
return;
}
if (errno == EINTR) {
continue;
}
ERR("Unknown read error: %d (%s) - restarting", errno, strerror(errno));
Restart();
return;
}
if (bytesRemaining == 0) {
// This means that vold probably crashed
ERR("Vold appears to have crashed - restarting");
Restart();
return;
}
// We got some data. Each line is terminated by a null character
DBG("Read %ld bytes", bytesRemaining);
while (bytesRemaining > 0) {
bytesRemaining--;
if (mRcvBuf[mRcvIdx] == '\0') {
// We found a line terminator. Each line is formatted as an
// integer response code followed by the rest of the line.
// Fish out the response code.
char *endPtr;
int responseCode = strtol(mRcvBuf, &endPtr, 10);
if (*endPtr == ' ') {
endPtr++;
}
// Now fish out the rest of the line after the response code
nsDependentCString responseLine(endPtr, &mRcvBuf[mRcvIdx] - endPtr);
DBG("Rcvd: %d '%s'", responseCode, responseLine.Data());
if (responseCode >= ResponseCode::UnsolicitedInformational) {
// These are unsolicited broadcasts. We intercept these and process
// them ourselves
HandleBroadcast(responseCode, responseLine);
} else {
// Everything else is considered to be part of the command response.
if (mCommands.size() > 0) {
VolumeCommand *cmd = mCommands.front();
cmd->HandleResponse(responseCode, responseLine);
if (responseCode >= ResponseCode::CommandOkay) {
// That's a terminating response. We can remove the command.
mCommands.pop();
mCommandPending = false;
// Start the next command, if there is one.
WriteCommandData();
}
} else {
ERR("Response with no command");
}
}
if (bytesRemaining > 0) {
// There is data in the receive buffer beyond the current line.
// Shift it down to the beginning.
memmove(&mRcvBuf[0], &mRcvBuf[mRcvIdx + 1], bytesRemaining);
}
mRcvIdx = 0;
} else {
mRcvIdx++;
}
}
}
}
void
VolumeManager::OnFileCanWriteWithoutBlocking(int aFd)
{
MOZ_ASSERT(aFd == mSocket.get());
WriteCommandData();
}
void
VolumeManager::HandleBroadcast(int aResponseCode, nsCString &aResponseLine)
{
if (aResponseCode != ResponseCode::VolumeStateChange) {
return;
}
// Format of the line is something like:
//
// Volume sdcard /mnt/sdcard state changed from 7 (Shared-Unmounted) to 1 (Idle-Unmounted)
//
// So we parse out the volume name and the state after the string " to "
nsCWhitespaceTokenizer tokenizer(aResponseLine);
tokenizer.nextToken(); // The word "Volume"
nsDependentCSubstring volName(tokenizer.nextToken());
RefPtr<Volume> vol = FindVolumeByName(volName);
if (!vol) {
return;
}
const char *s = strstr(aResponseLine.get(), " to ");
if (!s) {
return;
}
s += 4;
vol->SetState((Volume::STATE)atoi(s));
}
void
VolumeManager::Restart()
{
mReadWatcher.StopWatchingFileDescriptor();
mWriteWatcher.StopWatchingFileDescriptor();
while (!mCommands.empty()) {
mCommands.pop();
}
mCommandPending = false;
mSocket.dispose();
mRcvIdx = 0;
Start();
}
//static
void
VolumeManager::Start()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
if (!sVolumeManager) {
return;
}
if (!sVolumeManager->OpenSocket()) {
// Socket open failed, try again in a second.
MessageLoopForIO::current()->
PostDelayedTask(FROM_HERE,
NewRunnableFunction(VolumeManager::Start),
1000);
}
}
/***************************************************************************/
static void
InitVolumeManagerIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
MOZ_ASSERT(!sVolumeManager);
sVolumeManager = new VolumeManager();
VolumeManager::Start();
}
static void
ShutdownVolumeManagerIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
sVolumeManager = NULL;
}
/**************************************************************************
*
* Public API
*
* Since the VolumeManager runs in IO Thread context, we need to switch
* to IOThread context before we can do anything.
*
**************************************************************************/
void
InitVolumeManager()
{
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(InitVolumeManagerIOThread));
}
void
ShutdownVolumeManager()
{
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(ShutdownVolumeManagerIOThread));
}
} // system
} // mozilla

View File

@ -0,0 +1,183 @@
/* 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_system_volumemanager_h__
#define mozilla_system_volumemanager_h__
#include <vector>
#include <queue>
#include "base/message_loop.h"
#include "mozilla/FileUtils.h"
#include "mozilla/Observer.h"
#include "mozilla/RefPtr.h"
#include "nsString.h"
#include "Volume.h"
#include "VolumeCommand.h"
namespace mozilla {
namespace system {
/***************************************************************************
*
* All of the public API mentioned in this file (unless otherwise
* mentioned) must run from the IOThread.
*
***************************************************************************/
/***************************************************************************
*
* The VolumeManager class is a front-end for android's vold service.
*
* Vold uses a unix socket interface and accepts null-terminated string
* commands. The following commands were determined by examining the vold
* source code:
*
* volume list
* volume mount <volname>
* volume unmount <volname> [force]
* volume debug [on|off]
* volume format <volname>
* volume share <volname> <method>
* volume unshare <volname> <method>
* volume shared <volname> <method>
*
* <volname> is the name of the volume as used in /system/etc/vold.fstab
* <method> is ums
*
* dump
*
* share status <method> (Determines if a particular sharing method is available)
* (GB only - not available in ICS)
*
* storage users (??? always crashes vold ???)
*
* asec list
* asec ...lots more...
*
* obb list
* obb ...lots more...
*
* xwarp enable
* xwarp disable
* xwarp status
*
* There is also a command line tool called vdc, which can be used to send
* the above commands to vold.
*
* Currently, only the volume list, share/unshare, and mount/unmount
* commands are being used.
*
***************************************************************************/
class VolumeManager : public MessageLoopForIO::Watcher,
public RefCounted<VolumeManager>
{
public:
typedef std::vector<RefPtr<Volume> > VolumeArray;
VolumeManager();
virtual ~VolumeManager();
//-----------------------------------------------------------------------
//
// State related methods.
//
// The VolumeManager starts off in the STARTING state. Once a connection
// is established with vold, it asks for a list of volumes, and once the
// volume list has been received, then the VolumeManager enters the
// VOLUMES_READY state.
//
// If vold crashes, then the VolumeManager will once again enter the
// STARTING state and try to reestablish a connection with vold.
enum STATE
{
UNINITIALIZED,
STARTING,
VOLUMES_READY
};
static STATE State();
static const char *StateStr();
class StateChangedEvent
{
public:
StateChangedEvent() {}
};
typedef mozilla::Observer<StateChangedEvent> StateObserver;
typedef mozilla::ObserverList<StateChangedEvent> StateObserverList;
static void RegisterStateObserver(StateObserver *aObserver);
static void UnregisterStateObserver(StateObserver *aObserver);
//-----------------------------------------------------------------------
static void Start();
static TemporaryRef<Volume> FindVolumeByName(const nsCSubstring &aName);
static TemporaryRef<Volume> FindAddVolumeByName(const nsCSubstring &aName);
static void PostCommand(VolumeCommand *aCommand);
protected:
virtual void OnFileCanReadWithoutBlocking(int aFd);
virtual void OnFileCanWriteWithoutBlocking(int aFd);
private:
bool OpenSocket();
friend class VolumeListCallback; // Calls SetState
static void SetState(STATE aNewState);
void Restart();
void WriteCommandData();
void HandleBroadcast(int aResponseCode, nsCString &aResponseLine);
typedef std::queue<RefPtr<VolumeCommand> > CommandQueue;
static const int kRcvBufSize = 1024;
STATE mState;
ScopedClose mSocket;
VolumeArray mVolumeArray;
CommandQueue mCommands;
bool mCommandPending;
char mRcvBuf[kRcvBufSize];
size_t mRcvIdx;
StateObserverList mStateObserverList;
MessageLoopForIO *mIOLoop;
MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
MessageLoopForIO::FileDescriptorWatcher mWriteWatcher;
RefPtr<VolumeResponseCallback> mBroadcastCallback;
};
/***************************************************************************
*
* The initialization/shutdown functions do not need to be called from
* the IOThread context.
*
***************************************************************************/
/**
* Initialize the Volume Manager. On initialization, the VolumeManager will
* attempt to connect with vold and collect the list of volumes that vold
* knows about.
*/
void InitVolumeManager();
/**
* Shuts down the Volume Manager.
*/
void ShutdownVolumeManager();
} // system
} // mozilla
#endif // mozilla_system_volumemanager_h__

View File

@ -0,0 +1,20 @@
/* 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_system_volumemanagerlog_h__
#define mozilla_system_volumemanagerlog_h__
#define USE_DEBUG 0
#undef LOG
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "VolumeManager" , ## args)
#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "VolumeManager" , ## args)
#if USE_DEBUG
#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "VolumeManager" , ## args)
#else
#define DBG(args...)
#endif
#endif // mozilla_system_volumemanagerlog_h__

View File

@ -3326,17 +3326,29 @@ let GsmPDUHelper = {
((octet & 0x0f) <= 0x09) * (octet & 0x0f) * 10;
},
/**
* Convert a semi-octet (number) to a GSM BCD char.
*/
bcdChars: "0123456789*#,;",
semiOctetToBcdChar: function semiOctetToBcdChar(semiOctet) {
if (semiOctet >= 14) {
throw new RangeError();
}
return this.bcdChars.charAt(semiOctet);
},
/**
* Read a *swapped nibble* binary coded decimal (BCD)
*
* @param length
* @param pairs
* Number of nibble *pairs* to read.
*
* @return the decimal as a number.
*/
readSwappedNibbleBCD: function readSwappedNibbleBCD(length) {
readSwappedNibbleBcdNum: function readSwappedNibbleBcdNum(pairs) {
let number = 0;
for (let i = 0; i < length; i++) {
for (let i = 0; i < pairs; i++) {
let octet = this.readHexOctet();
// Ignore 'ff' octets as they're often used as filler.
if (octet == 0xff) {
@ -3355,6 +3367,32 @@ let GsmPDUHelper = {
return number;
},
/**
* Read a *swapped nibble* binary coded string (BCD)
*
* @param pairs
* Number of nibble *pairs* to read.
*
* @return The BCD string.
*/
readSwappedNibbleBcdString: function readSwappedNibbleBcdString(pairs) {
let str = "";
for (let i = 0; i < pairs; i++) {
let nibbleH = this.readHexNibble();
let nibbleL = this.readHexNibble();
if (nibbleL == 0x0F) {
break;
}
str += this.semiOctetToBcdChar(nibbleL);
if (nibbleH != 0x0F) {
str += this.semiOctetToBcdChar(nibbleH);
}
}
return str;
},
/**
* Write numerical data as swapped nibble BCD.
*
@ -3720,6 +3758,10 @@ let GsmPDUHelper = {
/**
* Read SM-TL Address.
*
* @param len
* Length of useful semi-octets within the Address-Value field. For
* example, the lenth of "12345" should be 5, and 4 for "1234".
*
* @see 3GPP TS 23.040 9.1.2.5
*/
readAddress: function readAddress(len) {
@ -3737,7 +3779,7 @@ let GsmPDUHelper = {
let toa = this.readHexOctet();
// Address-Value
let addr = this.readSwappedNibbleBCD(len / 2).toString();
let addr = this.readSwappedNibbleBcdString(len / 2);
if (addr.length <= 0) {
if (DEBUG) debug("PDU error: no number provided");
return null;
@ -3909,12 +3951,12 @@ let GsmPDUHelper = {
* @see 3GPP TS 23.040 9.2.3.11
*/
readTimestamp: function readTimestamp() {
let year = this.readSwappedNibbleBCD(1) + PDU_TIMESTAMP_YEAR_OFFSET;
let month = this.readSwappedNibbleBCD(1) - 1;
let day = this.readSwappedNibbleBCD(1);
let hour = this.readSwappedNibbleBCD(1);
let minute = this.readSwappedNibbleBCD(1);
let second = this.readSwappedNibbleBCD(1);
let year = this.readSwappedNibbleBcdNum(1) + PDU_TIMESTAMP_YEAR_OFFSET;
let month = this.readSwappedNibbleBcdNum(1) - 1;
let day = this.readSwappedNibbleBcdNum(1);
let hour = this.readSwappedNibbleBcdNum(1);
let minute = this.readSwappedNibbleBcdNum(1);
let second = this.readSwappedNibbleBcdNum(1);
let timestamp = Date.UTC(year, month, day, hour, minute, second);
// If the most significant bit of the least significant nibble is 1,
@ -4064,7 +4106,7 @@ let GsmPDUHelper = {
if (smscLength > 0) {
let smscTypeOfAddress = this.readHexOctet();
// Subtract the type-of-address octet we just read from the length.
msg.SMSC = this.readSwappedNibbleBCD(smscLength - 1).toString();
msg.SMSC = this.readSwappedNibbleBcdString(smscLength - 1);
if ((smscTypeOfAddress >> 4) == (PDU_TOA_INTERNATIONAL >> 4)) {
msg.SMSC = '+' + msg.SMSC;
}

View File

@ -80,7 +80,7 @@ function registerMockPromptService()
checkState: aCheckState
};
aCheckState.value = true;
SpecialPowers.wrap(aCheckState).value = true;
},
confirm: function(aDialogTitle, aText)
@ -106,7 +106,7 @@ function registerMockPromptService()
checkState: aCheckState
};
aCheckState.value = true;
SpecialPowers.wrap(aCheckState).value = true;
return true;
},
@ -125,7 +125,7 @@ function registerMockPromptService()
};
if (aCheckMsg != null)
aCheckState.value = true;
SpecialPowers.wrap(aCheckState).value = true;
return 0;
},
@ -143,7 +143,7 @@ function registerMockPromptService()
};
if (aCheckMsg != null)
aCheckState.value = true;
SpecialPowers.wrap(aCheckState).value = true;
return true;
},

View File

@ -134,28 +134,32 @@ function uninstall(appURL, check, next) {
function js_traverse(template, check, object) {
var type = typeof template;
// We apply SpecialPowers wrappers to the template to signal cases where
// we need to wrap the object to examine it. We do things this way, rather
// than wrapping unconditionally, to make sure that the default environment of
// the test suite is as close to that of the web as possible.
if (SpecialPowers.isWrapper(template))
object = SpecialPowers.wrap(object);
if (type == "object") {
if (Object.keys(template).length == 1 && template["status"]) {
check(!object || object.length == 0,"The return object from mozApps api was null as expected");
return;
}
for (var key in template) {
debug("key: ", key);
debug("key: " + key);
var accessor = key.split(".",1);
if (accessor.length > 1) {
js_traverse(template[key], check, object[accessor[0]].accessor[1]);
} else {
if(object[key]) {
js_traverse(template[key], check, object[key]);
var value = (key == "status") ? SpecialPowers.wrap(object)[key] : object[key];
if(value) {
js_traverse(template[key], check, value);
} else {
check(typeof template[key] == "undefined", key + " is undefined as expected");
}
}
}
} else if (type == "array") {
for (var i = 0; i < object.length; i++) {
js_traverse(template[i], check, object[i]);
}
} else {
var evaluate = "";
@ -188,14 +192,14 @@ function mozAppscb(pending, comparatorObj, check, next) {
pending.onsuccess = function () {
debug("success cb, called");
if(pending.result) {
if(pending.result.length) {
if(typeof pending.result.length !== 'undefined') {
for(i=0;i < pending.result.length;i++) {
pending.result[i].status= 'success';
SpecialPowers.wrap(pending).result[i].status= 'success';
js_traverse(comparatorObj[i], check, pending.result[i]);
}
} else {
debug("comparatorOBj in else");
pending.result.status = 'success';
SpecialPowers.wrap(pending).result.status = 'success';
js_traverse(comparatorObj[0], check, pending.result);
}
} else {
@ -208,7 +212,7 @@ function mozAppscb(pending, comparatorObj, check, next) {
};
pending.onerror = function () {
pending.error.status = 'error';
SpecialPowers.wrap(pending).error.status = 'error';
check(true, "failure cb called");
js_traverse(comparatorObj[0], check, pending.error);
if(typeof next == 'function') {
@ -267,10 +271,12 @@ function install(appURL, check, next) {
installOrigin: "== " + installOrigin.quote(),
origin: "== " + origin.quote(),
manifestURL: "== " + appURL.quote(),
manifest: {
// |manifest| is not accessible to content, so js_traverse needs to
// use SpecialPowers to see it. We signal this by wrapping it.
manifest: SpecialPowers.wrap({
name: "== " + unescape(manifest.name).quote(),
installs_allowed_from: manifest.installs_allowed_from
}
})
}], check,
next);
}
@ -301,10 +307,12 @@ function getInstalled(appURLs, check, next) {
origin: "== " + origin.quote(),
manifestURL: "== " + appURL.quote(),
installTime: " \> Date.now() - 3000",
manifest: {
// |manifest| is not accessible to content, so js_traverse needs to
// use SpecialPowers to see it. We signal this by wrapping it.
manifest: SpecialPowers.wrap({
name: "== " + unescape(manifest.name).quote(),
installs_allowed_from: manifest.installs_allowed_from
}
})
};
}
debug(JSON.stringify(checkInstalled));
@ -316,8 +324,8 @@ function getInstalled(appURLs, check, next) {
* @msg The message you want to output
*/
function debug(msg) {
if(DEBUG == true) {
info(msg);
if(DEBUG == true) {
dump(msg + "\n");
}
}

View File

@ -37,6 +37,8 @@
#include "nsIDOMWindow.h"
#include "nsContentUtils.h"
#include "nsIBidiKeyboard.h"
#include "mozilla/dom/Element.h"
#include "nsIFormControl.h"
using namespace mozilla;
@ -646,9 +648,11 @@ nsEditorEventListener::DragOver(nsIDOMDragEvent* aDragEvent)
}
else
{
// This is needed when dropping on an input, to prevent the editor for
// the editable parent from receiving the event.
aDragEvent->StopPropagation();
if (!IsFileControlTextBox()) {
// This is needed when dropping on an input, to prevent the editor for
// the editable parent from receiving the event.
aDragEvent->StopPropagation();
}
if (mCaret)
{
@ -704,8 +708,8 @@ nsEditorEventListener::Drop(nsIDOMDragEvent* aMouseEvent)
if (!dropParent->IsEditable() || !CanDrop(aMouseEvent)) {
// was it because we're read-only?
if (mEditor->IsReadonly() || mEditor->IsDisabled())
{
if ((mEditor->IsReadonly() || mEditor->IsDisabled()) &&
!IsFileControlTextBox()) {
// it was decided to "eat" the event as this is the "least surprise"
// since someone else handling it might be unintentional and the
// user could probably re-drag to be not over the disabled/readonly
@ -956,3 +960,18 @@ nsEditorEventListener::SpellCheckIfNeeded() {
}
}
bool
nsEditorEventListener::IsFileControlTextBox()
{
dom::Element* root = mEditor->GetRoot();
if (root && root->IsInNativeAnonymousSubtree()) {
nsIContent* parent = root->FindFirstNonNativeAnonymous();
if (parent && parent->IsHTML(nsGkAtoms::input)) {
nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(parent);
MOZ_ASSERT(formControl);
return formControl->GetType() == NS_FORM_INPUT_FILE;
}
}
return false;
}

View File

@ -67,6 +67,7 @@ protected:
nsresult DragGesture(nsIDOMDragEvent* aDragEvent);
void CleanupDragDropCaret();
already_AddRefed<nsIPresShell> GetPresShell();
bool IsFileControlTextBox();
protected:
nsEditor* mEditor; // weak

View File

@ -4,6 +4,9 @@ var gExpectedCharset;
var gOldPref;
var gDetectorList;
var gTestIndex;
var gLocalDir;
const Cc = Components.classes;
const Ci = Components.interfaces;
function CharsetDetectionTests(aTestFile, aExpectedCharset, aDetectorList)
{
@ -12,22 +15,28 @@ function CharsetDetectionTests(aTestFile, aExpectedCharset, aDetectorList)
InitDetectorTests();
$("testframe").src = aTestFile;
var fileURI = gLocalDir + aTestFile;
$("testframe").src = fileURI;
SimpleTest.waitForExplicitFinish();
}
function InitDetectorTests()
{
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var str = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
var prefService = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
var str = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
var ioService = Cc['@mozilla.org/network/io-service;1']
.getService(Ci.nsIIOService);
loader.loadSubScript("chrome://mochikit/content/chrome-harness.js");
try {
gOldPref = prefService
.getComplexValue("intl.charset.detector",
Components.interfaces.nsIPrefLocalizedString).data;
Ci.nsIPrefLocalizedString).data;
} catch (e) {
gOldPref = "";
}
@ -39,23 +48,32 @@ function InitDetectorTests()
try {
gExpectedCharset = prefService
.getComplexValue("intl.charset.default",
Components.interfaces.nsIPrefLocalizedString)
Ci.nsIPrefLocalizedString)
.data;
} catch (e) {
gExpectedCharset = "ISO-8859-8";
}
}
// Get the local directory. This needs to be a file: URI because chrome:
// URIs are always UTF-8 (bug 617339) and we are testing decoding from other
// charsets.
var jar = getJar(getRootDirectory(window.location.href));
var dir = jar ?
extractJarToTmp(jar) :
getChromeDir(getResolvedURI(window.location.href));
gLocalDir = ioService.newFileURI(dir).spec;
}
function SetDetectorPref(aPrefValue)
{
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var str = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
var prefService = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
var str = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
str.data = aPrefValue;
prefService.setComplexValue("intl.charset.detector",
Components.interfaces.nsISupportsString, str);
Ci.nsISupportsString, str);
gCurrentDetector = aPrefValue;
}

View File

@ -1077,7 +1077,7 @@ private:
// Assume IEEE 754 precision
range[0] = 127;
range[1] = 127;
*precision = 0;
*precision = 23;
break;
case LOCAL_GL_LOW_INT:
case LOCAL_GL_MEDIUM_INT:

View File

@ -187,7 +187,7 @@ CompositorParent::ScheduleResumeOnCompositorThread(int width, int height)
void
CompositorParent::ScheduleTask(CancelableTask* task, int time)
{
if (time) {
if (time == 0) {
MessageLoop::current()->PostTask(FROM_HERE, task);
} else {
MessageLoop::current()->PostDelayedTask(FROM_HERE, task, time);

View File

@ -35,6 +35,8 @@ public:
virtual bool SetupCairoFont(gfxContext *aContext);
virtual bool AllowSubpixelAA() { return mAllowManualShowGlyphs; }
virtual bool IsValid();
gfxFloat GetAdjustedSize() {

View File

@ -7,6 +7,8 @@
#include "gfxFT2Utils.h"
#include "harfbuzz/hb.h"
using namespace mozilla::gfx;
gfxFT2FontBase::gfxFT2FontBase(cairo_scaled_font_t *aScaledFont,
gfxFontEntry *aFontEntry,
const gfxFontStyle *aFontStyle)
@ -231,15 +233,15 @@ gfxFT2FontBase::ConstructFontOptions()
const gfxFontStyle* style = this->GetStyle();
if (style->style == NS_FONT_STYLE_ITALIC) {
if (style->weight == NS_FONT_WEIGHT_BOLD) {
mFontOptions.mStyle = mozilla::gfx::FontStyle::FONT_STYLE_BOLD_ITALIC;
mFontOptions.mStyle = FONT_STYLE_BOLD_ITALIC;
} else {
mFontOptions.mStyle = mozilla::gfx::FontStyle::FONT_STYLE_ITALIC;
mFontOptions.mStyle = FONT_STYLE_ITALIC;
}
} else {
if (style->weight == NS_FONT_WEIGHT_BOLD) {
mFontOptions.mStyle = mozilla::gfx::FontStyle::FONT_STYLE_BOLD;
mFontOptions.mStyle = FONT_STYLE_BOLD;
} else {
mFontOptions.mStyle = mozilla::gfx::FontStyle::FONT_STYLE_NORMAL;
mFontOptions.mStyle = FONT_STYLE_NORMAL;
}
}
}

View File

@ -1788,6 +1788,12 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
return;
}
bool oldSubpixelAA = dt->GetPermitSubpixelAA();
if (!AllowSubpixelAA()) {
dt->SetPermitSubpixelAA(false);
}
GlyphBufferAzure glyphs;
Glyph *glyph;
@ -1950,6 +1956,8 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
renderingOptions, aContext, passedInvMatrix, true);
dt->SetTransform(oldMat);
dt->SetPermitSubpixelAA(oldSubpixelAA);
}
// Restore matrix for stroke pattern

View File

@ -1457,6 +1457,8 @@ public:
// This is called by the default Draw() implementation above.
virtual bool SetupCairoFont(gfxContext *aContext) = 0;
virtual bool AllowSubpixelAA() { return true; }
bool IsSyntheticBold() { return mApplySyntheticBold; }
// Amount by which synthetic bold "fattens" the glyphs: 1/16 of the em-size

View File

@ -1753,7 +1753,7 @@ gfxFontUtils::DecodeFontName(const PRUint8 *aNameData, PRInt32 aByteLen,
}
nsCOMPtr<nsIUnicodeDecoder> decoder;
rv = ccm->GetUnicodeDecoderRawInternal(csName, getter_AddRefs(decoder));
rv = ccm->GetUnicodeDecoderRaw(csName, getter_AddRefs(decoder));
if (NS_FAILED(rv)) {
NS_WARNING("failed to get the decoder for a font name string");
return false;

View File

@ -207,7 +207,14 @@ public:
}
void BroadcastInformation(const InfoType& aInfo) {
MOZ_ASSERT(mObservers);
// It is possible for mObservers to be NULL here on some platforms,
// because a call to BroadcastInformation gets queued up asynchronously
// while RemoveObserver is running (and before the notifications are
// disabled). The queued call can then get run after mObservers has
// been nulled out. See bug 757025.
if (!mObservers) {
return;
}
mObservers->Broadcast(aInfo);
}

View File

@ -42,6 +42,7 @@ class SwitchEvent;
enum SwitchDevice {
SWITCH_DEVICE_UNKNOWN = -1,
SWITCH_HEADPHONES,
SWITCH_USB,
NUM_SWITCH_DEVICE
};

View File

@ -199,10 +199,8 @@ class PollSensor {
nsCOMPtr<nsIRunnable> PollSensor::mRunnable = NULL;
class SwitchSensor {
class SwitchSensor : public RefCounted<SwitchSensor> {
public:
NS_INLINE_DECL_REFCOUNTING(SwitchSensor)
SwitchSensor(bool aActivate, sensor_t aSensor, pthread_t aThreadId) :
mActivate(aActivate), mSensor(aSensor), mThreadId(aThreadId) { }

View File

@ -22,6 +22,7 @@ namespace hal_impl {
struct {const char* name; SwitchDevice device; } kSwitchNameMap[] = {
{ "h2w", SWITCH_HEADPHONES },
{ "usb_configuration", SWITCH_USB },
{ NULL, SWITCH_DEVICE_UNKNOWN },
};
@ -112,7 +113,25 @@ private:
//working around the android code not being const-correct
NetlinkEvent *e = const_cast<NetlinkEvent*>(&event);
const char* subsystem = e->getSubsystem();
if (subsystem && (strcmp(subsystem, "android_usb") == 0)) {
// Under GB, usb cable plugin was done using a virtual switch
// (usb_configuration). Under ICS, they changed to using the
// android_usb device, so we emulate the usb_configuration switch.
*name = "usb_configuration";
const char *usb_state = e->findParam("USB_STATE");
if (!usb_state) {
return false;
}
if (strcmp(usb_state, "CONFIGURED") == 0) {
*state = "1";
return true;
}
*state = "0";
return true;
}
if (!subsystem || strcmp(subsystem, "switch")) {
return false;
}
@ -127,9 +146,8 @@ private:
}
SwitchDevice ProcessEvent(const NetlinkEvent& event, const char** name, const char** state) {
bool rv = GetEventInfo(event, name, state);
NS_ENSURE_TRUE(rv, SWITCH_DEVICE_UNKNOWN);
return NameToDevice(*name);
return GetEventInfo(event, name, state) ?
NameToDevice(*name) : SWITCH_DEVICE_UNKNOWN;
}
};

View File

@ -39,6 +39,7 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../strres/src \
-I$(srcdir)/../locale/src \
-I$(srcdir)/../locale/src/$(LOCALE_DIR) \
-I$(srcdir)/../uconv/src \
$(NULL)
SHARED_LIBRARY_LIBS = \

View File

@ -28,6 +28,9 @@
// locale
#include "nsLocaleConstructors.h"
// uconv
#include "nsCharsetConverterManager.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJISx4051LineBreaker)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSampleWordBreaker)
@ -148,10 +151,20 @@ static const mozilla::Module::ContractIDEntry kIntlContracts[] = {
{ NULL }
};
static void
I18nModuleDtor()
{
nsCharsetConverterManager::Shutdown();
}
static const mozilla::Module kIntlModule = {
mozilla::Module::kVersion,
kIntlCIDs,
kIntlContracts,
NULL,
NULL,
NULL,
I18nModuleDtor
};
NSMODULE_DEFN(nsI18nModule) = &kIntlModule;

View File

@ -9,8 +9,12 @@
#include "nscore.h"
#include "nsStringGlue.h"
class nsCharsetConverterManager;
class nsCharsetAlias
{
friend class nsCharsetConverterManager;
static nsresult GetPreferredInternal(const nsACString& aAlias, nsACString& aResult);
public:
static nsresult GetPreferred(const nsACString& aAlias, nsACString& aResult);
static nsresult Equals(const nsACString& aCharset1, const nsACString& aCharset2, bool* aResult);

View File

@ -55,6 +55,10 @@ EXTRA_JS_MODULES = \
# we don't want the shared lib, but we want to force the creation of a static lib.
FORCE_STATIC_LIB = 1
LOCAL_INCLUDES = \
-I$(topsrcdir)/intl/uconv/src \
$(NULL)
include $(topsrcdir)/config/rules.mk
nsCharsetAlias.$(OBJ_SUFFIX): charsetalias.properties.h

View File

@ -8,6 +8,10 @@
#include "nsCharsetAlias.h"
#include "pratom.h"
// for NS_ERROR_UCONV_NOCONV
#include "nsEncoderDecoderUtils.h"
#include "nsCharsetConverterManager.h"
// for NS_IMPL_IDS only
#include "nsIPlatformCharset.h"
@ -25,11 +29,9 @@ static const char* kAliases[][3] = {
//--------------------------------------------------------------
// static
nsresult
nsCharsetAlias::GetPreferred(const nsACString& aAlias,
nsACString& oResult)
nsCharsetAlias::GetPreferredInternal(const nsACString& aAlias,
nsACString& oResult)
{
if (aAlias.IsEmpty()) return NS_ERROR_NULL_POINTER;
nsCAutoString key(aAlias);
ToLowerCase(key);
@ -37,6 +39,24 @@ nsCharsetAlias::GetPreferred(const nsACString& aAlias,
ArrayLength(kAliases), key, oResult);
}
//--------------------------------------------------------------
// static
nsresult
nsCharsetAlias::GetPreferred(const nsACString& aAlias,
nsACString& oResult)
{
if (aAlias.IsEmpty()) return NS_ERROR_NULL_POINTER;
nsresult res = GetPreferredInternal(aAlias, oResult);
if (NS_FAILED(res))
return res;
if (nsCharsetConverterManager::IsInternal(oResult))
return NS_ERROR_UCONV_NOCONV;
return res;
}
//--------------------------------------------------------------
// static
nsresult
@ -57,12 +77,12 @@ nsCharsetAlias::Equals(const nsACString& aCharset1,
*oResult = false;
nsCAutoString name1;
res = GetPreferred(aCharset1, name1);
res = GetPreferredInternal(aCharset1, name1);
if (NS_FAILED(res))
return res;
nsCAutoString name2;
res = GetPreferred(aCharset2, name2);
res = GetPreferredInternal(aCharset2, name2);
if (NS_FAILED(res))
return res;

View File

@ -33,20 +33,16 @@ interface nsIUTF8StringEnumerator;
* @created 21/Feb/2000
* @author Catalin Rotaru [CATA]
*/
[scriptable, uuid(bf733b00-198f-4553-a061-637a21793330)]
[scriptable, uuid(a0550d46-8d9c-47dd-acc7-c083620dff12)]
interface nsICharsetConverterManager : nsISupports
{
/**
* Get the Unicode decoder for the given charset.
* The "Raw" version skips charset alias resolution
* The "Internal" version will return a decoder for any charset; the others
* will return NS_ERROR_UCONV_NOCONV if the requested charsets is
* vulnerable to XSS attacks and should not be used with untrusted input
*/
[noscript] nsIUnicodeDecoder getUnicodeDecoder(in string charset);
[noscript] nsIUnicodeDecoder getUnicodeDecoderRaw(in string charset);
[noscript] nsIUnicodeDecoder getUnicodeDecoderInternal(in string charset);
[noscript] nsIUnicodeDecoder getUnicodeDecoderRawInternal(in string charset);
/**
* Get the Unicode encoder for the given charset.

View File

@ -27,26 +27,32 @@
// just for CONTRACTIDs
#include "nsCharsetConverterManager.h"
static nsIStringBundle * sDataBundle;
static nsIStringBundle * sTitleBundle;
// Class nsCharsetConverterManager [implementation]
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCharsetConverterManager,
nsICharsetConverterManager)
nsCharsetConverterManager::nsCharsetConverterManager()
: mDataBundle(NULL)
, mTitleBundle(NULL)
{
}
nsCharsetConverterManager::~nsCharsetConverterManager()
{
NS_IF_RELEASE(mDataBundle);
NS_IF_RELEASE(mTitleBundle);
}
nsresult nsCharsetConverterManager::LoadExtensibleBundle(
const char* aCategory,
nsIStringBundle ** aResult)
//static
void nsCharsetConverterManager::Shutdown()
{
NS_IF_RELEASE(sDataBundle);
NS_IF_RELEASE(sTitleBundle);
}
static
nsresult LoadExtensibleBundle(const char* aCategory,
nsIStringBundle ** aResult)
{
nsCOMPtr<nsIStringBundleService> sbServ =
mozilla::services::GetStringBundleService();
@ -56,10 +62,11 @@ nsresult nsCharsetConverterManager::LoadExtensibleBundle(
return sbServ->CreateExtensibleBundle(aCategory, aResult);
}
nsresult nsCharsetConverterManager::GetBundleValue(nsIStringBundle * aBundle,
const char * aName,
const nsAFlatString& aProp,
PRUnichar ** aResult)
static
nsresult GetBundleValue(nsIStringBundle * aBundle,
const char * aName,
const nsAFlatString& aProp,
PRUnichar ** aResult)
{
nsAutoString key;
@ -70,10 +77,11 @@ nsresult nsCharsetConverterManager::GetBundleValue(nsIStringBundle * aBundle,
return aBundle->GetStringFromName(key.get(), aResult);
}
nsresult nsCharsetConverterManager::GetBundleValue(nsIStringBundle * aBundle,
const char * aName,
const nsAFlatString& aProp,
nsAString& aResult)
static
nsresult GetBundleValue(nsIStringBundle * aBundle,
const char * aName,
const nsAFlatString& aProp,
nsAString& aResult)
{
nsresult rv = NS_OK;
@ -87,6 +95,35 @@ nsresult nsCharsetConverterManager::GetBundleValue(nsIStringBundle * aBundle,
return NS_OK;
}
static
nsresult GetCharsetDataImpl(const char * aCharset, const PRUnichar * aProp,
nsAString& aResult)
{
if (aCharset == NULL)
return NS_ERROR_NULL_POINTER;
// aProp can be NULL
if (sDataBundle == NULL) {
nsresult rv = LoadExtensibleBundle(NS_DATA_BUNDLE_CATEGORY, &sDataBundle);
if (NS_FAILED(rv))
return rv;
}
return GetBundleValue(sDataBundle, aCharset, nsDependentString(aProp), aResult);
}
//static
bool nsCharsetConverterManager::IsInternal(const nsACString& aCharset)
{
nsAutoString str;
// fully qualify to possibly avoid vtable call
nsresult rv = GetCharsetDataImpl(PromiseFlatCString(aCharset).get(),
NS_LITERAL_STRING(".isXSSVulnerable").get(),
str);
return NS_SUCCEEDED(rv);
}
//----------------------------------------------------------------------------//----------------------------------------------------------------------------
// Interface nsICharsetConverterManager [implementation]
@ -132,29 +169,17 @@ nsCharsetConverterManager::GetUnicodeEncoderRaw(const char * aDest,
return rv;
}
NS_IMETHODIMP
nsCharsetConverterManager::GetUnicodeDecoderRaw(const char * aSrc,
nsIUnicodeDecoder ** aResult)
{
nsresult rv;
nsAutoString str;
rv = GetCharsetData(aSrc, NS_LITERAL_STRING(".isXSSVulnerable").get(), str);
if (NS_SUCCEEDED(rv))
return NS_ERROR_UCONV_NOCONV;
return GetUnicodeDecoderRawInternal(aSrc, aResult);
}
NS_IMETHODIMP
nsCharsetConverterManager::GetUnicodeDecoder(const char * aSrc,
nsIUnicodeDecoder ** aResult)
{
// resolve the charset first
nsCAutoString charset;
// fully qualify to possibly avoid vtable call
nsCharsetConverterManager::GetCharsetAlias(aSrc, charset);
nsresult rv = nsCharsetConverterManager::GetCharsetAlias(aSrc, charset);
if (NS_FAILED(rv))
return rv;
return nsCharsetConverterManager::GetUnicodeDecoderRaw(charset.get(),
aResult);
@ -166,18 +191,18 @@ nsCharsetConverterManager::GetUnicodeDecoderInternal(const char * aSrc,
{
// resolve the charset first
nsCAutoString charset;
// fully qualify to possibly avoid vtable call
nsresult rv = nsCharsetConverterManager::GetCharsetAlias(aSrc, charset);
nsresult rv = nsCharsetAlias::GetPreferredInternal(nsDependentCString(aSrc),
charset);
NS_ENSURE_SUCCESS(rv, rv);
return nsCharsetConverterManager::GetUnicodeDecoderRawInternal(charset.get(),
aResult);
return nsCharsetConverterManager::GetUnicodeDecoderRaw(charset.get(),
aResult);
}
NS_IMETHODIMP
nsCharsetConverterManager::GetUnicodeDecoderRawInternal(const char * aSrc,
nsIUnicodeDecoder ** aResult)
nsCharsetConverterManager::GetUnicodeDecoderRaw(const char * aSrc,
nsIUnicodeDecoder ** aResult)
{
*aResult= nsnull;
nsCOMPtr<nsIUnicodeDecoder> decoder;
@ -186,7 +211,7 @@ nsCharsetConverterManager::GetUnicodeDecoderRawInternal(const char * aSrc,
NS_NAMED_LITERAL_CSTRING(contractbase, NS_UNICODEDECODER_CONTRACTID_BASE);
nsDependentCString src(aSrc);
decoder = do_CreateInstance(PromiseFlatCString(contractbase + src).get(),
&rv);
NS_ENSURE_SUCCESS(rv, NS_ERROR_UCONV_NOCONV);
@ -195,10 +220,10 @@ nsCharsetConverterManager::GetUnicodeDecoderRawInternal(const char * aSrc,
return rv;
}
nsresult
nsCharsetConverterManager::GetList(const nsACString& aCategory,
const nsACString& aPrefix,
nsIUTF8StringEnumerator** aResult)
static
nsresult GetList(const nsACString& aCategory,
const nsACString& aPrefix,
nsIUTF8StringEnumerator** aResult)
{
if (aResult == NULL)
return NS_ERROR_NULL_POINTER;
@ -289,12 +314,12 @@ nsCharsetConverterManager::GetCharsetTitle(const char * aCharset,
{
NS_ENSURE_ARG_POINTER(aCharset);
if (mTitleBundle == NULL) {
nsresult rv = LoadExtensibleBundle(NS_TITLE_BUNDLE_CATEGORY, &mTitleBundle);
if (sTitleBundle == NULL) {
nsresult rv = LoadExtensibleBundle(NS_TITLE_BUNDLE_CATEGORY, &sTitleBundle);
NS_ENSURE_SUCCESS(rv, rv);
}
return GetBundleValue(mTitleBundle, aCharset, NS_LITERAL_STRING(".title"), aResult);
return GetBundleValue(sTitleBundle, aCharset, NS_LITERAL_STRING(".title"), aResult);
}
NS_IMETHODIMP
@ -302,17 +327,7 @@ nsCharsetConverterManager::GetCharsetData(const char * aCharset,
const PRUnichar * aProp,
nsAString& aResult)
{
if (aCharset == NULL)
return NS_ERROR_NULL_POINTER;
// aProp can be NULL
if (mDataBundle == NULL) {
nsresult rv = LoadExtensibleBundle(NS_DATA_BUNDLE_CATEGORY, &mDataBundle);
if (NS_FAILED(rv))
return rv;
}
return GetBundleValue(mDataBundle, aCharset, nsDependentString(aProp), aResult);
return GetCharsetDataImpl(aCharset, aProp, aResult);
}
NS_IMETHODIMP
@ -336,19 +351,10 @@ nsCharsetConverterManager::GetCharsetLangGroupRaw(const char * aCharset,
{
*aResult = nsnull;
if (aCharset == NULL)
return NS_ERROR_NULL_POINTER;
nsresult rv = NS_OK;
if (mDataBundle == NULL) {
rv = LoadExtensibleBundle(NS_DATA_BUNDLE_CATEGORY, &mDataBundle);
if (NS_FAILED(rv))
return rv;
}
nsAutoString langGroup;
rv = GetBundleValue(mDataBundle, aCharset, NS_LITERAL_STRING(".LangGroup"), langGroup);
// fully qualify to possibly avoid vtable call
nsresult rv = nsCharsetConverterManager::GetCharsetData(
aCharset, NS_LITERAL_STRING(".LangGroup").get(), langGroup);
if (NS_SUCCEEDED(rv)) {
ToLowerCase(langGroup); // use lowercase for all language atoms

View File

@ -11,34 +11,24 @@
#include "nsInterfaceHashtable.h"
#include "mozilla/Mutex.h"
class nsCharsetAlias;
class nsCharsetConverterManager : public nsICharsetConverterManager
{
friend class nsCharsetAlias;
NS_DECL_ISUPPORTS
NS_DECL_NSICHARSETCONVERTERMANAGER
public:
nsCharsetConverterManager();
virtual ~nsCharsetConverterManager();
static void Shutdown();
private:
nsIStringBundle * mDataBundle;
nsIStringBundle * mTitleBundle;
nsresult LoadExtensibleBundle(const char * aRegistryKey,
nsIStringBundle ** aResult);
nsresult GetBundleValue(nsIStringBundle * aBundle,
const char * aName,
const nsAFlatString& aProp, PRUnichar ** aResult);
nsresult GetBundleValue(nsIStringBundle * aBundle,
const char * aName,
const nsAFlatString& aProp, nsAString& aResult);
nsresult GetList(const nsACString& aCategory,
const nsACString& aPrefix,
nsIUTF8StringEnumerator** aResult);
static bool IsInternal(const nsACString& aCharset);
};
#endif // nsCharsetConverterManager_h__

View File

@ -112,6 +112,9 @@ nsConverterOutputStream::Flush()
"1024 bytes ought to be enough for everyone");
if (NS_FAILED(rv))
return rv;
if (size == 0)
return NS_OK;
PRUint32 written;
rv = mOutStream->Write(buf, size, &written);
if (NS_FAILED(rv)) {

View File

@ -9,7 +9,7 @@ function run_test()
while (decoderList.hasMore()) {
var decoder = decoderList.getNext();
try {
var langGroup = ccManager.getCharsetLangGroup(decoder);
var langGroup = ccManager.getCharsetLangGroupRaw(decoder);
} catch(e) {
dump("no langGroup for " + decoder + "\n");
failures = true;

View File

@ -62,6 +62,8 @@ endif
include $(topsrcdir)/config/rules.mk
LDFLAGS += $(MOZ_ALLOW_HEAP_EXECUTE_FLAGS)
ifeq ($(OS_ARCH),WINNT) #{
#
# Control the default heap size.

View File

@ -11,7 +11,11 @@
#include <mach/mach.h>
#elif defined(OS_LINUX)
#include <sys/syscall.h>
#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)
#include <sys/prctl.h>
#elif !defined(__NetBSD__)
#include <pthread_np.h>
#endif
#include <unistd.h>
#endif
@ -34,7 +38,7 @@ PlatformThreadId PlatformThread::CurrentId() {
// into the kernel.
#if defined(OS_MACOSX)
return mach_thread_self();
#elif defined (__OpenBSD__)
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
// TODO(BSD): find a better thread ID
return (intptr_t)(pthread_self());
#elif defined(OS_LINUX)
@ -79,7 +83,13 @@ void PlatformThread::SetName(const char* name) {
// Note that glibc also has a 'pthread_setname_np' api, but it may not be
// available everywhere and it's only benefit over using prctl directly is
// that it can set the name of threads other than the current thread.
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
pthread_set_name_np(pthread_self(), name);
#elif defined(__NetBSD__)
pthread_setname_np(pthread_self(), "%s", name);
#else
prctl(PR_SET_NAME, reinterpret_cast<uintptr_t>(name), 0, 0, 0);
#endif
}
#endif // !OS_MACOSX

View File

@ -26,13 +26,13 @@ static JSObject *
InitClass(JSContext *cx, Handle<GlobalObject*> global, Class *clasp, JSProtoKey key, Native construct,
JSFunctionSpec *methods)
{
RootedVarObject proto(cx, global->createBlankPrototype(cx, clasp));
RootedObject proto(cx, global->createBlankPrototype(cx, clasp));
if (!proto)
return NULL;
proto->setPrivate(NULL);
JSAtom *atom = cx->runtime->atomState.classAtoms[key];
RootedVarFunction ctor(cx, global->createConstructor(cx, construct, atom, 1));
RootedFunction ctor(cx, global->createConstructor(cx, construct, atom, 1));
if (!ctor ||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
!DefinePropertiesAndBrand(cx, proto, NULL, methods) ||
@ -155,7 +155,7 @@ JSFunctionSpec MapObject::methods[] = {
JSObject *
MapObject::initClass(JSContext *cx, JSObject *obj)
{
return InitClass(cx, RootedVar<GlobalObject*>(cx, &obj->asGlobal()),
return InitClass(cx, Rooted<GlobalObject*>(cx, &obj->asGlobal()),
&class_, JSProto_Map, construct, methods);
}
@ -198,7 +198,7 @@ class AddToMap {
if (!hkey.setValue(cx, key))
return false;
HashableValue::StackRoot hkeyRoot(cx, &hkey);
HashableValue::AutoRooter hkeyRoot(cx, &hkey);
Value val;
if (!pairobj->getElement(cx, 1, &val))
@ -215,7 +215,7 @@ class AddToMap {
JSBool
MapObject::construct(JSContext *cx, unsigned argc, Value *vp)
{
RootedVarObject obj(cx, NewBuiltinClassInstance(cx, &class_));
RootedObject obj(cx, NewBuiltinClassInstance(cx, &class_));
if (!obj)
return false;
@ -357,7 +357,7 @@ JSFunctionSpec SetObject::methods[] = {
JSObject *
SetObject::initClass(JSContext *cx, JSObject *obj)
{
return InitClass(cx, RootedVar<GlobalObject*>(cx, &obj->asGlobal()),
return InitClass(cx, Rooted<GlobalObject*>(cx, &obj->asGlobal()),
&class_, JSProto_Set, construct, methods);
}
@ -401,7 +401,7 @@ class AddToSet {
JSBool
SetObject::construct(JSContext *cx, unsigned argc, Value *vp)
{
RootedVarObject obj(cx, NewBuiltinClassInstance(cx, &class_));
RootedObject obj(cx, NewBuiltinClassInstance(cx, &class_));
if (!obj)
return false;

View File

@ -41,9 +41,23 @@ class HashableValue {
bool equals(const HashableValue &other) const;
HashableValue mark(JSTracer *trc) const;
struct StackRoot {
StackRoot(JSContext *cx, HashableValue *pv) : valueRoot(cx, (Value*) &pv->value) {}
RootValue valueRoot;
class AutoRooter : private AutoGCRooter
{
public:
explicit AutoRooter(JSContext *cx, HashableValue *v_
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, HASHABLEVALUE), v(v_), skip(cx, v_)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
friend void AutoGCRooter::trace(JSTracer *trc);
void trace(JSTracer *trc);
private:
HashableValue *v;
SkipRoot skip;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
};

View File

@ -21,10 +21,10 @@ using namespace js::types;
class RegExpMatchBuilder
{
JSContext * const cx;
RootedVarObject array;
RootedObject array;
bool setProperty(JSAtom *name, Value v) {
return !!baseops::DefineProperty(cx, array, RootedVarId(cx, AtomToId(name)), &v,
return !!baseops::DefineProperty(cx, array, RootedId(cx, AtomToId(name)), &v,
JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
}
@ -51,7 +51,7 @@ static bool
CreateRegExpMatchResult(JSContext *cx, JSString *input_, const jschar *chars, size_t length,
MatchPairs *matchPairs, Value *rval)
{
RootedVarString input(cx, input_);
RootedString input(cx, input_);
/*
* Create the (slow) result array for a match.
@ -62,7 +62,7 @@ CreateRegExpMatchResult(JSContext *cx, JSString *input_, const jschar *chars, si
* input: input string
* index: start index for the match
*/
RootedVarObject array(cx, NewSlowEmptyArray(cx));
RootedObject array(cx, NewSlowEmptyArray(cx));
if (!array)
return false;
@ -194,7 +194,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
{
if (args.length() == 0) {
RegExpStatics *res = cx->regExpStatics();
RegExpObject *reobj = builder.build(RootedVarAtom(cx, cx->runtime->emptyString),
RegExpObject *reobj = builder.build(RootedAtom(cx, cx->runtime->emptyString),
res->getFlags());
if (!reobj)
return false;
@ -242,7 +242,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
if (!sourceObj.getProperty(cx, cx->runtime->atomState.sourceAtom, &v))
return false;
RegExpObject *reobj = builder.build(RootedVarAtom(cx, &v.toString()->asAtom()), flags);
RegExpObject *reobj = builder.build(RootedAtom(cx, &v.toString()->asAtom()), flags);
if (!reobj)
return false;
@ -274,7 +274,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
return false;
}
RootedVarAtom escapedSourceStr(cx, EscapeNakedForwardSlashes(cx, source));
RootedAtom escapedSourceStr(cx, EscapeNakedForwardSlashes(cx, source));
if (!escapedSourceStr)
return false;
@ -452,21 +452,21 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
RootedVar<GlobalObject*> global(cx, &obj->asGlobal());
Rooted<GlobalObject*> global(cx, &obj->asGlobal());
RootedVarObject proto(cx, global->createBlankPrototype(cx, &RegExpClass));
RootedObject proto(cx, global->createBlankPrototype(cx, &RegExpClass));
if (!proto)
return NULL;
proto->setPrivate(NULL);
RegExpObjectBuilder builder(cx, &proto->asRegExp());
if (!builder.build(RootedVarAtom(cx, cx->runtime->emptyString), RegExpFlag(0)))
if (!builder.build(RootedAtom(cx, cx->runtime->emptyString), RegExpFlag(0)))
return NULL;
if (!DefinePropertiesAndBrand(cx, proto, NULL, regexp_methods))
return NULL;
RootedVarFunction ctor(cx);
RootedFunction ctor(cx);
ctor = global->createConstructor(cx, regexp_construct, CLASS_NAME(cx, RegExp), 2);
if (!ctor)
return NULL;
@ -545,7 +545,7 @@ ExecuteRegExp(JSContext *cx, Native native, unsigned argc, Value *vp)
if (!obj)
return ok;
RootedVar<RegExpObject*> reobj(cx, &obj->asRegExp());
Rooted<RegExpObject*> reobj(cx, &obj->asRegExp());
RegExpGuard re;
if (StartsWithGreedyStar(reobj->getSource())) {

View File

@ -594,6 +594,7 @@ proto/exec.h
psap.h
Pt.h
pthread.h
pthread_np.h
pwd.h
Python.h
QDOffscreen.h

View File

@ -359,6 +359,7 @@ case "$target" in
CPPFLAGS="-isystem $android_platform/usr/include $CPPFLAGS"
CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS"
ASFLAGS="-isystem $android_platform/usr/include -DANDROID $ASFLAGS"
dnl Add -llog by default, since we use it all over the place.
dnl Add --allow-shlib-undefined, because libGLESv2 links to an
@ -2876,11 +2877,11 @@ EOF
"$ac_cv_have_visibility_class_bug" = "no"; then
VISIBILITY_FLAGS='-I$(DIST)/system_wrappers_js -include $(topsrcdir)/config/gcc_hidden.h'
WRAP_SYSTEM_INCLUDES=1
STL_FLAGS='-I$(DIST)/stl_wrappers'
WRAP_STL_INCLUDES=1
else
VISIBILITY_FLAGS='-fvisibility=hidden'
fi # have visibility pragma bug
STL_FLAGS='-I$(DIST)/stl_wrappers'
WRAP_STL_INCLUDES=1
fi # have visibility pragma
fi # have visibility(default) attribute
fi # have visibility(hidden) attribute

View File

@ -22,12 +22,12 @@ using namespace js;
using namespace js::frontend;
bool
MarkInnerAndOuterFunctions(JSContext *cx, JSScript* script)
MarkInnerAndOuterFunctions(JSContext *cx, JSScript* script_)
{
Root<JSScript*> root(cx, &script);
Rooted<JSScript*> script(cx, script_);
Vector<JSScript *, 16> worklist(cx);
if (!worklist.append(script))
if (!worklist.append(script.reference()))
return false;
while (worklist.length()) {
@ -243,7 +243,7 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
JS_ASSERT(bce.version() == version);
RootedVar<JSScript*> script(cx);
Rooted<JSScript*> script(cx);
script = JSScript::NewScriptFromEmitter(cx, &bce);
if (!script)
return NULL;

View File

@ -1015,7 +1015,7 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
if (!EmitObjectOp(cx, pn->pn_objbox, op, bce))
return false;
RootedVar<StaticBlockObject*> blockObj(cx, &pn->pn_objbox->object->asStaticBlock());
Rooted<StaticBlockObject*> blockObj(cx, &pn->pn_objbox->object->asStaticBlock());
int depth = bce->stackDepth -
(blockObj->slotCount() + ((op == JSOP_ENTERLET1) ? 1 : 0));
@ -1169,7 +1169,7 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return JS_TRUE;
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
RootedVarAtom atom(cx, pn->pn_atom);
RootedAtom atom(cx, pn->pn_atom);
UpvarCookie cookie = dn->pn_cookie;
dn_kind = dn->kind();
@ -3684,12 +3684,12 @@ ParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp)
case PNK_RB: {
JS_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
RootedVarObject obj(cx, NewDenseAllocatedArray(cx, pn_count));
RootedObject obj(cx, NewDenseAllocatedArray(cx, pn_count));
if (!obj)
return false;
unsigned idx = 0;
RootedVarId id(cx);
RootedId id(cx);
for (ParseNode *pn = pn_head; pn; idx++, pn = pn->pn_next) {
Value value;
if (!pn->getConstantValue(cx, strictChecks, &value))
@ -3708,7 +3708,7 @@ ParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp)
JS_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
gc::AllocKind kind = GuessObjectGCKind(pn_count);
RootedVarObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass, kind));
RootedObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass, kind));
if (!obj)
return false;
@ -3720,7 +3720,7 @@ ParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp)
ParseNode *pnid = pn->pn_left;
if (pnid->isKind(PNK_NUMBER)) {
Value idvalue = NumberValue(pnid->pn_dval);
RootedVarId id(cx);
RootedId id(cx);
if (idvalue.isInt32() && INT_FITS_IN_JSID(idvalue.toInt32()))
id = INT_TO_JSID(idvalue.toInt32());
else if (!InternNonIntElementId(cx, obj, idvalue, id.address()))
@ -3730,7 +3730,7 @@ ParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp)
} else {
JS_ASSERT(pnid->isKind(PNK_NAME) || pnid->isKind(PNK_STRING));
JS_ASSERT(pnid->pn_atom != cx->runtime->atomState.protoAtom);
RootedVarId id(cx, AtomToId(pnid->pn_atom));
RootedId id(cx, AtomToId(pnid->pn_atom));
if (!DefineNativeProperty(cx, obj, id, value, NULL, NULL,
JSPROP_ENUMERATE, 0, 0)) {
return false;
@ -4236,7 +4236,7 @@ EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
JS_ASSERT(varList->isArity(PN_LIST));
ParseNode *letBody = pnLet->pn_right;
JS_ASSERT(letBody->isLet() && letBody->isKind(PNK_LEXICALSCOPE));
RootedVar<StaticBlockObject*> blockObj(cx, &letBody->pn_objbox->object->asStaticBlock());
Rooted<StaticBlockObject*> blockObj(cx, &letBody->pn_objbox->object->asStaticBlock());
ptrdiff_t letHeadOffset = bce->offset();
int letHeadDepth = bce->stackDepth;
@ -4459,7 +4459,7 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
bool letDecl = pn1 && pn1->isKind(PNK_LEXICALSCOPE);
JS_ASSERT_IF(letDecl, pn1->isLet());
RootedVar<StaticBlockObject*> blockObj(cx, letDecl ? &pn1->pn_objbox->object->asStaticBlock() : NULL);
Rooted<StaticBlockObject*> blockObj(cx, letDecl ? &pn1->pn_objbox->object->asStaticBlock() : NULL);
uint32_t blockObjCount = blockObj ? blockObj->slotCount() : 0;
if (letDecl) {
@ -4782,7 +4782,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return Emit1(cx, bce, JSOP_GETFUNNS) >= 0;
#endif
RootedVarFunction fun(cx, pn->pn_funbox->function());
RootedFunction fun(cx, pn->pn_funbox->function());
JS_ASSERT(fun->isInterpreted());
if (fun->script()) {
/*
@ -5683,7 +5683,7 @@ EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* Try to construct the shape of the object as we go, so we can emit a
* JSOP_NEWOBJECT with the final shape instead.
*/
RootedVarObject obj(cx);
RootedObject obj(cx);
if (bce->parser->compileAndGo) {
gc::AllocKind kind = GuessObjectGCKind(pn->pn_count);
obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
@ -5733,7 +5733,7 @@ EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (obj) {
JS_ASSERT(!obj->inDictionaryMode());
if (!DefineNativeProperty(cx, obj, RootedVarId(cx, AtomToId(pn3->pn_atom)),
if (!DefineNativeProperty(cx, obj, RootedId(cx, AtomToId(pn3->pn_atom)),
UndefinedValue(), NULL, NULL,
JSPROP_ENUMERATE, 0, 0))
{

View File

@ -67,7 +67,7 @@ struct GlobalScope {
: globalObj(cx, globalObj)
{ }
RootedVarObject globalObj;
RootedObject globalObj;
};
struct BytecodeEmitter

View File

@ -200,8 +200,8 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, Parser *parser)
ParseNodeKind kind = pn->getKind();
ParseNode **pnp = &pn->pn_head;
ParseNode *pn1 = *pnp;
RootedVarString accum(cx);
RootedVarString str(cx);
RootedString accum(cx);
RootedString str(cx);
if ((pn->pn_xflags & PNX_CANTFOLD) == 0) {
if (kind == PNK_XMLETAGO)
accum = cx->runtime->atomState.etagoAtom;
@ -709,9 +709,9 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, Parser *parser, bool inGenexpLam
return false;
if (!pn1->isKind(PNK_STRING) || !pn2->isKind(PNK_STRING))
return true;
RootedVarString left(cx, pn1->pn_atom);
RootedVarString right(cx, pn2->pn_atom);
RootedVarString str(cx, js_ConcatStrings(cx, left, right));
RootedString left(cx, pn1->pn_atom);
RootedString right(cx, pn2->pn_atom);
RootedString str(cx, js_ConcatStrings(cx, left, right));
if (!str)
return false;
pn->pn_atom = js_AtomizeString(cx, str);

View File

@ -555,7 +555,7 @@ BindLocalVariable(JSContext *cx, SharedContext *sc, ParseNode *pn, BindingKind k
JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
unsigned index = sc->bindings.numVars();
if (!sc->bindings.add(cx, RootedVarAtom(cx, pn->pn_atom), kind))
if (!sc->bindings.add(cx, RootedAtom(cx, pn->pn_atom), kind))
return false;
pn->pn_cookie.set(sc->staticLevel, index);
@ -618,7 +618,7 @@ Parser::functionBody(FunctionBodyType type)
if (!CheckStrictParameters(context, this))
return NULL;
RootedVar<PropertyName*> const arguments(context, context->runtime->atomState.argumentsAtom);
Rooted<PropertyName*> const arguments(context, context->runtime->atomState.argumentsAtom);
/*
* Non-top-level functions use JSOP_DEFFUN which is a dynamic scope
@ -966,7 +966,7 @@ struct BindData {
struct LetData {
LetData(JSContext *cx) : blockObj(cx) {}
VarContext varContext;
RootedVar<StaticBlockObject*> blockObj;
Rooted<StaticBlockObject*> blockObj;
unsigned overflow;
} let;
@ -1047,10 +1047,10 @@ Parser::newFunction(TreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind)
while (tc->parent)
tc = tc->parent;
RootedVarObject parent(context);
RootedObject parent(context);
parent = tc->sc->inFunction ? NULL : tc->sc->scopeChain();
RootedVarFunction fun(context);
RootedFunction fun(context);
fun = js_NewFunction(context, NULL, NULL, 0,
JSFUN_INTERPRETED | (kind == Expression ? JSFUN_LAMBDA : 0),
parent, atom);
@ -1375,7 +1375,7 @@ Parser::functionArguments(ParseNode **listp, bool &hasRest)
case TOK_NAME:
{
RootedVar<PropertyName*> name(context, tokenStream.currentToken().name());
Rooted<PropertyName*> name(context, tokenStream.currentToken().name());
#ifdef JS_HAS_DESTRUCTURING
/*
@ -1562,7 +1562,7 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
if (outertc->sc->inStrictMode())
funsc.setInStrictMode(); // inherit strict mode from parent
RootedVarFunction fun(context, funbox->function());
RootedFunction fun(context, funbox->function());
/* Now parse formal argument list and compute fun->nargs. */
ParseNode *prelude = NULL;
@ -1752,7 +1752,7 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
ParseNode *
Parser::functionStmt()
{
RootedVarPropertyName name(context);
RootedPropertyName name(context);
if (tokenStream.getToken(TSF_KEYWORD_IS_NAME) == TOK_NAME) {
name = tokenStream.currentToken().name();
} else {
@ -1773,7 +1773,7 @@ Parser::functionStmt()
ParseNode *
Parser::functionExpr()
{
RootedVarPropertyName name(context);
RootedPropertyName name(context);
if (tokenStream.getToken(TSF_KEYWORD_IS_NAME) == TOK_NAME)
name = tokenStream.currentToken().name();
else
@ -1997,7 +1997,7 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
if (!CheckStrictBinding(cx, parser, atom->asPropertyName(), pn))
return false;
RootedVar<StaticBlockObject *> blockObj(cx, data->let.blockObj);
Rooted<StaticBlockObject *> blockObj(cx, data->let.blockObj);
unsigned blockCount = blockObj->slotCount();
if (blockCount == JS_BIT(16)) {
ReportCompileErrorNumber(cx, TS(parser), pn,
@ -2514,7 +2514,7 @@ CheckDestructuring(JSContext *cx, BindData *data, ParseNode *left, Parser *parse
return false;
}
RootedVar<StaticBlockObject *> blockObj(cx);
Rooted<StaticBlockObject *> blockObj(cx);
blockObj = data && data->binder == BindLet ? data->let.blockObj.reference() : NULL;
uint32_t blockCountBefore = blockObj ? blockObj->slotCount() : 0;
@ -2817,7 +2817,7 @@ Parser::letBlock(LetContext letContext)
if (!pnlet)
return NULL;
RootedVar<StaticBlockObject*> blockObj(context, StaticBlockObject::create(context));
Rooted<StaticBlockObject*> blockObj(context, StaticBlockObject::create(context));
if (!blockObj)
return NULL;
@ -3109,7 +3109,7 @@ Parser::forStatement()
bool forDecl = false;
/* Non-null when forDecl is true for a 'for (let ...)' statement. */
RootedVar<StaticBlockObject*> blockObj(context);
Rooted<StaticBlockObject*> blockObj(context);
/* Set to 'x' in 'for (x ;... ;...)' or 'for (x in ...)'. */
ParseNode *pn1;
@ -5291,7 +5291,7 @@ Parser::comprehensionTail(ParseNode *kid, unsigned blockid, bool isGenexp,
GenexpGuard guard(this);
RootedVarPropertyName name(context);
RootedPropertyName name(context);
tt = tokenStream.getToken();
switch (tt) {
#if JS_HAS_DESTRUCTURING
@ -6279,7 +6279,7 @@ Parser::xmlElementOrList(JSBool allowList)
ParseNode *pn, *pn2, *list;
TokenKind tt;
RootedVarAtom startAtom(context), endAtom(context);
RootedAtom startAtom(context), endAtom(context);
JS_CHECK_RECURSION(context, return NULL);
@ -6818,7 +6818,7 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
pn->pn_xflags |= PNX_NONCONST;
/* NB: Getter function in { get x(){} } is unnamed. */
pn2 = functionDef(RootedVarPropertyName(context, NULL),
pn2 = functionDef(RootedPropertyName(context, NULL),
op == JSOP_GETTER ? Getter : Setter, Expression);
if (!pn2)
return NULL;
@ -7035,7 +7035,7 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
RegExpFlag flags = tokenStream.currentToken().regExpFlags();
RegExpStatics *res = context->regExpStatics();
RootedVar<RegExpObject*> reobj(context);
Rooted<RegExpObject*> reobj(context);
if (context->hasfp())
reobj = RegExpObject::create(context, res, chars, length, flags, &tokenStream);
else

View File

@ -139,15 +139,15 @@ struct SharedContext {
StmtInfo *topStmt; /* top of statement info stack */
StmtInfo *topScopeStmt; /* top lexical scope statement */
RootedVar<StaticBlockObject *> blockChain;
Rooted<StaticBlockObject *> blockChain;
/* compile time block scope chain (NB: one
deeper than the topScopeStmt/downScope
chain when in head of let block/expr) */
private:
RootedVarFunction fun_; /* function to store argument and variable
RootedFunction fun_; /* function to store argument and variable
names when inFunction is set */
RootedVarObject scopeChain_; /* scope chain object for the script */
RootedObject scopeChain_; /* scope chain object for the script */
public:
unsigned staticLevel; /* static compilation unit nesting level */
@ -159,7 +159,7 @@ struct SharedContext {
Bindings bindings; /* bindings in this code, including
arguments if we're compiling a function */
Bindings::StackRoot bindingsRoot; /* root for stack allocated bindings. */
Bindings::AutoRooter bindingsRoot; /* root for stack allocated bindings. */
const bool inFunction:1; /* parsing/emitting inside function body */
@ -360,8 +360,8 @@ struct StmtInfo {
ptrdiff_t update; /* loop update offset (top if none) */
ptrdiff_t breaks; /* offset of last break in loop */
ptrdiff_t continues; /* offset of last continue in loop */
RootedVarAtom label; /* name of LABEL */
RootedVar<StaticBlockObject *> blockObj; /* block scope object */
RootedAtom label; /* name of LABEL */
Rooted<StaticBlockObject *> blockObj; /* block scope object */
StmtInfo *down; /* info for enclosing statement */
StmtInfo *downScope; /* next enclosing lexical scope */

View File

@ -44,27 +44,22 @@ namespace JS {
* on the type T of the value being rooted, for which RootMethods<T> must
* have an instantiation.
*
* - Root<T> roots an existing stack allocated variable or other location of
* type T. This is typically used either when a variable only needs to be
* rooted on certain rare paths, or when a function takes a bare GC thing
* pointer as an argument and needs to root it. In the latter case a
* Handle<T> is generally preferred, see below.
* - Rooted<T> declares a variable of type T, whose value is always rooted.
* Rooted<T> may be automatically coerced to a Handle<T>, below. Rooted<T>
* should be used whenever a local variable's value may be held live across a
* call which can allocate GC things or otherwise trigger a GC.
*
* - RootedVar<T> declares a variable of type T, whose value is always rooted.
*
* - Handle<T> is a const reference to a Root<T> or RootedVar<T>. Handles are
* coerced automatically from such a Root<T> or RootedVar<T>. Functions which
* take GC things or values as arguments and need to root those arguments
* should generally replace those arguments with handles and avoid any
* explicit rooting. This has two benefits. First, when several such
* functions call each other then redundant rooting of multiple copies of the
* GC thing can be avoided. Second, if the caller does not pass a rooted
* value a compile error will be generated, which is quicker and easier to
* fix than when relying on a separate rooting analysis.
* - Handle<T> is a const reference to a Rooted<T>. Functions which take GC
* things or values as arguments and need to root those arguments should
* generally use handles for those arguments and avoid any explicit rooting.
* This has two benefits. First, when several such functions call each other
* then redundant rooting of multiple copies of the GC thing can be avoided.
* Second, if the caller does not pass a rooted value a compile error will be
* generated, which is quicker and easier to fix than when relying on a
* separate rooting analysis.
*/
template <typename T> class Root;
template <typename T> class RootedVar;
template <typename T> class Rooted;
template <typename T>
struct RootMethods { };
@ -86,7 +81,7 @@ class Handle
/*
* This may be called only if the location of the T is guaranteed
* to be marked (for some reason other than being a Root or RootedVar),
* to be marked (for some reason other than being a Rooted),
* e.g., if it is guaranteed to be reachable from an implicit root.
*
* Create a Handle from a raw location of a T.
@ -99,10 +94,9 @@ class Handle
/*
* Construct a handle from an explicitly rooted location. This is the
* normal way to create a handle.
* normal way to create a handle, and normally happens implicitly.
*/
template <typename S> inline Handle(const Root<S> &root);
template <typename S> inline Handle(const RootedVar<S> &root);
template <typename S> inline Handle(const Rooted<S> &root);
const T *address() const { return ptr; }
T value() const { return *ptr; }
@ -141,39 +135,43 @@ struct RootMethods<T *>
};
/*
* Root a stack location holding a GC thing. This takes a stack pointer
* and ensures that throughout its lifetime the referenced variable
* will remain pinned against a moving GC.
*
* It is important to ensure that the location referenced by a Root is
* initialized, as otherwise the GC may try to use the the uninitialized value.
* It is generally preferable to use either RootedVar for local variables, or
* Handle for arguments.
* Local variable of type T whose value is always rooted. This is typically
* used for local variables, or for non-rooted values being passed to a
* function that requires a handle, e.g. Foo(Root<T>(cx, x)).
*/
template <typename T>
class Root
class Rooted
{
public:
Root(JSContext *cx_, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
void init(JSContext *cx_, T initial)
{
#ifdef JSGC_ROOT_ANALYSIS
ContextFriendFields *cx = ContextFriendFields::get(cx_);
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Root<T>**>(&cx->thingGCRooters[kind]);
this->stack = reinterpret_cast<Rooted<T>**>(&cx->thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(*ptr));
JS_ASSERT(!RootMethods<T>::poisoned(initial));
#endif
this->ptr = ptr;
JS_GUARD_OBJECT_NOTIFIER_INIT;
ptr = initial;
}
~Root()
public:
Rooted(JSContext *cx) { init(cx, RootMethods<T>::initial()); }
Rooted(JSContext *cx, T initial) { init(cx, initial); }
/*
* This method is only necessary due to an obscure C++98 requirement (that
* there be an accessible, usable copy constructor when passing a temporary
* to an implicitly-called constructor for use with a const-ref parameter).
* (Head spinning yet?) We can remove this when we build the JS engine
* with -std=c++11.
*/
operator Handle<T> () const { return Handle<T>(*this); }
~Rooted()
{
#ifdef JSGC_ROOT_ANALYSIS
JS_ASSERT(*stack == this);
@ -182,34 +180,53 @@ class Root
}
#ifdef JSGC_ROOT_ANALYSIS
Root<T> *previous() { return prev; }
Rooted<T> *previous() { return prev; }
#endif
const T *address() const { return ptr; }
operator T () const { return ptr; }
T operator ->() const { return ptr; }
T * address() { return &ptr; }
const T * address() const { return &ptr; }
T & reference() { return ptr; }
T raw() const { return ptr; }
T & operator =(T value)
{
JS_ASSERT(!RootMethods<T>::poisoned(value));
ptr = value;
return ptr;
}
T & operator =(const Rooted &value)
{
ptr = value;
return ptr;
}
private:
#ifdef JSGC_ROOT_ANALYSIS
Root<T> **stack, *prev;
Rooted<T> **stack, *prev;
#endif
const T *ptr;
T ptr;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
Rooted() MOZ_DELETE;
Rooted(const Rooted &) MOZ_DELETE;
};
template<typename T> template <typename S>
inline
Handle<T>::Handle(const Root<S> &root)
Handle<T>::Handle(const Rooted<S> &root)
{
testAssign<S>();
ptr = reinterpret_cast<const T *>(root.address());
}
typedef Root<JSObject*> RootObject;
typedef Root<JSFunction*> RootFunction;
typedef Root<JSString*> RootString;
typedef Root<jsid> RootId;
typedef Root<Value> RootValue;
typedef Rooted<JSObject*> RootedObject;
typedef Rooted<JSFunction*> RootedFunction;
typedef Rooted<JSString*> RootedString;
typedef Rooted<jsid> RootedId;
typedef Rooted<Value> RootedValue;
/*
* Mark a stack location as a root for the rooting analysis, without actually
@ -238,7 +255,7 @@ class SkipRoot
public:
template <typename T>
SkipRoot(JSContext *cx, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
init(ContextFriendFields::get(cx), ptr, 1);
JS_GUARD_OBJECT_NOTIFIER_INIT;
@ -246,7 +263,7 @@ class SkipRoot
template <typename T>
SkipRoot(JSContext *cx, const T *ptr, size_t count
JS_GUARD_OBJECT_NOTIFIER_PARAM)
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
init(ContextFriendFields::get(cx), ptr, count);
JS_GUARD_OBJECT_NOTIFIER_INIT;
@ -286,70 +303,6 @@ class SkipRoot
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/* Make a local variable which stays rooted throughout its lifetime. */
template <typename T>
class RootedVar
{
public:
RootedVar(JSContext *cx)
: ptr(RootMethods<T>::initial()), root(cx, &ptr)
{}
RootedVar(JSContext *cx, T initial)
: ptr(initial), root(cx, &ptr)
{}
operator T () const { return ptr; }
T operator ->() const { return ptr; }
T * address() { return &ptr; }
const T * address() const { return &ptr; }
T & reference() { return ptr; }
T raw() { return ptr; }
/*
* This method is only necessary due to an obscure C++98 requirement (that
* there be an accessible, usable copy constructor when passing a temporary
* to an implicitly-called constructor for use with a const-ref parameter).
* (Head spinning yet?) We can remove this when we build the JS engine
* with -std=c++11.
*/
operator Handle<T> () const { return Handle<T>(*this); }
T & operator =(T value)
{
JS_ASSERT(!RootMethods<T>::poisoned(value));
ptr = value;
return ptr;
}
T & operator =(const RootedVar &value)
{
ptr = value;
return ptr;
}
private:
T ptr;
Root<T> root;
RootedVar() MOZ_DELETE;
RootedVar(const RootedVar &) MOZ_DELETE;
};
template <typename T> template <typename S>
inline
Handle<T>::Handle(const RootedVar<S> &root)
{
testAssign<S>();
ptr = reinterpret_cast<const T *>(root.address());
}
typedef RootedVar<JSObject*> RootedVarObject;
typedef RootedVar<JSFunction*> RootedVarFunction;
typedef RootedVar<JSString*> RootedVarString;
typedef RootedVar<jsid> RootedVarId;
typedef RootedVar<Value> RootedVarValue;
/*
* Hook for dynamic root analysis. Checks the native stack and poisons
* references to GC things which have not been rooted.

View File

@ -539,7 +539,7 @@ JS_ValueToECMAInt32(JSContext *cx, jsval v, int32_t *ip)
CHECK_REQUEST(cx);
assertSameCompartment(cx, v);
RootedVarValue value(cx, v);
RootedValue value(cx, v);
return ToInt32(cx, value, ip);
}
@ -1766,7 +1766,7 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
assertSameCompartment(cx, obj);
return GlobalObject::initStandardClasses(cx, RootedVar<GlobalObject*>(cx, &obj->global()));
return GlobalObject::initStandardClasses(cx, Rooted<GlobalObject*>(cx, &obj->global()));
}
#define CLASP(name) (&name##Class)
@ -1911,7 +1911,7 @@ static JSStdName object_prototype_names[] = {
};
JS_PUBLIC_API(JSBool)
JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, JSBool *resolved)
JS_ResolveStandardClass(JSContext *cx, JSObject *obj_, jsid id, JSBool *resolved)
{
JSString *idstr;
JSRuntime *rt;
@ -1919,7 +1919,7 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, JSBool *resolved)
JSStdName *stdnm;
unsigned i;
RootObject objRoot(cx, &obj);
RootedObject obj(cx, obj_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
@ -2014,7 +2014,7 @@ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj_)
assertSameCompartment(cx, obj_);
rt = cx->runtime;
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
/*
* Check whether we need to bind 'undefined' and define it if so.
@ -3116,20 +3116,21 @@ JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp)
{
JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
JS_ASSERT(obj);
return DefaultValue(cx, RootedVarObject(cx, obj), type, vp);
return DefaultValue(cx, RootedObject(cx, obj), type, vp);
}
JS_PUBLIC_API(JSObject *)
JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
JS_InitClass(JSContext *cx, JSObject *obj_, JSObject *parent_proto,
JSClass *clasp, JSNative constructor, unsigned nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
{
RootedObject obj(cx, obj_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, parent_proto);
RootObject objRoot(cx, &obj);
return js_InitClass(cx, objRoot, parent_proto, Valueify(clasp), constructor,
return js_InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
nargs, ps, fs, static_ps, static_fs);
}
@ -3167,7 +3168,7 @@ JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
JS_PUBLIC_API(JSBool)
JS_HasInstance(JSContext *cx, JSObject *obj_, jsval v, JSBool *bp)
{
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
AssertNoGC(cx);
assertSameCompartment(cx, obj, v);
@ -3208,7 +3209,7 @@ JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, proto);
return SetProto(cx, RootedVarObject(cx, obj), RootedVarObject(cx, proto), JS_FALSE);
return SetProto(cx, RootedObject(cx, obj), RootedObject(cx, proto), JS_FALSE);
}
JS_PUBLIC_API(JSObject *)
@ -3226,7 +3227,7 @@ JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
JS_ASSERT(!obj->isScope());
JS_ASSERT(parent || !obj->getParent());
assertSameCompartment(cx, obj, parent);
return JSObject::setParent(cx, RootedVarObject(cx, obj), RootedVarObject(cx, parent));
return JSObject::setParent(cx, RootedObject(cx, obj), RootedObject(cx, parent));
}
JS_PUBLIC_API(JSObject *)
@ -3443,7 +3444,7 @@ JS_ConstructObjectWithArguments(JSContext *cx, JSClass *jsclasp, JSObject *paren
JSProtoKey protoKey = GetClassProtoKey(clasp);
/* Protect constructor in case a crazy getter for .prototype uproots it. */
RootedVarValue value(cx);
RootedValue value(cx);
if (!js_FindClassObject(cx, parent, protoKey, value.address(), clasp))
return NULL;
@ -3517,7 +3518,7 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, jsid id,
JS_PUBLIC_API(JSBool)
JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id_, jsval *vp)
{
RootedVarId id(cx, id_);
RootedId id(cx, id_);
JSObject *obj2;
JSProperty *prop;
@ -3553,8 +3554,8 @@ JS_PUBLIC_API(JSBool)
JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj_, jsid id_, unsigned flags,
JSObject **objp, jsval *vp)
{
RootedVarObject obj(cx, obj_);
RootedVarId id(cx, id_);
RootedObject obj(cx, obj_);
RootedId id(cx, id_);
JSBool ok;
JSProperty *prop;
@ -3579,7 +3580,7 @@ JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name, unsig
JS_PUBLIC_API(JSBool)
JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id_, JSBool *foundp)
{
RootedVarId id(cx, id_);
RootedId id(cx, id_);
JSObject *obj2;
JSProperty *prop;
@ -3617,7 +3618,7 @@ JS_HasUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namele
JS_PUBLIC_API(JSBool)
JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj, jsid id_, JSBool *foundp)
{
RootedVarId id(cx, id_);
RootedId id(cx, id_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
@ -3696,7 +3697,8 @@ DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue val
attrs |= JSPROP_GETTER;
}
if (setter) {
RootObject getRoot(cx, (JSObject **) &getter);
// Root just the getter, since the setter is not yet a JSObject.
AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, NULL);
JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, &obj->global(), NULL);
if (!setobj)
return false;
@ -3728,9 +3730,9 @@ JS_PUBLIC_API(JSBool)
JS_DefinePropertyById(JSContext *cx, JSObject *obj_, jsid id_, jsval value_,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
RootedVarObject obj(cx, obj_);
RootedVarId id(cx, id_);
RootedVarValue value(cx, value_);
RootedObject obj(cx, obj_);
RootedId id(cx, id_);
RootedValue value(cx, value_);
return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
}
@ -3738,12 +3740,12 @@ JS_PUBLIC_API(JSBool)
JS_DefineElement(JSContext *cx, JSObject *obj_, uint32_t index, jsval value_,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
RootedVarObject obj(cx, obj_);
RootedVarValue value(cx, value_);
RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
RootedObject obj(cx, obj_);
RootedValue value(cx, value_);
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
AssertNoGC(cx);
CHECK_REQUEST(cx);
RootedVarId id(cx);
RootedId id(cx);
if (!IndexToId(cx, index, id.address()))
return false;
return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
@ -3754,10 +3756,10 @@ DefineProperty(JSContext *cx, JSObject *obj_, const char *name, const Value &val
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int tinyid)
{
RootedVarObject obj(cx, obj_);
RootedVarValue value(cx, value_);
RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
RootedVarId id(cx);
RootedObject obj(cx, obj_);
RootedValue value(cx, value_);
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
RootedId id(cx);
if (attrs & JSPROP_INDEX) {
id = INT_TO_JSID(intptr_t(name));
@ -3791,13 +3793,13 @@ DefineUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namel
const Value &value_, PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int tinyid)
{
RootedVarObject obj(cx, obj_);
RootedVarValue value(cx, value_);
RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
RootedObject obj(cx, obj_);
RootedValue value(cx, value_);
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
if (!atom)
return false;
RootedVarId id(cx, AtomToId(atom));
RootedId id(cx, AtomToId(atom));
return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags, tinyid);
}
@ -3823,13 +3825,15 @@ JS_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, jsval descriptor, JS
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id, descriptor);
return js_DefineOwnProperty(cx, RootedVarObject(cx, obj), RootedVarId(cx, id), descriptor, bp);
return js_DefineOwnProperty(cx, RootedObject(cx, obj), RootedId(cx, id), descriptor, bp);
}
JS_PUBLIC_API(JSObject *)
JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *jsclasp,
JS_DefineObject(JSContext *cx, JSObject *obj_, const char *name, JSClass *jsclasp,
JSObject *proto, unsigned attrs)
{
RootedObject obj(cx, obj_), nobj(cx);
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, proto);
@ -3838,9 +3842,6 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *jsclasp
if (!clasp)
clasp = &ObjectClass; /* default class is Object */
RootObject root(cx, &obj);
RootedVarObject nobj(cx);
nobj = NewObjectWithClassProto(cx, clasp, proto, obj);
if (!nobj)
return NULL;
@ -3854,7 +3855,7 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *jsclasp
JS_PUBLIC_API(JSBool)
JS_DefineConstDoubles(JSContext *cx, JSObject *obj_, JSConstDoubleSpec *cds)
{
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
JSBool ok;
unsigned attrs;
@ -3874,10 +3875,10 @@ JS_DefineConstDoubles(JSContext *cx, JSObject *obj_, JSConstDoubleSpec *cds)
}
JS_PUBLIC_API(JSBool)
JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
JS_DefineProperties(JSContext *cx, JSObject *obj_, JSPropertySpec *ps)
{
JSBool ok;
RootObject root(cx, &obj);
RootedObject obj(cx, obj_);
for (ok = true; ps->name; ps++) {
ok = DefineProperty(cx, obj, ps->name, UndefinedValue(), ps->getter, ps->setter,
@ -3937,7 +3938,7 @@ JS_PUBLIC_API(JSBool)
JS_GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id_, unsigned flags,
JSPropertyDescriptor *desc)
{
RootedVarId id(cx, id_);
RootedId id(cx, id_);
return GetPropertyDescriptorById(cx, obj, id, flags, JS_FALSE, desc);
}
@ -3946,7 +3947,7 @@ JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *obj, jsid id_,
unsigned *attrsp, JSBool *foundp,
JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
{
RootedVarId id(cx, id_);
RootedId id(cx, id_);
PropertyDescriptor desc;
if (!GetPropertyDescriptorById(cx, obj, id, JSRESOLVE_QUALIFIED, JS_FALSE, &desc))
return false;
@ -4004,7 +4005,7 @@ JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
AssertNoGC(cx);
CHECK_REQUEST(cx);
return GetOwnPropertyDescriptor(cx, RootedVarObject(cx, obj), RootedVarId(cx, id), vp);
return GetOwnPropertyDescriptor(cx, RootedObject(cx, obj), RootedId(cx, id), vp);
}
static JSBool
@ -4033,7 +4034,7 @@ JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
unsigned attrs, JSBool *foundp)
{
JSAtom *atom = js_Atomize(cx, name, strlen(name));
return atom && SetPropertyAttributesById(cx, obj, RootedVarId(cx, AtomToId(atom)), attrs, foundp);
return atom && SetPropertyAttributesById(cx, obj, RootedId(cx, AtomToId(atom)), attrs, foundp);
}
JS_PUBLIC_API(JSBool)
@ -4041,7 +4042,7 @@ JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj, const jschar *name, siz
unsigned attrs, JSBool *foundp)
{
JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
return atom && SetPropertyAttributesById(cx, obj, RootedVarId(cx, AtomToId(atom)), attrs, foundp);
return atom && SetPropertyAttributesById(cx, obj, RootedId(cx, AtomToId(atom)), attrs, foundp);
}
JS_PUBLIC_API(JSBool)
@ -4053,8 +4054,8 @@ JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
JS_PUBLIC_API(JSBool)
JS_ForwardGetPropertyTo(JSContext *cx, JSObject *obj, jsid id_, JSObject *onBehalfOf_, jsval *vp)
{
RootedVarId id(cx, id_);
RootedVarObject onBehalfOf(cx, onBehalfOf_);
RootedId id(cx, id_);
RootedObject onBehalfOf(cx, onBehalfOf_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
@ -4067,7 +4068,7 @@ JS_ForwardGetPropertyTo(JSContext *cx, JSObject *obj, jsid id_, JSObject *onBeha
JS_PUBLIC_API(JSBool)
JS_GetPropertyByIdDefault(JSContext *cx, JSObject *obj, jsid id, jsval def, jsval *vp)
{
return baseops::GetPropertyDefault(cx, RootedVarObject(cx, obj), RootedVarId(cx, id), def, vp);
return baseops::GetPropertyDefault(cx, RootedObject(cx, obj), RootedId(cx, id), def, vp);
}
JS_PUBLIC_API(JSBool)
@ -4079,7 +4080,7 @@ JS_GetElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
JS_PUBLIC_API(JSBool)
JS_ForwardGetElementTo(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf_, jsval *vp)
{
RootedVarObject onBehalfOf(cx, onBehalfOf_);
RootedObject onBehalfOf(cx, onBehalfOf_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
@ -4091,7 +4092,7 @@ JS_ForwardGetElementTo(JSContext *cx, JSObject *obj, uint32_t index, JSObject *o
JS_PUBLIC_API(JSBool)
JS_GetElementIfPresent(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf_, jsval *vp, JSBool* present)
{
RootedVarObject onBehalfOf(cx, onBehalfOf_);
RootedObject onBehalfOf(cx, onBehalfOf_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
@ -4107,7 +4108,7 @@ JS_GetElementIfPresent(JSContext *cx, JSObject *obj, uint32_t index, JSObject *o
JS_PUBLIC_API(JSBool)
JS_GetProperty(JSContext *cx, JSObject *obj_, const char *name, jsval *vp)
{
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
JSAtom *atom = js_Atomize(cx, name, strlen(name));
return atom && JS_GetPropertyById(cx, obj, AtomToId(atom), vp);
}
@ -4115,7 +4116,7 @@ JS_GetProperty(JSContext *cx, JSObject *obj_, const char *name, jsval *vp)
JS_PUBLIC_API(JSBool)
JS_GetPropertyDefault(JSContext *cx, JSObject *obj_, const char *name, jsval def, jsval *vp)
{
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
JSAtom *atom = js_Atomize(cx, name, strlen(name));
return atom && JS_GetPropertyByIdDefault(cx, obj, AtomToId(atom), def, vp);
}
@ -4123,7 +4124,7 @@ JS_GetPropertyDefault(JSContext *cx, JSObject *obj_, const char *name, jsval def
JS_PUBLIC_API(JSBool)
JS_GetUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, jsval *vp)
{
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
return atom && JS_GetPropertyById(cx, obj, AtomToId(atom), vp);
}
@ -4131,8 +4132,8 @@ JS_GetUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namel
JS_PUBLIC_API(JSBool)
JS_GetMethodById(JSContext *cx, JSObject *obj_, jsid id_, JSObject **objp, jsval *vp)
{
RootedVarObject obj(cx, obj_);
RootedVarId id(cx, id_);
RootedObject obj(cx, obj_);
RootedId id(cx, id_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
@ -4154,7 +4155,7 @@ JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, js
JS_PUBLIC_API(JSBool)
JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id_, jsval *vp)
{
RootedVarId id(cx, id_);
RootedId id(cx, id_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
@ -4166,7 +4167,7 @@ JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id_, jsval *vp)
JS_PUBLIC_API(JSBool)
JS_SetElement(JSContext *cx, JSObject *obj_, uint32_t index, jsval *vp)
{
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
@ -4178,7 +4179,7 @@ JS_SetElement(JSContext *cx, JSObject *obj_, uint32_t index, jsval *vp)
JS_PUBLIC_API(JSBool)
JS_SetProperty(JSContext *cx, JSObject *obj_, const char *name, jsval *vp)
{
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
JSAtom *atom = js_Atomize(cx, name, strlen(name));
return atom && JS_SetPropertyById(cx, obj, AtomToId(atom), vp);
@ -4200,7 +4201,7 @@ JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
if (JSID_IS_SPECIAL(id))
return obj->deleteSpecial(cx, RootedVar<SpecialId>(cx, JSID_TO_SPECIALID(id)), rval, false);
return obj->deleteSpecial(cx, Rooted<SpecialId>(cx, JSID_TO_SPECIALID(id)), rval, false);
return obj->deleteByValue(cx, IdToValue(id), rval, false);
}
@ -4267,7 +4268,7 @@ JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
JS_PUBLIC_API(void)
JS_ClearScope(JSContext *cx, JSObject *obj_)
{
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
@ -4451,7 +4452,7 @@ JS_NewElementIterator(JSContext *cx, JSObject *obj)
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
return ElementIteratorObject::create(cx, RootedVarObject(cx, obj));
return ElementIteratorObject::create(cx, RootedObject(cx, obj));
}
JS_PUBLIC_API(JSObject *)
@ -4513,7 +4514,7 @@ JS_PUBLIC_API(JSBool)
JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id_, JSAccessMode mode,
jsval *vp, unsigned *attrsp)
{
RootedVarId id(cx, id_);
RootedId id(cx, id_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
@ -4564,11 +4565,13 @@ JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPri
JS_PUBLIC_API(JSFunction *)
JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
JSObject *parent, const char *name)
JSObject *parent_, const char *name)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
JSAtom *atom;
RootedObject parent(cx, parent_);
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, parent);
@ -4581,22 +4584,22 @@ JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
return NULL;
}
RootObject parentRoot(cx, &parent);
return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, atom);
return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
}
JS_PUBLIC_API(JSFunction *)
JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parent,
JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parent_,
jsid id)
{
RootedObject parent(cx, parent_);
JS_ASSERT(JSID_IS_STRING(id));
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, parent);
RootObject parentRoot(cx, &parent);
return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, JSID_TO_ATOM(id));
return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id));
}
JS_PUBLIC_API(JSObject *)
@ -4606,7 +4609,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent_)
CHECK_REQUEST(cx);
assertSameCompartment(cx, parent_); // XXX no funobj for now
RootedVarObject parent(cx, parent_);
RootedObject parent(cx, parent_);
if (!parent) {
if (cx->hasfp())
@ -4626,7 +4629,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent_)
return NULL;
}
RootedVarFunction fun(cx, funobj->toFunction());
RootedFunction fun(cx, funobj->toFunction());
if (fun->isInterpreted() && fun->script()->compileAndGo) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
@ -4690,8 +4693,8 @@ JS_IsNativeFunction(JSObject *funobj, JSNative call)
JS_PUBLIC_API(JSObject*)
JS_BindCallable(JSContext *cx, JSObject *callable, JSObject *newThis)
{
RootedVarObject target(cx, callable);
RootedVarValue thisArg(cx, ObjectValue(*newThis));
RootedObject target(cx, callable);
RootedValue thisArg(cx, ObjectValue(*newThis));
return js_fun_bind(cx, target, thisArg, NULL, 0);
}
@ -4722,13 +4725,13 @@ js_generic_native_method_dispatcher(JSContext *cx, unsigned argc, Value *vp)
}
JS_PUBLIC_API(JSBool)
JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
JS_DefineFunctions(JSContext *cx, JSObject *obj_, JSFunctionSpec *fs)
{
RootObject objRoot(cx, &obj);
RootedObject obj(cx, obj_);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
unsigned flags;
RootedVarObject ctor(cx);
RootedObject ctor(cx);
JSFunction *fun;
AssertNoGC(cx);
@ -4737,7 +4740,7 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
for (; fs->name; fs++) {
flags = fs->flags;
JSAtom *atom = js_Atomize(cx, fs->name, strlen(fs->name));
RootedAtom atom(cx, js_Atomize(cx, fs->name, strlen(fs->name)));
if (!atom)
return JS_FALSE;
@ -4746,8 +4749,6 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
* method if flags contains JSFUN_GENERIC_NATIVE.
*/
if (flags & JSFUN_GENERIC_NATIVE) {
RootAtom root(cx, &atom);
if (!ctor) {
ctor = JS_GetConstructor(cx, obj);
if (!ctor)
@ -4755,7 +4756,7 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
}
flags &= ~JSFUN_GENERIC_NATIVE;
fun = js_DefineFunction(cx, ctor, RootedVarId(cx, AtomToId(atom)),
fun = js_DefineFunction(cx, ctor, RootedId(cx, AtomToId(atom)),
js_generic_native_method_dispatcher,
fs->nargs + 1,
flags,
@ -4770,8 +4771,8 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
fun->setExtendedSlot(0, PrivateValue(fs));
}
fun = js_DefineFunction(cx, objRoot,
RootedVarId(cx, AtomToId(atom)), fs->call, fs->nargs, flags);
fun = js_DefineFunction(cx, obj,
RootedId(cx, AtomToId(atom)), fs->call, fs->nargs, flags);
if (!fun)
return JS_FALSE;
}
@ -4779,10 +4780,10 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
}
JS_PUBLIC_API(JSFunction *)
JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
JS_DefineFunction(JSContext *cx, JSObject *obj_, const char *name, JSNative call,
unsigned nargs, unsigned attrs)
{
RootObject objRoot(cx, &obj);
RootedObject obj(cx, obj_);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
AssertNoGC(cx);
@ -4791,15 +4792,15 @@ JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
JSAtom *atom = js_Atomize(cx, name, strlen(name));
if (!atom)
return NULL;
return js_DefineFunction(cx, objRoot, RootedVarId(cx, AtomToId(atom)), call, nargs, attrs);
return js_DefineFunction(cx, obj, RootedId(cx, AtomToId(atom)), call, nargs, attrs);
}
JS_PUBLIC_API(JSFunction *)
JS_DefineUCFunction(JSContext *cx, JSObject *obj,
JS_DefineUCFunction(JSContext *cx, JSObject *obj_,
const jschar *name, size_t namelen, JSNative call,
unsigned nargs, unsigned attrs)
{
RootObject objRoot(cx, &obj);
RootedObject obj(cx, obj_);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
AssertNoGC(cx);
@ -4808,15 +4809,15 @@ JS_DefineUCFunction(JSContext *cx, JSObject *obj,
JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
if (!atom)
return NULL;
return js_DefineFunction(cx, objRoot, RootedVarId(cx, AtomToId(atom)), call, nargs, attrs);
return js_DefineFunction(cx, obj, RootedId(cx, AtomToId(atom)), call, nargs, attrs);
}
extern JS_PUBLIC_API(JSFunction *)
JS_DefineFunctionById(JSContext *cx, JSObject *obj_, jsid id_, JSNative call,
unsigned nargs, unsigned attrs)
{
RootedVarObject obj(cx, obj_);
RootedVarId id(cx, id_);
RootedObject obj(cx, obj_);
RootedId id(cx, id_);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
AssertNoGC(cx);
@ -5136,13 +5137,13 @@ JS_GetGlobalFromScript(JSScript *script)
}
static JSFunction *
CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj_,
JSPrincipals *principals, const char *name,
unsigned nargs, const char **argnames,
const jschar *chars, size_t length,
const char *filename, unsigned lineno, JSVersion version)
{
RootObject objRoot(cx, &obj);
RootedObject obj(cx, obj_);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
AssertNoGC(cx);
@ -5150,7 +5151,7 @@ CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
assertSameCompartment(cx, obj, principals);
AutoLastFrameCheck lfc(cx);
RootedVarAtom funAtom(cx);
RootedAtom funAtom(cx);
if (name) {
funAtom = js_Atomize(cx, name, strlen(name));
if (!funAtom)
@ -5160,12 +5161,12 @@ CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
Bindings bindings(cx);
for (unsigned i = 0; i < nargs; i++) {
uint16_t dummy;
RootedVarAtom argAtom(cx, js_Atomize(cx, argnames[i], strlen(argnames[i])));
RootedAtom argAtom(cx, js_Atomize(cx, argnames[i], strlen(argnames[i])));
if (!argAtom || !bindings.addArgument(cx, argAtom, &dummy))
return NULL;
}
JSFunction *fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, objRoot, funAtom);
JSFunction *fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom);
if (!fun)
return NULL;
@ -5176,7 +5177,7 @@ CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
}
if (obj && funAtom &&
!obj->defineGeneric(cx, RootedVarId(cx, AtomToId(funAtom)), ObjectValue(*fun), NULL, NULL,
!obj->defineGeneric(cx, RootedId(cx, AtomToId(funAtom)), ObjectValue(*fun), NULL, NULL,
JSPROP_ENUMERATE))
{
return NULL;
@ -5351,7 +5352,7 @@ EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj_,
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
bool compileAndGo = true;
bool noScriptRval = !rval;
@ -5473,12 +5474,12 @@ JS_CallFunctionName(JSContext *cx, JSObject *obj_, const char *name, unsigned ar
assertSameCompartment(cx, obj_, JSValueArray(argv, argc));
AutoLastFrameCheck lfc(cx);
RootedVarObject obj(cx, obj_);
RootedObject obj(cx, obj_);
Value v;
JSAtom *atom = js_Atomize(cx, name, strlen(name));
return atom &&
GetMethod(cx, obj, RootedVarId(cx, AtomToId(atom)), 0, &v) &&
GetMethod(cx, obj, RootedId(cx, AtomToId(atom)), 0, &v) &&
Invoke(cx, ObjectOrNullValue(obj), v, argc, argv, rval);
}
@ -5857,7 +5858,7 @@ JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
{
AssertNoGC(cx);
CHECK_REQUEST(cx);
return js_ConcatStrings(cx, RootedVarString(cx, left), RootedVarString(cx, right));
return js_ConcatStrings(cx, RootedString(cx, left), RootedString(cx, right));
}
JS_PUBLIC_API(const jschar *)

View File

@ -919,7 +919,15 @@ class JS_PUBLIC_API(AutoGCRooter) {
STRING = -14, /* js::AutoStringRooter */
IDVECTOR = -15, /* js::AutoIdVector */
OBJVECTOR = -16, /* js::AutoObjectVector */
SCRIPTVECTOR =-17 /* js::AutoScriptVector */
SCRIPTVECTOR =-17, /* js::AutoScriptVector */
PROPDESC = -18, /* js::PropDesc::AutoRooter */
SHAPERANGE = -19, /* js::Shape::Range::AutoRooter */
STACKSHAPE = -20, /* js::StackShape::AutoRooter */
STACKBASESHAPE=-21,/* js::StackBaseShape::AutoRooter */
BINDINGS = -22, /* js::Bindings::AutoRooter */
GETTERSETTER =-23, /* js::AutoRooterGetterSetter */
REGEXPSTATICS=-24, /* js::RegExpStatics::AutoRooter */
HASHABLEVALUE=-25
};
private:
@ -1389,7 +1397,6 @@ typedef JSBool
* JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment
* JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence
* JSRESOLVE_DECLARING var, const, or function prolog declaration opcode
* JSRESOLVE_CLASSNAME class name used when constructing
*
* The *objp out parameter, on success, should be null to indicate that id
* was not resolved; and non-null, referring to obj or one of its prototypes,
@ -3803,8 +3810,7 @@ JS_IdToValue(JSContext *cx, jsid id, jsval *vp);
#define JSRESOLVE_ASSIGNING 0x02 /* resolve on the left of assignment */
#define JSRESOLVE_DETECTING 0x04 /* 'if (o.p)...' or '(o.p) ?...:...' */
#define JSRESOLVE_DECLARING 0x08 /* var, const, or function prolog op */
#define JSRESOLVE_CLASSNAME 0x10 /* class name used when constructing */
#define JSRESOLVE_WITH 0x20 /* resolve inside a with statement */
#define JSRESOLVE_WITH 0x10 /* resolve inside a with statement */
/*
* Invoke the [[DefaultValue]] hook (see ES5 8.6.2) with the provided hint on

View File

@ -133,7 +133,7 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, uint32_t *lengthp)
}
}
RootedVarValue value(cx);
RootedValue value(cx);
if (!obj->getProperty(cx, cx->runtime->atomState.lengthAtom, value.address()))
return false;
@ -335,8 +335,8 @@ JSObject::arrayGetOwnDataElement(JSContext *cx, size_t i, Value *vp)
static inline JSBool
DoGetElement(JSContext *cx, JSObject *obj_, double index, JSBool *hole, Value *vp)
{
RootedVarObject obj(cx, obj_);
RootedVarId id(cx);
RootedObject obj(cx, obj_);
RootedId id(cx);
*hole = JS_FALSE;
if (!IndexToId(cx, obj, index, hole, id.address()))
@ -479,13 +479,13 @@ SetArrayElement(JSContext *cx, HandleObject obj, double index, const Value &v)
return JS_FALSE;
}
RootedVarId id(cx);
RootedId id(cx);
if (!IndexToId(cx, obj, index, NULL, id.address(), JS_TRUE))
return JS_FALSE;
JS_ASSERT(!JSID_IS_VOID(id));
RootedVarValue tmp(cx, v);
RootedValue tmp(cx, v);
return obj->setGeneric(cx, id, tmp.address(), true);
}
@ -716,7 +716,7 @@ static JSBool
array_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, JSObject **objp,
JSProperty **propp)
{
return array_lookupGeneric(cx, obj, RootedVarId(cx, NameToId(name)), objp, propp);
return array_lookupGeneric(cx, obj, RootedId(cx, NameToId(name)), objp, propp);
}
static JSBool
@ -744,7 +744,7 @@ static JSBool
array_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, JSObject **objp,
JSProperty **propp)
{
return array_lookupGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), objp, propp);
return array_lookupGeneric(cx, obj, RootedId(cx, SPECIALID_TO_JSID(sid)), objp, propp);
}
JSBool
@ -776,7 +776,7 @@ array_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, Handle
}
if (!obj->isDenseArray())
return baseops::GetProperty(cx, obj, receiver, RootedVarId(cx, NameToId(name)), vp);
return baseops::GetProperty(cx, obj, receiver, RootedId(cx, NameToId(name)), vp);
JSObject *proto = obj->getProto();
if (!proto) {
@ -821,7 +821,7 @@ array_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleS
return true;
}
return baseops::GetProperty(cx, obj, receiver, RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp);
return baseops::GetProperty(cx, obj, receiver, RootedId(cx, SPECIALID_TO_JSID(sid)), vp);
}
static JSBool
@ -835,7 +835,7 @@ array_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleI
SpecialId sid;
if (ValueIsSpecial(obj, &idval, &sid, cx))
return array_getSpecial(cx, obj, receiver, RootedVar<SpecialId>(cx, sid), vp);
return array_getSpecial(cx, obj, receiver, Rooted<SpecialId>(cx, sid), vp);
JSAtom *atom;
if (!js_ValueToAtom(cx, idval, &atom))
@ -844,7 +844,7 @@ array_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleI
if (atom->isIndex(&index))
return array_getElement(cx, obj, receiver, index, vp);
return array_getProperty(cx, obj, receiver, RootedVarPropertyName(cx, atom->asPropertyName()), vp);
return array_getProperty(cx, obj, receiver, RootedPropertyName(cx, atom->asPropertyName()), vp);
}
static JSBool
@ -904,13 +904,13 @@ array_setGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool
static JSBool
array_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict)
{
return array_setGeneric(cx, obj, RootedVarId(cx, NameToId(name)), vp, strict);
return array_setGeneric(cx, obj, RootedId(cx, NameToId(name)), vp, strict);
}
static JSBool
array_setElement(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict)
{
RootedVarId id(cx);
RootedId id(cx);
if (!IndexToId(cx, index, id.address()))
return false;
@ -949,7 +949,7 @@ array_setElement(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSB
static JSBool
array_setSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict)
{
return array_setGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp, strict);
return array_setGeneric(cx, obj, RootedId(cx, SPECIALID_TO_JSID(sid)), vp, strict);
}
JSBool
@ -1004,7 +1004,7 @@ array_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, const Value *v
return true;
} while (false);
RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
if (!JSObject::makeDenseArraySlow(cx, obj))
return false;
@ -1015,7 +1015,7 @@ static JSBool
array_defineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *value,
JSPropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
return array_defineGeneric(cx, obj, RootedVarId(cx, NameToId(name)), value, getter, setter, attrs);
return array_defineGeneric(cx, obj, RootedId(cx, NameToId(name)), value, getter, setter, attrs);
}
namespace js {
@ -1050,8 +1050,7 @@ array_defineElement(JSContext *cx, HandleObject obj, uint32_t index, const Value
return true;
} while (false);
RootValue valueRoot(cx, value);
RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
if (!JSObject::makeDenseArraySlow(cx, obj))
return false;
@ -1064,7 +1063,7 @@ static JSBool
array_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
return array_defineGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)),
return array_defineGeneric(cx, obj, RootedId(cx, SPECIALID_TO_JSID(sid)),
value, getter, setter, attrs);
}
@ -1156,7 +1155,7 @@ array_deleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval
obj->setDenseArrayElement(index, MagicValue(JS_ARRAY_HOLE));
}
if (!js_SuppressDeletedElement(cx, RootedVarObject(cx, obj), index))
if (!js_SuppressDeletedElement(cx, RootedObject(cx, obj), index))
return false;
rval->setBoolean(true);
@ -1295,7 +1294,7 @@ AddLengthProperty(JSContext *cx, JSObject *obj)
* as accesses to 'length' will use the elements header.
*/
RootedVarId lengthId(cx, NameToId(cx->runtime->atomState.lengthAtom));
RootedId lengthId(cx, NameToId(cx->runtime->atomState.lengthAtom));
JS_ASSERT(!obj->nativeLookup(cx, lengthId));
if (!obj->allocateSlowArrayElements(cx))
@ -1437,7 +1436,7 @@ array_toSource(JSContext *cx, unsigned argc, Value *vp)
JS_CHECK_RECURSION(cx, return false);
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
if (!obj->isArray())
@ -1631,7 +1630,7 @@ array_toString_sub(JSContext *cx, HandleObject obj, JSBool locale,
JSObject *robj = ToObject(cx, &elt);
if (!robj)
return false;
RootedVarId id(cx, NameToId(cx->runtime->atomState.toLocaleStringAtom));
RootedId id(cx, NameToId(cx->runtime->atomState.toLocaleStringAtom));
if (!robj->callMethod(cx, id, 0, NULL, &elt))
return false;
}
@ -1661,7 +1660,7 @@ array_toString(JSContext *cx, unsigned argc, Value *vp)
JS_CHECK_RECURSION(cx, return false);
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -1697,7 +1696,7 @@ array_toLocaleString(JSContext *cx, unsigned argc, Value *vp)
JS_CHECK_RECURSION(cx, return false);
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -1705,7 +1704,7 @@ array_toLocaleString(JSContext *cx, unsigned argc, Value *vp)
* Passing comma here as the separator. Need a way to get a
* locale-specific version.
*/
return array_toString_sub(cx, obj, JS_TRUE, RootedVarString(cx), args);
return array_toString_sub(cx, obj, JS_TRUE, RootedString(cx), args);
}
static inline bool
@ -1788,8 +1787,8 @@ InitArrayElements(JSContext *cx, HandleObject obj, uint32_t start, uint32_t coun
return false;
JS_ASSERT(start == MAX_ARRAY_INDEX + 1);
RootedVarValue value(cx);
RootedVarId id(cx);
RootedValue value(cx);
RootedId id(cx);
Value idval = DoubleValue(MAX_ARRAY_INDEX + 1);
do {
value = *vector++;
@ -1844,7 +1843,7 @@ array_join(JSContext *cx, unsigned argc, Value *vp)
JS_CHECK_RECURSION(cx, return false);
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarString str(cx);
RootedString str(cx);
if (args.hasDefined(0)) {
str = ToString(cx, args[0]);
if (!str)
@ -1853,7 +1852,7 @@ array_join(JSContext *cx, unsigned argc, Value *vp)
} else {
str = NULL;
}
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
return array_toString_sub(cx, obj, JS_FALSE, str, args);
@ -1863,7 +1862,7 @@ static JSBool
array_reverse(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -2159,7 +2158,10 @@ JSBool
js::array_sort(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
Value fval;
RootedValue fvalRoot(cx);
Value &fval = fvalRoot.reference();
if (args.hasDefined(0)) {
if (args[0].isPrimitive()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_SORT_ARG);
@ -2170,9 +2172,7 @@ js::array_sort(JSContext *cx, unsigned argc, Value *vp)
fval.setNull();
}
RootValue fvalRoot(cx, &fval);
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -2383,7 +2383,7 @@ NewbornArrayPushImpl(JSContext *cx, HandleObject obj, const Value &v)
uint32_t length = obj->getArrayLength();
if (obj->isSlowArray()) {
/* This can happen in one evil case. See bug 630377. */
RootedVarId id(cx);
RootedId id(cx);
return IndexToId(cx, length, id.address()) &&
baseops::DefineProperty(cx, obj, id, &v, NULL, NULL, JSPROP_ENUMERATE);
}
@ -2410,7 +2410,7 @@ JSBool
js::array_push(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -2436,7 +2436,7 @@ array_pop_slowly(JSContext *cx, HandleObject obj, CallArgs &args)
index--;
JSBool hole;
RootedVarValue elt(cx);
RootedValue elt(cx);
if (!GetElement(cx, obj, index, &hole, elt.address()))
return false;
@ -2459,7 +2459,7 @@ array_pop_dense(JSContext *cx, HandleObject obj, CallArgs &args)
index--;
JSBool hole;
RootedVarValue elt(cx);
RootedValue elt(cx);
if (!GetElement(cx, obj, index, &hole, elt.address()))
return JS_FALSE;
@ -2478,7 +2478,7 @@ JSBool
js::array_pop(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
if (obj->isDenseArray())
@ -2507,7 +2507,7 @@ JSBool
js::array_shift(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return JS_FALSE;
@ -2539,7 +2539,7 @@ js::array_shift(JSContext *cx, unsigned argc, Value *vp)
return JS_FALSE;
/* Slide down the array above the first element. */
RootedVarValue value(cx);
RootedValue value(cx);
for (uint32_t i = 0; i < length; i++) {
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
!GetElement(cx, obj, i + 1, &hole, value.address()) ||
@ -2559,7 +2559,7 @@ static JSBool
array_unshift(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -2593,7 +2593,7 @@ array_unshift(JSContext *cx, unsigned argc, Value *vp)
if (!optimized) {
double last = length;
double upperIndex = last + args.length();
RootedVarValue value(cx);
RootedValue value(cx);
do {
--last, --upperIndex;
JSBool hole;
@ -2681,7 +2681,7 @@ array_splice(JSContext *cx, unsigned argc, Value *vp)
CallArgs args = CallArgsFromVp(argc, vp);
/* Step 1. */
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -2720,7 +2720,7 @@ array_splice(JSContext *cx, unsigned argc, Value *vp)
JS_ASSERT(len - actualStart >= actualDeleteCount);
/* Steps 2, 8-9. */
RootedVarObject arr(cx);
RootedObject arr(cx);
if (CanOptimizeForDenseStorage(obj, actualStart, actualDeleteCount, cx)) {
arr = NewDenseCopiedArray(cx, actualDeleteCount,
obj->getDenseArrayElements() + actualStart);
@ -2904,11 +2904,11 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp)
Value *p = JS_ARGV(cx, vp) - 1;
/* Create a new Array object and root it using *vp. */
RootedVarObject aobj(cx, ToObject(cx, &vp[1]));
RootedObject aobj(cx, ToObject(cx, &vp[1]));
if (!aobj)
return false;
RootedVarObject nobj(cx);
RootedObject nobj(cx);
uint32_t length;
if (aobj->isDenseArray()) {
length = aobj->getArrayLength();
@ -2938,7 +2938,7 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp)
return false;
const Value &v = p[i];
if (v.isObject()) {
RootedVarObject obj(cx, &v.toObject());
RootedObject obj(cx, &v.toObject());
if (ObjectClassIs(*obj, ESClass_Array, cx)) {
uint32_t alength;
if (!js_GetLengthProperty(cx, obj, &alength))
@ -2977,7 +2977,7 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -3016,7 +3016,7 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
if (begin > end)
begin = end;
RootedVarObject nobj(cx);
RootedObject nobj(cx);
if (obj->isDenseArray() && end <= obj->getDenseArrayInitializedLength() &&
!js_PrototypeHasIndexedProperties(cx, obj)) {
@ -3033,7 +3033,7 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
return JS_FALSE;
TryReuseArrayType(obj, nobj);
RootedVarValue value(cx);
RootedValue value(cx);
for (slot = begin; slot < end; slot++) {
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
!GetElement(cx, obj, slot, &hole, value.address())) {
@ -3183,7 +3183,7 @@ static inline bool
array_readonlyCommon(JSContext *cx, CallArgs &args)
{
/* Step 1. */
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -3197,7 +3197,7 @@ array_readonlyCommon(JSContext *cx, CallArgs &args)
js_ReportMissingArg(cx, args.calleev(), 0);
return false;
}
RootedVarObject callable(cx, js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK));
RootedObject callable(cx, js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK));
if (!callable)
return false;
@ -3275,7 +3275,7 @@ array_map(JSContext *cx, unsigned argc, Value *vp)
CallArgs args = CallArgsFromVp(argc, vp);
/* Step 1. */
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -3289,7 +3289,7 @@ array_map(JSContext *cx, unsigned argc, Value *vp)
js_ReportMissingArg(cx, args.calleev(), 0);
return false;
}
RootedVarObject callable(cx, js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK));
RootedObject callable(cx, js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK));
if (!callable)
return false;
@ -3297,7 +3297,7 @@ array_map(JSContext *cx, unsigned argc, Value *vp)
Value thisv = args.length() >= 2 ? args[1] : UndefinedValue();
/* Step 6. */
RootedVarObject arr(cx, NewDenseAllocatedArray(cx, len));
RootedObject arr(cx, NewDenseAllocatedArray(cx, len));
if (!arr)
return false;
TypeObject *newtype = GetTypeCallerInitObject(cx, JSProto_Array);
@ -3351,7 +3351,7 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
CallArgs args = CallArgsFromVp(argc, vp);
/* Step 1. */
RootedVarObject obj(cx, ToObject(cx, &args.thisv()));
RootedObject obj(cx, ToObject(cx, &args.thisv()));
if (!obj)
return false;
@ -3365,7 +3365,7 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
js_ReportMissingArg(cx, args.calleev(), 0);
return false;
}
RootedVarObject callable(cx, js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK));
RootedObject callable(cx, js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK));
if (!callable)
return false;
@ -3373,7 +3373,7 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
Value thisv = args.length() >= 2 ? args[1] : UndefinedValue();
/* Step 6. */
RootedVarObject arr(cx, NewDenseAllocatedArray(cx, 0));
RootedObject arr(cx, NewDenseAllocatedArray(cx, 0));
if (!arr)
return false;
TypeObject *newtype = GetTypeCallerInitObject(cx, JSProto_Array);
@ -3612,7 +3612,7 @@ JSBool
js_Array(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedVarTypeObject type(cx, GetTypeCallerInitObject(cx, JSProto_Array));
RootedTypeObject type(cx, GetTypeCallerInitObject(cx, JSProto_Array));
if (!type)
return JS_FALSE;
@ -3665,16 +3665,16 @@ js_InitArrayClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
RootedVar<GlobalObject*> global(cx);
Rooted<GlobalObject*> global(cx);
global = &obj->asGlobal();
RootedVarObject arrayProto(cx);
RootedObject arrayProto(cx);
arrayProto = global->createBlankPrototype(cx, &SlowArrayClass);
if (!arrayProto || !AddLengthProperty(cx, arrayProto))
return NULL;
arrayProto->setArrayLength(cx, 0);
RootedVarFunction ctor(cx);
RootedFunction ctor(cx);
ctor = global->createConstructor(cx, js_Array, CLASS_NAME(cx, Array), 1);
if (!ctor)
return NULL;
@ -3727,7 +3727,7 @@ EnsureNewArrayElements(JSContext *cx, JSObject *obj, uint32_t length)
template<bool allocateCapacity>
static JS_ALWAYS_INLINE JSObject *
NewArray(JSContext *cx, uint32_t length, JSObject *proto)
NewArray(JSContext *cx, uint32_t length, JSObject *proto_)
{
gc::AllocKind kind = GuessArrayGCKind(length);
@ -3736,12 +3736,12 @@ NewArray(JSContext *cx, uint32_t length, JSObject *proto)
kind = GetBackgroundAllocKind(kind);
#endif
GlobalObject *parent = GetCurrentGlobal(cx);
GlobalObject *parent_ = GetCurrentGlobal(cx);
NewObjectCache &cache = cx->runtime->newObjectCache;
NewObjectCache::EntryIndex entry = -1;
if (cache.lookupGlobal(&ArrayClass, parent, kind, &entry)) {
if (cache.lookupGlobal(&ArrayClass, parent_, kind, &entry)) {
JSObject *obj = cache.newObjectFromHit(cx, entry);
if (!obj)
return NULL;
@ -3753,13 +3753,13 @@ NewArray(JSContext *cx, uint32_t length, JSObject *proto)
return obj;
}
JS::Root<GlobalObject*> parentRoot(cx, &parent);
Rooted<GlobalObject*> parent(cx, parent_);
if (!proto && !FindProto(cx, &ArrayClass, parentRoot, &proto))
if (!proto_ && !FindProto(cx, &ArrayClass, parent, &proto_))
return NULL;
RootObject protoRoot(cx, &proto);
RootedVarTypeObject type(cx);
RootedObject proto(cx, proto_);
RootedTypeObject type(cx);
type = proto->getNewType(cx);
if (!type)
@ -3769,7 +3769,7 @@ NewArray(JSContext *cx, uint32_t length, JSObject *proto)
* Get a shape with zero fixed slots, regardless of the size class.
* See JSObject::createDenseArray.
*/
RootedVarShape shape(cx);
RootedShape shape(cx);
shape = EmptyShape::getInitialShape(cx, &ArrayClass, proto,
parent, gc::FINALIZE_OBJECT0);
if (!shape)
@ -3849,7 +3849,7 @@ NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *vp, JSObject *p
JSObject *
NewSlowEmptyArray(JSContext *cx)
{
RootedVarObject obj(cx, NewBuiltinClassInstance(cx, &SlowArrayClass));
RootedObject obj(cx, NewBuiltinClassInstance(cx, &SlowArrayClass));
if (!obj || !AddLengthProperty(cx, obj))
return NULL;

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