зеркало из https://github.com/mozilla/gecko-dev.git
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
68c7b298d0
|
@ -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, ¤tfp),
|
||||
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 ®s = 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;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче