Merge last PGO-green changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Ed Morley 2012-06-29 08:41:44 +01:00
Родитель 2ed11f64db c4d15f545f
Коммит 68c7b298d0
76 изменённых файлов: 842 добавлений и 745 удалений

Просмотреть файл

@ -7,6 +7,7 @@
var browser;
var dialog = {};
var pref = null;
let openLocationModule = {};
try {
pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
@ -14,7 +15,8 @@ try {
// not critical, remain silent
}
Components.utils.import("resource:///modules/openLocationLastURL.jsm");
Components.utils.import("resource:///modules/openLocationLastURL.jsm", openLocationModule);
let gOpenLocationLastURL = new openLocationModule.OpenLocationLastURL(window.opener);
function onLoad()
{

Просмотреть файл

@ -476,10 +476,13 @@ BrowserGlue.prototype = {
var windowcount = 0;
var pagecount = 0;
var browserEnum = Services.wm.getEnumerator("navigator:browser");
let allWindowsPrivate = true;
while (browserEnum.hasMoreElements()) {
windowcount++;
var browser = browserEnum.getNext();
if (("gPrivateBrowsingUI" in browser) && !browser.gPrivateBrowsingUI.privateWindow)
allWindowsPrivate = false;
var tabbrowser = browser.document.getElementById("content");
if (tabbrowser)
pagecount += tabbrowser.browsers.length - tabbrowser._numPinnedTabs;
@ -523,10 +526,8 @@ BrowserGlue.prototype = {
return;
}
var inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService).
privateBrowsingEnabled;
if (inPrivateBrowsing)
// Never show a prompt inside private browsing mode
if (allWindowsPrivate)
return;
if (!showPrompt)
@ -1573,6 +1574,8 @@ ContentPermissionPrompt.prototype = {
var message;
var secondaryActions = [];
var requestingWindow = request.window.top;
var chromeWin = getChromeWindow(requestingWindow).wrappedJSObject;
// Different message/options if it is a local file
if (requestingURI.schemeIs("file")) {
@ -1583,11 +1586,7 @@ ContentPermissionPrompt.prototype = {
[requestingURI.host], 1);
// Don't offer to "always/never share" in PB mode
var inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService).
privateBrowsingEnabled;
if (!inPrivateBrowsing) {
if (("gPrivateBrowsingUI" in chromeWin) && !chromeWin.gPrivateBrowsingUI.privateWindow) {
secondaryActions.push({
label: browserBundle.GetStringFromName("geolocation.alwaysShareLocation"),
accessKey: browserBundle.GetStringFromName("geolocation.alwaysShareLocation.accesskey"),
@ -1607,8 +1606,6 @@ ContentPermissionPrompt.prototype = {
}
}
var requestingWindow = request.window.top;
var chromeWin = getChromeWindow(requestingWindow).wrappedJSObject;
var browser = chromeWin.gBrowser.getBrowserForDocument(requestingWindow.document);
chromeWin.PopupNotifications.show(browser, "geolocation", message, "geo-notification-icon",

Просмотреть файл

@ -66,11 +66,11 @@ var SidebarUtils = {
handleTreeKeyPress: function SU_handleTreeKeyPress(aEvent) {
// XXX Bug 627901: Post Fx4, this method should take a tree parameter.
let node = aEvent.target.selectedNode;
let tree = aEvent.target;
let node = tree.selectedNode;
if (node) {
let view = PlacesUIUtils.getViewForNode(node);
if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
PlacesUIUtils.openNodeWithEvent(node, aEvent, view);
PlacesUIUtils.openNodeWithEvent(node, aEvent, tree);
}
},

Просмотреть файл

@ -2,6 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
const PTV_interfaces = [Ci.nsITreeView,
Ci.nsINavHistoryResultObserver,
Ci.nsINavHistoryResultTreeViewer,
Ci.nsISupportsWeakReference];
function PlacesTreeView(aFlatList, aOnOpenFlatContainer, aController) {
this._tree = null;
this._result = null;
@ -39,15 +46,17 @@ PlacesTreeView.prototype = {
return this.__dateService;
},
QueryInterface: function PTV_QueryInterface(aIID) {
if (aIID.equals(Ci.nsITreeView) ||
aIID.equals(Ci.nsINavHistoryResultObserver) ||
aIID.equals(Ci.nsINavHistoryResultTreeViewer) ||
aIID.equals(Ci.nsISupportsWeakReference) ||
aIID.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
QueryInterface: XPCOMUtils.generateQI(PTV_interfaces),
// Bug 761494:
// ----------
// Some addons use methods from nsINavHistoryResultObserver and
// nsINavHistoryResultTreeViewer, without QIing to these intefaces first.
// That's not a problem when the view is retrieved through the
// <tree>.view getter (which returns the wrappedJSObject of this object),
// it raises an issue when the view retrieved through the treeBoxObject.view
// getter. Thus, to avoid breaking addons, the interfaces are prefetched.
classInfo: XPCOMUtils.generateCI({ interfaces: PTV_interfaces }),
/**
* This is called once both the result and the tree are set.

Просмотреть файл

@ -6,15 +6,19 @@
function run_test_on_service()
{
Cu.import("resource:///modules/openLocationLastURL.jsm");
let openLocationModule = {};
// This variable fakes the window required for getting the PB flag
let window = { gPrivateBrowsingUI: { privateWindow: false } };
Cu.import("resource:///modules/openLocationLastURL.jsm", openLocationModule);
let gOpenLocationLastURL = new openLocationModule.OpenLocationLastURL(window);
function clearHistory() {
// simulate clearing the private data
Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService).
notifyObservers(null, "browser:purge-session-history", "");
}
let pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
getService(Ci.nsIPrivateBrowsingService);
let pref = Cc["@mozilla.org/preferences-service;1"].
@ -24,6 +28,11 @@ function run_test_on_service()
do_check_eq(typeof gOpenLocationLastURL, "object");
do_check_eq(gOpenLocationLastURL.value, "");
function switchPrivateBrowsing(flag) {
pb.privateBrowsingEnabled = flag;
window.gPrivateBrowsingUI.privateWindow = flag;
}
const url1 = "mozilla.org";
const url2 = "mozilla.com";
@ -40,26 +49,26 @@ function run_test_on_service()
do_check_eq(gOpenLocationLastURL.value, "");
gOpenLocationLastURL.value = url2;
pb.privateBrowsingEnabled = true;
switchPrivateBrowsing(true);
do_check_eq(gOpenLocationLastURL.value, "");
pb.privateBrowsingEnabled = false;
switchPrivateBrowsing(false);
do_check_eq(gOpenLocationLastURL.value, url2);
pb.privateBrowsingEnabled = true;
switchPrivateBrowsing(true);
gOpenLocationLastURL.value = url1;
do_check_eq(gOpenLocationLastURL.value, url1);
pb.privateBrowsingEnabled = false;
switchPrivateBrowsing(false);
do_check_eq(gOpenLocationLastURL.value, url2);
pb.privateBrowsingEnabled = true;
switchPrivateBrowsing(true);
gOpenLocationLastURL.value = url1;
do_check_neq(gOpenLocationLastURL.value, "");
clearHistory();
do_check_eq(gOpenLocationLastURL.value, "");
pb.privateBrowsingEnabled = false;
switchPrivateBrowsing(false);
do_check_eq(gOpenLocationLastURL.value, "");
}

Просмотреть файл

@ -4,13 +4,13 @@
const LAST_URL_PREF = "general.open_location.last_url";
const nsISupportsString = Components.interfaces.nsISupportsString;
const Ci = Components.interfaces;
var EXPORTED_SYMBOLS = [ "gOpenLocationLastURL" ];
var EXPORTED_SYMBOLS = [ "OpenLocationLastURL" ];
let pbSvc = Components.classes["@mozilla.org/privatebrowsing;1"]
.getService(Components.interfaces.nsIPrivateBrowsingService);
let prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
let gOpenLocationLastURLData = "";
let observer = {
QueryInterface: function (aIID) {
@ -22,11 +22,12 @@ let observer = {
},
observe: function (aSubject, aTopic, aData) {
switch (aTopic) {
case "private-browsing":
case "last-pb-context-exited":
gOpenLocationLastURLData = "";
break;
case "browser:purge-session-history":
gOpenLocationLastURL.reset();
prefSvc.clearUserPref(LAST_URL_PREF);
gOpenLocationLastURLData = "";
break;
}
}
@ -34,13 +35,25 @@ let observer = {
let os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.addObserver(observer, "private-browsing", true);
os.addObserver(observer, "last-pb-context-exited", true);
os.addObserver(observer, "browser:purge-session-history", true);
let gOpenLocationLastURLData = "";
let gOpenLocationLastURL = {
function OpenLocationLastURL(aWindow) {
this.window = aWindow;
}
OpenLocationLastURL.prototype = {
isPrivate: function OpenLocationLastURL_isPrivate() {
// Assume not in private browsing mode, unless the browser window is
// in private mode.
if (!this.window || !("gPrivateBrowsingUI" in this.window))
return false;
return this.window.gPrivateBrowsingUI.privateWindow;
},
get value() {
if (pbSvc.privateBrowsingEnabled)
if (this.isPrivate())
return gOpenLocationLastURLData;
else {
try {
@ -54,7 +67,7 @@ let gOpenLocationLastURL = {
set value(val) {
if (typeof val != "string")
val = "";
if (pbSvc.privateBrowsingEnabled)
if (this.isPrivate())
gOpenLocationLastURLData = val;
else {
let str = Components.classes["@mozilla.org/supports-string;1"]

Просмотреть файл

@ -36,6 +36,7 @@ public class FennecNativeActions implements Actions {
private Solo mSolo;
private Instrumentation mInstr;
private Activity mGeckoApp;
private Assert mAsserter;
// Objects for reflexive access of fennec classes.
private ClassLoader mClassLoader;
@ -50,10 +51,11 @@ public class FennecNativeActions implements Actions {
private Method mSetDrawListener;
private static final String LOGTAG = "FennecNativeActions";
public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation) {
public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation, Assert asserter) {
mSolo = robocop;
mInstr = instrumentation;
mGeckoApp = activity;
mAsserter = asserter;
// Set up reflexive access of java classes and methods.
try {
mClassLoader = activity.getClassLoader();
@ -117,6 +119,7 @@ public class FennecNativeActions implements Actions {
private final String mGeckoEvent;
private final Object[] mRegistrationParams;
private boolean mEventReceived;
private static final int MAX_WAIT_MS = 90000;
GeckoEventExpecter(String geckoEvent, Object[] registrationParams) {
mGeckoEvent = geckoEvent;
@ -124,13 +127,21 @@ public class FennecNativeActions implements Actions {
}
public synchronized void blockForEvent() {
long startTime = SystemClock.uptimeMillis();
long endTime = 0;
while (! mEventReceived) {
try {
this.wait();
this.wait(MAX_WAIT_MS);
} catch (InterruptedException ie) {
FennecNativeDriver.log(LogLevel.ERROR, ie);
break;
}
endTime = SystemClock.uptimeMillis();
if (!mEventReceived && (endTime - startTime >= MAX_WAIT_MS)) {
mAsserter.ok(false, "GeckoEventExpecter",
"blockForEvent timeout: "+mGeckoEvent);
return;
}
}
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
"unblocked on expecter for " + mGeckoEvent);
@ -222,6 +233,7 @@ public class FennecNativeActions implements Actions {
class PaintExpecter implements RepeatedEventExpecter {
private Object mLayerClient;
private boolean mPaintDone;
private static final int MAX_WAIT_MS = 90000;
PaintExpecter() throws IllegalAccessException, InvocationTargetException {
mLayerClient = mGetLayerClient.invoke(mGeckoApp);
@ -236,13 +248,20 @@ public class FennecNativeActions implements Actions {
}
public synchronized void blockForEvent() {
long startTime = SystemClock.uptimeMillis();
long endTime = 0;
while (!mPaintDone) {
try {
this.wait();
this.wait(MAX_WAIT_MS);
} catch (InterruptedException ie) {
FennecNativeDriver.log(LogLevel.ERROR, ie);
break;
}
endTime = SystemClock.uptimeMillis();
if (!mPaintDone && (endTime - startTime >= MAX_WAIT_MS)) {
mAsserter.ok(false, "PaintExpecter", "blockForEvent timeout");
return;
}
}
try {
mSetDrawListener.invoke(mLayerClient, (Object)null);
@ -260,16 +279,23 @@ public class FennecNativeActions implements Actions {
throw new IllegalArgumentException("millis must be > 0");
}
// wait for at least one event
long startTime = SystemClock.uptimeMillis();
long endTime = 0;
while (!mPaintDone) {
try {
this.wait();
this.wait(MAX_WAIT_MS);
} catch (InterruptedException ie) {
FennecNativeDriver.log(LogLevel.ERROR, ie);
break;
}
endTime = SystemClock.uptimeMillis();
if (!mPaintDone && (endTime - startTime >= MAX_WAIT_MS)) {
mAsserter.ok(false, "PaintExpecter", "blockUtilClear timeout");
return;
}
}
// now wait for a period of millis where we don't get an event
long startTime = SystemClock.uptimeMillis();
startTime = SystemClock.uptimeMillis();
while (true) {
try {
this.wait(millis);
@ -277,7 +303,7 @@ public class FennecNativeActions implements Actions {
FennecNativeDriver.log(LogLevel.ERROR, ie);
break;
}
long endTime = SystemClock.uptimeMillis();
endTime = SystemClock.uptimeMillis();
if (endTime - startTime >= millis) {
// success
break;

Просмотреть файл

@ -9,7 +9,7 @@
interface nsIURI;
interface nsIChannel;
[scriptable, uuid(3708aa92-e2d9-4fd1-9e46-edfa3eb5ebf5)]
[scriptable, uuid(cdb27711-492b-4973-938b-de81ac124658)]
interface nsIScriptSecurityManager : nsIXPCSecurityManager
{
///////////////// Security Checks //////////////////
@ -260,29 +260,6 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipal(in JSContextPtr cx);
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipalAndFrame(in JSContextPtr cx,
out JSStackFramePtr fp);
/**
* If no scripted code is running "above" (or called from) fp, then
* instead of looking at cx->globalObject, we will return |principal|.
* This function only affects |cx|. If someone pushes another context onto
* the context stack, then it supersedes this call.
* NOTE: If |fp| is non-null popContextPrincipal must be called before fp
* has finished executing.
*
* @param cx The context to clamp.
* @param fp The frame pointer to clamp at. May be 'null'.
* @param principal The principal to clamp to.
*/
[noscript] void pushContextPrincipal(in JSContextPtr cx,
in JSStackFramePtr fp,
in nsIPrincipal principal);
/**
* Removes a clamp set by pushContextPrincipal from cx. This must be
* called in a stack-like fashion (e.g., given two contexts |a| and |b|,
* it is not legal to do: push(a) push(b) pop(a)).
*/
[noscript] void popContextPrincipal(in JSContextPtr cx);
};
%{C++

Просмотреть файл

@ -403,12 +403,11 @@ private:
// Returns null if a principal cannot be found; generally callers
// should error out at that point.
static nsIPrincipal*
doGetObjectPrincipal(JSObject *obj
static nsIPrincipal* doGetObjectPrincipal(JSObject *obj);
#ifdef DEBUG
, bool aAllowShortCircuit = true
static nsIPrincipal*
old_doGetObjectPrincipal(JSObject *obj, bool aAllowShortCircuit = true);
#endif
);
// Returns null if a principal cannot be found. Note that rv can be NS_OK
// when this happens -- this means that there was no JS running.
@ -554,17 +553,6 @@ private:
PrintPolicyDB();
#endif
struct ContextPrincipal {
ContextPrincipal(ContextPrincipal *next, JSContext *cx,
JSStackFrame *fp, nsIPrincipal *principal)
: mNext(next), mCx(cx), mFp(fp), mPrincipal(principal) {}
ContextPrincipal *mNext;
JSContext *mCx;
JSStackFrame *mFp;
nsCOMPtr<nsIPrincipal> mPrincipal;
};
// JS strings we need to clean up on shutdown
static jsid sEnabledID;
@ -577,7 +565,6 @@ private:
nsCOMPtr<nsIPrincipal> mSystemPrincipal;
nsCOMPtr<nsIPrincipal> mSystemCertificate;
ContextPrincipal *mContextPrincipals;
nsInterfaceHashtable<PrincipalKey, nsIPrincipal> mPrincipals;
bool mPrefInitialized;
bool mIsJavaScriptEnabled;

Просмотреть файл

@ -163,44 +163,6 @@ GetScriptContext(JSContext *cx)
return GetScriptContextFromJSContext(cx);
}
// Callbacks for the JS engine to use to push/pop context principals.
static JSBool
PushPrincipalCallback(JSContext *cx, JSPrincipals *principals)
{
// We should already be in the compartment of the given principal.
MOZ_ASSERT(principals ==
JS_GetCompartmentPrincipals((js::GetContextCompartment(cx))));
// Get the security manager.
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (!ssm) {
return true;
}
// Push the principal.
JSStackFrame *fp = NULL;
nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp),
nsJSPrincipals::get(principals));
if (NS_FAILED(rv)) {
JS_ReportOutOfMemory(cx);
return false;
}
return true;
}
static JSBool
PopPrincipalCallback(JSContext *cx)
{
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (ssm) {
ssm->PopContextPrincipal(cx);
}
return true;
}
inline void SetPendingException(JSContext *cx, const char *aMsg)
{
JSAutoRequest ar(cx);
@ -405,34 +367,6 @@ nsScriptSecurityManager::GetCxSubjectPrincipalAndFrame(JSContext *cx, JSStackFra
return principal;
}
NS_IMETHODIMP
nsScriptSecurityManager::PushContextPrincipal(JSContext *cx,
JSStackFrame *fp,
nsIPrincipal *principal)
{
NS_ASSERTION(principal, "Must pass a non-null principal");
ContextPrincipal *cp = new ContextPrincipal(mContextPrincipals, cx, fp,
principal);
if (!cp)
return NS_ERROR_OUT_OF_MEMORY;
mContextPrincipals = cp;
return NS_OK;
}
NS_IMETHODIMP
nsScriptSecurityManager::PopContextPrincipal(JSContext *cx)
{
NS_ASSERTION(mContextPrincipals->mCx == cx, "Mismatched push/pop");
ContextPrincipal *next = mContextPrincipals->mNext;
delete mContextPrincipals;
mContextPrincipals = next;
return NS_OK;
}
////////////////////
// Policy Storage //
////////////////////
@ -2304,24 +2238,10 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
if (cx)
{
JSStackFrame *target = nsnull;
nsIPrincipal *targetPrincipal = nsnull;
for (ContextPrincipal *cp = mContextPrincipals; cp; cp = cp->mNext)
{
if (cp->mCx == cx)
{
target = cp->mFp;
targetPrincipal = cp->mPrincipal;
break;
}
}
// Get principals from innermost JavaScript frame.
JSStackFrame *fp = nsnull; // tell JS_FrameIterator to start at innermost
for (fp = JS_FrameIterator(cx, &fp); fp; fp = JS_FrameIterator(cx, &fp))
{
if (fp == target)
break;
nsIPrincipal* result = GetFramePrincipal(cx, fp, rv);
if (result)
{
@ -2331,25 +2251,6 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
}
}
// If targetPrincipal is non-null, then it means that someone wants to
// clamp the principals on this context to this principal. Note that
// fp might not equal target here (fp might be null) because someone
// could have set aside the frame chain in the meantime.
if (targetPrincipal)
{
if (fp && fp == target)
{
*frameResult = fp;
}
else
{
JSStackFrame *inner = nsnull;
*frameResult = JS_FrameIterator(cx, &inner);
}
return targetPrincipal;
}
nsIScriptContextPrincipal* scp =
GetScriptContextPrincipalFromJSContext(cx);
if (scp)
@ -2380,9 +2281,15 @@ nsIPrincipal*
nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
nsresult* rv)
{
NS_PRECONDITION(rv, "Null out param");
JSStackFrame *fp;
return GetPrincipalAndFrame(cx, &fp, rv);
*rv = NS_OK;
JSCompartment *compartment = js::GetContextCompartment(cx);
// The context should always be in a compartment, either one it has entered
// or the one associated with its global.
MOZ_ASSERT(!!compartment);
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
return nsJSPrincipals::get(principals);
}
NS_IMETHODIMP
@ -2398,19 +2305,33 @@ nsScriptSecurityManager::GetObjectPrincipal(JSContext *aCx, JSObject *aObj,
// static
nsIPrincipal*
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
{
JSCompartment *compartment = js::GetObjectCompartment(aObj);
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
nsIPrincipal *principal = nsJSPrincipals::get(principals);
// We leave the old code in for a little while to make sure that pulling
// object principals directly off the compartment always gives an equivalent
// result (from a security perspective).
#ifdef DEBUG
, bool aAllowShortCircuit
nsIPrincipal *old = old_doGetObjectPrincipal(aObj);
MOZ_ASSERT(NS_SUCCEEDED(CheckSameOriginPrincipal(principal, old)));
#endif
)
return principal;
}
#ifdef DEBUG
// static
nsIPrincipal*
nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
bool aAllowShortCircuit)
{
NS_ASSERTION(aObj, "Bad call to doGetObjectPrincipal()!");
nsIPrincipal* result = nsnull;
#ifdef DEBUG
JSObject* origObj = aObj;
#endif
js::Class *jsClass = js::GetObjectClass(aObj);
// A common case seen in this code is that we enter this function
@ -2444,12 +2365,7 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
if (IS_WRAPPER_CLASS(jsClass)) {
result = sXPConnect->GetPrincipal(aObj,
#ifdef DEBUG
aAllowShortCircuit
#else
true
#endif
);
aAllowShortCircuit);
if (result) {
break;
}
@ -2465,7 +2381,6 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
priv = nsnull;
}
#ifdef DEBUG
if (aAllowShortCircuit) {
nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
do_QueryInterface(priv);
@ -2475,7 +2390,6 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
"Uh, an nsIXPConnectWrappedNative with the "
"wrong JSClass or getObjectOps hooks!");
}
#endif
nsCOMPtr<nsIScriptObjectPrincipal> objPrin =
do_QueryInterface(priv);
@ -2497,9 +2411,8 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
jsClass = js::GetObjectClass(aObj);
} while (1);
#ifdef DEBUG
if (aAllowShortCircuit) {
nsIPrincipal *principal = doGetObjectPrincipal(origObj, false);
nsIPrincipal *principal = old_doGetObjectPrincipal(origObj, false);
// Because of inner window reuse, we can have objects with one principal
// living in a scope with a different (but same-origin) principal. So
@ -2507,10 +2420,10 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
NS_ASSERTION(NS_SUCCEEDED(CheckSameOriginPrincipal(result, principal)),
"Principal mismatch. Not good");
}
#endif
return result;
}
#endif /* DEBUG */
///////////////// Capabilities API /////////////////////
NS_IMETHODIMP
@ -2522,28 +2435,13 @@ nsScriptSecurityManager::IsCapabilityEnabled(const char *capability,
JSContext *cx = GetCurrentJSContext();
fp = cx ? JS_FrameIterator(cx, &fp) : nsnull;
JSStackFrame *target = nsnull;
nsIPrincipal *targetPrincipal = nsnull;
for (ContextPrincipal *cp = mContextPrincipals; cp; cp = cp->mNext)
{
if (cp->mCx == cx)
{
target = cp->mFp;
targetPrincipal = cp->mPrincipal;
break;
}
}
if (!fp)
{
// No script code on stack. If we had a principal pushed for this
// context and fp is null, then we use that principal. Otherwise, we
// don't have enough information and have to allow execution.
*result = (targetPrincipal && !target)
? (targetPrincipal == mSystemPrincipal)
: true;
// No script code on stack. Allow access if and only if the subject
// principal is system.
nsresult ignored;
nsIPrincipal *subjectPrin = doGetSubjectPrincipal(&ignored);
*result = (!subjectPrin || subjectPrin == mSystemPrincipal);
return NS_OK;
}
@ -2586,7 +2484,7 @@ nsScriptSecurityManager::IsCapabilityEnabled(const char *capability,
// the JS engine via JS_EvaluateScript or similar APIs.
if (JS_IsGlobalFrame(cx, fp))
break;
} while (fp != target && (fp = JS_FrameIterator(cx, &fp)) != nsnull);
} while ((fp = JS_FrameIterator(cx, &fp)) != nsnull);
if (!previousPrincipal)
{
@ -3070,7 +2968,6 @@ nsScriptSecurityManager::nsScriptSecurityManager(void)
: mOriginToPolicyMap(nsnull),
mDefaultPolicy(nsnull),
mCapabilities(nsnull),
mContextPrincipals(nsnull),
mPrefInitialized(false),
mIsJavaScriptEnabled(false),
mIsWritingPrefs(false),
@ -3131,9 +3028,7 @@ nsresult nsScriptSecurityManager::Init()
CheckObjectAccess,
nsJSPrincipals::Subsume,
ObjectPrincipalFinder,
ContentSecurityPolicyPermitsJSAction,
PushPrincipalCallback,
PopPrincipalCallback
ContentSecurityPolicyPermitsJSAction
};
MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));
@ -3152,7 +3047,6 @@ jsid nsScriptSecurityManager::sEnabledID = JSID_VOID;
nsScriptSecurityManager::~nsScriptSecurityManager(void)
{
Preferences::RemoveObservers(this, kObservedPrefs);
NS_ASSERTION(!mContextPrincipals, "Leaking mContextPrincipals");
delete mOriginToPolicyMap;
if(mDefaultPolicy)
mDefaultPolicy->Drop();

Просмотреть файл

@ -257,7 +257,7 @@ NS_IMETHODIMP
nsFrameMessageManager::Dump(const nsAString& aStr)
{
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "Gecko", NS_ConvertUTF16toUTF8(aStr).get());
__android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", NS_ConvertUTF16toUTF8(aStr).get());
#endif
fputs(NS_ConvertUTF16toUTF8(aStr).get(), stdout);
fflush(stdout);

Просмотреть файл

@ -213,14 +213,20 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
ls->mListener = aListener;
ls->mEventType = aType;
ls->mTypeAtom = aTypeAtom;
ls->mWrappedJS = false;
ls->mFlags = aFlags;
ls->mHandlerIsString = false;
nsCOMPtr<nsIXPConnectWrappedJS> wjs = do_QueryInterface(aListener);
if (wjs) {
ls->mWrappedJS = true;
// Detect the type of event listener.
nsCOMPtr<nsIXPConnectWrappedJS> wjs;
if (aFlags & NS_PRIV_EVENT_FLAG_SCRIPT) {
ls->mListenerType = eJSEventListener;
} else if ((wjs = do_QueryInterface(aListener))) {
ls->mListenerType = eWrappedJSListener;
} else {
ls->mListenerType = eNativeListener;
}
if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
mMayHaveSystemGroupListeners = true;
}
@ -458,7 +464,8 @@ nsEventListenerManager::FindJSEventListener(PRUint32 aEventType,
for (PRUint32 i = 0; i < count; ++i) {
ls = &mListeners.ElementAt(i);
if (EVENT_TYPE_EQUALS(ls, aEventType, aTypeAtom) &&
ls->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) {
(ls->mListenerType == eJSEventListener))
{
return ls;
}
}
@ -796,7 +803,7 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
// If this is a script handler and we haven't yet
// compiled the event handler itself
if ((aListenerStruct->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) &&
if ((aListenerStruct->mListenerType == eJSEventListener) &&
aListenerStruct->mHandlerIsString) {
nsIJSEventListener *jslistener = aListenerStruct->GetJSListener();
result = CompileEventHandlerInternal(aListenerStruct,
@ -863,13 +870,28 @@ nsEventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
break;
}
}
// Push the appropriate context. Note that we explicitly don't push a
// context in the case that the listener is non-scripted, in which case
// it's the native code's responsibility to push a context if it ever
// enters JS. Ideally we'd do things this way for all scripted callbacks,
// but that would involve a lot of changes and context pushing is going
// away soon anyhow.
//
// NB: Since we're looping here, the no-RePush() case needs to actually be
// a Pop(), otherwise we might end up with whatever was pushed in a
// previous iteration.
if (ls->mListenerType == eNativeListener) {
aPusher->Pop();
} else if (!aPusher->RePush(aCurrentTarget)) {
continue;
}
nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = ls->mListener;
if (aPusher->RePush(aCurrentTarget)) {
if (NS_FAILED(HandleEventSubType(ls, ls->mListener, *aDOMEvent,
aCurrentTarget, aFlags,
aPusher))) {
aEvent->flags |= NS_EVENT_FLAG_EXCEPTION_THROWN;
}
if (NS_FAILED(HandleEventSubType(ls, ls->mListener, *aDOMEvent,
aCurrentTarget, aFlags,
aPusher))) {
aEvent->flags |= NS_EVENT_FLAG_EXCEPTION_THROWN;
}
}
}
@ -992,7 +1014,7 @@ nsEventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
bool allowsUntrusted = !!(ls.mFlags & NS_PRIV_EVENT_UNTRUSTED_PERMITTED);
// If this is a script handler and we haven't yet
// compiled the event handler itself go ahead and compile it
if ((ls.mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) && ls.mHandlerIsString) {
if ((ls.mListenerType == eJSEventListener) && ls.mHandlerIsString) {
CompileEventHandlerInternal(const_cast<nsListenerStruct*>(&ls),
true, nsnull);
}
@ -1107,7 +1129,7 @@ nsEventListenerManager::UnmarkGrayJSListeners()
if (jsl) {
xpc_UnmarkGrayObject(jsl->GetHandler());
xpc_UnmarkGrayObject(jsl->GetEventScope());
} else if (ls.mWrappedJS) {
} else if (ls.mListenerType == eWrappedJSListener) {
xpc_TryUnmarkWrappedGrayObject(ls.mListener);
}
}

Просмотреть файл

@ -31,23 +31,30 @@ class nsCxPusher;
class nsIEventListenerInfo;
class nsIDocument;
typedef enum
{
eNativeListener = 0,
eJSEventListener,
eWrappedJSListener
} nsListenerType;
struct nsListenerStruct
{
nsRefPtr<nsIDOMEventListener> mListener;
PRUint32 mEventType;
nsCOMPtr<nsIAtom> mTypeAtom;
PRUint16 mFlags;
PRUint8 mListenerType;
bool mHandlerIsString;
bool mWrappedJS;
nsIJSEventListener* GetJSListener() const {
return (mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) ?
return (mListenerType == eJSEventListener) ?
static_cast<nsIJSEventListener *>(mListener.get()) : nsnull;
}
~nsListenerStruct()
{
if ((mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) && mListener) {
if ((mListenerType == eJSEventListener) && mListener) {
static_cast<nsIJSEventListener*>(mListener.get())->Disconnect();
}
}

Просмотреть файл

@ -280,6 +280,12 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventTarget* aTarget,
scriptTarget = aTarget;
}
// We're about to create a new nsJSEventListener, which means that we're
// responsible for pushing the context of the event target. See the similar
// comment in nsEventManagerListener.cpp.
nsCxPusher pusher;
NS_ENSURE_STATE(pusher.Push(aTarget));
rv = EnsureEventHandler(boundGlobal, boundContext, onEventAtom, handler);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -1199,27 +1199,29 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
xpc_UnmarkGrayObject(aScopeObject);
nsAutoMicroTask mt;
// Safety first: get an object representing the script's principals, i.e.,
// the entities who signed this script, or the fully-qualified-domain-name
// or "codebase" from which it was loaded.
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
nsresult rv;
if (!aPrincipal) {
nsIScriptGlobalObject *global = GetGlobalObject();
if (!global)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
do_QueryInterface(global, &rv);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
principal = objPrincipal->GetPrincipal();
if (!principal)
return NS_ERROR_FAILURE;
}
// Ignore the principal that was passed in, and just assert that it matches
// the one we pull off the global.
nsCOMPtr<nsIPrincipal> principal;
nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal = do_QueryInterface(GetGlobalObject());
if (!objPrincipal)
return NS_ERROR_FAILURE;
principal = objPrincipal->GetPrincipal();
if (!principal)
return NS_ERROR_FAILURE;
#ifdef DEBUG
bool equal = false;
principal->Equals(aPrincipal, &equal);
MOZ_ASSERT(equal);
nsIPrincipal *scopeObjectPrincipal =
nsJSPrincipals::get(JS_GetCompartmentPrincipals(js::GetObjectCompartment(aScopeObject)));
equal = false;
principal->Equals(scopeObjectPrincipal, &equal);
MOZ_ASSERT(equal);
#endif
bool ok = false;
rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok);
nsresult rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok);
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;
}
@ -1236,9 +1238,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
jsval val;
rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
NS_ENSURE_SUCCESS(rv, rv);
nsJSContext::TerminationFuncHolder holder(this);
// SecurityManager said "ok", but don't compile if aVersion is unknown.
@ -1294,8 +1293,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
}
}
sSecurityManager->PopContextPrincipal(mContext);
// Pop here, after JS_ValueToString and any other possible evaluation.
if (NS_FAILED(stack->Pop(nsnull)))
rv = NS_ERROR_FAILURE;
@ -1401,19 +1398,25 @@ nsJSContext::EvaluateString(const nsAString& aScript,
xpc_UnmarkGrayObject(aScopeObject);
// Safety first: get an object representing the script's principals, i.e.,
// the entities who signed this script, or the fully-qualified-domain-name
// or "codebase" from which it was loaded.
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
if (!aPrincipal) {
nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
do_QueryInterface(GetGlobalObject());
if (!objPrincipal)
return NS_ERROR_FAILURE;
principal = objPrincipal->GetPrincipal();
if (!principal)
return NS_ERROR_FAILURE;
}
// Ignore the principal that was passed in, and just assert that it matches
// the one we pull off the global.
nsCOMPtr<nsIPrincipal> principal;
nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal = do_QueryInterface(GetGlobalObject());
if (!objPrincipal)
return NS_ERROR_FAILURE;
principal = objPrincipal->GetPrincipal();
if (!principal)
return NS_ERROR_FAILURE;
#ifdef DEBUG
bool equal = false;
principal->Equals(aPrincipal, &equal);
MOZ_ASSERT(equal);
nsIPrincipal *scopeObjectPrincipal =
nsJSPrincipals::get(JS_GetCompartmentPrincipals(js::GetObjectCompartment(aScopeObject)));
equal = false;
principal->Equals(scopeObjectPrincipal, &equal);
MOZ_ASSERT(equal);
#endif
bool ok = false;
@ -1438,9 +1441,6 @@ nsJSContext::EvaluateString(const nsAString& aScript,
jsval val = JSVAL_VOID;
jsval* vp = aRetValue ? &val : NULL;
rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
NS_ENSURE_SUCCESS(rv, rv);
nsJSContext::TerminationFuncHolder holder(this);
++mExecuteDepth;
@ -1492,8 +1492,6 @@ nsJSContext::EvaluateString(const nsAString& aScript,
--mExecuteDepth;
sSecurityManager->PopContextPrincipal(mContext);
// Pop here, after JS_ValueToString and any other possible evaluation.
if (NS_FAILED(stack->Pop(nsnull)))
rv = NS_ERROR_FAILURE;
@ -1591,15 +1589,6 @@ nsJSContext::ExecuteScript(JSScript* aScriptObject,
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPrincipal> principal;
rv = sSecurityManager->GetObjectPrincipal(mContext,
JS_GetGlobalFromScript(aScriptObject),
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
NS_ENSURE_SUCCESS(rv, rv);
nsJSContext::TerminationFuncHolder holder(this);
XPCAutoRequest ar(mContext);
++mExecuteDepth;
@ -1626,8 +1615,6 @@ nsJSContext::ExecuteScript(JSScript* aScriptObject,
--mExecuteDepth;
sSecurityManager->PopContextPrincipal(mContext);
// Pop here, after JS_ValueToString and any other possible evaluation.
if (NS_FAILED(stack->Pop(nsnull)))
rv = NS_ERROR_FAILURE;
@ -1868,24 +1855,12 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
jsval *argv = nsnull;
JSObject *funobj = aHandler;
nsCOMPtr<nsIPrincipal> principal;
rv = sSecurityManager->GetObjectPrincipal(mContext, funobj,
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
JSStackFrame *currentfp = nsnull;
rv = sSecurityManager->PushContextPrincipal(mContext,
JS_FrameIterator(mContext, &currentfp),
principal);
NS_ENSURE_SUCCESS(rv, rv);
jsval funval = OBJECT_TO_JSVAL(funobj);
JSAutoEnterCompartment ac;
js::ForceFrame ff(mContext, funobj);
if (!ac.enter(mContext, funobj) || !ff.enter() ||
!JS_WrapObject(mContext, &target)) {
ReportPendingException();
sSecurityManager->PopContextPrincipal(mContext);
return NS_ERROR_FAILURE;
}
@ -1928,8 +1903,6 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
// nested calls through XPConnect.
if (NS_FAILED(rv))
ReportPendingException();
sSecurityManager->PopContextPrincipal(mContext);
}
pusher.Pop();

Просмотреть файл

@ -377,7 +377,7 @@ IndexedDBDatabaseParent::HandleDatabaseEvent(nsIDOMEvent* aEvent,
nsresult rv;
if (aType.EqualsLiteral(VERSIONCHANGE_EVT_STR)) {
JSContext* cx = nsContentUtils::GetCurrentJSContext();
JSContext* cx = nsContentUtils::GetSafeJSContext();
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
nsCOMPtr<nsIIDBVersionChangeEvent> changeEvent = do_QueryInterface(aEvent);

Просмотреть файл

@ -177,32 +177,15 @@ nsJSON::EncodeFromJSVal(JS::Value *value, JSContext *cx, nsAString &result)
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
nsIScriptSecurityManager *ssm = nsnull;
if (value->isObject()) {
JSObject *obj = &value->toObject();
if (!ac.enter(cx, obj)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPrincipal> principal;
ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->GetObjectPrincipal(cx, obj, getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
JSStackFrame *fp = nsnull;
rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), principal);
NS_ENSURE_SUCCESS(rv, rv);
}
nsJSONWriter writer;
JSBool ok = JS_Stringify(cx, value, NULL, JSVAL_NULL,
WriteCallback, &writer);
if (ssm) {
ssm->PopContextPrincipal(cx);
}
if (!ok) {
if (!JS_Stringify(cx, value, NULL, JSVAL_NULL, WriteCallback, &writer)) {
return NS_ERROR_XPC_BAD_CONVERT_JS;
}

Просмотреть файл

@ -37,9 +37,7 @@
function respond(msg)
{
// ...so get privileges and test that this works with privileges
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.parent.postMessage(msg, "*");
SpecialPowers.wrap(window).parent.postMessage(msg, "*");
}
window.addEventListener("message", receiveMessage, false);

Просмотреть файл

@ -93,10 +93,6 @@ function chromePathIsSet(evt)
function receiveContent(evt)
{
is(evt.isTrusted, true, "should have sent a trusted event");
is(evt.origin, "http://example.org", "content response event has wrong URI");
is(evt.source, window.frames.contentDomain,
"wrong source for same-domain message!");
finish();
}

Просмотреть файл

@ -718,9 +718,11 @@ var WifiManager = (function() {
fields.state = supplicantStatesMap[fields.state];
// The BSSID field is only valid in the ASSOCIATING and ASSOCIATED
// states.
if (fields.state === "ASSOCIATING" || fields.state == "ASSOCIATED")
// states, except when we "reauth", except this seems to depend on the
// driver, so simply check to make sure that we don't have a null BSSID.
if (fields.BSSID !== "00:00:00:00:00:00")
manager.connectionInfo.bssid = fields.BSSID;
notifyStateChange(fields);
return true;
}

Просмотреть файл

@ -1233,7 +1233,7 @@ public:
if (!logged) {
NS_ConvertUTF16toUTF8 msg(aMessage);
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "Gecko", msg.get());
__android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", msg.get());
#endif
fputs(msg.get(), stderr);
fflush(stderr);

Просмотреть файл

@ -542,7 +542,7 @@ private:
}
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "Gecko", buffer.ptr());
__android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", buffer.ptr());
#endif
fputs(buffer.ptr(), stdout);
fflush(stdout);

Просмотреть файл

@ -1147,9 +1147,9 @@ public:
MainThreadRun()
{
nsCOMPtr<nsIVariant> variant;
RuntimeService::AutoSafeJSContext cx;
if (mBody.data()) {
RuntimeService::AutoSafeJSContext cx;
nsIXPConnect* xpc = nsContentUtils::XPConnect();
NS_ASSERTION(xpc, "This should never be null!");

Просмотреть файл

@ -749,24 +749,27 @@ gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
return nsnull;
}
// create a new font entry with the proxy entry style characteristics
PRUint16 w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight);
bool isCFF = false; // jtdfix -- need to determine this
// use the face name from the lookup font entry, which will be the localized
// face name which GDI mapping tables use (e.g. with the system locale set to
// Dutch, a fullname of 'Arial Bold' will find a font entry with the face name
// 'Arial Vet' which can be used as a key in GDI font lookups).
gfxFontEntry *fe = GDIFontEntry::CreateFontEntry(lookup->Name(),
GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(lookup->Name(),
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
PRUint32(aProxyEntry->mItalic ? NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL),
w, aProxyEntry->mStretch, nsnull);
lookup->mItalic ? NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL,
lookup->mWeight, aProxyEntry->mStretch, nsnull);
if (!fe)
return nsnull;
fe->mIsUserFont = true;
fe->mIsLocalUserFont = true;
// make the new font entry match the proxy entry style characteristics
fe->mWeight = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight);
fe->mItalic = aProxyEntry->mItalic;
return fe;
}

Просмотреть файл

@ -880,20 +880,6 @@ FullTrustSecMan::GetCxSubjectPrincipalAndFrame(JSContext *cx,
return mSystemPrincipal;
}
NS_IMETHODIMP
FullTrustSecMan::PushContextPrincipal(JSContext *cx,
JSStackFrame *fp,
nsIPrincipal *principal)
{
return NS_OK;
}
NS_IMETHODIMP
FullTrustSecMan::PopContextPrincipal(JSContext *cx)
{
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
XPCShellDirProvider::AddRef()
{

Просмотреть файл

@ -1664,16 +1664,6 @@ typedef JSPrincipals *
typedef JSBool
(* JSCSPEvalChecker)(JSContext *cx);
/*
* Security callbacks for pushing and popping context principals. These are only
* temporarily necessary and will hopefully be gone again in a matter of weeks.
*/
typedef JSBool
(* JSPushContextPrincipalOp)(JSContext *cx, JSPrincipals *principals);
typedef JSBool
(* JSPopContextPrincipalOp)(JSContext *cx);
/*
* Callback used to ask the embedding for the cross compartment wrapper handler
* that implements the desired prolicy for this kind of object in the
@ -4343,8 +4333,6 @@ struct JSSecurityCallbacks {
JSSubsumePrincipalsOp subsumePrincipals;
JSObjectPrincipalsFinder findObjectPrincipals;
JSCSPEvalChecker contentSecurityPolicyAllows;
JSPushContextPrincipalOp pushContextPrincipal;
JSPopContextPrincipalOp popContextPrincipal;
};
extern JS_PUBLIC_API(void)

Просмотреть файл

@ -472,37 +472,6 @@ JSStructuredCloneWriter::startObject(JSObject *obj)
return out.writePair(obj->isArray() ? SCTAG_ARRAY_OBJECT : SCTAG_OBJECT_OBJECT, 0);
}
class AutoEnterCompartmentAndPushPrincipal : public JSAutoEnterCompartment
{
public:
bool enter(JSContext *cx, JSObject *target) {
// First, enter the compartment.
if (!JSAutoEnterCompartment::enter(cx, target))
return false;
// We only need to push a principal if we changed compartments.
if (state != STATE_OTHER_COMPARTMENT)
return true;
// Push.
const JSSecurityCallbacks *cb = cx->runtime->securityCallbacks;
if (cb->pushContextPrincipal)
return cb->pushContextPrincipal(cx, target->principals(cx));
return true;
}
~AutoEnterCompartmentAndPushPrincipal() {
// Pop the principal if necessary.
if (state == STATE_OTHER_COMPARTMENT) {
AutoCompartment *ac = getAutoCompartment();
const JSSecurityCallbacks *cb = ac->context->runtime->securityCallbacks;
if (cb->popContextPrincipal)
cb->popContextPrincipal(ac->context);
}
}
};
bool
JSStructuredCloneWriter::startWrite(const Value &v)
{
@ -529,7 +498,7 @@ JSStructuredCloneWriter::startWrite(const Value &v)
// If we unwrapped above, we'll need to enter the underlying compartment.
// Let the AutoEnterCompartment do the right thing for us.
AutoEnterCompartmentAndPushPrincipal ac;
JSAutoEnterCompartment ac;
if (!ac.enter(context(), obj))
return false;
@ -574,7 +543,7 @@ JSStructuredCloneWriter::write(const Value &v)
RootedObject obj(context(), &objs.back().toObject());
// The objects in |obj| can live in other compartments.
AutoEnterCompartmentAndPushPrincipal ac;
JSAutoEnterCompartment ac;
if (!ac.enter(context(), obj))
return false;

Просмотреть файл

@ -913,17 +913,16 @@ inline InterpreterFrames::~InterpreterFrames()
#if defined(DEBUG) && !defined(JS_THREADSAFE) && !defined(JSGC_ROOT_ANALYSIS)
void
js::AssertValidPropertyCacheHit(JSContext *cx,
JSObject *start_, JSObject *found,
PropertyCacheEntry *entry)
js::AssertValidPropertyCacheHit(JSContext *cx, JSObject *start_,
JSObject *found, PropertyCacheEntry *entry)
{
jsbytecode *pc;
cx->stack.currentScript(&pc);
JSScript *script = cx->stack.currentScript(&pc);
uint64_t sample = cx->runtime->gcNumber;
PropertyCacheEntry savedEntry = *entry;
RootedPropertyName name(cx, GetNameFromBytecode(cx, pc, JSOp(*pc)));
RootedPropertyName name(cx, GetNameFromBytecode(cx, script, pc, JSOp(*pc)));
RootedObject start(cx, start_);
JSObject *obj, *pobj;
@ -2330,7 +2329,7 @@ BEGIN_CASE(JSOP_LENGTH)
BEGIN_CASE(JSOP_CALLPROP)
{
RootedValue rval(cx);
if (!GetPropertyOperation(cx, regs.pc, regs.sp[-1], rval.address()))
if (!GetPropertyOperation(cx, script, regs.pc, regs.sp[-1], rval.address()))
goto error;
TypeScript::Monitor(cx, script, regs.pc, rval.reference());
@ -2542,7 +2541,7 @@ BEGIN_CASE(JSOP_CALLNAME)
{
RootedValue &rval = rootValue0;
if (!NameOperation(cx, regs.pc, rval.address()))
if (!NameOperation(cx, script, regs.pc, rval.address()))
goto error;
PUSH_COPY(rval);

Просмотреть файл

@ -166,7 +166,8 @@ GetPropertyGenericMaybeCallXML(JSContext *cx, JSOp op, HandleObject obj, HandleI
}
inline bool
GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp)
GetPropertyOperation(JSContext *cx, JSScript *script, jsbytecode *pc,
const Value &lval, Value *vp)
{
JS_ASSERT(vp != &lval);
@ -320,7 +321,7 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Val
}
inline bool
NameOperation(JSContext *cx, jsbytecode *pc, Value *vp)
NameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value *vp)
{
RootedObject obj(cx, cx->stack.currentScriptedScopeChain());

Просмотреть файл

@ -11,7 +11,7 @@
namespace js {
static inline PropertyName *
GetNameFromBytecode(JSContext *cx, jsbytecode *pc, JSOp op)
GetNameFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc, JSOp op)
{
if (op == JSOP_LENGTH)
return cx->runtime->atomState.lengthAtom;
@ -21,7 +21,6 @@ GetNameFromBytecode(JSContext *cx, jsbytecode *pc, JSOp op)
if (op == JSOP_INSTANCEOF)
return cx->runtime->atomState.classPrototypeAtom;
JSScript *script = cx->stack.currentScriptWithDiagnostics();
PropertyName *name;
GET_NAME_FROM_BYTECODE(script, pc, 0, name);
return name;

Просмотреть файл

@ -122,9 +122,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
PropertyCacheEntry *entry)
{
JSObject *obj, *pobj, *tmp;
#ifdef DEBUG
JSScript *script = cx->stack.currentScript();
#endif
JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
JS_ASSERT(uint32_t(pc - script->code) < script->length);
@ -137,7 +135,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
if (entry->kpc != pc) {
PCMETER(kpcmisses++);
PropertyName *name = GetNameFromBytecode(cx, pc, op);
PropertyName *name = GetNameFromBytecode(cx, script, pc, op);
#ifdef DEBUG_notme
JSAutoByteString printable;
fprintf(stderr,
@ -160,7 +158,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
if (entry->kshape != obj->lastProperty()) {
PCMETER(kshapemisses++);
return GetNameFromBytecode(cx, pc, op);
return GetNameFromBytecode(cx, script, pc, op);
}
/*
@ -193,7 +191,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
if (pobj->lastProperty() == entry->pshape) {
#ifdef DEBUG
PropertyName *name = GetNameFromBytecode(cx, pc, op);
PropertyName *name = GetNameFromBytecode(cx, script, pc, op);
JS_ASSERT(pobj->nativeContains(cx, NameToId(name)));
#endif
*pobjp = pobj;
@ -201,7 +199,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
}
PCMETER(vcapmisses++);
return GetNameFromBytecode(cx, pc, op);
return GetNameFromBytecode(cx, script, pc, op);
}
#ifdef DEBUG

Просмотреть файл

@ -1924,7 +1924,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
Value v;
if (cached) {
if (!GetPropertyOperation(f.cx, f.pc(), f.regs.sp[-1], &v))
if (!GetPropertyOperation(f.cx, f.script(), f.pc(), f.regs.sp[-1], &v))
THROW();
} else {
if (!obj->getProperty(f.cx, name, &v))

Просмотреть файл

@ -98,7 +98,7 @@ void JS_FASTCALL
stubs::Name(VMFrame &f)
{
Value rval;
if (!NameOperation(f.cx, f.pc(), &rval))
if (!NameOperation(f.cx, f.script(), f.pc(), &rval))
THROW();
f.regs.sp[0] = rval;
}
@ -980,7 +980,7 @@ stubs::GetProp(VMFrame &f, PropertyName *name)
FrameRegs &regs = f.regs;
Value rval;
if (!GetPropertyOperation(cx, f.pc(), f.regs.sp[-1], &rval))
if (!GetPropertyOperation(cx, f.script(), f.pc(), f.regs.sp[-1], &rval))
THROW();
regs.sp[-1] = rval;

Просмотреть файл

@ -557,45 +557,6 @@ ContextStack::currentScript(jsbytecode **ppc) const
return script;
}
inline JSScript *
ContextStack::currentScriptWithDiagnostics(jsbytecode **ppc) const
{
if (ppc)
*ppc = NULL;
FrameRegs *regs = maybeRegs();
StackFrame *fp = regs ? regs->fp() : NULL;
while (fp && fp->isDummyFrame())
fp = fp->prev();
if (!fp)
*(int *) 0x10 = 0;
#ifdef JS_METHODJIT
mjit::CallSite *inlined = regs->inlined();
if (inlined) {
mjit::JITChunk *chunk = fp->jit()->chunk(regs->pc);
JS_ASSERT(inlined->inlineIndex < chunk->nInlineFrames);
mjit::InlineFrame *frame = &chunk->inlineFrames()[inlined->inlineIndex];
JSScript *script = frame->fun->script();
if (script->compartment() != cx_->compartment)
*(int *) 0x20 = 0;
if (ppc)
*ppc = script->code + inlined->pcOffset;
return script;
}
#endif
JSScript *script = fp->script();
if (script->compartment() != cx_->compartment)
*(int *) 0x30 = 0;
if (ppc)
*ppc = fp->pcQuadratic(*this);
if (!script)
*(int *) 0x40 = 0;
return script;
}
inline HandleObject
ContextStack::currentScriptedScopeChain() const
{

Просмотреть файл

@ -1660,7 +1660,6 @@ class ContextStack
/* Get the topmost script and optional pc on the stack. */
inline JSScript *currentScript(jsbytecode **pc = NULL) const;
inline JSScript *currentScriptWithDiagnostics(jsbytecode **pc = NULL) const;
/* Get the scope chain for the topmost scripted call on the stack. */
inline HandleObject currentScriptedScopeChain() const;

Просмотреть файл

@ -176,7 +176,7 @@ Dump(JSContext *cx, unsigned argc, jsval *vp)
NS_ConvertUTF16toUTF8 utf8str(reinterpret_cast<const PRUnichar*>(chars));
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "Gecko", utf8str.get());
__android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", utf8str.get());
#endif
fputs(utf8str.get(), stdout);
fflush(stdout);

Просмотреть файл

@ -423,7 +423,7 @@ Dump(JSContext *cx, unsigned argc, jsval *vp)
return false;
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "Gecko", bytes.ptr());
__android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", bytes.ptr());
#endif
fputs(bytes.ptr(), gOutFile);
fflush(gOutFile);
@ -1381,20 +1381,6 @@ FullTrustSecMan::GetSubjectPrincipal(nsIPrincipal **_retval)
return *_retval ? NS_OK : NS_ERROR_FAILURE;
}
/* [noscript] void pushContextPrincipal (in JSContextPtr cx, in JSStackFramePtr fp, in nsIPrincipal principal); */
NS_IMETHODIMP
FullTrustSecMan::PushContextPrincipal(JSContext * cx, JSStackFrame * fp, nsIPrincipal *principal)
{
return NS_OK;
}
/* [noscript] void popContextPrincipal (in JSContextPtr cx); */
NS_IMETHODIMP
FullTrustSecMan::PopContextPrincipal(JSContext * cx)
{
return NS_OK;
}
/* [noscript] nsIPrincipal getSystemPrincipal (); */
NS_IMETHODIMP
FullTrustSecMan::GetSystemPrincipal(nsIPrincipal **_retval)

Просмотреть файл

@ -1112,17 +1112,6 @@ nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
return NS_ERROR_FAILURE;
}
class ContextPrincipalGuard
{
nsIScriptSecurityManager *ssm;
XPCCallContext &ccx;
public:
ContextPrincipalGuard(XPCCallContext &ccx)
: ssm(nsnull), ccx(ccx) {}
void principalPushed(nsIScriptSecurityManager *ssm) { this->ssm = ssm; }
~ContextPrincipalGuard() { if (ssm) ssm->PopContextPrincipal(ccx); }
};
NS_IMETHODIMP
nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
const XPTMethodDescriptor* info,
@ -1166,7 +1155,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
JS::AutoValueVector args(cx);
AutoScriptEvaluate scriptEval(cx);
ContextPrincipalGuard principalGuard(ccx);
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
uint8_t paramCount = info->num_args;
@ -1180,29 +1168,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
xpcc->SetException(nsnull);
XPCJSRuntime::Get()->SetPendingException(nsnull);
// This scoping is necessary due to the gotos here. Ugh.
{
// TODO Remove me in favor of security wrappers.
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (ssm) {
nsIPrincipal *objPrincipal =
xpc::AccessCheck::getPrincipal(js::GetObjectCompartment(obj));
if (objPrincipal) {
JSStackFrame* fp = nsnull;
nsresult rv =
ssm->PushContextPrincipal(ccx, JS_FrameIterator(ccx, &fp),
objPrincipal);
if (NS_FAILED(rv)) {
JS_ReportOutOfMemory(ccx);
retval = NS_ERROR_OUT_OF_MEMORY;
goto pre_call_clean_up;
}
principalGuard.principalPushed(ssm);
}
}
}
// We use js_Invoke so that the gcthings we use as args will be rooted by
// the engine as we do conversions and prepare to do the function call.

Просмотреть файл

@ -15,15 +15,7 @@
namespace xpc {
NoWaiverWrapper::NoWaiverWrapper(unsigned flags) : js::CrossCompartmentWrapper(flags)
{
}
NoWaiverWrapper::~NoWaiverWrapper()
{
}
CrossOriginWrapper::CrossOriginWrapper(unsigned flags) : NoWaiverWrapper(flags)
CrossOriginWrapper::CrossOriginWrapper(unsigned flags) : js::CrossCompartmentWrapper(flags)
{
}
@ -70,36 +62,4 @@ CrossOriginWrapper::construct(JSContext *cx, JSObject *wrapper,
WrapperFactory::WaiveXrayAndWrap(cx, rval);
}
bool
NoWaiverWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp)
{
*bp = true; // always allowed
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (!ssm) {
return true;
}
// Note: By the time enter is called here, CrossCompartmentWrapper has
// already pushed the fake stack frame onto cx. Because of this, the frame
// that we're clamping is the one that we want (the one in our compartment).
JSStackFrame *fp = NULL;
nsIPrincipal *principal = GetCompartmentPrincipal(js::GetObjectCompartment(wrappedObject(wrapper)));
nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), principal);
if (NS_FAILED(rv)) {
NS_WARNING("Not allowing call because we're out of memory");
JS_ReportOutOfMemory(cx);
return false;
}
return true;
}
void
NoWaiverWrapper::leave(JSContext *cx, JSObject *wrapper)
{
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (ssm) {
ssm->PopContextPrincipal(cx);
}
}
}

Просмотреть файл

@ -15,18 +15,7 @@
namespace xpc {
class NoWaiverWrapper : public js::CrossCompartmentWrapper {
public:
NoWaiverWrapper(unsigned flags);
virtual ~NoWaiverWrapper();
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp) MOZ_OVERRIDE;
virtual void leave(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
static NoWaiverWrapper singleton;
};
class CrossOriginWrapper : public NoWaiverWrapper {
class CrossOriginWrapper : public js::CrossCompartmentWrapper {
public:
CrossOriginWrapper(unsigned flags);
virtual ~CrossOriginWrapper();

Просмотреть файл

@ -31,13 +31,6 @@ namespace xpc {
// we know to not apply an X-ray wrapper.
DirectWrapper WaiveXrayWrapperWrapper(WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG);
// Objects that haven't been explicitly waived, but have been exposed
// to chrome don't want a CrossOriginWrapper, since that deeply-waives
// but need the transparent behavior of a CrossOriginWrapper. The
// NoWaiverWrapper is like a CrossOriginWrapper that can also hand out
// XrayWrappers as return values.
NoWaiverWrapper NoWaiverWrapper::singleton(0);
// When objects for which we waived the X-ray wrapper cross into
// chrome, we wrap them into a special cross-compartment wrapper
// that transitively extends the waiver to all properties we get
@ -341,7 +334,7 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
usingXray = true;
wrapper = &Xray::singleton;
} else {
wrapper = &NoWaiverWrapper::singleton;
wrapper = &CrossCompartmentWrapper::singleton;
}
}
}

Просмотреть файл

@ -56,7 +56,7 @@ enum Type {
TYPE_SELECTION_OVERLAY,
TYPE_SOLID_COLOR,
TYPE_SVG_EFFECTS,
TYPE_SVG_EVENT_RECEIVER,
TYPE_SVG_OUTER_SVG,
TYPE_TABLE_CELL_BACKGROUND,
TYPE_TABLE_CELL_SELECTION,
TYPE_TABLE_ROW_BACKGROUND,

Просмотреть файл

@ -7,7 +7,8 @@
<style type="text/css">
body {
font-family: Nimbus Sans L, Helvetica, Bitstream Vera Sans,
Arial, Liberation Sans, SwissA, serif;
Arial, Liberation Sans, SwissA,
Droid Sans, Roboto, serif;
}
</style>
</head>

Просмотреть файл

@ -34,7 +34,8 @@
font-family: "Local";
src: local(Nimbus Sans L), local(NimbusSansL-Regu),
local(Helvetica), local(Bitstream Vera Sans),
local(Arial), local(Liberation Sans), local(SwissA);
local(Arial), local(Liberation Sans), local(SwissA),
local(Droid Sans), local(Roboto);
font-weight: 100;
}
@font-face {
@ -42,7 +43,8 @@
src: local(Nimbus Sans L Bold), local(NimbusSansL-Bold),
local(Helvetica Bold), local(Helvetica-Bold),
local(Bitstream Vera Sans Bold),
local(Arial Bold), local(Liberation Sans Bold), local(SwissA Bold);
local(Arial Bold), local(Liberation Sans Bold), local(SwissA Bold),
local(Droid Sans Bold), local(Roboto Bold);
font-weight: normal;
}
body { font-family: Local, serif }

Просмотреть файл

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@font-face {
font-family: test;
src: local(Nimbus Sans L), local(NimbusSansL-Regu),
local(Helvetica), local(Bitstream Vera Sans),
local(Arial), local(Liberation Sans), local(SwissA),
local(Droid Sans), local(Roboto);
}
div {
font-family: test, serif;
margin: 10px;
}
</style>
</head>
<body>
<div style="font-family:serif">
This serif font should NOT be used below.
</div>
<hr>
<div>
These three lines should all use the same font face.
</div>
<div>
This line should NOT be bold.
</div>
<div>
This line should NOT be italic.
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@font-face {
font-family: test;
src: local(Nimbus Sans L), local(NimbusSansL-Regu),
local(Helvetica), local(Bitstream Vera Sans),
local(Arial), local(Liberation Sans), local(SwissA),
local(Droid Sans), local(Roboto);
}
@font-face {
font-family: test;
font-style: italic;
src: local(Nimbus Sans L), local(NimbusSansL-Regu),
local(Helvetica), local(Bitstream Vera Sans),
local(Arial), local(Liberation Sans), local(SwissA),
local(Droid Sans), local(Roboto);
}
@font-face {
font-family: test;
font-weight: bold;
src: local(Nimbus Sans L), local(NimbusSansL-Regu),
local(Helvetica), local(Bitstream Vera Sans),
local(Arial), local(Liberation Sans), local(SwissA),
local(Droid Sans), local(Roboto);
}
div {
font-family: test, serif;
margin: 10px;
}
</style>
</head>
<body>
<div style="font-family:serif">
This serif font should NOT be used below.
</div>
<hr>
<div>
These three lines should all use the same font face.
</div>
<div>
<b>This line should NOT be bold.</b>
</div>
<div>
<i>This line should NOT be italic.</i>
</div>
</body>
</html>

Просмотреть файл

@ -94,7 +94,10 @@ HTTP(..) == ex-unit-1-dynamic.html ex-unit-1-ref.html
# random-if(!cocoaWidget) HTTP(..) == src-format-arabic.html src-format-arabic-aat-ref.html
# random-if(cocoaWidget) HTTP(..) == src-format-arabic.html src-format-arabic-ot-ref.html
# bug 769194 - src:local() completely broken on android
fails-if(Android) == local-1.html local-1-ref.html
fails-if(Android) == local-styled-1.html local-styled-1-ref.html
HTTP(..) == synthetic-weight-style.html synthetic-weight-style-ref.html
HTTP(..) == synthetic-variations.html synthetic-variations-ref.html

Просмотреть файл

@ -1,4 +1,4 @@
fuzzy-if(d2d,85,20) == move-right-bottom.html move-right-bottom-ref.html # Bug 742176
random-if(cocoaWidget) fuzzy-if(d2d,85,20) == move-right-bottom.html move-right-bottom-ref.html # Bug 742176
random-if(cocoaWidget) fuzzy-if(d2d,85,20) == move-top-left.html move-top-left-ref.html # Bug 688545, bug 742176
fuzzy-if(d2d,85,20) == move-right-bottom-table.html move-right-bottom-table-ref.html # Bug 742176
random-if(cocoaWidget) fuzzy-if(d2d,85,20) == move-right-bottom-table.html move-right-bottom-table-ref.html # Bug 742176
random-if(cocoaWidget) fuzzy-if(d2d,85,20) == move-top-left-table.html move-top-left-table-ref.html # Bug 688545, bug 742176

Просмотреть файл

@ -0,0 +1,42 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test SVG masking of transformed HTML elements</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=769103 -->
<style type="text/css">
* { margin: 0; border: 0; padding: 0;}
div {
position: absolute;
left: 1px;
top: 1px;
width: 3px;
height: 3px;
-moz-transform: scale(100,100);
-moz-transform-origin: 0 0;
}
</style>
</head>
<body bgcolor="lime">
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300"
style="display:block; position:absolute;">
<mask id="mask1" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.48" fill="white"/>
</mask>
<mask id="mask2" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.5" fill="white"/>
</mask>
<circle cx="150" cy="150" r="147" fill="red"/>
</svg>
<div style="background: red; mask: url(#mask1);"/>
<div style="background: lime; mask: url(#mask2);"/>
</body>
</html>

Просмотреть файл

@ -0,0 +1,42 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test SVG masking of transformed HTML elements</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=769103 -->
<style type="text/css">
* { margin: 0; border: 0; padding: 0;}
div {
position: absolute;
left: 50px;
top: 50px;
width: 150px;
height: 150px;
-moz-transform: scale(2,2);
-moz-transform-origin: 0 0;
}
</style>
</head>
<body bgcolor="lime">
<svg xmlns="http://www.w3.org/2000/svg" width="350" height="350"
style="display:block; position:absolute;">
<mask id="mask1" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.48" fill="white"/>
</mask>
<mask id="mask2" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.50" fill="white"/>
</mask>
<circle cx="200" cy="200" r="147" fill="red"/>
</svg>
<div style="background: red; mask: url(#mask1);"/>
<div style="background: lime; mask: url(#mask2);"/>
</body>
</html>

Просмотреть файл

@ -25,3 +25,7 @@
== mask-html-01-extref-02.xhtml mask-html-01-ref.svg
== mask-html-zoomed-01.xhtml mask-html-01-ref.svg
== mask-html-xbl-bound-01.html mask-html-01-ref.svg
== mask-transformed-html-01.xhtml ../pass.svg
== mask-transformed-html-02.xhtml ../pass.svg

Просмотреть файл

@ -363,13 +363,13 @@ private:
void
nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
nsIFrame* aEffectsFrame,
nsIFrame* aFrame,
const nsRect& aDirtyRect,
nsDisplayListBuilder* aBuilder,
nsDisplayList* aInnerList)
{
#ifdef DEBUG
nsISVGChildFrame *svgChildFrame = do_QueryFrame(aEffectsFrame);
nsISVGChildFrame *svgChildFrame = do_QueryFrame(aFrame);
NS_ASSERTION(!svgChildFrame, "Should never be called on an SVG frame");
#endif
@ -387,7 +387,7 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
* + Merge opacity and masking if both used together.
*/
float opacity = aEffectsFrame->GetStyleDisplay()->mOpacity;
float opacity = aFrame->GetStyleDisplay()->mOpacity;
if (opacity == 0.0f) {
return;
}
@ -395,7 +395,7 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
/* Properties are added lazily and may have been removed by a restyle,
so make sure all applicable ones are set again. */
nsIFrame* firstFrame =
nsLayoutUtils::GetFirstContinuationOrSpecialSibling(aEffectsFrame);
nsLayoutUtils::GetFirstContinuationOrSpecialSibling(aFrame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
@ -413,14 +413,14 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(gfx);
PRInt32 appUnitsPerDevPixel =
aEffectsFrame->PresContext()->AppUnitsPerDevPixel();
aFrame->PresContext()->AppUnitsPerDevPixel();
nsPoint firstFrameOffset = GetOffsetToUserSpace(firstFrame);
nsPoint offset = (aBuilder->ToReferenceFrame(firstFrame) - firstFrameOffset).
ToNearestPixels(appUnitsPerDevPixel).
ToAppUnits(appUnitsPerDevPixel);
aCtx->Translate(offset);
gfxMatrix cssPxToDevPxMatrix = GetCSSPxToDevPxMatrix(aEffectsFrame);
gfxMatrix cssPxToDevPxMatrix = GetCSSPxToDevPxMatrix(aFrame);
bool complexEffects = false;
/* Check if we need to do additional operations on this child's
@ -428,7 +428,7 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
if (opacity != 1.0f || maskFrame || (clipPathFrame && !isTrivialClip)) {
complexEffects = true;
gfx->Save();
aCtx->IntersectClip(aEffectsFrame->GetVisualOverflowRect());
aCtx->IntersectClip(aFrame->GetVisualOverflowRect());
gfx->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
}
@ -437,18 +437,18 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
*/
if (clipPathFrame && isTrivialClip) {
gfx->Save();
clipPathFrame->ClipPaint(aCtx, aEffectsFrame, cssPxToDevPxMatrix);
clipPathFrame->ClipPaint(aCtx, aFrame, cssPxToDevPxMatrix);
}
/* Paint the child */
if (filterFrame) {
RegularFramePaintCallback callback(aBuilder, aInnerList, aEffectsFrame,
RegularFramePaintCallback callback(aBuilder, aInnerList, aFrame,
offset);
nsRect dirtyRect = aDirtyRect - offset;
filterFrame->PaintFilteredFrame(aCtx, aEffectsFrame, &callback, &dirtyRect);
filterFrame->PaintFilteredFrame(aCtx, aFrame, &callback, &dirtyRect);
} else {
gfx->SetMatrix(matrixAutoSaveRestore.Matrix());
aInnerList->PaintForFrame(aBuilder, aCtx, aEffectsFrame,
aInnerList->PaintForFrame(aBuilder, aCtx, aFrame,
nsDisplayList::PAINT_DEFAULT);
aCtx->Translate(offset);
}
@ -465,14 +465,14 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
gfx->PopGroupToSource();
nsRefPtr<gfxPattern> maskSurface =
maskFrame ? maskFrame->ComputeMaskAlpha(aCtx, aEffectsFrame,
maskFrame ? maskFrame->ComputeMaskAlpha(aCtx, aFrame,
cssPxToDevPxMatrix, opacity) : nsnull;
nsRefPtr<gfxPattern> clipMaskSurface;
if (clipPathFrame && !isTrivialClip) {
gfx->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
nsresult rv = clipPathFrame->ClipPaint(aCtx, aEffectsFrame, cssPxToDevPxMatrix);
nsresult rv = clipPathFrame->ClipPaint(aCtx, aFrame, cssPxToDevPxMatrix);
clipMaskSurface = gfx->PopGroup();
if (NS_SUCCEEDED(rv) && clipMaskSurface) {

Просмотреть файл

@ -129,12 +129,10 @@ public:
/**
* Paint non-SVG frame with SVG effects.
* @param aOffset the offset in appunits where aFrame should be positioned
* in aCtx's coordinate system
*/
static void
PaintFramesWithEffects(nsRenderingContext* aCtx,
nsIFrame* aEffectsFrame, const nsRect& aDirtyRect,
nsIFrame* aFrame, const nsRect& aDirtyRect,
nsDisplayListBuilder* aBuilder,
nsDisplayList* aInnerList);

Просмотреть файл

@ -53,18 +53,14 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *aContext,
gfxContext *gfx = aContext->ThebesContext();
// Get the clip extents in device space:
gfx->Save();
nsSVGUtils::SetClipRect(gfx, aMatrix, maskArea);
gfx->IdentityMatrix();
gfxRect clipExtents = gfx->GetClipExtents();
clipExtents.RoundOut();
gfx->Restore();
#ifdef DEBUG_tor
fprintf(stderr, "clip extent: %f,%f %fx%f\n",
clipExtents.X(), clipExtents.Y(),
clipExtents.Width(), clipExtents.Height());
#endif
bool resultOverflows;
gfxIntSize surfaceSize =
nsSVGUtils::ConvertToSurfaceSize(gfxSize(clipExtents.Width(),
@ -82,10 +78,19 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *aContext,
new gfxImageSurface(surfaceSize, gfxASurface::ImageFormatARGB32);
if (!image || image->CairoStatus())
return nsnull;
image->SetDeviceOffset(-clipExtents.TopLeft());
// We would like to use gfxImageSurface::SetDeviceOffset() to position
// 'image'. However, we need to set the same matrix on the temporary context
// and pattern that we create below as is currently set on 'gfx'.
// Unfortunately, any device offset set by SetDeviceOffset() is affected by
// the transform passed to the SetMatrix() calls, so to avoid that we account
// for the device offset in the transform rather than use SetDeviceOffset().
gfxMatrix matrix =
gfx->CurrentMatrix() * gfxMatrix().Translate(-clipExtents.TopLeft());
nsRenderingContext tmpCtx;
tmpCtx.Init(this->PresContext()->DeviceContext(), image);
tmpCtx.ThebesContext()->SetMatrix(matrix);
mMaskParent = aParent;
if (mMaskParentMatrix) {
@ -132,6 +137,7 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *aContext,
}
gfxPattern *retval = new gfxPattern(image);
retval->SetMatrix(matrix);
NS_IF_ADDREF(retval);
return retval;
}

Просмотреть файл

@ -440,16 +440,16 @@ nsSVGOuterSVGFrame::DidReflow(nsPresContext* aPresContext,
//----------------------------------------------------------------------
// container methods
class nsDisplaySVG : public nsDisplayItem {
class nsDisplayOuterSVG : public nsDisplayItem {
public:
nsDisplaySVG(nsDisplayListBuilder* aBuilder,
nsSVGOuterSVGFrame* aFrame) :
nsDisplayOuterSVG(nsDisplayListBuilder* aBuilder,
nsSVGOuterSVGFrame* aFrame) :
nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplaySVG);
MOZ_COUNT_CTOR(nsDisplayOuterSVG);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplaySVG() {
MOZ_COUNT_DTOR(nsDisplaySVG);
virtual ~nsDisplayOuterSVG() {
MOZ_COUNT_DTOR(nsDisplayOuterSVG);
}
#endif
@ -457,12 +457,12 @@ public:
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("SVGEventReceiver", TYPE_SVG_EVENT_RECEIVER)
NS_DISPLAY_DECL_NAME("SVGOuterSVG", TYPE_SVG_OUTER_SVG)
};
void
nsDisplaySVG::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
nsDisplayOuterSVG::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
nsSVGOuterSVGFrame *outerSVGFrame = static_cast<nsSVGOuterSVGFrame*>(mFrame);
nsRect rectAtOrigin = aRect - ToReferenceFrame();
@ -482,20 +482,17 @@ nsDisplaySVG::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
}
void
nsDisplaySVG::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aContext)
nsDisplayOuterSVG::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aContext)
{
nsSVGOuterSVGFrame *frame = static_cast<nsSVGOuterSVGFrame*>(mFrame);
if (frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)
return;
#if defined(DEBUG) && defined(SVG_DEBUG_PAINT_TIMING)
PRTime start = PR_Now();
#endif
aContext->PushState();
nsSVGOuterSVGFrame *frame = static_cast<nsSVGOuterSVGFrame*>(mFrame);
#ifdef XP_MACOSX
if (frame->BitmapFallbackEnabled()) {
// nquartz fallback paths, which svg tends to trigger, need
@ -504,7 +501,14 @@ nsDisplaySVG::Paint(nsDisplayListBuilder* aBuilder,
}
#endif
frame->Paint(aBuilder, aContext, mVisibleRect, ToReferenceFrame());
nsRect viewportRect =
frame->GetContentRectRelativeToSelf() + ToReferenceFrame();
nsRect clipRect = mVisibleRect.Intersect(viewportRect);
aContext->IntersectClip(clipRect);
aContext->Translate(viewportRect.TopLeft());
frame->Paint(aBuilder, aContext, clipRect - viewportRect.TopLeft());
#ifdef XP_MACOSX
if (frame->BitmapFallbackEnabled()) {
@ -619,13 +623,17 @@ nsSVGOuterSVGFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) {
return NS_OK;
}
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
nsDisplayList replacedContent;
rv = replacedContent.AppendNewToTop(
new (aBuilder) nsDisplaySVG(aBuilder, this));
new (aBuilder) nsDisplayOuterSVG(aBuilder, this));
NS_ENSURE_SUCCESS(rv, rv);
WrapReplacedContentForBorderRadius(aBuilder, &replacedContent, aLists);
@ -636,20 +644,8 @@ nsSVGOuterSVGFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
void
nsSVGOuterSVGFrame::Paint(const nsDisplayListBuilder* aBuilder,
nsRenderingContext* aContext,
const nsRect& aDirtyRect, nsPoint aPt)
const nsRect& aDirtyRect)
{
nsRect viewportRect = GetContentRect();
nsPoint viewportOffset = aPt + viewportRect.TopLeft() - GetPosition();
viewportRect.MoveTo(viewportOffset);
nsRect clipRect;
clipRect.IntersectRect(aDirtyRect, viewportRect);
aContext->IntersectClip(clipRect);
aContext->Translate(viewportRect.TopLeft());
nsRect dirtyRect = clipRect - viewportOffset;
nsIntRect dirtyPxRect = dirtyRect.ToOutsidePixels(PresContext()->AppUnitsPerDevPixel());
// Create an SVGAutoRenderState so we can call SetPaintingToWindow on
// it, but don't change the render mode:
SVGAutoRenderState state(aContext, SVGAutoRenderState::GetRenderMode(aContext));
@ -658,6 +654,10 @@ nsSVGOuterSVGFrame::Paint(const nsDisplayListBuilder* aBuilder,
state.SetPaintingToWindow(true);
}
// Convert the (content area relative) dirty rect to dev pixels:
nsIntRect dirtyPxRect =
aDirtyRect.ToOutsidePixels(PresContext()->AppUnitsPerDevPixel());
nsSVGUtils::PaintFrameWithEffects(aContext, &dirtyPxRect, this);
}

Просмотреть файл

@ -67,7 +67,7 @@ public:
void Paint(const nsDisplayListBuilder* aBuilder,
nsRenderingContext* aContext,
const nsRect& aDirtyRect, nsPoint aPt);
const nsRect& aDirtyRect);
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const

Просмотреть файл

@ -220,6 +220,15 @@ public class AwesomeBar extends GeckoActivity implements GeckoEventListener {
}
});
mText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
});
registerForContextMenu(mAwesomeTabs.findViewById(R.id.all_pages_list));
registerForContextMenu(mAwesomeTabs.findViewById(R.id.bookmarks_list));
registerForContextMenu(mAwesomeTabs.findViewById(R.id.history_list));
@ -353,6 +362,11 @@ public class AwesomeBar extends GeckoActivity implements GeckoEventListener {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Galaxy Note sends key events for the stylus that are outside of the
// valid keyCode range (see bug 758427)
if (keyCode > KeyEvent.getMaxKeyCode())
return true;
// This method is called only if the key event was not handled
// by any of the views, which usually means the edit box lost focus
if (keyCode == KeyEvent.KEYCODE_BACK ||

Просмотреть файл

@ -68,6 +68,7 @@ public class AwesomeBarTabs extends TabHost {
private boolean mInflated;
private LayoutInflater mInflater;
private OnUrlOpenListener mUrlOpenListener;
private View.OnTouchListener mListTouchListener;
private ContentResolver mContentResolver;
private ContentObserver mContentObserver;
private SearchEngine mSuggestEngine;
@ -886,6 +887,14 @@ public class AwesomeBarTabs extends TabHost {
// to the TabHost.
setup();
mListTouchListener = new View.OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN)
hideSoftInput(view);
return false;
}
};
addAllPagesTab();
addBookmarksTab();
addHistoryTab();
@ -974,6 +983,7 @@ public class AwesomeBarTabs extends TabHost {
});
allPagesList.setAdapter(mAllPagesCursorAdapter);
allPagesList.setOnTouchListener(mListTouchListener);
}
private void addBookmarksTab() {
@ -984,6 +994,7 @@ public class AwesomeBarTabs extends TabHost {
R.id.bookmarks_list);
ListView bookmarksList = (ListView) findViewById(R.id.bookmarks_list);
bookmarksList.setOnTouchListener(mListTouchListener);
// Only load bookmark list when tab is actually used.
// See OnTabChangeListener above.
@ -997,6 +1008,7 @@ public class AwesomeBarTabs extends TabHost {
R.id.history_list);
ListView historyList = (ListView) findViewById(R.id.history_list);
historyList.setOnTouchListener(mListTouchListener);
// Only load history list when tab is actually used.
// See OnTabChangeListener above.
@ -1224,16 +1236,4 @@ public class AwesomeBarTabs extends TabHost {
public boolean isInReadingList() {
return mInReadingList;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// we should only have to hide the soft keyboard once - when the user
// initially touches the screen
if (ev.getAction() == MotionEvent.ACTION_DOWN)
hideSoftInput(this);
// the android docs make no sense, but returning false will cause this and other
// motion events to be sent to the view the user tapped on
return false;
}
}

Просмотреть файл

@ -2152,7 +2152,7 @@ abstract public class GeckoApp
return uri;
final String action = intent.getAction();
if (action.startsWith(ACTION_WEBAPP_PREFIX) || ACTION_BOOKMARK.equals(action)) {
if ((action != null && action.startsWith(ACTION_WEBAPP_PREFIX)) || ACTION_BOOKMARK.equals(action)) {
uri = intent.getStringExtra("args");
if (uri != null && uri.startsWith("--url=")) {
uri.replace("--url=", "");

Просмотреть файл

@ -876,6 +876,9 @@ public class GeckoInputConnection
+ isPreIme + ")");
}
if (keyCode > KeyEvent.getMaxKeyCode())
return false;
clampSelection();
switch (keyCode) {
@ -935,6 +938,9 @@ public class GeckoInputConnection
+ isPreIme + ")");
}
if (keyCode > KeyEvent.getMaxKeyCode())
return false;
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_SEARCH:

Просмотреть файл

@ -73,9 +73,12 @@ public class GeckoThread extends Thread {
// find the right intent type
final String action = mIntent.getAction();
String type = action.startsWith(GeckoApp.ACTION_WEBAPP_PREFIX) ? "-webapp" :
GeckoApp.ACTION_BOOKMARK.equals(action) ? "-bookmark" :
null;
String type = null;
if (action != null && action.startsWith(GeckoApp.ACTION_WEBAPP_PREFIX))
type = "-webapp";
else if (GeckoApp.ACTION_BOOKMARK.equals(action))
type = "-bookmark";
String args = mIntent.getStringExtra("args");

Просмотреть файл

@ -68,11 +68,6 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2<Activity> {
setActivityIntent(i);
mActivity = getActivity();
// Set up Robotium.solo and Driver objects
mSolo = new Solo(getInstrumentation());
mDriver = new FennecNativeDriver(mActivity, mSolo);
mActions = new FennecNativeActions(mActivity, mSolo, getInstrumentation());
mLogFile = (String)config.get("logfile");
mBaseUrl = ((String)config.get("host")).replaceAll("(/$)", "");
mRawBaseUrl = ((String)config.get("rawhost")).replaceAll("(/$)", "");
@ -85,6 +80,11 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2<Activity> {
}
mAsserter.setLogFile(mLogFile);
mAsserter.setTestName(this.getClass().getName());
// Set up Robotium.solo and Driver objects
mSolo = new Solo(getInstrumentation());
mDriver = new FennecNativeDriver(mActivity, mSolo);
mActions = new FennecNativeActions(mActivity, mSolo, getInstrumentation(), mAsserter);
}
@Override

Просмотреть файл

@ -1384,6 +1384,7 @@ var SelectionHandler = {
// Keeps track of data about the dimensions of the selection
cache: null,
_active: false,
_viewOffset: null,
// The window that holds the selection (can be a sub-frame)
get _view() {
@ -1427,17 +1428,31 @@ var SelectionHandler = {
init: function sh_init() {
Services.obs.addObserver(this, "Gesture:SingleTap", false);
Services.obs.addObserver(this, "Window:Resize", false);
},
uninit: function sh_uninit() {
Services.obs.removeObserver(this, "Gesture:SingleTap", false);
Services.obs.removeObserver(this, "Window:Resize", false);
},
observe: function sh_observe(aSubject, aTopic, aData) {
let data = JSON.parse(aData);
switch (aTopic) {
case "Gesture:SingleTap": {
if (!this._active)
return;
if (this._active)
this.endSelection(data.x, data.y);
let data = JSON.parse(aData);
this.endSelection(data.x, data.y);
break;
}
case "Window:Resize": {
// Knowing when the page is done drawing is hard, so let's just cancel
// the selection when the window changes. We should fix this later.
this.endSelection();
break;
}
}
},
notifySelectionChanged: function sh_notifySelectionChanged(aDoc, aSel, aReason) {
@ -1463,6 +1478,10 @@ var SelectionHandler = {
this._view = aElement.ownerDocument.defaultView;
this._isRTL = (this._view.getComputedStyle(aElement, "").direction == "rtl");
let computedStyle = this._view.getComputedStyle(this._view.document.documentElement);
this._viewOffset = { top: parseInt(computedStyle.getPropertyValue("margin-top").replace("px", "")),
left: parseInt(computedStyle.getPropertyValue("margin-left").replace("px", "")) };
// Remove any previous selected or created ranges. Tapping anywhere on a
// page will create an empty range.
let selection = this._view.getSelection();
@ -1577,11 +1596,11 @@ var SelectionHandler = {
// Update the handle position as it's dragged
if (aIsStartHandle) {
this._start.style.left = aX + this._view.scrollX + "px";
this._start.style.top = aY + this._view.scrollY + "px";
this._start.style.left = aX + this._view.scrollX - this._viewOffset.left + "px";
this._start.style.top = aY + this._view.scrollY - this._viewOffset.top + "px";
} else {
this._end.style.left = aX + this._view.scrollX + "px";
this._end.style.top = aY + this._view.scrollY + "px";
this._end.style.left = aX + this._view.scrollX - this._viewOffset.left + "px";
this._end.style.top = aY + this._view.scrollY - this._viewOffset.top + "px";
}
let cwu = this._view.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
@ -1696,6 +1715,7 @@ var SelectionHandler = {
this._isRTL = false;
this._view = null;
this._viewOffset = null;
this.cache = null;
return selectedText;
@ -1744,11 +1764,11 @@ var SelectionHandler = {
// Adjust start/end positions to account for scroll, and account for the dimensions of the
// handle elements to ensure the handles point exactly at the ends of the selection.
positionHandles: function sh_positionHandles() {
this._start.style.left = (this.cache.start.x + this._view.scrollX - this.HANDLE_WIDTH - this.HANDLE_PADDING) + "px";
this._start.style.top = (this.cache.start.y + this._view.scrollY - this.HANDLE_VERTICAL_OFFSET) + "px";
this._start.style.left = (this.cache.start.x + this._view.scrollX - this._viewOffset.left - this.HANDLE_WIDTH - this.HANDLE_PADDING) + "px";
this._start.style.top = (this.cache.start.y + this._view.scrollY - this._viewOffset.top - this.HANDLE_VERTICAL_OFFSET) + "px";
this._end.style.left = (this.cache.end.x + this._view.scrollX - this.HANDLE_PADDING) + "px";
this._end.style.top = (this.cache.end.y + this._view.scrollY - this.HANDLE_VERTICAL_OFFSET) + "px";
this._end.style.left = (this.cache.end.x + this._view.scrollX - this._viewOffset.left - this.HANDLE_PADDING) + "px";
this._end.style.top = (this.cache.end.y + this._view.scrollY - this._viewOffset.top - this.HANDLE_VERTICAL_OFFSET) + "px";
},
showHandles: function sh_showHandles() {

Просмотреть файл

@ -49,6 +49,7 @@ nsHttpConnection::nsHttpConnection()
, mTotalBytesWritten(0)
, mKeepAlive(true) // assume to keep-alive by default
, mKeepAliveMask(true)
, mDontReuse(false)
, mSupportsPipelining(false) // assume low-grade server
, mIsReused(false)
, mCompletedProxyConnect(false)
@ -516,6 +517,7 @@ nsHttpConnection::DontReuse()
{
mKeepAliveMask = false;
mKeepAlive = false;
mDontReuse = true;
mIdleTimeout = 0;
if (mSpdySession)
mSpdySession->DontReuse();
@ -532,12 +534,15 @@ nsHttpConnection::SupportsPipelining()
this, mTransaction->PipelineDepth(), mRemainingConnectionUses));
return false;
}
return mSupportsPipelining && IsKeepAlive();
return mSupportsPipelining && IsKeepAlive() && !mDontReuse;
}
bool
nsHttpConnection::CanReuse()
{
if (mDontReuse)
return false;
if ((mTransaction ? mTransaction->PipelineDepth() : 0) >=
mRemainingConnectionUses) {
return false;

Просмотреть файл

@ -217,6 +217,7 @@ private:
bool mKeepAlive;
bool mKeepAliveMask;
bool mDontReuse;
bool mSupportsPipelining;
bool mIsReused;
bool mCompletedProxyConnect;

Просмотреть файл

@ -15,6 +15,9 @@
#include "nsISocketProvider.h"
#include "nsSOCKSIOLayer.h"
#include "nsNetCID.h"
#include "nsIDNSListener.h"
#include "nsICancelable.h"
#include "nsThreadUtils.h"
static PRDescIdentity nsSOCKSIOLayerIdentity;
static PRIOMethods nsSOCKSIOLayerMethods;
@ -31,9 +34,12 @@ static PRLogModuleInfo *gSOCKSLog;
#endif
class nsSOCKSSocketInfo : public nsISOCKSSocketInfo
, public nsIDNSListener
{
enum State {
SOCKS_INITIAL,
SOCKS_DNS_IN_PROGRESS,
SOCKS_DNS_COMPLETE,
SOCKS_CONNECTING_TO_PROXY,
SOCKS4_WRITE_CONNECT_REQUEST,
SOCKS4_READ_CONNECT_RESPONSE,
@ -57,6 +63,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSISOCKSSOCKETINFO
NS_DECL_NSIDNSLISTENER
void Init(PRInt32 version,
const char *proxyHost,
@ -71,6 +78,7 @@ public:
private:
void HandshakeFinished(PRErrorCode err = 0);
PRStatus StartDNS(PRFileDesc *fd);
PRStatus ConnectToProxy(PRFileDesc *fd);
PRStatus ContinueConnectingToProxy(PRFileDesc *fd, PRInt16 oflags);
PRStatus WriteV4ConnectRequest();
@ -106,7 +114,10 @@ private:
PRUint32 mDataLength;
PRUint32 mReadOffset;
PRUint32 mAmountToRead;
nsCOMPtr<nsIDNSRecord> mDnsRec;
nsCOMPtr<nsIDNSRecord> mDnsRec;
nsCOMPtr<nsICancelable> mLookup;
nsresult mLookupStatus;
PRFileDesc *mFD;
nsCString mDestinationHost;
nsCString mProxyHost;
@ -146,7 +157,7 @@ nsSOCKSSocketInfo::Init(PRInt32 version, const char *proxyHost, PRInt32 proxyPor
mFlags = flags;
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsSOCKSSocketInfo, nsISOCKSSocketInfo)
NS_IMPL_THREADSAFE_ISUPPORTS2(nsSOCKSSocketInfo, nsISOCKSSocketInfo, nsIDNSListener)
NS_IMETHODIMP
nsSOCKSSocketInfo::GetExternalProxyAddr(PRNetAddr * *aExternalProxyAddr)
@ -214,6 +225,50 @@ nsSOCKSSocketInfo::HandshakeFinished(PRErrorCode err)
mDataLength = 0;
mReadOffset = 0;
mAmountToRead = 0;
if (mLookup) {
mLookup->Cancel(NS_ERROR_FAILURE);
mLookup = nsnull;
}
}
PRStatus
nsSOCKSSocketInfo::StartDNS(PRFileDesc *fd)
{
NS_ABORT_IF_FALSE(!mDnsRec && mState == SOCKS_INITIAL,
"Must be in initial state to make DNS Lookup");
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
if (!dns)
return PR_FAILURE;
mFD = fd;
nsresult rv = dns->AsyncResolve(mProxyHost, 0, this,
NS_GetCurrentThread(),
getter_AddRefs(mLookup));
if (NS_FAILED(rv)) {
LOGERROR(("socks: DNS lookup for SOCKS proxy %s failed",
mProxyHost.get()));
return PR_FAILURE;
}
mState = SOCKS_DNS_IN_PROGRESS;
PR_SetError(PR_IN_PROGRESS_ERROR, 0);
return PR_FAILURE;
}
NS_IMETHODIMP
nsSOCKSSocketInfo::OnLookupComplete(nsICancelable *aRequest,
nsIDNSRecord *aRecord,
nsresult aStatus)
{
NS_ABORT_IF_FALSE(aRequest == mLookup, "wrong DNS query");
mLookup = nsnull;
mLookupStatus = aStatus;
mDnsRec = aRecord;
mState = SOCKS_DNS_COMPLETE;
ConnectToProxy(mFD);
mFD = nsnull;
return NS_OK;
}
PRStatus
@ -222,21 +277,12 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFileDesc *fd)
PRStatus status;
nsresult rv;
NS_ABORT_IF_FALSE(mState == SOCKS_INITIAL,
"Must be in initial state to make connection!");
NS_ABORT_IF_FALSE(mState == SOCKS_DNS_COMPLETE,
"Must have DNS to make connection!");
// If we haven't performed the DNS lookup, do that now.
if (!mDnsRec) {
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
if (!dns)
return PR_FAILURE;
rv = dns->Resolve(mProxyHost, 0, getter_AddRefs(mDnsRec));
if (NS_FAILED(rv)) {
LOGERROR(("socks: DNS lookup for SOCKS proxy %s failed",
mProxyHost.get()));
return PR_FAILURE;
}
if (NS_FAILED(mLookupStatus)) {
PR_SetError(PR_BAD_ADDRESS_ERROR, 0);
return PR_FAILURE;
}
PRInt32 addresses = 0;
@ -291,7 +337,7 @@ nsSOCKSSocketInfo::ContinueConnectingToProxy(PRFileDesc *fd, PRInt16 oflags)
PRErrorCode c = PR_GetError();
if (c != PR_WOULD_BLOCK_ERROR && c != PR_IN_PROGRESS_ERROR) {
// A connection failure occured, try another address
mState = SOCKS_INITIAL;
mState = SOCKS_DNS_COMPLETE;
return ConnectToProxy(fd);
}
@ -634,6 +680,11 @@ nsSOCKSSocketInfo::DoHandshake(PRFileDesc *fd, PRInt16 oflags)
switch (mState) {
case SOCKS_INITIAL:
return StartDNS(fd);
case SOCKS_DNS_IN_PROGRESS:
PR_SetError(PR_IN_PROGRESS_ERROR, 0);
return PR_FAILURE;
case SOCKS_DNS_COMPLETE:
return ConnectToProxy(fd);
case SOCKS_CONNECTING_TO_PROXY:
return ContinueConnectingToProxy(fd, oflags);
@ -696,6 +747,8 @@ PRInt16
nsSOCKSSocketInfo::GetPollFlags() const
{
switch (mState) {
case SOCKS_DNS_IN_PROGRESS:
case SOCKS_DNS_COMPLETE:
case SOCKS_CONNECTING_TO_PROXY:
return PR_POLL_EXCEPT | PR_POLL_WRITE;
case SOCKS4_WRITE_CONNECT_REQUEST:
@ -1139,7 +1192,7 @@ nsSOCKSIOLayerAddToSocket(PRInt32 family,
return NS_ERROR_FAILURE;
}
*info = infoObject;
*info = static_cast<nsISOCKSSocketInfo*>(infoObject);
NS_ADDREF(*info);
return NS_OK;
}

Просмотреть файл

@ -2879,8 +2879,13 @@ nsDownload::OpenWithApplication()
// Even if we are unable to get this service we return the result
// of LaunchWithFile() which makes more sense.
if (appLauncher)
(void)appLauncher->DeleteTemporaryFileOnExit(target);
if (appLauncher) {
if (nsDownloadManager::gDownloadManagerService->mInPrivateBrowsing) {
(void)appLauncher->DeleteTemporaryPrivateFileWhenPossible(target);
} else {
(void)appLauncher->DeleteTemporaryFileOnExit(target);
}
}
}
return retVal;

Просмотреть файл

@ -65,6 +65,8 @@ const IDLE_TIMEOUT_SECONDS = 5 * 60;
var gLastMemoryPoll = null;
let gWasDebuggerAttached = false;
function getLocale() {
return Cc["@mozilla.org/chrome/chrome-registry;1"].
getService(Ci.nsIXULChromeRegistry).
@ -121,6 +123,12 @@ function getSimpleMeasurements() {
ret.startupInterrupted = new Number(Services.startup.interrupted);
// Update debuggerAttached flag
let debugService = Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2);
let isDebuggerAttached = debugService.isDebuggerAttached;
gWasDebuggerAttached = gWasDebuggerAttached || isDebuggerAttached;
ret.debuggerAttached = new Number(gWasDebuggerAttached);
ret.js = Cc["@mozilla.org/js/xpc/XPConnect;1"]
.getService(Ci.nsIJSEngineTelemetryStats)
.telemetryValue;
@ -776,6 +784,9 @@ TelemetryPing.prototype = {
case "sessionstore-windows-restored":
Services.obs.removeObserver(this, "sessionstore-windows-restored");
this._hasWindowRestoredObserver = false;
// Check whether debugger was attached during startup
let debugService = Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2);
gWasDebuggerAttached = debugService.isDebuggerAttached;
// fall through
case "test-gather-startup":
this.gatherStartupInformation();

Просмотреть файл

@ -119,10 +119,28 @@ var gViewSourceUtils = {
webBrowserPersist.progressListener = this.viewSourceProgressListener;
webBrowserPersist.saveURI(uri, null, null, null, null, file);
// register the file to be deleted on app exit
Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
.getService(Components.interfaces.nsPIExternalAppLauncher)
.deleteTemporaryFileOnExit(file);
let fromPrivateWindow = false;
if (aDocument) {
try {
fromPrivateWindow =
aDocument.defaultView
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsILoadContext)
.usePrivateBrowsing;
} catch (e) {
}
}
let helperService = Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
.getService(Components.interfaces.nsPIExternalAppLauncher);
if (fromPrivateWindow) {
// register the file to be deleted when possible
helperService.deleteTemporaryPrivateFileWhenPossible(file);
} else {
// register the file to be deleted on app exit
helperService.deleteTemporaryFileOnExit(file);
}
} else {
// we'll use nsIWebPageDescriptor to get the source because it may
// not have to refetch the file from the server
@ -264,10 +282,22 @@ var gViewSourceUtils = {
coStream.close();
foStream.close();
// register the file to be deleted on app exit
Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
.getService(Components.interfaces.nsPIExternalAppLauncher)
.deleteTemporaryFileOnExit(this.file);
let fromPrivateWindow =
this.data.doc.defaultView
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsILoadContext)
.usePrivateBrowsing;
let helperService = Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
.getService(Components.interfaces.nsPIExternalAppLauncher);
if (fromPrivateWindow) {
// register the file to be deleted when possible
helperService.deleteTemporaryPrivateFileWhenPossible(this.file);
} else {
// register the file to be deleted on app exit
helperService.deleteTemporaryFileOnExit(this.file);
}
}
var editorArgs = gViewSourceUtils.buildEditorArgs(this.file.path,

Просмотреть файл

@ -298,6 +298,13 @@ public:
b.DefineProperty(sample, "frames", frames);
b.ArrayPush(samples, sample);
break;
case 'r':
{
if (sample) {
b.DefineProperty(sample, "responsiveness", entry.mTagFloat);
}
}
break;
case 'c':
case 'l':
{

Просмотреть файл

@ -100,14 +100,13 @@
#include "plbase64.h"
#include "prmem.h"
#include "nsIPrivateBrowsingService.h"
#include "ContentChild.h"
#include "nsXULAppAPI.h"
#include "nsPIDOMWindow.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDocShellTreeItem.h"
#include "ExternalHelperAppChild.h"
#include "nsILoadContext.h"
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
@ -504,18 +503,11 @@ NS_IMPL_ISUPPORTS6(
nsIObserver,
nsISupportsWeakReference)
nsExternalHelperAppService::nsExternalHelperAppService() :
mInPrivateBrowsing(false)
nsExternalHelperAppService::nsExternalHelperAppService()
{
}
nsresult nsExternalHelperAppService::Init()
{
nsCOMPtr<nsIPrivateBrowsingService> pbs =
do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
if (pbs) {
pbs->GetPrivateBrowsingEnabled(&mInPrivateBrowsing);
}
// Add an observer for profile change
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (!obs)
@ -531,7 +523,7 @@ nsresult nsExternalHelperAppService::Init()
nsresult rv = obs->AddObserver(this, "profile-before-change", true);
NS_ENSURE_SUCCESS(rv, rv);
return obs->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, true);
return obs->AddObserver(this, "last-pb-context-exited", true);
}
nsExternalHelperAppService::~nsExternalHelperAppService()
@ -923,7 +915,10 @@ NS_IMETHODIMP nsExternalHelperAppService::GetApplicationDescription(const nsACSt
// Methods related to deleting temporary files on exit
//////////////////////////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP nsExternalHelperAppService::DeleteTemporaryFileOnExit(nsIFile * aTemporaryFile)
/* static */
nsresult
nsExternalHelperAppService::DeleteTemporaryFileHelper(nsIFile * aTemporaryFile,
nsCOMArray<nsIFile> &aFileList)
{
bool isFile = false;
@ -931,14 +926,23 @@ NS_IMETHODIMP nsExternalHelperAppService::DeleteTemporaryFileOnExit(nsIFile * aT
aTemporaryFile->IsFile(&isFile);
if (!isFile) return NS_OK;
if (mInPrivateBrowsing)
mTemporaryPrivateFilesList.AppendObject(aTemporaryFile);
else
mTemporaryFilesList.AppendObject(aTemporaryFile);
aFileList.AppendObject(aTemporaryFile);
return NS_OK;
}
NS_IMETHODIMP
nsExternalHelperAppService::DeleteTemporaryFileOnExit(nsIFile* aTemporaryFile)
{
return DeleteTemporaryFileHelper(aTemporaryFile, mTemporaryFilesList);
}
NS_IMETHODIMP
nsExternalHelperAppService::DeleteTemporaryPrivateFileWhenPossible(nsIFile* aTemporaryFile)
{
return DeleteTemporaryFileHelper(aTemporaryFile, mTemporaryPrivateFilesList);
}
void nsExternalHelperAppService::FixFilePermissions(nsIFile* aFile)
{
// This space intentionally left blank
@ -1052,13 +1056,8 @@ nsExternalHelperAppService::Observe(nsISupports *aSubject, const char *aTopic, c
{
if (!strcmp(aTopic, "profile-before-change")) {
ExpungeTemporaryFiles();
} else if (!strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC)) {
if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(someData))
mInPrivateBrowsing = true;
else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(someData)) {
mInPrivateBrowsing = false;
ExpungeTemporaryPrivateFiles();
}
} else if (!strcmp(aTopic, "last-pb-context-exited")) {
ExpungeTemporaryPrivateFiles();
}
return NS_OK;
}
@ -2180,9 +2179,21 @@ nsresult nsExternalAppHandler::OpenWithApplication()
false);
#endif
// See whether the channel has been opened in private browsing mode
bool inPrivateBrowsing = false;
NS_ASSERTION(mRequest, "This should never be called with a null request");
nsCOMPtr<nsIChannel> channel = do_QueryInterface(mRequest);
if (channel) {
nsCOMPtr<nsILoadContext> ctx;
NS_QueryNotificationCallbacks(channel, ctx);
if (ctx) {
inPrivateBrowsing = ctx->UsePrivateBrowsing();
}
}
// make the tmp file readonly so users won't edit it and lose the changes
// only if we're going to delete the file
if (deleteTempFileOnExit || mExtProtSvc->InPrivateBrowsing())
if (deleteTempFileOnExit || inPrivateBrowsing)
mFinalFileDestination->SetPermissions(0400);
rv = mMimeInfo->LaunchWithFile(mFinalFileDestination);
@ -2196,9 +2207,12 @@ nsresult nsExternalAppHandler::OpenWithApplication()
}
// Always schedule files to be deleted at the end of the private browsing
// mode, regardless of the value of the pref.
else if (deleteTempFileOnExit || mExtProtSvc->InPrivateBrowsing()) {
else if (deleteTempFileOnExit) {
mExtProtSvc->DeleteTemporaryFileOnExit(mFinalFileDestination);
}
else if (inPrivateBrowsing) {
mExtProtSvc->DeleteTemporaryPrivateFileWhenPossible(mFinalFileDestination);
}
}
return rv;

Просмотреть файл

@ -111,12 +111,6 @@ public:
virtual NS_HIDDEN_(nsresult) OSProtocolHandlerExists(const char *aScheme,
bool *aExists) = 0;
/**
* Simple accessor to let nsExternalAppHandler know if we are currently
* inside the private browsing mode.
*/
bool InPrivateBrowsing() const { return mInPrivateBrowsing; }
protected:
/**
* Searches the "extra" array of MIMEInfo objects for an object
@ -172,6 +166,11 @@ protected:
* Helper function for ExpungeTemporaryFiles and ExpungeTemporaryPrivateFiles
*/
static void ExpungeTemporaryFilesHelper(nsCOMArray<nsIFile> &fileList);
/**
* Helper function for DeleteTemporaryFileOnExit and DeleteTemporaryPrivateFileWhenPossible
*/
static nsresult DeleteTemporaryFileHelper(nsIFile* aTemporaryFile,
nsCOMArray<nsIFile> &aFileList);
/**
* Functions related to the tempory file cleanup service provided by
* nsExternalHelperAppService
@ -192,10 +191,6 @@ protected:
* added during the private browsing mode)
*/
nsCOMArray<nsIFile> mTemporaryPrivateFilesList;
/**
* Whether we are in private browsing mode
*/
bool mInPrivateBrowsing;
};
/**

Просмотреть файл

@ -53,7 +53,7 @@ interface nsIExternalHelperAppService : nsISupports
* This is a private interface shared between external app handlers and the platform specific
* external helper app service
*/
[scriptable, uuid(d0b5d7d3-9565-403d-9fb5-e5089c4567c6)]
[scriptable, uuid(6613e2e7-feab-4e3a-bb1f-b03200d544ec)]
interface nsPIExternalAppLauncher : nsISupports
{
/**
@ -62,6 +62,11 @@ interface nsPIExternalAppLauncher : nsISupports
* @param aTemporaryFile A temporary file we should delete on exit.
*/
void deleteTemporaryFileOnExit(in nsIFile aTemporaryFile);
/**
* Delete a temporary file created inside private browsing mode when
* the private browsing mode has ended.
*/
void deleteTemporaryPrivateFileWhenPossible(in nsIFile aTemporaryFile);
};
/**

Просмотреть файл

@ -178,6 +178,10 @@ nsIdleServiceDaily::~nsIdleServiceDaily()
void
nsIdleServiceDaily::DailyCallback(nsITimer* aTimer, void* aClosure)
{
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "IdleService", "DailyCallback running, registering Idle observer");
#endif
nsIdleServiceDaily* me = static_cast<nsIdleServiceDaily*>(aClosure);
// The one thing we do every day is to start waiting for the user to "have

Просмотреть файл

@ -43,6 +43,13 @@
#include "nsString.h"
#endif
#if defined(XP_MACOSX)
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>
#endif
#include "mozilla/mozalloc_abort.h"
static void
@ -136,6 +143,40 @@ nsDebugImpl::GetAssertionCount(PRInt32* aResult)
return NS_OK;
}
NS_IMETHODIMP
nsDebugImpl::GetIsDebuggerAttached(bool* aResult)
{
*aResult = false;
#if defined(XP_WIN)
*aResult = ::IsDebuggerPresent();
#elif defined(XP_MACOSX)
// Specify the info we're looking for
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getpid();
size_t mibSize = sizeof(mib) / sizeof(int);
struct kinfo_proc info;
size_t infoSize = sizeof(info);
memset(&info, 0, infoSize);
if (sysctl(mib, mibSize, &info, &infoSize, NULL, 0)) {
// if the call fails, default to false
*aResult = false;
return NS_OK;
}
if (info.kp_proc.p_flag & P_TRACED) {
*aResult = true;
}
#endif
return NS_OK;
}
/* static */ void
nsDebugImpl::SetMultiprocessMode(const char *aDesc)
{

Просмотреть файл

@ -7,7 +7,7 @@
#include "nsIDebug.idl"
[scriptable, uuid(9c9307ed-480a-4f2a-8f29-21378c03bcbc)]
[scriptable, uuid(6cb17fec-cdf7-4f7c-b267-37a0acaa9cf1)]
interface nsIDebug2 : nsIDebug
{
/**
@ -21,4 +21,10 @@ interface nsIDebug2 : nsIDebug
* The number of assertions since process start.
*/
readonly attribute long assertionCount;
/**
* Whether a debugger is currently attached.
* Supports Windows + Mac
*/
readonly attribute bool isDebuggerAttached;
};