mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Merge m-c to m-i.
This commit is contained in:
commit
65aa2a4593
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
}
|
||||
]
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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 ()
|
||||
{
|
||||
|
@ -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;"/>
|
||||
|
@ -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 \
|
||||
|
@ -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";
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
34
build/virtualenv/Makefile.in
Normal file
34
build/virtualenv/Makefile.in
Normal 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
|
@ -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);
|
||||
|
@ -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@
|
||||
|
@ -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
|
||||
|
||||
|
@ -594,6 +594,7 @@ proto/exec.h
|
||||
psap.h
|
||||
Pt.h
|
||||
pthread.h
|
||||
pthread_np.h
|
||||
pwd.h
|
||||
Python.h
|
||||
QDOffscreen.h
|
||||
|
50
configure.in
50
configure.in
@ -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} \
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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"));
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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 =
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {};
|
@ -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
|
||||
|
@ -299,7 +299,7 @@ nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer()
|
||||
#endif
|
||||
|
||||
if (mPStreamListener) {
|
||||
mPStreamListener->SetStreamListenerPeer(this);
|
||||
mPStreamListener->SetStreamListenerPeer(nsnull);
|
||||
}
|
||||
|
||||
// close FD of mFileCacheOutputStream if it's still open
|
||||
|
490
dom/system/gonk/AutoMounter.cpp
Normal file
490
dom/system/gonk/AutoMounter.cpp
Normal 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
|
47
dom/system/gonk/AutoMounter.h
Normal file
47
dom/system/gonk/AutoMounter.h
Normal 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__
|
150
dom/system/gonk/AutoMounterSetting.cpp
Normal file
150
dom/system/gonk/AutoMounterSetting.cpp
Normal 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
|
29
dom/system/gonk/AutoMounterSetting.h
Normal file
29
dom/system/gonk/AutoMounterSetting.h
Normal 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__
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
71
dom/system/gonk/Volume.cpp
Normal file
71
dom/system/gonk/Volume.cpp
Normal 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
95
dom/system/gonk/Volume.h
Normal 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__
|
85
dom/system/gonk/VolumeCommand.cpp
Normal file
85
dom/system/gonk/VolumeCommand.cpp
Normal 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
|
||||
|
185
dom/system/gonk/VolumeCommand.h
Normal file
185
dom/system/gonk/VolumeCommand.h
Normal 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__
|
448
dom/system/gonk/VolumeManager.cpp
Normal file
448
dom/system/gonk/VolumeManager.cpp
Normal 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
|
||||
|
183
dom/system/gonk/VolumeManager.h
Normal file
183
dom/system/gonk/VolumeManager.h
Normal 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__
|
20
dom/system/gonk/VolumeManagerLog.h
Normal file
20
dom/system/gonk/VolumeManagerLog.h
Normal 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__
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
},
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ protected:
|
||||
nsresult DragGesture(nsIDOMDragEvent* aDragEvent);
|
||||
void CleanupDragDropCaret();
|
||||
already_AddRefed<nsIPresShell> GetPresShell();
|
||||
bool IsFileControlTextBox();
|
||||
|
||||
protected:
|
||||
nsEditor* mEditor; // weak
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -35,6 +35,8 @@ public:
|
||||
|
||||
virtual bool SetupCairoFont(gfxContext *aContext);
|
||||
|
||||
virtual bool AllowSubpixelAA() { return mAllowManualShowGlyphs; }
|
||||
|
||||
virtual bool IsValid();
|
||||
|
||||
gfxFloat GetAdjustedSize() {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ class SwitchEvent;
|
||||
enum SwitchDevice {
|
||||
SWITCH_DEVICE_UNKNOWN = -1,
|
||||
SWITCH_HEADPHONES,
|
||||
SWITCH_USB,
|
||||
NUM_SWITCH_DEVICE
|
||||
};
|
||||
|
||||
|
@ -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) { }
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 = \
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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__
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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())) {
|
||||
|
@ -594,6 +594,7 @@ proto/exec.h
|
||||
psap.h
|
||||
Pt.h
|
||||
pthread.h
|
||||
pthread_np.h
|
||||
pwd.h
|
||||
Python.h
|
||||
QDOffscreen.h
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -67,7 +67,7 @@ struct GlobalScope {
|
||||
: globalObj(cx, globalObj)
|
||||
{ }
|
||||
|
||||
RootedVarObject globalObj;
|
||||
RootedObject globalObj;
|
||||
};
|
||||
|
||||
struct BytecodeEmitter
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
187
js/src/gc/Root.h
187
js/src/gc/Root.h
@ -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.
|
||||
|
203
js/src/jsapi.cpp
203
js/src/jsapi.cpp
@ -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 *)
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user