зеркало из https://github.com/mozilla/gecko-dev.git
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
4a43704eee
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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__
|
|
@ -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
|
|
@ -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();
|
||||
|
|
|
@ -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
|
|
@ -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__
|
|
@ -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
|
||||
|
|
@ -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__
|
|
@ -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
|
||||
|
|
@ -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__
|
|
@ -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
|
||||
|
|
|
@ -54,12 +54,6 @@ nsPlatformCharset::InitGetCharset(nsACString &oString)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlatformCharset::ConvertLocaleToCharsetUsingDeprecatedConfig(nsACString& locale, nsACString& oResult)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlatformCharset::VerifyCharset(nsCString &aCharset)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ private:
|
|||
|
||||
nsresult MapToCharset(nsAString& inANSICodePage, nsACString& outCharset);
|
||||
nsresult InitGetCharset(nsACString& oString);
|
||||
nsresult ConvertLocaleToCharsetUsingDeprecatedConfig(nsACString& locale, nsACString& oResult);
|
||||
nsresult VerifyCharset(nsCString &aCharset);
|
||||
};
|
||||
|
||||
|
|
|
@ -114,12 +114,6 @@ nsPlatformCharset::InitGetCharset(nsACString &oString)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlatformCharset::ConvertLocaleToCharsetUsingDeprecatedConfig(nsACString& locale, nsACString& oResult)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlatformCharset::VerifyCharset(nsCString &aCharset)
|
||||
{
|
||||
|
|
|
@ -36,12 +36,6 @@ nsPlatformCharset::GetDefaultCharsetForLocale(const nsAString& localeName, nsACS
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlatformCharset::ConvertLocaleToCharsetUsingDeprecatedConfig(nsACString& locale, nsACString& oResult)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlatformCharset::InitGetCharset(nsACString &oString)
|
||||
{
|
||||
|
|
|
@ -43,35 +43,22 @@ nsPlatformCharset::nsPlatformCharset()
|
|||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlatformCharset::ConvertLocaleToCharsetUsingDeprecatedConfig(nsACString& locale, nsACString& oResult)
|
||||
static nsresult
|
||||
ConvertLocaleToCharsetUsingDeprecatedConfig(const nsACString& locale,
|
||||
nsACString& oResult)
|
||||
{
|
||||
if (!(locale.IsEmpty())) {
|
||||
nsCAutoString platformLocaleKey;
|
||||
// note: NS_LITERAL_STRING("locale." OSTYPE ".") does not compile on AIX
|
||||
platformLocaleKey.AssignLiteral("locale.");
|
||||
platformLocaleKey.Append(OSTYPE);
|
||||
platformLocaleKey.AppendLiteral(".");
|
||||
platformLocaleKey.Append(locale);
|
||||
|
||||
nsresult res = nsUConvPropertySearch::SearchPropertyValue(kUnixCharsets,
|
||||
ArrayLength(kUnixCharsets), platformLocaleKey, oResult);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCAutoString localeKey;
|
||||
localeKey.AssignLiteral("locale.all.");
|
||||
localeKey.Append(locale);
|
||||
res = nsUConvPropertySearch::SearchPropertyValue(kUnixCharsets,
|
||||
ArrayLength(kUnixCharsets), localeKey, oResult);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
if (NS_SUCCEEDED(nsUConvPropertySearch::SearchPropertyValue(kUnixCharsets,
|
||||
ArrayLength(kUnixCharsets), localeKey, oResult))) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
NS_ERROR("unable to convert locale to charset using deprecated config");
|
||||
mCharset.AssignLiteral("ISO-8859-1");
|
||||
oResult.AssignLiteral("ISO-8859-1");
|
||||
return NS_SUCCESS_USING_FALLBACK_LOCALE;
|
||||
}
|
||||
NS_ERROR("unable to convert locale to charset using deprecated config");
|
||||
oResult.AssignLiteral("ISO-8859-1");
|
||||
return NS_SUCCESS_USING_FALLBACK_LOCALE;
|
||||
}
|
||||
|
||||
nsPlatformCharset::~nsPlatformCharset()
|
||||
|
@ -129,13 +116,7 @@ nsPlatformCharset::GetDefaultCharsetForLocale(const nsAString& localeName, nsACS
|
|||
// using the deprecated locale to charset mapping
|
||||
//
|
||||
NS_LossyConvertUTF16toASCII localeStr(localeName);
|
||||
nsresult res = ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oResult);
|
||||
if (NS_SUCCEEDED(res))
|
||||
return res;
|
||||
|
||||
NS_ERROR("unable to convert locale to charset using deprecated config");
|
||||
oResult.AssignLiteral("ISO-8859-1");
|
||||
return NS_SUCCESS_USING_FALLBACK_LOCALE;
|
||||
return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oResult);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -171,19 +152,12 @@ nsPlatformCharset::InitGetCharset(nsACString &oString)
|
|||
char* locale = setlocale(LC_CTYPE, nsnull);
|
||||
nsCAutoString localeStr;
|
||||
localeStr.Assign(locale);
|
||||
res = ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oString);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
return res; // succeeded
|
||||
}
|
||||
|
||||
oString.Truncate();
|
||||
return res;
|
||||
return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oString);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPlatformCharset::Init()
|
||||
{
|
||||
nsCAutoString charset;
|
||||
nsresult res = NS_OK;
|
||||
|
||||
//
|
||||
|
@ -198,21 +172,18 @@ nsPlatformCharset::Init()
|
|||
mLocale.AssignLiteral("en_US");
|
||||
}
|
||||
|
||||
res = InitGetCharset(charset);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
mCharset = charset;
|
||||
return res; // succeeded
|
||||
}
|
||||
|
||||
// last resort fallback
|
||||
NS_ERROR("unable to convert locale to charset using deprecated config");
|
||||
mCharset.AssignLiteral("ISO-8859-1");
|
||||
return NS_SUCCESS_USING_FALLBACK_LOCALE;
|
||||
// InitGetCharset only returns NS_OK or NS_SUCESS_USING_FALLBACK_LOCALE
|
||||
return InitGetCharset(mCharset);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlatformCharset::VerifyCharset(nsCString &aCharset)
|
||||
{
|
||||
// fast path for UTF-8. Most platform uses UTF-8 as charset now.
|
||||
if (aCharset.EqualsLiteral("UTF-8")) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult res;
|
||||
//
|
||||
// get the convert manager
|
||||
|
@ -257,6 +228,5 @@ nsPlatformCharset::VerifyCharset(nsCString &aCharset)
|
|||
//
|
||||
|
||||
aCharset.Assign(result);
|
||||
NS_ASSERTION(NS_SUCCEEDED(res), "failed to get preferred charset name, using non-preferred");
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -7,41 +7,6 @@
|
|||
## except for those *nix systems that do not support
|
||||
## nl_langinfo(CODESET) this file should not be used
|
||||
##
|
||||
##
|
||||
## Platform specific section.
|
||||
## Map a given locale name in a particular platform (OS) to a charset name
|
||||
## This have highgher priority than the all section
|
||||
## Use this section to overwrite those locale name which *CONFLICT WITH*
|
||||
## most other platform
|
||||
## Do not use this section if the locale is unique in the platform. Only use
|
||||
## this when it have CONFLICT w/ other platform.
|
||||
##
|
||||
## Example, most platform use EUC-JP in "japanese" locale, but
|
||||
## hpux, unixware, and sco use Shift_JIS, so we put
|
||||
## locale.all.japanese=EUC-JP
|
||||
## in the all platform section and put
|
||||
## locale.HP-UXB.10.japanese=Shift_JIS
|
||||
## locale.SCOOS5.0.japanese=Shift_JIS
|
||||
## in the platform specific section
|
||||
##
|
||||
## The key is "locale." + OSTYPE + "." + locale name
|
||||
## Read mozilla/config/config.mk to find out the correct OSTYPE
|
||||
## for your system.
|
||||
##
|
||||
## References:
|
||||
## Solaris - http://www.sun.com/software/white-papers/wp-unicode/
|
||||
## - http://www.sun.com/software/white-papers/wp-eurocurrency/
|
||||
## - http://www.sun.com/software/white-papers/wp-cttlanguage/
|
||||
## AIX - http://www.software.ibm.com/ts/mqseries/library/manuals/amqaac/AMQAAC2Q.HTM
|
||||
## <have not check the following>
|
||||
## http://www.rs6000.ibm.com/doc_link/en_US/a_doc_lib/aixbman/baseadmn/locale.htm
|
||||
## HP - http://www.hp.com/unixwork/euro/release_notes/index.html
|
||||
## <have not check the following>
|
||||
## IRIX -
|
||||
##
|
||||
locale.HP-UXB.10.japanese=Shift_JIS
|
||||
locale.SCOOS5.0.japanese=Shift_JIS
|
||||
##
|
||||
## All platform section
|
||||
## Put the general locale to charset mapping here.
|
||||
## If somehow two platform use the same locale name with different
|
||||
|
@ -585,5 +550,3 @@ locale.all.Zh_TW.big5=Big5
|
|||
locale.all.zh_TW.Big5=Big5
|
||||
# SunOS 5.7 according to pofeng@linux.org.tw (already above)
|
||||
# locale.all.zh_TW.BIG5=Big5
|
||||
# OpenVMS
|
||||
locale.all.ja_JP.sdeckanji=EUC-JP
|
||||
|
|
|
@ -96,12 +96,6 @@ nsPlatformCharset::InitGetCharset(nsACString &oString)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlatformCharset::ConvertLocaleToCharsetUsingDeprecatedConfig(nsACString& locale, nsACString& oResult)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlatformCharset::VerifyCharset(nsCString &aCharset)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче