Merge mozilla-central into electrolysis.

This commit is contained in:
Benjamin Smedberg 2009-12-15 20:31:04 -05:00
commit 83b97480d2
108 changed files with 2365 additions and 1363 deletions

View File

@ -408,6 +408,17 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eARIASelectable,
eARIAReadonly
},
{
"scrollbar",
nsIAccessibleRole::ROLE_SCROLLBAR,
kUseMapRole,
eHasValueMinMax,
eNoAction,
eNoLiveAttr,
kNoReqStates,
eARIAOrientation,
eARIAReadonly
},
{
"separator",
nsIAccessibleRole::ROLE_SEPARATOR,
@ -628,6 +639,11 @@ nsStateMapEntry nsARIAMap::gWAIStateMap[] = {
nsStateMapEntry(&nsAccessibilityAtoms::aria_multiselectable, kBoolType, 0,
nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE, 0),
// eARIAOrientation
nsStateMapEntry(&nsAccessibilityAtoms::aria_orientation, eUseFirstState,
"vertical", 0, nsIAccessibleStates::EXT_STATE_VERTICAL,
"horizontal", 0, nsIAccessibleStates::EXT_STATE_HORIZONTAL),
// eARIAPressed
nsStateMapEntry(&nsAccessibilityAtoms::aria_pressed, kMixedType,
nsIAccessibleStates::STATE_CHECKABLE,
@ -693,6 +709,7 @@ nsAttributeCharacteristics nsARIAMap::gWAIUnivAttrMap[] = {
{&nsAccessibilityAtoms::aria_multiline, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
{&nsAccessibilityAtoms::aria_multiselectable, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
{&nsAccessibilityAtoms::aria_owns, ATTR_BYPASSOBJ },
{&nsAccessibilityAtoms::aria_orientation, ATTR_VALTOKEN },
{&nsAccessibilityAtoms::aria_pressed, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
{&nsAccessibilityAtoms::aria_readonly, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
{&nsAccessibilityAtoms::aria_relevant, ATTR_BYPASSOBJ },
@ -749,6 +766,26 @@ nsStateMapEntry::nsStateMapEntry(nsIAtom **aAttrName,
{
}
nsStateMapEntry::nsStateMapEntry(nsIAtom **aAttrName,
EDefaultStateRule aDefaultStateRule,
const char *aValue1,
PRUint32 aState1, PRUint32 aExtraState1,
const char *aValue2,
PRUint32 aState2, PRUint32 aExtraState2,
const char *aValue3,
PRUint32 aState3, PRUint32 aExtraState3) :
attributeName(aAttrName), isToken(PR_TRUE), permanentState(0),
value1(aValue1), state1(aState1), extraState1(aExtraState1),
value2(aValue2), state2(aState2), extraState2(aExtraState2),
value3(aValue3), state3(aState3), extraState3(aExtraState3),
defaultState(0), defaultExtraState(0), definedIfAbsent(PR_TRUE)
{
if (aDefaultStateRule == eUseFirstState) {
defaultState = aState1;
defaultExtraState = aExtraState1;
}
}
PRBool
nsStateMapEntry::MapToStates(nsIContent *aContent,
PRUint32 *aState, PRUint32 *aExtraState,

View File

@ -157,6 +157,12 @@ enum eStateValueType
kMixedType
};
enum EDefaultStateRule
{
//eNoDefaultState,
eUseFirstState
};
/**
* ID for state map entry, used in nsRoleMapEntry.
*/
@ -174,6 +180,7 @@ enum eStateMapEntryID
eARIAInvalid,
eARIAMultiline,
eARIAMultiSelectable,
eARIAOrientation,
eARIAPressed,
eARIAReadonly,
eARIAReadonlyOrEditable,
@ -207,6 +214,17 @@ public:
const char *aValue3 = 0, PRUint32 aState3 = 0,
PRUint32 aExtraState3 = 0);
/**
* Used for ARIA attributes having enumerated values, and where a default
* attribute state should be assumed when not supplied by the author.
*/
nsStateMapEntry(nsIAtom **aAttrName,
EDefaultStateRule aDefaultStateRule,
const char *aValue1, PRUint32 aState1, PRUint32 aExtraState1,
const char *aValue2, PRUint32 aState2, PRUint32 aExtraState2,
const char *aValue3 = 0, PRUint32 aState3 = 0,
PRUint32 aExtraState3 = 0);
/**
* Maps ARIA state map pointed by state map entry ID to accessible states.
*

View File

@ -241,6 +241,7 @@ ACCESSIBILITY_ATOM(aria_level, "aria-level")
ACCESSIBILITY_ATOM(aria_live, "aria-live")
ACCESSIBILITY_ATOM(aria_multiline, "aria-multiline")
ACCESSIBILITY_ATOM(aria_multiselectable, "aria-multiselectable")
ACCESSIBILITY_ATOM(aria_orientation, "aria-orientation")
ACCESSIBILITY_ATOM(aria_owns, "aria-owns")
ACCESSIBILITY_ATOM(aria_posinset, "aria-posinset")
ACCESSIBILITY_ATOM(aria_pressed, "aria-pressed")

View File

@ -79,6 +79,7 @@ const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
////////////////////////////////////////////////////////////////////////////////
// OS detect

View File

@ -44,6 +44,7 @@ const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON;
const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR;
const ROLE_SECTION = nsIAccessibleRole.ROLE_SECTION;
const ROLE_SEPARATOR = nsIAccessibleRole.ROLE_SEPARATOR;
const ROLE_SLIDER = nsIAccessibleRole.ROLE_SLIDER;

View File

@ -3,6 +3,7 @@
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=481114
https://bugzilla.mozilla.org/show_bug.cgi?id=469688
https://bugzilla.mozilla.org/show_bug.cgi?id=529289
-->
<head>
<title>Test weak ARIA roles</title>
@ -63,6 +64,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=469688
for (a in abstract_roles)
testRole(abstract_roles[a], ROLE_SECTION);
// aria scrollbar
testRole("scrollbar", ROLE_SCROLLBAR);
SimpleTest.finish();
}
@ -74,6 +77,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=469688
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481114">Mozilla Bug 481114</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469688">Mozilla Bug 469688</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289">Mozilla Bug 529289</a>
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -134,5 +139,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=469688
<div role="section" id="section">section</div>
<div role="sectionhead" id="sectionhead">sectionhead</div>
<!-- aria scrollbar -->
<div role="scrollbar" id="scrollbar">scrollbar</div>
</body>
</html>

View File

@ -66,6 +66,7 @@
testValue("slider_vn", "5", 5, 0, 1000, 0);
testValue("slider_vnvt", "plain", 0, 0, 5, 0);
testValue("slider_vt", "hi", 0, 0, 3, 0);
testValue("scrollbar", "5", 5, 0, 1000, 0);
// Test value change events
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_VALUE_CHANGE);
@ -73,6 +74,7 @@
gQueue.push(new changeValue("slider_vn", "6", undefined));
gQueue.push(new changeValue("slider_vt", undefined, "hey!"));
gQueue.push(new changeValue("slider_vnvt", "3", "sweet"));
gQueue.push(new changeValue("scrollbar", "6", undefined));
gQueue.invoke(); // Will call SimpleTest.finish();
}
@ -89,6 +91,11 @@
title=" Fire delayed value changed event for aria-valuetext changes">
Mozilla Bug 478032
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289"
title="We dont expose new aria role 'scrollbar' and property aria-orientation">
Mozilla Bug 529289
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -98,12 +105,16 @@
<!-- ARIA sliders -->
<div id="slider_vn" role="slider" aria-valuenow="5"
aria-valuemin="0" aria-valuemax="1000">slider</div>
aria-valuemin="0" aria-valuemax="1000">slider</div>
<div id="slider_vt" role="slider" aria-valuetext="hi"
aria-valuemin="0" aria-valuemax="3">greeting slider</div>
aria-valuemin="0" aria-valuemax="3">greeting slider</div>
<div id="slider_vnvt" role="slider" aria-valuenow="0" aria-valuetext="plain"
aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
<!-- ARIA scrollbar -->
<div id="scrollbar" role="scrollbar" aria-valuenow="5"
aria-valuemin="0" aria-valuemax="1000">slider</div>
</body>
</html>

View File

@ -93,6 +93,11 @@
testStates("aria_main_anchor", STATE_SELECTABLE);
testStates("aria_navigation_anchor", STATE_SELECTABLE);
// scrollbar
testStates("aria_scrollbar", 0, EXT_STATE_VERTICAL);
testStates("aria_hscrollbar", 0, EXT_STATE_HORIZONTAL);
testStates("aria_vscrollbar", 0, EXT_STATE_VERTICAL);
SimpleTest.finish();
}
@ -183,5 +188,9 @@
<a id="aria_main_anchor" role="main" name="main_anchor">main</a>
<a id="aria_navigation_anchor" role="navigation" name="nav_anchor">nav</a>
<!-- scrollbar -->
<div id="aria_scrollbar" role="scrollbar">scrollbar</a>
<div id="aria_hscrollbar" role="scrollbar" aria-orientation="horizontal">horizontal scrollbar</a>
<div id="aria_vscrollbar" role="scrollbar" aria-orientation="vertical">vertical scrollbar</a>
</body>
</html>

View File

@ -311,8 +311,13 @@ pref("browser.microsummary.updateGenerators", true);
pref("browser.search.suggest.enabled", true);
pref("browser.sessionhistory.max_entries", 50);
#ifndef WINCE
pref("browser.history_expire_days", 180);
pref("browser.history_expire_days_min", 90);
#else
pref("browser.history_expire_days", 90);
pref("browser.history_expire_days_min", 45);
#endif
pref("browser.history_expire_sites", 40000);
// handle links targeting new windows

View File

@ -2292,7 +2292,7 @@ function SetPageProxyState(aState)
gLastValidURLStr = gURLBar.value;
gURLBar.addEventListener("input", UpdatePageProxyState, false);
PageProxySetIcon(gBrowser.selectedBrowser.mIconURL);
PageProxySetIcon(gBrowser.getIcon());
} else if (aState == "invalid") {
gURLBar.removeEventListener("input", UpdatePageProxyState, false);
PageProxyClearIcon();
@ -3913,9 +3913,9 @@ var XULBrowserWindow = {
}
},
onLinkIconAvailable: function (aBrowser) {
onLinkIconAvailable: function (aBrowser, aIconURL) {
if (gProxyFavIcon && gBrowser.userTypedValue === null)
PageProxySetIcon(aBrowser.mIconURL); // update the favicon in the URL bar
PageProxySetIcon(aIconURL); // update the favicon in the URL bar
},
onProgressChange: function (aWebProgress, aRequest,
@ -3980,7 +3980,7 @@ var XULBrowserWindow = {
if (aWebProgress.DOMWindow == content) {
if (aRequest)
this.endDocumentLoad(aRequest, aStatus);
if (!gBrowser.mTabbedMode && !gBrowser.selectedBrowser.mIconURL)
if (!gBrowser.mTabbedMode && !gBrowser.getIcon())
gBrowser.useDefaultIcon(gBrowser.selectedTab);
}
}

View File

@ -700,7 +700,7 @@
let p = this.mProgressListeners[i];
if ('onLinkIconAvailable' in p)
try {
p.onLinkIconAvailable(browser);
p.onLinkIconAvailable(browser, browser.mIconURL);
} catch (e) {
// don't inhibit other listeners
Components.utils.reportError(e);
@ -712,7 +712,7 @@
let p = this.mTabsProgressListeners[i];
if ('onLinkIconAvailable' in p)
try {
p.onLinkIconAvailable(browser);
p.onLinkIconAvailable(browser, browser.mIconURL);
} catch (e) {
// don't inhibit other listeners
Components.utils.reportError(e);
@ -722,6 +722,16 @@
</body>
</method>
<method name="getIcon">
<parameter name="aTab"/>
<body>
<![CDATA[
let browser = aTab ? this.getBrowserForTab(aTab) : this.selectedBrowser;
return browser.mIconURL;
]]>
</body>
</method>
<method name="updateIcon">
<parameter name="aTab"/>
<body>

View File

@ -76,7 +76,7 @@ function test() {
}
is(newWindow.gBrowser.selectedTab.hasAttribute("busy"), true);
is(newWindow.gBrowser.selectedTab.linkedBrowser.mIconURL,iconURLSpec);
is(newWindow.gBrowser.getIcon(), iconURLSpec);
newWindow.close();
finish();
}

View File

@ -316,6 +316,18 @@ BrowserGlue.prototype = {
// profile shutdown handler (contains profile cleanup routines)
_onProfileShutdown: function()
{
#ifdef WINCE
// If there's a pending update, clear cache to free up disk space.
try {
let um = Cc["@mozilla.org/updates/update-manager;1"].
getService(Ci.nsIUpdateManager);
if (um.activeUpdate && um.activeUpdate.state == "pending") {
let cacheService = Cc["@mozilla.org/network/cache-service;1"].
getService(Ci.nsICacheService);
cacheService.evictEntries(Ci.nsICache.STORE_ANYWHERE);
}
} catch (e) { }
#endif
this._shutdownPlaces();
this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
this._isIdleObserver = false;

View File

@ -102,7 +102,6 @@ function test() {
onSecurityChange: function() {},
onStatusChange: function() {},
onRefreshAttempted: function() {},
onLinkIconAvailable: function() {},
onStateChange: function(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
if (aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP |
Ci.nsIWebProgressListener.STATE_IS_WINDOW)) {

View File

@ -226,7 +226,7 @@ var gEngineManagerDialog = {
function onDragEngineStart(event) {
var selectedIndex = gEngineView.selectedIndex;
if (selectedIndex > 0) {
if (selectedIndex >= 0) {
event.dataTransfer.setData(ENGINE_FLAVOR, selectedIndex.toString());
event.dataTransfer.effectAllowed = "move";
}

View File

@ -443,7 +443,29 @@ function test() {
newWin.BrowserTryToCloseWindow();
newWin2.BrowserTryToCloseWindow();
browserWindowsCount([0, 1], "browser windows while running testOpenCloseRestoreFromPopup");
newWin = undoCloseWindow(0);
newWin.addEventListener("load", function () {
info(["testOpenCloseRestoreFromPopup: newWin loaded", newWin.closed, newWin.document]);
var ds = newWin.delayedStartup;
newWin.delayedStartup = function () {
info(["testOpenCloseRestoreFromPopup: newWin delayedStartup", newWin.closed, newWin.document]);
ds.apply(newWin, arguments);
};
}, false);
newWin.addEventListener("unload", function () {
info("testOpenCloseRestoreFromPopup: newWin unloaded");
/*
var data;
try {
data = Cc["@mozilla.org/browser/sessionstore;1"]
.getService(Ci.nsISessionStore)
.getWindowState(newWin);
} catch (e) { }
ok(!data, "getWindowState should not have data about newWin");
*/
}, false);
newWin2 = openDialog(location, "_blank", CHROME_FEATURES);
newWin2.addEventListener("load", function() {
@ -454,10 +476,14 @@ function test() {
is(TEST_URLS.indexOf(newWin2.gBrowser.browsers[0].currentURI.spec), -1,
"Did not restore, as undoCloseWindow() was last called (2)");
browserWindowsCount([2, 3], "browser windows while running testOpenCloseRestoreFromPopup");
// Cleanup
newWin.close();
newWin2.close();
browserWindowsCount([0, 1], "browser windows while running testOpenCloseRestoreFromPopup");
// Next please
executeSoon(nextFn);
});
@ -536,7 +562,7 @@ function test() {
browserWindowsCount([0, 1], "browser windows after testOpenCloseWindowAndPopup");
testOpenCloseOnlyPopup(function () {
browserWindowsCount([0, 1], "browser windows after testOpenCloseOnlyPopup");
testOpenCloseRestoreFromPopup (function () {
testOpenCloseRestoreFromPopup(function () {
browserWindowsCount([0, 1], "browser windows after testOpenCloseRestoreFromPopup");
testNotificationCount(function () {
cleanupTestsuite();

View File

@ -341,7 +341,7 @@ var WinTaskbarJumpList =
createInstance(Ci.nsILocalHandlerApp);
handlerApp.executable = file;
// handlers default to the leaf name if a name is not specified
if (name.length != 0)
if (name && name.length != 0)
handlerApp.name = name;
handlerApp.detailedDescription = description;
handlerApp.appendParameter(args);

View File

@ -517,9 +517,9 @@ TabWindow.prototype = {
},
onStatusChange: function () {
},
onLinkIconAvailable: function (aBrowser) {
onLinkIconAvailable: function (aBrowser, aIconURL) {
let self = this;
getFaviconAsImage(aBrowser.mIconURL, function (img) {
getFaviconAsImage(aIconURL, function (img) {
let index = self.tabbrowser.browsers.indexOf(aBrowser);
// Only add it if we've found the index. The tab could have closed!
if (index != -1)

View File

@ -90,7 +90,7 @@
#elifdef XP_OS2
@BINPATH@/plugins/npnulos2.dll
#endif
@BINPATH@/@DLL_PREFIX@sqlite3@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@mozsqlite3@DLL_SUFFIX@
@BINPATH@/README.txt
@BINPATH@/LICENSE
@BINPATH@/blocklist.xml

View File

@ -843,4 +843,5 @@ components/brwsrcmp.dll
components/nsUpdateService.js
components/nsUpdateServiceStub.js
#endif
@DLL_PREFIX@sqlite3@DLL_SUFFIX@
old-homepage-default.properties

View File

@ -74,7 +74,7 @@ _LEAKTEST_DIR = $(DEPTH)/_leaktest
_LEAKTEST_FILES = \
automation.py \
$(CURDIR)/automationutils.py \
automationutils.py \
leaktest.py \
bloatcycle.html \
$(topsrcdir)/build/pgo/server-locations.txt \

View File

@ -74,11 +74,6 @@ else
AUTOMATION_PPARGS += -DCRASHREPORTER=0
endif
$(CURDIR)/automationutils.py: $(MOZILLA_DIR)/build/automationutils.py
$(INSTALL) $< .
automation.py: $(MOZILLA_DIR)/build/automation.py.in $(MOZILLA_DIR)/build/automation-build.mk $(CURDIR)/automationutils.py
automation.py: $(MOZILLA_DIR)/build/automation.py.in $(MOZILLA_DIR)/build/automation-build.mk
$(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
GARBAGE += automation.py $(CURDIR)/automationutils.py

View File

@ -59,7 +59,7 @@ include $(topsrcdir)/build/automation-build.mk
_PGO_FILES = \
automation.py \
$(CURDIR)/automationutils.py \
$(topsrcdir)/build/automationutils.py \
profileserver.py \
genpgocert.py \
index.html \

View File

@ -6182,7 +6182,7 @@ MOZ_NATIVE_SQLITE= )
if test -z "$MOZ_NATIVE_SQLITE"
then
SQLITE_CFLAGS=
SQLITE_LIBS='$(call EXPAND_LIBNAME_PATH,sqlite3,$(DIST)/lib)'
SQLITE_LIBS='$(call EXPAND_LIBNAME_PATH,mozsqlite3,$(DIST)/lib)'
else
PKG_CHECK_MODULES(SQLITE, sqlite3 >= $SQLITE_VERSION)
fi

View File

@ -245,7 +245,13 @@ nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest,
PRBool succeeded;
rv = http->GetRequestSucceeded(&succeeded);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(succeeded, NS_ERROR_DOM_BAD_URI);
if (!succeeded) {
PRUint32 responseStatus;
rv = http->GetResponseStatus(&responseStatus);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(mAllowedHTTPErrors.Contains(responseStatus),
NS_ERROR_DOM_BAD_URI);
}
}
// Check the Access-Control-Allow-Origin header

View File

@ -81,6 +81,11 @@ public:
// Must be called at startup.
static void Startup();
void AllowHTTPResult(PRUint32 aResultCode)
{
mAllowedHTTPErrors.AppendElement(aResultCode);
}
private:
nsresult UpdateChannel(nsIChannel* aChannel);
nsresult CheckRequestApproved(nsIRequest* aRequest, PRBool aIsRedirect);
@ -94,6 +99,7 @@ private:
PRBool mIsPreflight;
nsCString mPreflightMethod;
nsTArray<nsCString> mPreflightHeaders;
nsTArray<PRUint32> mAllowedHTTPErrors;
};
#endif

View File

@ -631,13 +631,16 @@ nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
nsCOMPtr<nsIStreamListener> listener;
if (ShouldCheckAllowOrigin()) {
listener = new nsCrossSiteListenerProxy(loadListener,
NodePrincipal(),
mChannel,
PR_FALSE,
&rv);
NS_ENSURE_SUCCESS(rv,rv);
if (!listener) return NS_ERROR_OUT_OF_MEMORY;
nsCrossSiteListenerProxy* crossSiteListener =
new nsCrossSiteListenerProxy(loadListener,
NodePrincipal(),
mChannel,
PR_FALSE,
&rv);
listener = crossSiteListener;
NS_ENSURE_TRUE(crossSiteListener, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_SUCCESS(rv, rv);
crossSiteListener->AllowHTTPResult(HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE);
} else {
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(NodePrincipal(),

View File

@ -59,7 +59,6 @@
#define HTTP_OK_CODE 200
#define HTTP_PARTIAL_RESPONSE_CODE 206
#define HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE 416
using mozilla::TimeStamp;
@ -425,13 +424,16 @@ nsresult nsMediaChannelStream::OpenChannel(nsIStreamListener** aStreamListener)
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
if (element->ShouldCheckAllowOrigin()) {
nsresult rv;
listener = new nsCrossSiteListenerProxy(mListener,
element->NodePrincipal(),
mChannel,
PR_FALSE,
&rv);
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
nsCrossSiteListenerProxy* crossSiteListener =
new nsCrossSiteListenerProxy(mListener,
element->NodePrincipal(),
mChannel,
PR_FALSE,
&rv);
listener = crossSiteListener;
NS_ENSURE_TRUE(crossSiteListener, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_SUCCESS(rv, rv);
crossSiteListener->AllowHTTPResult(HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE);
} else {
nsresult rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(element->NodePrincipal(),

View File

@ -53,6 +53,8 @@
// done rather than a byte range request.
#define SEEK_VS_READ_THRESHOLD (32*1024)
#define HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE 416
class nsMediaDecoder;
/**

View File

@ -179,6 +179,7 @@ ifdef MOZ_OGG
_TEST_FILES += \
dynamic_redirect.sjs \
file_access_controls.html \
test_access_control.html \
test_bug448534.html \
test_bug468190.html \
test_bug486646.html \
@ -227,7 +228,6 @@ ifneq ($(OS_ARCH),WINNT)
# figure out the random failures. See bug 475369 and bug 526323
_TEST_FILES += \
test_timeupdate3.html \
test_access_control.html \
$(NULL)
endif
endif

View File

@ -15,7 +15,7 @@ var gTests = [
},{
// Test 1
url: "redirect.sjs?http://example.com/tests/content/media/test/320x240.allow-origin.ogv",
result: "loaded",
result: "loadeddata",
description: "Can load when redirected to different domain with allow-origin",
},{
// Test 2
@ -25,17 +25,17 @@ var gTests = [
},{
// Test 3
url: "redirect.sjs?http://test1.example.org/tests/content/media/test/320x240.allow-origin.ogv",
result: "loaded",
result: "loadeddata",
description: "Can load when redirected to subdomain with allow-origin",
},{
// Test 4
url: "redirect.sjs?http://example.org/tests/content/media/test/320x240.ogv",
result: "loaded",
result: "loadeddata",
description: "Can load when redirected to same domain",
},{
// Test 5
url: "http://example.org/tests/content/media/test/320x240.ogv",
result: "loaded",
result: "loadeddata",
description: "Can load from same domain"
},{
// Test 6
@ -45,7 +45,7 @@ var gTests = [
},{
// Test 7
url: "http://example.org:8000/tests/content/media/test/320x240.allow-origin.ogv",
result: "loaded",
result: "loadeddata",
description: "Can load from different port on same domain with allow-origin",
},{
// Test 8
@ -55,12 +55,12 @@ var gTests = [
},{
// Test 9
url: "http://example.com/tests/content/media/test/320x240.allow-origin.ogv",
result: "loaded",
result: "loadeddata",
description: "Can load cross domain with allow-origin",
},{
// Test 10
url: "http://test1.example.org/tests/content/media/test/320x240.allow-origin.ogv",
result: "loaded",
result: "loadeddata",
description: "Can load from subdomain with allow-origin",
},{
// Test 11
@ -71,24 +71,25 @@ var gTests = [
];
var gTestNum = 0;
var gExpectedResult = null;
var gTestDescription = null;
var gVideo = null;
var gTestedRemoved = false;
var gOldPref;
function result(code) {
//dump((gTestNum - 1) + ": " + code + "\n");
function eventHandler(event) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
opener.is(code, gExpectedResult, gTestDescription);
//dump((gTestNum - 1) + ": " + event.type + "\n");
var video = event.target;
opener.is(event.type, video.expectedResult, video.testDescription +
(gTestedRemoved ? " (element not in document)" : " (element in document)"));
// Make sure any extra events cause an error
video.expectedResult = "<none>";
nextTest();
}
function createVideo() {
var v = document.createElement('video');
v.addEventListener('loadeddata', function(){result('loaded');}, false);
v.addEventListener('error', function(){result('error');}, false);
v.id = 'video';
v.addEventListener('loadeddata', eventHandler, false);
v.addEventListener('error', eventHandler, false);
return v;
}
@ -112,7 +113,6 @@ function load() {
function nextTest() {
//dump("nextTest() called, gTestNum="+gTestNum+" gTestedRemoved="+gTestedRemoved+"\n");
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
if (gTestNum == gTests.length) {
//dump("gTestNum == gTests.length\n");
if (!gTestedRemoved) {
@ -126,15 +126,15 @@ function nextTest() {
return;
}
}
gExpectedResult = gTests[gTestNum].result;
gTestDescription = gTests[gTestNum].description;
//dump("Starting test " + gTestNum + " at " + gTests[gTestNum].url + " expecting:" + gExpectedResult + "\n");
if (gVideo && gVideo.parentNode)
gVideo.parentNode.removeChild(gVideo);
gVideo = createVideo();
gVideo.expectedResult = gTests[gTestNum].result;
gVideo.testDescription = gTests[gTestNum].description;
gVideo.src = gTests[gTestNum].url;
//dump("Starting test " + gTestNum + " at " + gVideo.src + " expecting:" + gVideo.expectedResult + "\n");
if (!gTestedRemoved) {
document.body.appendChild(gVideo);
// Will cause load() to be invoked.

View File

@ -1870,9 +1870,11 @@ nsXULTemplateBuilder::CompileTemplate(nsIContent* aTemplate,
getter_AddRefs(action));
if (action){
nsCOMPtr<nsIAtom> memberVariable;
DetermineMemberVariable(action, getter_AddRefs(memberVariable));
if (! memberVariable) continue;
nsCOMPtr<nsIAtom> memberVariable = mMemberVariable;
if (!memberVariable) {
memberVariable = DetermineMemberVariable(action);
if (!memberVariable) continue;
}
if (hasQuery) {
nsCOMPtr<nsIAtom> tag;
@ -1994,9 +1996,11 @@ nsXULTemplateBuilder::CompileTemplate(nsIContent* aTemplate,
if (tag)
aQuerySet->SetTag(tag);
nsCOMPtr<nsIAtom> memberVariable;
DetermineMemberVariable(rulenode, getter_AddRefs(memberVariable));
if (! memberVariable) continue;
nsCOMPtr<nsIAtom> memberVariable = mMemberVariable;
if (!memberVariable) {
memberVariable = DetermineMemberVariable(rulenode);
if (!memberVariable) continue;
}
nsCOMPtr<nsIDOMNode> query(do_QueryInterface(aQuerySet->mQueryNode));
@ -2077,53 +2081,26 @@ nsXULTemplateBuilder::CompileExtendedQuery(nsIContent* aRuleElement,
return NS_OK;
}
nsresult
nsXULTemplateBuilder::DetermineMemberVariable(nsIContent* aActionElement,
nsIAtom** aMemberVariable)
already_AddRefed<nsIAtom>
nsXULTemplateBuilder::DetermineMemberVariable(nsIContent* aElement)
{
// If the member variable hasn't already been specified, then
// grovel over <action> to find it. We'll use the first one
// that we find in a breadth-first search.
// recursively iterate over the children looking for an element
// with uri="?..."
for (nsINode::ChildIterator iter(aElement); !iter.IsDone(); iter.Next()) {
nsAutoString uri;
nsIContent *child = iter;
child->GetAttr(kNameSpaceID_None, nsGkAtoms::uri, uri);
if (!uri.IsEmpty() && uri[0] == PRUnichar('?')) {
return NS_NewAtom(uri);
}
if (mMemberVariable) {
*aMemberVariable = mMemberVariable;
NS_IF_ADDREF(*aMemberVariable);
}
else {
*aMemberVariable = nsnull;
nsCOMArray<nsIContent> unvisited;
if (!unvisited.AppendObject(aActionElement))
return NS_ERROR_OUT_OF_MEMORY;
while (unvisited.Count()) {
nsIContent* next = unvisited[0];
unvisited.RemoveObjectAt(0);
nsAutoString uri;
next->GetAttr(kNameSpaceID_None, nsGkAtoms::uri, uri);
if (!uri.IsEmpty() && uri[0] == PRUnichar('?')) {
// Found it.
*aMemberVariable = NS_NewAtom(uri);
break;
}
// otherwise, append the children to the unvisited list: this
// results in a breadth-first search.
PRUint32 count = next->GetChildCount();
for (PRUint32 i = 0; i < count; ++i) {
nsIContent *child = next->GetChildAt(i);
if (!unvisited.AppendObject(child))
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIAtom> result = DetermineMemberVariable(child);
if (result) {
return result.forget();
}
}
return NS_OK;
return nsnull;
}
void

View File

@ -212,8 +212,7 @@ public:
* Determine the member variable from inside an action body. It will be
* the value of the uri attribute on a node.
*/
nsresult
DetermineMemberVariable(nsIContent* aActionElement, nsIAtom** aMemberVariable);
already_AddRefed<nsIAtom> DetermineMemberVariable(nsIContent* aElement);
/**
* Compile a simple query. A simple query is one that doesn't have a

View File

@ -46,7 +46,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = sqlite3
LIBRARY_NAME = sqlite3
LIBRARY_NAME = mozsqlite3
FORCE_SHARED_LIB = 1
VISIBILITY_FLAGS =
LIB_IS_C_ONLY = 1

View File

@ -33,7 +33,7 @@
;
; ***** END LICENSE BLOCK *****
LIBRARY sqlite3.dll
LIBRARY mozsqlite3.dll
EXPORTS
sqlite3_aggregate_context

View File

@ -63,7 +63,7 @@
toolkit/components/places/src/nsFaviconService.h should be updated. -->
<link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/warning-16.png"/>
<script type="application/x-javascript"><![CDATA[
<script type="application/javascript"><![CDATA[
// Error url MUST be formatted like this:
// moz-neterror:page?e=error&u=url&d=desc
//
@ -376,7 +376,7 @@
- an onload handler. This is because error pages are loaded as
- LOAD_BACKGROUND, which means that onload handlers will not be executed.
-->
<script type="application/x-javascript">initPage();</script>
<script type="application/javascript">initPage();</script>
</body>
</html>

View File

@ -419,6 +419,7 @@ public:
NPError ShowNativeContextMenu(NPMenu* menu, void* event);
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace);
void SendIdleEvent();
NS_DECL_CYCLE_COLLECTION_CLASS(nsDummyJavaPluginOwner)
@ -563,6 +564,11 @@ nsDummyJavaPluginOwner::SetEventModel(PRInt32 eventModel)
return NS_ERROR_NOT_IMPLEMENTED;
}
void
nsDummyJavaPluginOwner::SendIdleEvent()
{
}
/**
* An indirect observer object that means we don't have to implement nsIObserver
* on nsGlobalWindow, where any script could see it.

View File

@ -1,6 +1,10 @@
function test() {
waitForExplicitFinish();
let secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
.getService(Components.interfaces
.nsIScriptSecurityManager);
let fm = Components.classes["@mozilla.org/focus-manager;1"]
.getService(Components.interfaces.nsIFocusManager);
@ -136,6 +140,32 @@ function test() {
return;
}
// XXX puts some useful information for bug 534420
let activeWindow = fm.activeWindow;
let focusedWindow = fm.focusedWindow;
ok(activeWindow, "We're not active");
ok(focusedWindow, "There is no focused window");
is(activeWindow, window.top, "our window isn't active");
let searchbar = BrowserSearch.searchBar;
let focusedElement = fm.focusedElement;
if (searchbar) {
let principal = searchbar.nodePrincipal;
ok(principal, "principal is null");
info("search bar: tagName=" + searchbar.tagName + " id=" + searchbar.id);
ok(secMan.isSystemPrincipal(principal), "search bar isn't chrome");
} else {
info("search bar is NULL!!");
}
if (focusedElement) {
let principal = focusedElement.nodePrincipal;
ok(principal, "principal is null");
info("focusedElement: tagName=" + focusedElement.tagName +
" id=" + focusedElement.id);
ok(secMan.isSystemPrincipal(principal), "focusedElement isn't chrome");
} else {
info("focusedElement is NULL!!");
}
// The contents shouldn't be able to steal the focus from chrome.
// in foreground tab

View File

@ -315,6 +315,11 @@ nsAuthSSPI::GetNextToken(const void *inToken,
LOG(("entering nsAuthSSPI::GetNextToken()\n"));
if (!mCtxt.dwLower && !mCtxt.dwUpper) {
LOG(("nsAuthSSPI::GetNextToken(), not initialized. exiting."));
return NS_ERROR_NOT_INITIALIZED;
}
if (mServiceFlags & REQ_DELEGATE)
ctxReq |= ISC_REQ_DELEGATE;
if (mServiceFlags & REQ_MUTUAL_AUTH)

View File

@ -0,0 +1,89 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
function run_test()
{
var cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
// twiddle prefs to convenient values for this test
prefs.setIntPref("network.cookie.purgeAge", 1);
prefs.setIntPref("network.cookie.maxNumber", 1000);
// eviction is performed based on two limits: when the total number of cookies
// exceeds maxNumber + 10% (1100), and when cookies are older than purgeAge
// (1 second). purging is done when both conditions are satisfied, and only
// those cookies are purged.
// we test the following cases of eviction:
// 1) excess and age are satisfied, but only some of the excess are old enough
// to be purged.
do_check_eq(testEviction(cm, 1101, 2, 50, 1051), 1051);
// 2) excess and age are satisfied, and all of the excess are old enough
// to be purged.
do_check_eq(testEviction(cm, 1101, 2, 100, 1001), 1001);
// 3) excess and age are satisfied, and more than the excess are old enough
// to be purged.
do_check_eq(testEviction(cm, 1101, 2, 500, 1001), 1001);
// 4) excess but not age are satisfied.
do_check_eq(testEviction(cm, 2000, 0, 0, 2000), 2000);
// 5) age but not excess are satisfied.
do_check_eq(testEviction(cm, 1100, 2, 200, 1100), 1100);
cm.removeAll();
// reset prefs to defaults
prefs.setIntPref("network.cookie.purgeAge", 30 * 24 * 60 * 60);
prefs.setIntPref("network.cookie.maxNumber", 2000);
}
// test that cookies are evicted by order of lastAccessed time, if both the limit
// on total cookies (maxNumber + 10%) and the purge age are exceeded
function
testEviction(aCM, aNumberTotal, aSleepDuration, aNumberOld, aNumberToExpect)
{
aCM.removeAll();
var expiry = (Date.now() + 1e6) * 1000;
var i;
for (i = 0; i < aNumberTotal; ++i) {
var host = "eviction." + i + ".tests";
aCM.add(host, "", "test", "eviction", false, false, false, expiry);
if ((i == aNumberOld - 1) && aSleepDuration) {
// sleep a while, to make sure the first batch of cookies is older than
// the second (timer resolution varies on different platforms).
sleep(aSleepDuration * 1000);
}
}
var enumerator = aCM.enumerator;
i = 0;
while (enumerator.hasMoreElements()) {
var cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
++i;
if (aNumberTotal != aNumberToExpect) {
// make sure the cookie is one of the batch we expect was purged.
var hostNumber = new Number(cookie.rawHost.split(".")[1]);
if (hostNumber < (aNumberOld - aNumberToExpect)) break;
}
}
return i;
}
// delay for a number of milliseconds
function sleep(delay)
{
var start = Date.now();
while (Date.now() < start + delay);
}

View File

@ -68,7 +68,6 @@ var reporterListener = {
onProgressChange: function() { },
onStatusChange: function() { },
onSecurityChange: function() { },
onLinkIconAvailable: function() { },
onProgressChange64: function() { },
onRefreshAttempted: function() { return true; }
}

View File

@ -646,11 +646,12 @@ nsThebesDeviceContext::SetDPI()
break;
#ifdef XP_WIN
case gfxASurface::SurfaceTypeWin32:
case gfxASurface::SurfaceTypeWin32Printing:
case gfxASurface::SurfaceTypeWin32Printing: {
PRInt32 OSVal = GetDeviceCaps(GetPrintHDC(), LOGPIXELSY);
dpi = 144;
mPrintingScale = float(OSVal) / dpi;
break;
}
#endif
#ifdef XP_OS2
case gfxASurface::SurfaceTypeOS2:
@ -659,6 +660,9 @@ nsThebesDeviceContext::SetDPI()
dpi = lDPI;
break;
#endif
default:
NS_NOTREACHED("Unexpected printing surface type");
break;
}
dotsArePixels = PR_FALSE;
} else {

View File

@ -63,7 +63,11 @@ public:
// this is in points!
const gfxSize& GetSize() const { return mSize; }
virtual PRInt32 GetDefaultContextFlags() const { return gfxContext::FLAG_DISABLE_SNAPPING; }
virtual PRInt32 GetDefaultContextFlags() const
{
return gfxContext::FLAG_SIMPLIFY_OPERATORS |
gfxContext::FLAG_DISABLE_SNAPPING;
}
private:
nsCOMPtr<nsIOutputStream> mStream;

View File

@ -63,7 +63,11 @@ public:
// this is in points!
const gfxSize& GetSize() const { return mSize; }
virtual PRInt32 GetDefaultContextFlags() const { return gfxContext::FLAG_DISABLE_SNAPPING; }
virtual PRInt32 GetDefaultContextFlags() const
{
return gfxContext::FLAG_SIMPLIFY_OPERATORS |
gfxContext::FLAG_DISABLE_SNAPPING;
}
private:
nsCOMPtr<nsIOutputStream> mStream;

View File

@ -70,7 +70,9 @@ public:
ATSFontRef GetFontRef();
nsresult ReadCMAP();
#ifndef __LP64__
PRBool UseLiGothicAtsuiHack() { return mUseLiGothicAtsuiHack; }
#endif
protected:
// for use with data fonts
@ -82,7 +84,9 @@ protected:
ATSFontRef mATSFontRef;
PRPackedBool mATSFontRefInitialized;
#ifndef __LP64__
PRPackedBool mUseLiGothicAtsuiHack;
#endif
};
class gfxMacPlatformFontList : public gfxPlatformFontList {

View File

@ -117,8 +117,10 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
PRBool aIsStandardFace)
: gfxFontEntry(aPostscriptName, aFamily, aIsStandardFace),
mATSFontRef(0),
mATSFontRefInitialized(PR_FALSE),
mUseLiGothicAtsuiHack(PR_FALSE)
mATSFontRefInitialized(PR_FALSE)
#ifndef __LP64__
, mUseLiGothicAtsuiHack(PR_FALSE)
#endif
{
mWeight = aWeight;
}
@ -128,8 +130,10 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, ATSFontRef aFon
gfxUserFontData *aUserFontData)
: gfxFontEntry(aPostscriptName),
mATSFontRef(aFontRef),
mATSFontRefInitialized(PR_TRUE),
mUseLiGothicAtsuiHack(PR_FALSE)
mATSFontRefInitialized(PR_TRUE)
#ifndef __LP64__
, mUseLiGothicAtsuiHack(PR_FALSE)
#endif
{
// xxx - stretch is basically ignored for now
@ -265,6 +269,8 @@ MacOSFontEntry::ReadCMAP()
}
}
#ifndef __LP64__ /* ATSUI not available on 64-bit */
if ((gfxPlatformMac::GetPlatform()->OSXVersion() &
MAC_OS_X_MAJOR_VERSION_MASK) == MAC_OS_X_VERSION_10_6_HEX) {
// even ruder hack - LiGothic font on 10.6 has a bad glyph for U+775B
@ -281,6 +287,8 @@ MacOSFontEntry::ReadCMAP()
}
}
#endif /* not __LP64__ */
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontinit-cmap) psname: %s, size: %d\n",
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));

View File

@ -40,7 +40,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include "zlib.h"
#ifdef WOFF_MOZILLA_CLIENT /* define this when building as part of Gecko */
# include "prmem.h"

View File

@ -43,10 +43,5 @@
*/
MSG_DEF(CTYPESMSG_PLACEHOLDER_0, 0, 0, JSEXN_NONE, NULL)
MSG_DEF(CTYPESMSG_PLACEHOLDER_1, 1, 0, JSEXN_NONE, NULL)
MSG_DEF(CTYPESMSG_PLACEHOLDER_2, 2, 0, JSEXN_NONE, NULL)
// This error has to be number 3 in order to be a TypeError,
// due to a bug in the js engine.
MSG_DEF(CTYPESMSG_TYPE_ERROR, 3, 2, JSEXN_TYPEERR, "expected type {0}, got {1}")
MSG_DEF(CTYPESMSG_TYPE_ERROR, 1, 2, JSEXN_TYPEERR, "expected type {0}, got {1}")

View File

@ -1041,6 +1041,9 @@ jsd_InitObjectManager(JSDContext* jsdc);
extern void
jsd_DestroyObjectManager(JSDContext* jsdc);
extern void
jsd_DestroyObjects(JSDContext* jsdc);
extern void
jsd_ObjectHook(JSContext *cx, JSObject *obj, JSBool isNew, void *closure);

View File

@ -238,11 +238,19 @@ jsd_InitObjectManager(JSDContext* jsdc)
void
jsd_DestroyObjectManager(JSDContext* jsdc)
{
jsd_DestroyObjects(jsdc);
JSD_LOCK_OBJECTS(jsdc);
JS_HashTableDestroy(jsdc->objectsTable);
JSD_UNLOCK_OBJECTS(jsdc);
}
void
jsd_DestroyObjects(JSDContext* jsdc)
{
JSD_LOCK_OBJECTS(jsdc);
while( !JS_CLIST_IS_EMPTY(&jsdc->objectsList) )
_destroyJSDObject(jsdc, (JSDObject*)JS_NEXT_LINK(&jsdc->objectsList));
JS_HashTableDestroy(jsdc->objectsTable);
JSD_UNLOCK_OBJECTS(jsdc);
}

View File

@ -140,18 +140,17 @@ JSD_SetContextFlags(JSDContext *jsdc, uint32 flags)
jsdc->flags = flags;
if ((flags & JSD_COLLECT_PROFILE_DATA) ||
!(flags & JSD_DISABLE_OBJECT_TRACE)) {
// Need to reenable our call hooks now
/* Need to reenable our call hooks now */
JS_SetExecuteHook(jsdc->jsrt, jsd_TopLevelCallHook, jsdc);
JS_SetCallHook(jsdc->jsrt, jsd_FunctionCallHook, jsdc);
}
if ((oldFlags ^ flags) & JSD_DISABLE_OBJECT_TRACE) {
// Changing our JSD_DISABLE_OBJECT_TRACE flag
/* Changing our JSD_DISABLE_OBJECT_TRACE flag */
if (!(flags & JSD_DISABLE_OBJECT_TRACE)) {
// Need to reenable our object hooks now
if (jsd_InitObjectManager(jsdc))
JS_SetObjectHook(jsdc->jsrt, jsd_ObjectHook, jsdc);
/* Need to reenable our object hooks now */
JS_SetObjectHook(jsdc->jsrt, jsd_ObjectHook, jsdc);
} else {
jsd_DestroyObjectManager(jsdc);
jsd_DestroyObjects(jsdc);
JS_SetObjectHook(jsdc->jsrt, NULL, NULL);
}
}

View File

@ -5827,7 +5827,8 @@ JS_PUBLIC_API(JSBool)
JS_ThrowReportedError(JSContext *cx, const char *message,
JSErrorReport *reportp)
{
return JS_IsRunning(cx) && js_ErrorToException(cx, message, reportp);
return JS_IsRunning(cx) &&
js_ErrorToException(cx, message, reportp, NULL, NULL);
}
JS_PUBLIC_API(JSBool)

View File

@ -1281,7 +1281,8 @@ MarkLocalRoots(JSTracer *trc, JSLocalRootStack *lrs)
}
static void
ReportError(JSContext *cx, const char *message, JSErrorReport *reportp)
ReportError(JSContext *cx, const char *message, JSErrorReport *reportp,
JSErrorCallback callback, void *userRef)
{
/*
* Check the error report, and set a JavaScript-catchable exception
@ -1290,7 +1291,8 @@ ReportError(JSContext *cx, const char *message, JSErrorReport *reportp)
* on the error report, and exception-aware hosts should ignore it.
*/
JS_ASSERT(reportp);
if (reportp->errorNumber == JSMSG_UNCAUGHT_EXCEPTION)
if ((!callback || callback == js_GetErrorMessage) &&
reportp->errorNumber == JSMSG_UNCAUGHT_EXCEPTION)
reportp->flags |= JSREPORT_EXCEPTION;
/*
@ -1301,7 +1303,8 @@ ReportError(JSContext *cx, const char *message, JSErrorReport *reportp)
* propagates out of scope. This is needed for compatability
* with the old scheme.
*/
if (!JS_IsRunning(cx) || !js_ErrorToException(cx, message, reportp)) {
if (!JS_IsRunning(cx) ||
!js_ErrorToException(cx, message, reportp, callback, userRef)) {
js_ReportErrorAgain(cx, message, reportp);
} else if (cx->debugHooks->debugErrorHook && cx->errorReporter) {
JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
@ -1457,7 +1460,7 @@ js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
warning = JSREPORT_IS_WARNING(report.flags);
ReportError(cx, message, &report);
ReportError(cx, message, &report, NULL, NULL);
js_free(message);
cx->free(ucmessage);
return warning;
@ -1651,7 +1654,7 @@ js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
return JS_FALSE;
}
ReportError(cx, message, &report);
ReportError(cx, message, &report, callback, userRef);
if (message)
cx->free(message);

View File

@ -1104,7 +1104,8 @@ static struct exnname { char *name; char *exception; } errortoexnname[] = {
#endif /* DEBUG */
JSBool
js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
JSErrorCallback callback, void *userRef)
{
JSErrNum errorNumber;
const JSErrorFormatString *errorString;
@ -1124,7 +1125,10 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
/* Find the exception index associated with this error. */
errorNumber = (JSErrNum) reportp->errorNumber;
errorString = js_GetLocalizedErrorMessage(cx, NULL, NULL, errorNumber);
if (!callback || callback == js_GetErrorMessage)
errorString = js_GetLocalizedErrorMessage(cx, NULL, NULL, errorNumber);
else
errorString = callback(userRef, NULL, errorNumber);
exn = errorString ? (JSExnType) errorString->exnType : JSEXN_NONE;
JS_ASSERT(exn < JSEXN_LIMIT);

View File

@ -63,7 +63,8 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj);
* found and set, JS_FALSE otherwise.
*/
extern JSBool
js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp);
js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
JSErrorCallback callback, void *userRef);
/*
* Called if a JS API call to js_Execute or js_InternalCall fails; calls the

View File

@ -607,7 +607,7 @@ ReportCompileErrorNumberVA(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
* which is likely spurious.
*/
if (!(ts->flags & TSF_ERROR)) {
if (js_ErrorToException(cx, message, &report))
if (js_ErrorToException(cx, message, &report, NULL, NULL))
onError = NULL;
}

View File

@ -3254,7 +3254,9 @@ Scatter(JSContext *cx, uintN argc, jsval *vp)
);
if (!newcx)
goto fail;
JS_BeginRequest(newcx);
JS_SetGlobalObject(newcx, JS_GetGlobalObject(cx));
JS_EndRequest(newcx);
JS_ClearContextThread(newcx);
sd.threads[i].cx = newcx;
}

View File

@ -1010,6 +1010,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext,
InlineReflowState irs;
irs.mPrevFrame = nsnull;
irs.mLineContainer = lineContainer;
irs.mLineLayout = aReflowState.mLineLayout;
irs.mNextInFlow = (nsInlineFrame*) GetNextInFlow();
nsresult rv;

View File

@ -224,9 +224,9 @@ enum { XKeyPress = KeyPress };
static PRLogModuleInfo *nsObjectFrameLM = PR_NewLogModule("nsObjectFrame");
#endif /* PR_LOGGING */
#define NORMAL_PLUGIN_DELAY 20
// must avoid audio skipping/delays
#define HIDDEN_PLUGIN_DELAY 125
#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
#define MAC_CARBON_PLUGINS
#endif
// special class for handeling DOM context menu events because for
// some reason it starves other mouse events if implemented on the
@ -257,7 +257,6 @@ public:
class nsPluginInstanceOwner : public nsIPluginInstanceOwner,
public nsIPluginTagInfo,
public nsITimerCallback,
public nsIDOMMouseListener,
public nsIDOMMouseMotionListener,
public nsIDOMKeyListener,
@ -325,11 +324,11 @@ public:
void Paint(const nsRect& aDirtyRect, HPS aHPS);
#endif
// nsITimerCallback interface
NS_DECL_NSITIMERCALLBACK
#ifdef MAC_CARBON_PLUGINS
void CancelTimer();
void StartTimer(unsigned int aDelay);
void StartTimer(PRBool isVisible);
#endif
void SendIdleEvent();
// nsIScrollPositionListener interface
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
@ -432,7 +431,6 @@ private:
nsCString mDocumentBase;
char *mTagText;
nsCOMPtr<nsIWidget> mWidget;
nsCOMPtr<nsITimer> mPluginTimer;
nsCOMPtr<nsIPluginHost> mPluginHost;
#ifdef XP_MACOSX
@ -452,7 +450,6 @@ private:
// If true, destroy the widget on destruction. Used when plugin stop
// is being delayed to a safer point in time.
PRPackedBool mDestroyWidget;
PRPackedBool mTimerCanceled;
PRUint16 mNumCachedAttrs;
PRUint16 mNumCachedParams;
char **mCachedAttrParamNames;
@ -1368,7 +1365,7 @@ nsObjectFrame::PrintPlugin(nsIRenderingContext& aRenderingContext,
window.clipRect.left = 0; window.clipRect.right = 0;
// platform specific printing code
#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
#ifdef MAC_CARBON_PLUGINS
nsSize contentSize = GetContentRect().Size();
window.x = 0;
window.y = 0;
@ -1933,7 +1930,9 @@ nsObjectFrame::HandleEvent(nsPresContext* aPresContext,
#endif
if (anEvent->message == NS_DESTROY) {
#ifdef MAC_CARBON_PLUGINS
mInstanceOwner->CancelTimer();
#endif
return rv;
}
@ -2433,7 +2432,6 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
mCachedAttrParamNames = nsnull;
mCachedAttrParamValues = nsnull;
mDestroyWidget = PR_FALSE;
mTimerCanceled = PR_TRUE;
#ifdef MOZ_COMPOSITED_PLUGINS
mLastPoint = nsIntPoint(0,0);
@ -2464,8 +2462,9 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
("nsPluginInstanceOwner %p deleted\n", this));
// shut off the timer.
#ifdef MAC_CARBON_PLUGINS
CancelTimer();
#endif
mObjectFrame = nsnull;
@ -2522,7 +2521,6 @@ NS_IMPL_RELEASE(nsPluginInstanceOwner)
NS_INTERFACE_MAP_BEGIN(nsPluginInstanceOwner)
NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner)
NS_INTERFACE_MAP_ENTRY(nsIPluginTagInfo)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
@ -3572,7 +3570,7 @@ nsPluginInstanceOwner::GetEventloopNestingLevel()
nsresult nsPluginInstanceOwner::ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
{
#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
#ifdef MAC_CARBON_PLUGINS
if (GetEventModel() != NPEventModelCarbon)
return NS_OK;
@ -3599,7 +3597,7 @@ nsresult nsPluginInstanceOwner::ScrollPositionWillChange(nsIScrollableView* aScr
nsresult nsPluginInstanceOwner::ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
{
#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
#ifdef MAC_CARBON_PLUGINS
if (GetEventModel() != NPEventModelCarbon)
return NS_OK;
@ -3618,9 +3616,9 @@ nsresult nsPluginInstanceOwner::ScrollPositionDidChange(nsIScrollableView* aScro
pluginWidget->EndDrawPlugin();
}
}
#endif
StartTimer(NORMAL_PLUGIN_DELAY);
StartTimer(PR_TRUE);
#endif
return NS_OK;
}
@ -3680,7 +3678,7 @@ nsresult nsPluginInstanceOwner::KeyUp(nsIDOMEvent* aKeyEvent)
nsresult nsPluginInstanceOwner::KeyPress(nsIDOMEvent* aKeyEvent)
{
#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
#ifdef MAC_CARBON_PLUGINS
// send KeyPress events only for Mac OS X Carbon event model
if (GetEventModel() != NPEventModelCarbon)
return aKeyEvent->PreventDefault();
@ -4635,8 +4633,10 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
nsresult
nsPluginInstanceOwner::Destroy()
{
#ifdef MAC_CARBON_PLUGINS
// stop the timer explicitly to reduce reference count.
CancelTimer();
#endif
// unregister context menu listener
if (mCXMenuListener) {
@ -5362,14 +5362,9 @@ nsPluginInstanceOwner::Renderer::NativeDraw(QWidget * drawable,
}
#endif
// Here's how we give idle time to plugins.
NS_IMETHODIMP nsPluginInstanceOwner::Notify(nsITimer* timer)
void nsPluginInstanceOwner::SendIdleEvent()
{
#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
if (GetEventModel() != NPEventModelCarbon)
return NS_OK;
#ifdef MAC_CARBON_PLUGINS
// validate the plugin clipping information by syncing the plugin window info to
// reflect the current widget location. This makes sure that everything is updated
// correctly in the event of scrolling in the window.
@ -5395,36 +5390,22 @@ NS_IMETHODIMP nsPluginInstanceOwner::Notify(nsITimer* timer)
}
}
#endif
return NS_OK;
}
void nsPluginInstanceOwner::StartTimer(unsigned int aDelay)
#ifdef MAC_CARBON_PLUGINS
void nsPluginInstanceOwner::StartTimer(PRBool isVisible)
{
#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
if (GetEventModel() != NPEventModelCarbon)
return;
if (!mTimerCanceled)
return;
// start a periodic timer to provide null events to the plugin instance.
if (!mPluginTimer) {
mPluginTimer = do_CreateInstance("@mozilla.org/timer;1");
}
if (mPluginTimer) {
mTimerCanceled = PR_FALSE;
mPluginTimer->InitWithCallback(this, aDelay, nsITimer::TYPE_REPEATING_SLACK);
}
#endif
mPluginHost->AddIdleTimeTarget(this, isVisible);
}
void nsPluginInstanceOwner::CancelTimer()
{
if (mPluginTimer) {
mPluginTimer->Cancel();
}
mTimerCanceled = PR_TRUE;
mPluginHost->RemoveIdleTimeTarget(this);
}
#endif
nsresult nsPluginInstanceOwner::Init(nsPresContext* aPresContext,
nsObjectFrame* aFrame,
@ -5597,8 +5578,10 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
mPluginWindow->type = NPWindowTypeWindow;
mPluginWindow->window = GetPluginPort();
#ifdef MAC_CARBON_PLUGINS
// start the idle timer.
StartTimer(NORMAL_PLUGIN_DELAY);
StartTimer(PR_TRUE);
#endif
// tell the plugin window about the widget
mPluginWindow->SetPluginWidget(mWidget);
@ -5639,7 +5622,7 @@ PRBool nsPluginInstanceOwner::UpdateVisibility()
}
#endif
// Mac specific code to fix up the port location and clipping region
// Mac specific code to fix up the port location and clipping region
#ifdef XP_MACOSX
void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
@ -5735,15 +5718,17 @@ void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
{
mInstance->SetWindow(mPluginWindow);
mPluginPortChanged = PR_FALSE;
#ifdef MAC_CARBON_PLUGINS
// if the clipRect is of size 0, make the null timer fire less often
CancelTimer();
if (mPluginWindow->clipRect.left == mPluginWindow->clipRect.right ||
mPluginWindow->clipRect.top == mPluginWindow->clipRect.bottom) {
StartTimer(HIDDEN_PLUGIN_DELAY);
StartTimer(PR_FALSE);
}
else {
StartTimer(NORMAL_PLUGIN_DELAY);
StartTimer(PR_TRUE);
}
#endif
} else if (mPluginPortChanged) {
mInstance->SetWindow(mPluginWindow);
mPluginPortChanged = PR_FALSE;

View File

@ -67,33 +67,37 @@ function makeResult() {
};
}
function waitInterrupt(result, gen, timewait) {
function makeListener(result, eventGen) {
return function(ev) {
result.success = true;
result.event = ev;
setTimeout(function() { eventGen.next(); }, 0);
};
}
function waitInterrupt(result, gen) {
result.event = null;
result.success = false;
setTimeout(function() { if (!result.success) gen.next(); }, (timewait || 2000));
setTimeout(function() { if (!result.success) gen.next(); }, 3500);
}
function testPhoom(isCapturing, x, y, expectEvent) {
var result;
var eventGen = (function() {
var innerdoc = document.getElementById('testframe').contentDocument;
for each (var doc in [document, innerdoc]) {
var inner = (doc == innerdoc);
var w, h;
var listener = function(ev) {
result.success = true;
result.event = ev;
setTimeout(function() { eventGen.next(); }, 0);
};
var w, h, result, listener;
/* --- EXPANSION --- */
result = makeResult();
listener = makeListener(result, eventGen);
doc.addEventListener("MozScrolledAreaChanged", listener, isCapturing);
result = makeResult();
waitInterrupt(result, eventGen, 1200);
if (!expectEvent) waitInterrupt(result, eventGen);
phoom(doc, x, y);
yield;
@ -103,7 +107,7 @@ function testPhoom(isCapturing, x, y, expectEvent) {
one can still arrive, but we don't complain if it did not. In either case, any event
that arrives will have its data checked below. */
if (expectEvent) {
ok(result.success, "Received expected expansion event");
ok(result.success, "Received expected " + (inner ? "inner" : "") + " expansion event");
}
if (result.success) {
@ -129,17 +133,19 @@ function testPhoom(isCapturing, x, y, expectEvent) {
/* --- CONTRACTION --- */
result = makeResult();
listener = makeListener(result, eventGen);
doc.addEventListener("MozScrolledAreaChanged", listener, isCapturing);
result = makeResult();
waitInterrupt(result, eventGen, 1200);
if (!expectEvent) waitInterrupt(result, eventGen);
unphoom(doc);
yield;
doc.removeEventListener("MozScrolledAreaChanged", listener, isCapturing);
if (expectEvent) {
ok(result.success, "Received expected contraction event");
ok(result.success, "Received expected " + (inner ? "inner" : "") + " contraction event");
}
if (result.success) {

View File

@ -1878,8 +1878,10 @@ nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO)
}
// Without a frame, this document can't be displayed; therefore, there is no
// point to reflowing it
if (!frame)
if (!frame) {
aPO->mDontPrint = PR_TRUE;
return NS_OK;
}
adjSize = frame->GetContentRect().Size();
documentIsTopLevel = PR_FALSE;

View File

@ -0,0 +1,42 @@
<!doctype html>
<html><head>
<style>
html {
background-image: -moz-linear-gradient(black, white 20%)
}
body {
font-size: 1em;
padding: 2em;
margin: 50px auto;
width: 14em;
border: 1px solid black;
background-color: white;
}
</style>
</head><body>
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
</body>
</html>

View File

@ -0,0 +1,52 @@
<!doctype html>
<html class="reftest-wait"><head>
<style>
html {
background-image: -moz-linear-gradient(black, white 20%)
}
body {
font-size: 1em;
padding: 2em;
margin: 50px auto;
width: 28em;
border: 1px solid black;
background-color: white;
}
</style>
<script>
window.onload = function() {
setTimeout(function() {
document.body.style.width = "14em";
setTimeout(function() {
document.documentElement.removeAttribute("class");
}, 100);
}, 100);
}
</script>
</head><body>
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
</body>
</html>

View File

@ -0,0 +1,43 @@
<!doctype html>
<html><head>
<style>
html {
background-image: -moz-linear-gradient(black, white 20%);
-moz-background-size: 400px 400px;
}
body {
font-size: 1em;
padding: 2em;
margin: 50px auto;
width: 14em;
border: 1px solid black;
background-color: white;
}
</style>
</head><body>
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
</body>
</html>

View File

@ -0,0 +1,53 @@
<!doctype html>
<html class="reftest-wait"><head>
<style>
html {
background-image: -moz-linear-gradient(black, white 20%);
-moz-background-size: 400px 400px;
}
body {
font-size: 1em;
padding: 2em;
margin: 50px auto;
width: 28em;
border: 1px solid black;
background-color: white;
}
</style>
<script>
window.onload = function() {
setTimeout(function() {
document.body.style.width = "14em";
setTimeout(function() {
document.documentElement.removeAttribute("class");
}, 100);
}, 100);
}
</script>
</head><body>
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
</body>
</html>

View File

@ -0,0 +1,44 @@
<!doctype html>
<html><head>
<style>
html {
background-image: -moz-linear-gradient(black, white 20%);
background-repeat: repeat-x;
-moz-background-size: 1px 80%;
}
body {
font-size: 1em;
padding: 2em;
margin: 50px auto;
width: 14em;
border: 1px solid black;
background-color: white;
}
</style>
</head><body>
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
</body>
</html>

View File

@ -0,0 +1,54 @@
<!doctype html>
<html class="reftest-wait"><head>
<style>
html {
background-image: -moz-linear-gradient(black, white 20%);
background-repeat: repeat-x;
-moz-background-size: 1px 80%;
}
body {
font-size: 1em;
padding: 2em;
margin: 50px auto;
width: 28em;
border: 1px solid black;
background-color: white;
}
</style>
<script>
window.onload = function() {
setTimeout(function() {
document.body.style.width = "14em";
setTimeout(function() {
document.documentElement.removeAttribute("class");
}, 100);
}, 100);
}
</script>
</head><body>
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
pad pad pad pad pad pad pad pad
</body>
</html>

View File

@ -85,4 +85,6 @@ fails == aja-linear-2d.html aja-linear-2-ref.html # bug 526694
== aja-linear-5a.html aja-linear-5-ref.html
fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == aja-linear-6a.html aja-linear-6-ref.html # bug 526708
fails == aja-linear-6b.html aja-linear-6-ref.html # bug 522607
== height-dependence-1.html height-dependence-1-ref.html
== height-dependence-2.html height-dependence-2-ref.html
== height-dependence-3.html height-dependence-3-ref.html

View File

@ -876,6 +876,12 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty,
const nsCSSValuePairList *size =
* data->ValuePairListStorageFor(eCSSProperty__moz_background_size);
for (;;) {
if (size->mXValue.GetUnit() != eCSSUnit_Auto ||
size->mYValue.GetUnit() != eCSSUnit_Auto) {
// Non-default background-size, so can't be serialized as shorthand.
aValue.Truncate();
return NS_OK;
}
AppendCSSValueToString(eCSSProperty_background_image,
image->mValue, aValue);
aValue.Append(PRUnichar(' '));

View File

@ -413,10 +413,19 @@ struct nsStyleBackground {
};
PRUint8 mWidthType, mHeightType;
// True if the effective image size described by this depends on the size
// of the corresponding frame.
PRBool DependsOnFrameSize() const {
return mWidthType <= ePercentage || mHeightType <= ePercentage;
// True if the effective image size described by this depends on
// the size of the corresponding frame. Gradients depend on the
// frame size when their dimensions are 'auto', images don't; both
// types depend on the frame size when their dimensions are
// 'contain', 'cover', or a percentage.
PRBool DependsOnFrameSize(nsStyleImageType aType) const {
if (aType == eStyleImageType_Image) {
return mWidthType <= ePercentage || mHeightType <= ePercentage;
} else if (aType == eStyleImageType_Gradient) {
return mWidthType <= eAuto || mHeightType <= eAuto;
} else {
NS_NOTREACHED("unrecognized image type");
}
}
// Initialize nothing
@ -448,12 +457,16 @@ struct nsStyleBackground {
void SetInitialValues();
// True if the rendering of this layer might change when the size of the
// corresponding frame changes (if its position or size is a percentage of
// the frame's dimensions).
// True if the rendering of this layer might change when the size
// of the corresponding frame changes. This is true for any
// non-solid-color background whose position or size depends on
// the frame size (that is, was specified with percentages) and is
// also true for nearly all gradients. We don't currently bother
// trying to identify gradients that don't depend on the frame size.
PRBool RenderingMightDependOnFrameSize() const {
return !mImage.IsEmpty() &&
(mPosition.DependsOnFrameSize() || mSize.DependsOnFrameSize());
return (!mImage.IsEmpty() &&
(mPosition.DependsOnFrameSize() ||
mSize.DependsOnFrameSize(mImage.GetType())));
}
// An equality operator that compares the images using URL-equality

View File

@ -122,29 +122,35 @@ is(e.style.background, "", "should not have background shorthand (origin:content
//is(e.style.background, "", "should not have background shorthand (clip:content)");
//e.setAttribute("style", "background: red; -moz-background-clip: content; -moz-background-origin: content;");
//isnot(e.style.background, "", "should have background shorthand (clip:content;origin:content)");
e.setAttribute("style", "background: red; -moz-background-size: 100% 100%");
is(e.style.background, "", "should not have background shorthand (size:100% 100%)");
e.setAttribute("style", "background: red; -moz-background-size: 100% auto");
is(e.style.background, "", "should not have background shorthand (size:100% auto)");
e.setAttribute("style", "background: red; -moz-background-size: auto 100%");
is(e.style.background, "", "should not have background shorthand (size:auto 100%)");
e.setAttribute("style", "background: red; -moz-background-inline-policy: each-box");
isnot(e.style.background, "", "should have background shorthand (-moz-background-inline-policy not relevant)");
// Check that we only serialize background when the lists (of layers) for
// the subproperties are the same length.
// XXX Should change background-clip to border,padding,border and
// background-origin to border,padding,padding once serialization does
// clip/origin.
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
// background-origin to border,padding,padding and background-size to
// cover,auto,contain once serialization does clip/origin/size.
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: auto, auto, auto; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
isnot(e.style.background, "", "should have background shorthand (all lists length 3)");
e.setAttribute("style", "-moz-background-clip: border, border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
e.setAttribute("style", "-moz-background-clip: border, border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: auto, auto, auto; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
is(e.style.background, "", "should not have background shorthand (background-clip too long)");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: border, padding; -moz-background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding; -moz-background-size: auto, auto, auto; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
is(e.style.background, "", "should not have background shorthand (background-origin too short)");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png), none; background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: auto, auto, auto; background-color: blue; background-image: url(404.png), none, url(404-2.png), none; background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
is(e.style.background, "", "should not have background shorthand (background-image too long)");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: auto, auto, auto; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
is(e.style.background, "", "should not have background shorthand (background-attachment too short)");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px, bottom; background-repeat: repeat-x, repeat, no-repeat");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: auto, auto, auto; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px, bottom; background-repeat: repeat-x, repeat, no-repeat");
is(e.style.background, "", "should not have background shorthand (background-position too long)");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: auto, auto, auto; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat");
is(e.style.background, "", "should not have background shorthand (background-repeat too short)");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: cover, auto, contain, cover; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
e.setAttribute("style", "-moz-background-clip: border, border, border; -moz-background-origin: padding, padding, padding; -moz-background-size: auto, auto, auto, auto; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
is(e.style.background, "", "should not have background shorthand (-moz-background-size too long)");
// Check that we only serialize transition when the lists are the same length.

View File

@ -75,7 +75,7 @@ endif
_HARNESS_FILES = \
$(srcdir)/runreftest.py \
automation.py \
$(CURDIR)/automationutils.py \
$(topsrcdir)/build/automationutils.py \
$(NULL)
$(_DEST_DIR):

View File

@ -702,8 +702,11 @@ function OnDocumentLoad(event)
// above causes 2 assertions. So that we don't have to annotate
// the manifests for every reftest-print reftest, bump the
// assertion count by two right here.
gURLs[0].minAsserts += 2;
gURLs[0].maxAsserts += 2;
// And on Mac, it causes *three* assertions.
var xr = CC[NS_XREAPPINFO_CONTRACTID].getService(CI.nsIXULRuntime);
var count = (xr.widgetToolkit == "cocoa") ? 3 : 2;
gURLs[0].minAsserts += count;
gURLs[0].maxAsserts += count;
}
setupZoom(contentRootElement);

View File

@ -77,7 +77,12 @@ protected:
nsButtonBoxFrame(aPresShell, aContext) {}
void StartRepeat() {
nsRepeatService::GetInstance()->Start(Notify, this, 0);
if (IsActivatedOnHover()) {
// No initial delay on hover.
nsRepeatService::GetInstance()->Start(Notify, this, 0);
} else {
nsRepeatService::GetInstance()->Start(Notify, this);
}
}
void StopRepeat() {
nsRepeatService::GetInstance()->Stop(Notify, this);

View File

@ -59,7 +59,11 @@ pref("general.warnOnAboutConfig", true);
pref("browser.bookmarks.max_backups", 5);
pref("browser.cache.disk.enable", true);
#ifndef WINCE
pref("browser.cache.disk.capacity", 51200);
#else
pref("browser.cache.disk.capacity", 20000);
#endif
pref("browser.cache.memory.enable", true);
//pref("browser.cache.memory.capacity", -1);
// -1 = determine dynamically, 0 = none, n = memory capacity in kilobytes
@ -68,6 +72,7 @@ pref("browser.cache.disk_cache_ssl", false);
pref("browser.cache.check_doc_frequency", 3);
pref("browser.cache.offline.enable", true);
#ifndef WINCE
// offline cache capacity in kilobytes
pref("browser.cache.offline.capacity", 512000);
@ -78,6 +83,12 @@ pref("offline-apps.quota.max", 204800);
// the user should be warned if offline app disk usage exceeds this amount
// (in kilobytes)
pref("offline-apps.quota.warn", 51200);
#else
// Limited disk space on WinCE, tighten limits.
pref("browser.cache.offline.capacity", 15000);
pref("offline-apps.quota.max", 7000);
pref("offline-apps.quota.warn", 4000);
#endif
// Fastback caching - if this pref is negative, then we calculate the number
// of content viewers to cache based on the amount of available memory.

View File

@ -67,6 +67,7 @@ struct PrefCallbackData {
nsPrefBranch *pBranch;
nsIObserver *pObserver;
nsIWeakReference *pWeakRef;
char pDomain[1];
};
@ -591,7 +592,7 @@ NS_IMETHODIMP nsPrefBranch::AddObserver(const char *aDomain, nsIObserver *aObser
return NS_ERROR_OUT_OF_MEMORY;
}
pCallback = (PrefCallbackData *)nsMemory::Alloc(sizeof(PrefCallbackData));
pCallback = (PrefCallbackData *)NS_Alloc(sizeof(PrefCallbackData) + strlen(aDomain));
if (nsnull == pCallback)
return NS_ERROR_OUT_OF_MEMORY;
@ -613,8 +614,8 @@ NS_IMETHODIMP nsPrefBranch::AddObserver(const char *aDomain, nsIObserver *aObser
NS_ADDREF(pCallback->pObserver);
}
strcpy(pCallback->pDomain, aDomain);
mObservers->AppendElement(pCallback);
mObserverDomains.AppendElement(nsCString(aDomain));
// We must pass a fully qualified preference name to the callback
pref = getPrefName(aDomain); // aDomain == nsnull only possible failure, trapped above
@ -644,28 +645,24 @@ NS_IMETHODIMP nsPrefBranch::RemoveObserver(const char *aDomain, nsIObserver *aOb
for (i = 0; i < count; i++) {
pCallback = (PrefCallbackData *)mObservers->ElementAt(i);
if (pCallback) {
if (pCallback->pObserver == aObserver) {
domain = mObserverDomains[i];
if (domain.Equals(aDomain)) {
// We must pass a fully qualified preference name to remove the callback
pref = getPrefName(aDomain); // aDomain == nsnull only possible failure, trapped above
rv = PREF_UnregisterCallback(pref, NotifyObserver, pCallback);
if (NS_SUCCEEDED(rv)) {
// Remove this observer from our array so that nobody else can remove
// what we're trying to remove ourselves right now.
mObservers->RemoveElementAt(i);
mObserverDomains.RemoveElementAt(i);
if (pCallback->pWeakRef) {
NS_RELEASE(pCallback->pWeakRef);
} else {
NS_RELEASE(pCallback->pObserver);
}
nsMemory::Free(pCallback);
}
return rv;
if (pCallback &&
pCallback->pObserver == aObserver &&
!strcmp(pCallback->pDomain, aDomain)) {
// We must pass a fully qualified preference name to remove the callback
pref = getPrefName(aDomain); // aDomain == nsnull only possible failure, trapped above
rv = PREF_UnregisterCallback(pref, NotifyObserver, pCallback);
if (NS_SUCCEEDED(rv)) {
// Remove this observer from our array so that nobody else can remove
// what we're trying to remove ourselves right now.
mObservers->RemoveElementAt(i);
if (pCallback->pWeakRef) {
NS_RELEASE(pCallback->pWeakRef);
} else {
NS_RELEASE(pCallback->pObserver);
}
NS_Free(pCallback);
}
return rv;
}
}
@ -695,7 +692,7 @@ static nsresult NotifyObserver(const char *newpref, void *data)
observer = do_QueryReferent(pData->pWeakRef);
if (!observer) {
// this weak referenced observer went away, remove them from the list
pData->pBranch->RemoveObserver(newpref, pData->pObserver);
pData->pBranch->RemoveObserver(pData->pDomain, pData->pObserver);
return NS_OK;
}
} else {
@ -725,9 +722,8 @@ void nsPrefBranch::freeObserverList(void)
for (i = 0; i < count; ++i) {
pCallback = (PrefCallbackData *)mObservers->ElementAt(i);
if (pCallback) {
domain = mObserverDomains[i];
// We must pass a fully qualified preference name to remove the callback
pref = getPrefName(domain.get()); // can't fail because domain must be valid
pref = getPrefName(pCallback->pDomain);
// Remove this observer from our array so that nobody else can remove
// what we're trying to remove right now.
mObservers->ReplaceElementAt(nsnull, i);
@ -740,9 +736,6 @@ void nsPrefBranch::freeObserverList(void)
nsMemory::Free(pCallback);
}
}
// now empty the observer domains array in bulk
mObserverDomains.Clear();
}
delete mObservers;
mObservers = 0;

View File

@ -83,7 +83,6 @@ private:
PRInt32 mPrefRootLength;
nsAutoVoidArray *mObservers;
nsCString mPrefRoot;
nsTArray<nsCString> mObserverDomains;
PRBool mIsDefault;
};

View File

@ -64,7 +64,7 @@ interface nsIPluginStreamListener;
[ref] native nsIStreamListenerRef(nsIStreamListener *);
[ptr] native nsPluginNativeWindowPtr(nsPluginNativeWindow);
[scriptable, uuid(30C7C529-B05C-4950-B5B8-9AF673E46521)]
[scriptable, uuid(AA13B116-2AFC-4F23-8395-913C0475D173)]
interface nsIPluginHost : nsISupports
{
[noscript] void init();
@ -285,6 +285,11 @@ interface nsIPluginHost : nsISupports
* @return plugin tag object
*/
[noscript] nsIPluginTag getPluginTagForInstance(in nsIPluginInstance aInstance);
%{C++
virtual void AddIdleTimeTarget(nsIPluginInstanceOwner* objectFrame, PRBool isVisible) = 0;
virtual void RemoveIdleTimeTarget(nsIPluginInstanceOwner* objectFrame) = 0;
%}
};
%{C++

View File

@ -49,7 +49,7 @@ class nsPluginEvent;
[ref] native nsIPluginInstanceRef(nsIPluginInstance*);
[uuid(8080E717-7261-4707-B8B4-48250F47055F)]
[uuid(D8776CDC-00DF-4395-A432-2E78EBCC12B6)]
interface nsIPluginInstanceOwner : nsISupports
{
/**
@ -137,4 +137,8 @@ interface nsIPluginInstanceOwner : nsISupports
%}
void setEventModel(in PRInt32 eventModel);
%{C++
virtual void SendIdleEvent() = 0;
%}
};

View File

@ -57,6 +57,7 @@ CPPSRCS = \
nsPluginHost.cpp \
nsPluginModule.cpp \
nsJSNPRuntime.cpp \
nsPluginTags.cpp \
$(NULL)
ifeq ($(OS_ARCH), BeOS)

View File

@ -92,7 +92,6 @@
#include "nsEnumeratorUtils.h"
#include "nsXPCOM.h"
#include "nsXPCOMCID.h"
#include "nsICategoryManager.h"
#include "nsISupportsPrimitives.h"
// for the dialog
@ -226,8 +225,6 @@ PRLogModuleInfo* nsPluginLogging::gPluginLog = nsnull;
#define MAGIC_REQUEST_CONTEXT 0x01020304
nsresult PostPluginUnloadEvent(PRLibrary * aLibrary);
static nsPluginInstanceTagList *gActivePluginList;
#ifdef CALL_SAFETY_ON
@ -309,619 +306,6 @@ NS_IMETHODIMP nsPluginDocReframeEvent::Run() {
return mDocs->Clear();
}
nsPluginInstanceTag::nsPluginInstanceTag(nsPluginTag* aPluginTag,
nsIPluginInstance* aInstance,
const char * url,
PRBool aDefaultPlugin)
{
mNext = nsnull;
mPluginTag = aPluginTag;
mURL = PL_strdup(url);
mInstance = aInstance;
if (aInstance)
NS_ADDREF(aInstance);
mXPConnected = PR_FALSE;
mDefaultPlugin = aDefaultPlugin;
mStopped = PR_FALSE;
mllStopTime = LL_ZERO;
}
nsPluginInstanceTag::~nsPluginInstanceTag()
{
mPluginTag = nsnull;
if (mInstance) {
nsCOMPtr<nsIPluginInstanceOwner> owner;
mInstance->GetOwner(getter_AddRefs(owner));
if (owner)
owner->SetInstance(nsnull);
mInstance->InvalidateOwner();
NS_RELEASE(mInstance);
}
PL_strfree(mURL);
}
void nsPluginInstanceTag::setStopped(PRBool stopped)
{
mStopped = stopped;
if (mStopped) // plugin instance is told to stop
mllStopTime = PR_Now();
else
mllStopTime = LL_ZERO;
}
nsPluginInstanceTagList::nsPluginInstanceTagList()
{
mFirst = nsnull;
mLast = nsnull;
mCount = 0;
}
nsPluginInstanceTagList::~nsPluginInstanceTagList()
{
if (!mFirst)
return;
shutdown();
}
void nsPluginInstanceTagList::shutdown()
{
if (!mFirst)
return;
for (nsPluginInstanceTag * plugin = mFirst; plugin != nsnull;) {
nsPluginInstanceTag * next = plugin->mNext;
remove(plugin);
plugin = next;
}
mFirst = nsnull;
mLast = nsnull;
}
PRInt32 nsPluginInstanceTagList::add(nsPluginInstanceTag * plugin)
{
if (!mFirst) {
mFirst = plugin;
mLast = plugin;
mFirst->mNext = nsnull;
}
else {
mLast->mNext = plugin;
mLast = plugin;
}
mLast->mNext = nsnull;
mCount++;
return mCount;
}
PRBool nsPluginInstanceTagList::IsLastInstance(nsPluginInstanceTag * plugin)
{
if (!plugin)
return PR_FALSE;
if (!plugin->mPluginTag)
return PR_FALSE;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if ((p->mPluginTag == plugin->mPluginTag) && (p != plugin))
return PR_FALSE;
}
return PR_TRUE;
}
PRBool nsPluginInstanceTagList::remove(nsPluginInstanceTag * plugin)
{
if (!mFirst)
return PR_FALSE;
nsPluginInstanceTag * prev = nsnull;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p == plugin) {
PRBool lastInstance = IsLastInstance(p);
if (p == mFirst)
mFirst = p->mNext;
else
prev->mNext = p->mNext;
if (prev && !prev->mNext)
mLast = prev;
if (lastInstance) {
nsRefPtr<nsPluginTag> pluginTag = p->mPluginTag;
delete p;
if (pluginTag) {
nsresult rv;
nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
PRBool unloadPluginsASAP = PR_FALSE;
rv = pref->GetBoolPref("plugins.unloadASAP", &unloadPluginsASAP);
if (NS_SUCCEEDED(rv) && unloadPluginsASAP)
pluginTag->TryUnloadPlugin();
} else {
NS_ASSERTION(pluginTag, "pluginTag was not set, plugin not shutdown");
}
} else {
delete p;
}
mCount--;
return PR_TRUE;
}
prev = p;
}
return PR_FALSE;
}
// This method terminates all running instances of plugins and collects their
// documents to be returned through an array. This method is used
// when we are shutting down or when a plugins.refresh(1) happens.
// If aPluginTag is given, then only that plugin is terminated
void nsPluginInstanceTagList::stopRunning(nsISupportsArray* aReloadDocs,
nsPluginTag* aPluginTag)
{
if (!mFirst)
return;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!p->mStopped && p->mInstance &&
(!aPluginTag || aPluginTag == p->mPluginTag)) {
p->mInstance->SetWindow(nsnull);
p->mInstance->Stop();
p->setStopped(PR_TRUE);
// If we've been passed an array to return, lets collect all our documents,
// removing duplicates. These will be reframed (embedded) or reloaded (full-page) later
// to kickstart our instances.
if (aReloadDocs && p->mInstance) {
nsCOMPtr<nsIPluginInstanceOwner> owner;
p->mInstance->GetOwner(getter_AddRefs(owner));
if (owner) {
nsCOMPtr<nsIDocument> doc;
owner->GetDocument(getter_AddRefs(doc));
if (doc && aReloadDocs->IndexOf(doc) == -1) // don't allow for duplicates
aReloadDocs->AppendElement(doc);
}
}
}
}
}
void nsPluginInstanceTagList::removeAllStopped()
{
if (!mFirst)
return;
nsPluginInstanceTag * next = nsnull;
for (nsPluginInstanceTag * p = mFirst; p != nsnull;) {
next = p->mNext;
if (p->mStopped)
remove(p);
p = next;
}
return;
}
nsPluginInstanceTag * nsPluginInstanceTagList::find(nsIPluginInstance* instance)
{
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p->mInstance == instance)
return p;
}
return nsnull;
}
nsPluginInstanceTag * nsPluginInstanceTagList::find(const char * mimetype)
{
PRBool defaultplugin = (PL_strcmp(mimetype, "*") == 0);
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
// give it some special treatment for the default plugin first
// because we cannot tell the default plugin by asking instance for a mime type
if (defaultplugin && p->mDefaultPlugin)
return p;
if (!p->mInstance)
continue;
const char* mt;
nsresult rv = p->mInstance->GetMIMEType(&mt);
if (NS_FAILED(rv))
continue;
if (PL_strcasecmp(mt, mimetype) == 0)
return p;
}
return nsnull;
}
nsPluginInstanceTag * nsPluginInstanceTagList::findStopped(const char * url)
{
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!PL_strcmp(url, p->mURL) && p->mStopped)
return p;
}
return nsnull;
}
PRUint32 nsPluginInstanceTagList::getStoppedCount()
{
PRUint32 stoppedCount = 0;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p->mStopped)
stoppedCount++;
}
return stoppedCount;
}
nsPluginInstanceTag * nsPluginInstanceTagList::findOldestStopped()
{
nsPluginInstanceTag * res = nsnull;
PRInt64 llTime = LL_MAXINT;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!p->mStopped)
continue;
if (LL_CMP(p->mllStopTime, <, llTime)) {
llTime = p->mllStopTime;
res = p;
}
}
return res;
}
inline char* new_str(const char* str)
{
if (str == nsnull)
return nsnull;
char* result = new char[strlen(str) + 1];
if (result != nsnull)
return strcpy(result, str);
return result;
}
nsPluginTag::nsPluginTag(nsPluginTag* aPluginTag)
: mPluginHost(nsnull),
mName(aPluginTag->mName),
mDescription(aPluginTag->mDescription),
mVariants(aPluginTag->mVariants),
mMimeTypeArray(nsnull),
mMimeDescriptionArray(aPluginTag->mMimeDescriptionArray),
mExtensionsArray(nsnull),
mLibrary(nsnull),
mCanUnloadLibrary(PR_TRUE),
mXPConnected(PR_FALSE),
mIsJavaPlugin(aPluginTag->mIsJavaPlugin),
mIsNPRuntimeEnabledJavaPlugin(aPluginTag->mIsNPRuntimeEnabledJavaPlugin),
mFileName(aPluginTag->mFileName),
mFullPath(aPluginTag->mFullPath),
mVersion(aPluginTag->mVersion),
mLastModifiedTime(0),
mFlags(NS_PLUGIN_FLAG_ENABLED)
{
if (aPluginTag->mMimeTypeArray != nsnull) {
mMimeTypeArray = new char*[mVariants];
for (int i = 0; i < mVariants; i++)
mMimeTypeArray[i] = new_str(aPluginTag->mMimeTypeArray[i]);
}
if (aPluginTag->mExtensionsArray != nsnull) {
mExtensionsArray = new char*[mVariants];
for (int i = 0; i < mVariants; i++)
mExtensionsArray[i] = new_str(aPluginTag->mExtensionsArray[i]);
}
}
nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo)
: mPluginHost(nsnull),
mName(aPluginInfo->fName),
mDescription(aPluginInfo->fDescription),
mVariants(aPluginInfo->fVariantCount),
mMimeTypeArray(nsnull),
mExtensionsArray(nsnull),
mLibrary(nsnull),
#ifdef XP_MACOSX
mCanUnloadLibrary(!aPluginInfo->fBundle),
#else
mCanUnloadLibrary(PR_TRUE),
#endif
mXPConnected(PR_FALSE),
mIsJavaPlugin(PR_FALSE),
mIsNPRuntimeEnabledJavaPlugin(PR_FALSE),
mFileName(aPluginInfo->fFileName),
mFullPath(aPluginInfo->fFullPath),
mVersion(aPluginInfo->fVersion),
mLastModifiedTime(0),
mFlags(NS_PLUGIN_FLAG_ENABLED)
{
if (aPluginInfo->fMimeTypeArray != nsnull) {
mMimeTypeArray = new char*[mVariants];
for (int i = 0; i < mVariants; i++) {
if (mIsJavaPlugin && aPluginInfo->fMimeTypeArray[i] &&
strcmp(aPluginInfo->fMimeTypeArray[i],
"application/x-java-vm-npruntime") == 0) {
mIsNPRuntimeEnabledJavaPlugin = PR_TRUE;
// Stop processing here, any mimetypes after the magic "I'm a
// NPRuntime enabled Java plugin" mimetype will be ignored.
mVariants = i;
break;
}
mMimeTypeArray[i] = new_str(aPluginInfo->fMimeTypeArray[i]);
if (nsPluginHost::IsJavaMIMEType(mMimeTypeArray[i]))
mIsJavaPlugin = PR_TRUE;
}
}
if (aPluginInfo->fMimeDescriptionArray != nsnull) {
for (int i = 0; i < mVariants; i++) {
// we should cut off the list of suffixes which the mime
// description string may have, see bug 53895
// it is usually in form "some description (*.sf1, *.sf2)"
// so we can search for the opening round bracket
char cur = '\0';
char pre = '\0';
char * p = PL_strrchr(aPluginInfo->fMimeDescriptionArray[i], '(');
if (p && (p != aPluginInfo->fMimeDescriptionArray[i])) {
if ((p - 1) && *(p - 1) == ' ') {
pre = *(p - 1);
*(p - 1) = '\0';
} else {
cur = *p;
*p = '\0';
}
}
mMimeDescriptionArray.AppendElement(
aPluginInfo->fMimeDescriptionArray[i]);
// restore the original string
if (cur != '\0')
*p = cur;
if (pre != '\0')
*(p - 1) = pre;
}
} else {
mMimeDescriptionArray.SetLength(mVariants);
}
if (aPluginInfo->fExtensionArray != nsnull) {
mExtensionsArray = new char*[mVariants];
for (int i = 0; i < mVariants; i++)
mExtensionsArray[i] = new_str(aPluginInfo->fExtensionArray[i]);
}
EnsureMembersAreUTF8();
}
nsPluginTag::nsPluginTag(const char* aName,
const char* aDescription,
const char* aFileName,
const char* aFullPath,
const char* aVersion,
const char* const* aMimeTypes,
const char* const* aMimeDescriptions,
const char* const* aExtensions,
PRInt32 aVariants,
PRInt64 aLastModifiedTime,
PRBool aCanUnload,
PRBool aArgsAreUTF8)
: mPluginHost(nsnull),
mName(aName),
mDescription(aDescription),
mVariants(aVariants),
mMimeTypeArray(nsnull),
mExtensionsArray(nsnull),
mLibrary(nsnull),
mCanUnloadLibrary(aCanUnload),
mXPConnected(PR_FALSE),
mIsJavaPlugin(PR_FALSE),
mIsNPRuntimeEnabledJavaPlugin(PR_FALSE),
mFileName(aFileName),
mFullPath(aFullPath),
mVersion(aVersion),
mLastModifiedTime(aLastModifiedTime),
mFlags(0) // Caller will read in our flags from cache
{
if (aVariants) {
mMimeTypeArray = new char*[mVariants];
mExtensionsArray = new char*[mVariants];
for (PRInt32 i = 0; i < aVariants; ++i) {
if (mIsJavaPlugin && aMimeTypes[i] &&
strcmp(aMimeTypes[i], "application/x-java-vm-npruntime") == 0) {
mIsNPRuntimeEnabledJavaPlugin = PR_TRUE;
// Stop processing here, any mimetypes after the magic "I'm a
// NPRuntime enabled Java plugin" mimetype will be ignored.
mVariants = i;
break;
}
mMimeTypeArray[i] = new_str(aMimeTypes[i]);
mMimeDescriptionArray.AppendElement(aMimeDescriptions[i]);
mExtensionsArray[i] = new_str(aExtensions[i]);
if (nsPluginHost::IsJavaMIMEType(mMimeTypeArray[i]))
mIsJavaPlugin = PR_TRUE;
}
}
if (!aArgsAreUTF8)
EnsureMembersAreUTF8();
}
nsPluginTag::~nsPluginTag()
{
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
if (mMimeTypeArray) {
for (int i = 0; i < mVariants; i++)
delete[] mMimeTypeArray[i];
delete[] (mMimeTypeArray);
mMimeTypeArray = nsnull;
}
if (mExtensionsArray) {
for (int i = 0; i < mVariants; i++)
delete[] mExtensionsArray[i];
delete[] (mExtensionsArray);
mExtensionsArray = nsnull;
}
}
NS_IMPL_ISUPPORTS1(nsPluginTag, nsIPluginTag)
static nsresult ConvertToUTF8(nsIUnicodeDecoder *aUnicodeDecoder,
nsAFlatCString& aString)
{
PRInt32 numberOfBytes = aString.Length();
PRInt32 outUnicodeLen;
nsAutoString buffer;
nsresult rv = aUnicodeDecoder->GetMaxLength(aString.get(), numberOfBytes,
&outUnicodeLen);
NS_ENSURE_SUCCESS(rv, rv);
if (!EnsureStringLength(buffer, outUnicodeLen))
return NS_ERROR_OUT_OF_MEMORY;
rv = aUnicodeDecoder->Convert(aString.get(), &numberOfBytes,
buffer.BeginWriting(), &outUnicodeLen);
NS_ENSURE_SUCCESS(rv, rv);
buffer.SetLength(outUnicodeLen);
CopyUTF16toUTF8(buffer, aString);
return NS_OK;
}
nsresult nsPluginTag::EnsureMembersAreUTF8()
{
nsresult rv;
nsCOMPtr<nsIPlatformCharset> pcs =
do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIUnicodeDecoder> decoder;
nsCOMPtr<nsICharsetConverterManager> ccm =
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString charset;
rv = pcs->GetCharset(kPlatformCharsetSel_FileName, charset);
NS_ENSURE_SUCCESS(rv, rv);
if (!charset.LowerCaseEqualsLiteral("utf-8")) {
rv = ccm->GetUnicodeDecoderRaw(charset.get(), getter_AddRefs(decoder));
NS_ENSURE_SUCCESS(rv, rv);
ConvertToUTF8(decoder, mFileName);
ConvertToUTF8(decoder, mFullPath);
}
// The description of the plug-in and the various MIME type descriptions
// should be encoded in the standard plain text file encoding for this system.
// XXX should we add kPlatformCharsetSel_PluginResource?
rv = pcs->GetCharset(kPlatformCharsetSel_PlainTextInFile, charset);
NS_ENSURE_SUCCESS(rv, rv);
if (!charset.LowerCaseEqualsLiteral("utf-8")) {
rv = ccm->GetUnicodeDecoderRaw(charset.get(), getter_AddRefs(decoder));
NS_ENSURE_SUCCESS(rv, rv);
ConvertToUTF8(decoder, mName);
ConvertToUTF8(decoder, mDescription);
for (PRUint32 i = 0; i < mMimeDescriptionArray.Length(); ++i) {
ConvertToUTF8(decoder, mMimeDescriptionArray[i]);
}
}
return NS_OK;
}
void nsPluginTag::SetHost(nsPluginHost * aHost)
{
mPluginHost = aHost;
}
NS_IMETHODIMP
nsPluginTag::GetDescription(nsACString& aDescription)
{
aDescription = mDescription;
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetFilename(nsACString& aFileName)
{
aFileName = mFileName;
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetVersion(nsACString& aVersion)
{
aVersion = mVersion;
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetName(nsACString& aName)
{
aName = mName;
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetDisabled(PRBool* aDisabled)
{
*aDisabled = !HasFlag(NS_PLUGIN_FLAG_ENABLED);
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::SetDisabled(PRBool aDisabled)
{
if (HasFlag(NS_PLUGIN_FLAG_ENABLED) == !aDisabled)
return NS_OK;
if (aDisabled)
UnMark(NS_PLUGIN_FLAG_ENABLED);
else
Mark(NS_PLUGIN_FLAG_ENABLED);
mPluginHost->UpdatePluginInfo(this);
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetBlocklisted(PRBool* aBlocklisted)
{
*aBlocklisted = HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::SetBlocklisted(PRBool aBlocklisted)
{
if (HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED) == aBlocklisted)
return NS_OK;
if (aBlocklisted)
Mark(NS_PLUGIN_FLAG_BLOCKLISTED);
else
UnMark(NS_PLUGIN_FLAG_BLOCKLISTED);
mPluginHost->UpdatePluginInfo(nsnull);
return NS_OK;
}
// helper struct for asynchronous handling of plugin unloading
class nsPluginUnloadEvent : public nsRunnable {
public:
@ -946,7 +330,7 @@ NS_IMETHODIMP nsPluginUnloadEvent::Run()
}
// unload plugin asynchronously if possible, otherwise just unload now
nsresult PostPluginUnloadEvent(PRLibrary* aLibrary)
nsresult nsPluginHost::PostPluginUnloadEvent(PRLibrary* aLibrary)
{
nsCOMPtr<nsIRunnable> ev = new nsPluginUnloadEvent(aLibrary);
if (ev && NS_SUCCEEDED(NS_DispatchToCurrentThread(ev)))
@ -958,99 +342,6 @@ nsresult PostPluginUnloadEvent(PRLibrary* aLibrary)
return NS_ERROR_FAILURE;
}
void nsPluginTag::TryUnloadPlugin()
{
if (mEntryPoint) {
mEntryPoint->Shutdown();
mEntryPoint = nsnull;
}
// before we unload check if we are allowed to, see bug #61388
if (mLibrary && mCanUnloadLibrary) {
// NPAPI plugins can be unloaded now if they don't use XPConnect
if (!mXPConnected) {
// unload the plugin asynchronously by posting a PLEvent
PostPluginUnloadEvent(mLibrary);
}
else {
// add library to the unused library list to handle it later
if (mPluginHost)
mPluginHost->AddUnusedLibrary(mLibrary);
}
}
// we should zero it anyway, it is going to be unloaded by
// CleanUnsedLibraries before we need to call the library
// again so the calling code should not be fooled and reload
// the library fresh
mLibrary = nsnull;
// Remove mime types added to the category manager
// only if we were made 'active' by setting the host
if (mPluginHost) {
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
}
}
void nsPluginTag::Mark(PRUint32 mask)
{
PRBool wasEnabled = IsEnabled();
mFlags |= mask;
// Update entries in the category manager if necessary.
if (mPluginHost && wasEnabled != IsEnabled()) {
if (wasEnabled)
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
else
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginRegister);
}
}
void nsPluginTag::UnMark(PRUint32 mask)
{
PRBool wasEnabled = IsEnabled();
mFlags &= ~mask;
// Update entries in the category manager if necessary.
if (mPluginHost && wasEnabled != IsEnabled()) {
if (wasEnabled)
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
else
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginRegister);
}
}
PRBool nsPluginTag::HasFlag(PRUint32 flag)
{
return (mFlags & flag) != 0;
}
PRUint32 nsPluginTag::Flags()
{
return mFlags;
}
PRBool nsPluginTag::IsEnabled()
{
return HasFlag(NS_PLUGIN_FLAG_ENABLED) && !HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
}
PRBool nsPluginTag::Equals(nsPluginTag *aPluginTag)
{
NS_ENSURE_TRUE(aPluginTag, PR_FALSE);
if ((!mName.Equals(aPluginTag->mName)) ||
(!mDescription.Equals(aPluginTag->mDescription)) ||
(mVariants != aPluginTag->mVariants))
return PR_FALSE;
if (mVariants && mMimeTypeArray && aPluginTag->mMimeTypeArray) {
for (PRInt32 i = 0; i < mVariants; i++) {
if (PL_strcmp(mMimeTypeArray[i], aPluginTag->mMimeTypeArray[i]) != 0)
return PR_FALSE;
}
}
return PR_TRUE;
}
class nsPluginStreamListenerPeer;
class nsPluginStreamInfo : public nsINPAPIPluginStreamInfo
@ -2448,6 +1739,11 @@ nsPluginHost::nsPluginHost()
PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("nsPluginHost::ctor\n"));
PR_LogFlush();
#endif
#ifdef MAC_CARBON_PLUGINS
mVisiblePluginTimer = do_CreateInstance("@mozilla.org/timer;1");
mHiddenPluginTimer = do_CreateInstance("@mozilla.org/timer;1");
#endif
}
nsPluginHost::~nsPluginHost()
@ -2997,7 +2293,7 @@ NS_IMETHODIMP nsPluginHost::InstantiatePluginForChannel(nsIChannel* aChannel,
return NewEmbeddedPluginStreamListener(uri, aOwner, nsnull, aListener);
}
// Called by nsPluginInstanceOwner (nsObjectFrame.cpp - embedded case)
// Called by nsPluginInstanceOwner
NS_IMETHODIMP nsPluginHost::InstantiateEmbeddedPlugin(const char *aMimeType,
nsIURI* aURL,
nsIPluginInstanceOwner *aOwner)
@ -3340,80 +2636,6 @@ nsresult nsPluginHost::AddInstanceToActiveList(nsCOMPtr<nsIPlugin> aPlugin,
return NS_OK;
}
void
nsPluginTag::RegisterWithCategoryManager(PRBool aOverrideInternalTypes,
nsPluginTag::nsRegisterType aType)
{
if (!mMimeTypeArray)
return;
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginTag::RegisterWithCategoryManager plugin=%s, removing = %s\n",
mFileName.get(), aType == ePluginUnregister ? "yes" : "no"));
nsCOMPtr<nsICategoryManager> catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
if (!catMan)
return;
const char *contractId = "@mozilla.org/content/plugin/document-loader-factory;1";
nsCOMPtr<nsIPrefBranch> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (!psvc)
return; // NS_ERROR_OUT_OF_MEMORY
// A preference controls whether or not the full page plugin is disabled for
// a particular type. The string must be in the form:
// type1,type2,type3,type4
// Note: need an actual interface to control this and subsequent disabling
// (and other plugin host settings) so applications can reliably disable
// plugins - without relying on implementation details such as prefs/category
// manager entries.
nsXPIDLCString overrideTypes;
psvc->GetCharPref("plugin.disable_full_page_plugin_for_types", getter_Copies(overrideTypes));
nsCAutoString overrideTypesFormatted;
overrideTypesFormatted.Assign(',');
overrideTypesFormatted += overrideTypes;
overrideTypesFormatted.Append(',');
nsACString::const_iterator start, end;
for (int i = 0; i < mVariants; i++) {
if (aType == ePluginUnregister) {
nsXPIDLCString value;
if (NS_SUCCEEDED(catMan->GetCategoryEntry("Gecko-Content-Viewers",
mMimeTypeArray[i],
getter_Copies(value)))) {
// Only delete the entry if a plugin registered for it
if (strcmp(value, contractId) == 0) {
catMan->DeleteCategoryEntry("Gecko-Content-Viewers",
mMimeTypeArray[i],
PR_TRUE);
}
}
} else {
overrideTypesFormatted.BeginReading(start);
overrideTypesFormatted.EndReading(end);
nsDependentCString mimeType(mMimeTypeArray[i]);
nsCAutoString commaSeparated;
commaSeparated.Assign(',');
commaSeparated += mimeType;
commaSeparated.Append(',');
if (!FindInReadable(commaSeparated, start, end)) {
catMan->AddCategoryEntry("Gecko-Content-Viewers",
mMimeTypeArray[i],
contractId,
PR_FALSE, /* persist: broken by bug 193031 */
aOverrideInternalTypes, /* replace if we're told to */
nsnull);
}
}
PLUGIN_LOG(PLUGIN_LOG_NOISY,
("nsPluginTag::RegisterWithCategoryManager mime=%s, plugin=%s\n",
mMimeTypeArray[i], mFileName.get()));
}
}
NS_IMETHODIMP nsPluginHost::SetUpPluginInstance(const char *aMimeType,
nsIURI *aURL,
nsIPluginInstanceOwner *aOwner)
@ -3536,9 +2758,14 @@ nsPluginHost::TrySetUpPluginInstance(const char *aMimeType,
// it is adreffed here
aOwner->SetInstance(instance);
result = instance->Initialize(aOwner, mimetype); // this should not addref the instance or owner
if (NS_FAILED(result)) // except in some cases not Java, see bug 140931
return result; // our COM pointer will free the peer
// this should not addref the instance or owner
// except in some cases not Java, see bug 140931
// our COM pointer will free the peer
result = instance->Initialize(aOwner, mimetype);
if (NS_FAILED(result)) {
aOwner->SetInstance(nsnull);
return result;
}
// instance and peer will be addreffed here
result = AddInstanceToActiveList(plugin, instance, aURL, PR_FALSE);
@ -3600,8 +2827,10 @@ nsPluginHost::SetUpDefaultPluginInstance(const char *aMimeType,
// this should not addref the instance or owner
result = instance->Initialize(aOwner, mimetype);
if (NS_FAILED(result))
if (NS_FAILED(result)) {
aOwner->SetInstance(nsnull);
return result;
}
// instance will be addreffed here
result = AddInstanceToActiveList(plugin, instance, aURL, PR_TRUE);
@ -5881,6 +5110,76 @@ nsresult nsPluginHost::AddUnusedLibrary(PRLibrary * aLibrary)
return NS_OK;
}
#ifdef MAC_CARBON_PLUGINS
// Flash requires a minimum of 8 events per second to avoid audio skipping.
// Since WebKit uses a hidden plugin event rate of 4 events per second Flash
// uses a Carbon timer for WebKit which fires at 8 events per second.
#define HIDDEN_PLUGIN_DELAY 125
#define VISIBLE_PLUGIN_DELAY 20
#endif
void nsPluginHost::AddIdleTimeTarget(nsIPluginInstanceOwner* objectFrame, PRBool isVisible)
{
#ifdef MAC_CARBON_PLUGINS
nsTObserverArray<nsIPluginInstanceOwner*> *targetArray;
if (isVisible) {
targetArray = &mVisibleTimerTargets;
} else {
targetArray = &mHiddenTimerTargets;
}
if (targetArray->Contains(objectFrame)) {
return;
}
targetArray->AppendElement(objectFrame);
if (targetArray->Length() == 1) {
if (isVisible) {
mVisiblePluginTimer->InitWithCallback(this, VISIBLE_PLUGIN_DELAY, nsITimer::TYPE_REPEATING_SLACK);
} else {
mHiddenPluginTimer->InitWithCallback(this, HIDDEN_PLUGIN_DELAY, nsITimer::TYPE_REPEATING_SLACK);
}
}
#endif
}
void nsPluginHost::RemoveIdleTimeTarget(nsIPluginInstanceOwner* objectFrame)
{
#ifdef MAC_CARBON_PLUGINS
PRBool visibleRemoved = mVisibleTimerTargets.RemoveElement(objectFrame);
if (visibleRemoved && mVisibleTimerTargets.IsEmpty()) {
mVisiblePluginTimer->Cancel();
}
PRBool hiddenRemoved = mHiddenTimerTargets.RemoveElement(objectFrame);
if (hiddenRemoved && mHiddenTimerTargets.IsEmpty()) {
mHiddenPluginTimer->Cancel();
}
NS_ASSERTION(!(hiddenRemoved && visibleRemoved), "Plugin instance received visible and hidden idle event notifications");
#endif
}
NS_IMETHODIMP nsPluginHost::Notify(nsITimer* timer)
{
#ifdef MAC_CARBON_PLUGINS
if (timer == mVisiblePluginTimer) {
nsTObserverArray<nsIPluginInstanceOwner*>::ForwardIterator iter(mVisibleTimerTargets);
while (iter.HasMore()) {
iter.GetNext()->SendIdleEvent();
}
return NS_OK;
} else if (timer == mHiddenPluginTimer) {
nsTObserverArray<nsIPluginInstanceOwner*>::ForwardIterator iter(mHiddenTimerTargets);
while (iter.HasMore()) {
iter.GetNext()->SendIdleEvent();
}
return NS_OK;
}
#endif
return NS_ERROR_FAILURE;
}
nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request,
nsISupports* aContext)
{

View File

@ -58,132 +58,22 @@
#include "nsWeakReference.h"
#include "nsThreadUtils.h"
#include "nsTArray.h"
#include "nsTObserverArray.h"
#include "nsITimer.h"
#include "nsPluginTags.h"
class nsNPAPIPlugin;
class nsIComponentManager;
class nsIFile;
class nsIChannel;
class nsPluginHost;
// Remember that flags are written out to pluginreg.dat, be careful
// changing their meaning.
#define NS_PLUGIN_FLAG_ENABLED 0x0001 // is this plugin enabled?
// no longer used 0x0002 // reuse only if regenerating pluginreg.dat
#define NS_PLUGIN_FLAG_FROMCACHE 0x0004 // this plugintag info was loaded from cache
#define NS_PLUGIN_FLAG_UNWANTED 0x0008 // this is an unwanted plugin
#define NS_PLUGIN_FLAG_BLOCKLISTED 0x0010 // this is a blocklisted plugin
// A linked-list of plugin information that is used for instantiating plugins
// and reflecting plugin information into JavaScript.
class nsPluginTag : public nsIPluginTag
{
public:
enum nsRegisterType {
ePluginRegister,
ePluginUnregister
};
NS_DECL_ISUPPORTS
NS_DECL_NSIPLUGINTAG
nsPluginTag(nsPluginTag* aPluginTag);
nsPluginTag(nsPluginInfo* aPluginInfo);
nsPluginTag(const char* aName,
const char* aDescription,
const char* aFileName,
const char* aFullPath,
const char* aVersion,
const char* const* aMimeTypes,
const char* const* aMimeDescriptions,
const char* const* aExtensions,
PRInt32 aVariants,
PRInt64 aLastModifiedTime = 0,
PRBool aCanUnload = PR_TRUE,
PRBool aArgsAreUTF8 = PR_FALSE);
~nsPluginTag();
void SetHost(nsPluginHost * aHost);
void TryUnloadPlugin();
void Mark(PRUint32 mask);
void UnMark(PRUint32 mask);
PRBool HasFlag(PRUint32 flag);
PRUint32 Flags();
PRBool Equals(nsPluginTag* aPluginTag);
PRBool IsEnabled();
void RegisterWithCategoryManager(PRBool aOverrideInternalTypes,
nsRegisterType aType = ePluginRegister);
nsRefPtr<nsPluginTag> mNext;
nsPluginHost *mPluginHost;
nsCString mName; // UTF-8
nsCString mDescription; // UTF-8
PRInt32 mVariants;
char **mMimeTypeArray;
nsTArray<nsCString> mMimeDescriptionArray; // UTF-8
char **mExtensionsArray;
PRLibrary *mLibrary;
nsCOMPtr<nsIPlugin> mEntryPoint;
PRPackedBool mCanUnloadLibrary;
PRPackedBool mXPConnected;
PRPackedBool mIsJavaPlugin;
PRPackedBool mIsNPRuntimeEnabledJavaPlugin;
nsCString mFileName; // UTF-8
nsCString mFullPath; // UTF-8
nsCString mVersion; // UTF-8
PRInt64 mLastModifiedTime;
private:
PRUint32 mFlags;
nsresult EnsureMembersAreUTF8();
};
struct nsPluginInstanceTag
{
nsPluginInstanceTag* mNext;
char* mURL;
nsRefPtr<nsPluginTag> mPluginTag;
nsIPluginInstance* mInstance;
PRTime mllStopTime;
PRPackedBool mStopped;
PRPackedBool mDefaultPlugin;
PRPackedBool mXPConnected;
// Array holding all opened stream listeners for this entry
nsCOMPtr <nsISupportsArray> mStreams;
nsPluginInstanceTag(nsPluginTag* aPluginTag,
nsIPluginInstance* aInstance,
const char * url,
PRBool aDefaultPlugin);
~nsPluginInstanceTag();
void setStopped(PRBool stopped);
};
class nsPluginInstanceTagList
{
public:
nsPluginInstanceTag *mFirst;
nsPluginInstanceTag *mLast;
PRInt32 mCount;
nsPluginInstanceTagList();
~nsPluginInstanceTagList();
void shutdown();
PRBool add(nsPluginInstanceTag *plugin);
PRBool remove(nsPluginInstanceTag *plugin);
nsPluginInstanceTag *find(nsIPluginInstance *instance);
nsPluginInstanceTag *find(const char *mimetype);
nsPluginInstanceTag *findStopped(const char *url);
PRUint32 getStoppedCount();
nsPluginInstanceTag *findOldestStopped();
void removeAllStopped();
void stopRunning(nsISupportsArray *aReloadDocs, nsPluginTag *aPluginTag);
PRBool IsLastInstance(nsPluginInstanceTag *plugin);
};
#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
#define MAC_CARBON_PLUGINS
#endif
class nsPluginHost : public nsIPluginHost,
public nsIObserver,
public nsITimerCallback,
public nsSupportsWeakReference
{
public:
@ -198,6 +88,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPLUGINHOST
NS_DECL_NSIOBSERVER
NS_DECL_NSITIMERCALLBACK
NS_IMETHOD
GetURL(nsISupports* pluginInst,
@ -266,6 +157,11 @@ public:
static nsresult GetPrompt(nsIPluginInstanceOwner *aOwner, nsIPrompt **aPrompt);
static nsresult PostPluginUnloadEvent(PRLibrary* aLibrary);
void AddIdleTimeTarget(nsIPluginInstanceOwner* objectFrame, PRBool isVisible);
void RemoveIdleTimeTarget(nsIPluginInstanceOwner* objectFrame);
private:
nsresult
TrySetUpPluginInstance(const char *aMimeType, nsIURI *aURL, nsIPluginInstanceOwner *aOwner);
@ -373,6 +269,13 @@ private:
// We need to hold a global ptr to ourselves because we register for
// two different CIDs for some reason...
static nsPluginHost* sInst;
#ifdef MAC_CARBON_PLUGINS
nsCOMPtr<nsITimer> mVisiblePluginTimer;
nsTObserverArray<nsIPluginInstanceOwner*> mVisibleTimerTargets;
nsCOMPtr<nsITimer> mHiddenPluginTimer;
nsTObserverArray<nsIPluginInstanceOwner*> mHiddenTimerTargets;
#endif
};
class NS_STACK_CLASS PluginDestructionGuard : protected PRCList

View File

@ -0,0 +1,842 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Sean Echevarria <sean@beatnik.com>
* Håkan Waara <hwaara@chello.se>
* Josh Aas <josh@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsPluginTags.h"
#include "prlink.h"
#include "plstr.h"
#include "nsIPluginInstanceOwner.h"
#include "nsIDocument.h"
#include "nsServiceManagerUtils.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsPluginsDir.h"
#include "nsPluginHost.h"
#include "nsIUnicodeDecoder.h"
#include "nsIPlatformCharset.h"
#include "nsICharsetConverterManager.h"
#include "nsPluginLogging.h"
#include "nsICategoryManager.h"
inline char* new_str(const char* str)
{
if (str == nsnull)
return nsnull;
char* result = new char[strlen(str) + 1];
if (result != nsnull)
return strcpy(result, str);
return result;
}
/* nsPluginTag */
nsPluginTag::nsPluginTag(nsPluginTag* aPluginTag)
: mPluginHost(nsnull),
mName(aPluginTag->mName),
mDescription(aPluginTag->mDescription),
mVariants(aPluginTag->mVariants),
mMimeTypeArray(nsnull),
mMimeDescriptionArray(aPluginTag->mMimeDescriptionArray),
mExtensionsArray(nsnull),
mLibrary(nsnull),
mCanUnloadLibrary(PR_TRUE),
mXPConnected(PR_FALSE),
mIsJavaPlugin(aPluginTag->mIsJavaPlugin),
mIsNPRuntimeEnabledJavaPlugin(aPluginTag->mIsNPRuntimeEnabledJavaPlugin),
mFileName(aPluginTag->mFileName),
mFullPath(aPluginTag->mFullPath),
mVersion(aPluginTag->mVersion),
mLastModifiedTime(0),
mFlags(NS_PLUGIN_FLAG_ENABLED)
{
if (aPluginTag->mMimeTypeArray != nsnull) {
mMimeTypeArray = new char*[mVariants];
for (int i = 0; i < mVariants; i++)
mMimeTypeArray[i] = new_str(aPluginTag->mMimeTypeArray[i]);
}
if (aPluginTag->mExtensionsArray != nsnull) {
mExtensionsArray = new char*[mVariants];
for (int i = 0; i < mVariants; i++)
mExtensionsArray[i] = new_str(aPluginTag->mExtensionsArray[i]);
}
}
nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo)
: mPluginHost(nsnull),
mName(aPluginInfo->fName),
mDescription(aPluginInfo->fDescription),
mVariants(aPluginInfo->fVariantCount),
mMimeTypeArray(nsnull),
mExtensionsArray(nsnull),
mLibrary(nsnull),
#ifdef XP_MACOSX
mCanUnloadLibrary(!aPluginInfo->fBundle),
#else
mCanUnloadLibrary(PR_TRUE),
#endif
mXPConnected(PR_FALSE),
mIsJavaPlugin(PR_FALSE),
mIsNPRuntimeEnabledJavaPlugin(PR_FALSE),
mFileName(aPluginInfo->fFileName),
mFullPath(aPluginInfo->fFullPath),
mVersion(aPluginInfo->fVersion),
mLastModifiedTime(0),
mFlags(NS_PLUGIN_FLAG_ENABLED)
{
if (aPluginInfo->fMimeTypeArray != nsnull) {
mMimeTypeArray = new char*[mVariants];
for (int i = 0; i < mVariants; i++) {
if (mIsJavaPlugin && aPluginInfo->fMimeTypeArray[i] &&
strcmp(aPluginInfo->fMimeTypeArray[i],
"application/x-java-vm-npruntime") == 0) {
mIsNPRuntimeEnabledJavaPlugin = PR_TRUE;
// Stop processing here, any mimetypes after the magic "I'm a
// NPRuntime enabled Java plugin" mimetype will be ignored.
mVariants = i;
break;
}
mMimeTypeArray[i] = new_str(aPluginInfo->fMimeTypeArray[i]);
if (nsPluginHost::IsJavaMIMEType(mMimeTypeArray[i]))
mIsJavaPlugin = PR_TRUE;
}
}
if (aPluginInfo->fMimeDescriptionArray != nsnull) {
for (int i = 0; i < mVariants; i++) {
// we should cut off the list of suffixes which the mime
// description string may have, see bug 53895
// it is usually in form "some description (*.sf1, *.sf2)"
// so we can search for the opening round bracket
char cur = '\0';
char pre = '\0';
char * p = PL_strrchr(aPluginInfo->fMimeDescriptionArray[i], '(');
if (p && (p != aPluginInfo->fMimeDescriptionArray[i])) {
if ((p - 1) && *(p - 1) == ' ') {
pre = *(p - 1);
*(p - 1) = '\0';
} else {
cur = *p;
*p = '\0';
}
}
mMimeDescriptionArray.AppendElement(
aPluginInfo->fMimeDescriptionArray[i]);
// restore the original string
if (cur != '\0')
*p = cur;
if (pre != '\0')
*(p - 1) = pre;
}
} else {
mMimeDescriptionArray.SetLength(mVariants);
}
if (aPluginInfo->fExtensionArray != nsnull) {
mExtensionsArray = new char*[mVariants];
for (int i = 0; i < mVariants; i++)
mExtensionsArray[i] = new_str(aPluginInfo->fExtensionArray[i]);
}
EnsureMembersAreUTF8();
}
nsPluginTag::nsPluginTag(const char* aName,
const char* aDescription,
const char* aFileName,
const char* aFullPath,
const char* aVersion,
const char* const* aMimeTypes,
const char* const* aMimeDescriptions,
const char* const* aExtensions,
PRInt32 aVariants,
PRInt64 aLastModifiedTime,
PRBool aCanUnload,
PRBool aArgsAreUTF8)
: mPluginHost(nsnull),
mName(aName),
mDescription(aDescription),
mVariants(aVariants),
mMimeTypeArray(nsnull),
mExtensionsArray(nsnull),
mLibrary(nsnull),
mCanUnloadLibrary(aCanUnload),
mXPConnected(PR_FALSE),
mIsJavaPlugin(PR_FALSE),
mIsNPRuntimeEnabledJavaPlugin(PR_FALSE),
mFileName(aFileName),
mFullPath(aFullPath),
mVersion(aVersion),
mLastModifiedTime(aLastModifiedTime),
mFlags(0) // Caller will read in our flags from cache
{
if (aVariants) {
mMimeTypeArray = new char*[mVariants];
mExtensionsArray = new char*[mVariants];
for (PRInt32 i = 0; i < aVariants; ++i) {
if (mIsJavaPlugin && aMimeTypes[i] &&
strcmp(aMimeTypes[i], "application/x-java-vm-npruntime") == 0) {
mIsNPRuntimeEnabledJavaPlugin = PR_TRUE;
// Stop processing here, any mimetypes after the magic "I'm a
// NPRuntime enabled Java plugin" mimetype will be ignored.
mVariants = i;
break;
}
mMimeTypeArray[i] = new_str(aMimeTypes[i]);
mMimeDescriptionArray.AppendElement(aMimeDescriptions[i]);
mExtensionsArray[i] = new_str(aExtensions[i]);
if (nsPluginHost::IsJavaMIMEType(mMimeTypeArray[i]))
mIsJavaPlugin = PR_TRUE;
}
}
if (!aArgsAreUTF8)
EnsureMembersAreUTF8();
}
nsPluginTag::~nsPluginTag()
{
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
if (mMimeTypeArray) {
for (int i = 0; i < mVariants; i++)
delete[] mMimeTypeArray[i];
delete[] (mMimeTypeArray);
mMimeTypeArray = nsnull;
}
if (mExtensionsArray) {
for (int i = 0; i < mVariants; i++)
delete[] mExtensionsArray[i];
delete[] (mExtensionsArray);
mExtensionsArray = nsnull;
}
}
NS_IMPL_ISUPPORTS1(nsPluginTag, nsIPluginTag)
static nsresult ConvertToUTF8(nsIUnicodeDecoder *aUnicodeDecoder,
nsAFlatCString& aString)
{
PRInt32 numberOfBytes = aString.Length();
PRInt32 outUnicodeLen;
nsAutoString buffer;
nsresult rv = aUnicodeDecoder->GetMaxLength(aString.get(), numberOfBytes,
&outUnicodeLen);
NS_ENSURE_SUCCESS(rv, rv);
if (!EnsureStringLength(buffer, outUnicodeLen))
return NS_ERROR_OUT_OF_MEMORY;
rv = aUnicodeDecoder->Convert(aString.get(), &numberOfBytes,
buffer.BeginWriting(), &outUnicodeLen);
NS_ENSURE_SUCCESS(rv, rv);
buffer.SetLength(outUnicodeLen);
CopyUTF16toUTF8(buffer, aString);
return NS_OK;
}
nsresult nsPluginTag::EnsureMembersAreUTF8()
{
nsresult rv;
nsCOMPtr<nsIPlatformCharset> pcs =
do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIUnicodeDecoder> decoder;
nsCOMPtr<nsICharsetConverterManager> ccm =
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString charset;
rv = pcs->GetCharset(kPlatformCharsetSel_FileName, charset);
NS_ENSURE_SUCCESS(rv, rv);
if (!charset.LowerCaseEqualsLiteral("utf-8")) {
rv = ccm->GetUnicodeDecoderRaw(charset.get(), getter_AddRefs(decoder));
NS_ENSURE_SUCCESS(rv, rv);
ConvertToUTF8(decoder, mFileName);
ConvertToUTF8(decoder, mFullPath);
}
// The description of the plug-in and the various MIME type descriptions
// should be encoded in the standard plain text file encoding for this system.
// XXX should we add kPlatformCharsetSel_PluginResource?
rv = pcs->GetCharset(kPlatformCharsetSel_PlainTextInFile, charset);
NS_ENSURE_SUCCESS(rv, rv);
if (!charset.LowerCaseEqualsLiteral("utf-8")) {
rv = ccm->GetUnicodeDecoderRaw(charset.get(), getter_AddRefs(decoder));
NS_ENSURE_SUCCESS(rv, rv);
ConvertToUTF8(decoder, mName);
ConvertToUTF8(decoder, mDescription);
for (PRUint32 i = 0; i < mMimeDescriptionArray.Length(); ++i) {
ConvertToUTF8(decoder, mMimeDescriptionArray[i]);
}
}
return NS_OK;
}
void nsPluginTag::SetHost(nsPluginHost * aHost)
{
mPluginHost = aHost;
}
NS_IMETHODIMP
nsPluginTag::GetDescription(nsACString& aDescription)
{
aDescription = mDescription;
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetFilename(nsACString& aFileName)
{
aFileName = mFileName;
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetVersion(nsACString& aVersion)
{
aVersion = mVersion;
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetName(nsACString& aName)
{
aName = mName;
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetDisabled(PRBool* aDisabled)
{
*aDisabled = !HasFlag(NS_PLUGIN_FLAG_ENABLED);
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::SetDisabled(PRBool aDisabled)
{
if (HasFlag(NS_PLUGIN_FLAG_ENABLED) == !aDisabled)
return NS_OK;
if (aDisabled)
UnMark(NS_PLUGIN_FLAG_ENABLED);
else
Mark(NS_PLUGIN_FLAG_ENABLED);
mPluginHost->UpdatePluginInfo(this);
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetBlocklisted(PRBool* aBlocklisted)
{
*aBlocklisted = HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::SetBlocklisted(PRBool aBlocklisted)
{
if (HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED) == aBlocklisted)
return NS_OK;
if (aBlocklisted)
Mark(NS_PLUGIN_FLAG_BLOCKLISTED);
else
UnMark(NS_PLUGIN_FLAG_BLOCKLISTED);
mPluginHost->UpdatePluginInfo(nsnull);
return NS_OK;
}
void
nsPluginTag::RegisterWithCategoryManager(PRBool aOverrideInternalTypes,
nsPluginTag::nsRegisterType aType)
{
if (!mMimeTypeArray)
return;
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginTag::RegisterWithCategoryManager plugin=%s, removing = %s\n",
mFileName.get(), aType == ePluginUnregister ? "yes" : "no"));
nsCOMPtr<nsICategoryManager> catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
if (!catMan)
return;
const char *contractId = "@mozilla.org/content/plugin/document-loader-factory;1";
nsCOMPtr<nsIPrefBranch> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (!psvc)
return; // NS_ERROR_OUT_OF_MEMORY
// A preference controls whether or not the full page plugin is disabled for
// a particular type. The string must be in the form:
// type1,type2,type3,type4
// Note: need an actual interface to control this and subsequent disabling
// (and other plugin host settings) so applications can reliably disable
// plugins - without relying on implementation details such as prefs/category
// manager entries.
nsXPIDLCString overrideTypes;
psvc->GetCharPref("plugin.disable_full_page_plugin_for_types", getter_Copies(overrideTypes));
nsCAutoString overrideTypesFormatted;
overrideTypesFormatted.Assign(',');
overrideTypesFormatted += overrideTypes;
overrideTypesFormatted.Append(',');
nsACString::const_iterator start, end;
for (int i = 0; i < mVariants; i++) {
if (aType == ePluginUnregister) {
nsXPIDLCString value;
if (NS_SUCCEEDED(catMan->GetCategoryEntry("Gecko-Content-Viewers",
mMimeTypeArray[i],
getter_Copies(value)))) {
// Only delete the entry if a plugin registered for it
if (strcmp(value, contractId) == 0) {
catMan->DeleteCategoryEntry("Gecko-Content-Viewers",
mMimeTypeArray[i],
PR_TRUE);
}
}
} else {
overrideTypesFormatted.BeginReading(start);
overrideTypesFormatted.EndReading(end);
nsDependentCString mimeType(mMimeTypeArray[i]);
nsCAutoString commaSeparated;
commaSeparated.Assign(',');
commaSeparated += mimeType;
commaSeparated.Append(',');
if (!FindInReadable(commaSeparated, start, end)) {
catMan->AddCategoryEntry("Gecko-Content-Viewers",
mMimeTypeArray[i],
contractId,
PR_FALSE, /* persist: broken by bug 193031 */
aOverrideInternalTypes, /* replace if we're told to */
nsnull);
}
}
PLUGIN_LOG(PLUGIN_LOG_NOISY,
("nsPluginTag::RegisterWithCategoryManager mime=%s, plugin=%s\n",
mMimeTypeArray[i], mFileName.get()));
}
}
void nsPluginTag::Mark(PRUint32 mask)
{
PRBool wasEnabled = IsEnabled();
mFlags |= mask;
// Update entries in the category manager if necessary.
if (mPluginHost && wasEnabled != IsEnabled()) {
if (wasEnabled)
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
else
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginRegister);
}
}
void nsPluginTag::UnMark(PRUint32 mask)
{
PRBool wasEnabled = IsEnabled();
mFlags &= ~mask;
// Update entries in the category manager if necessary.
if (mPluginHost && wasEnabled != IsEnabled()) {
if (wasEnabled)
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
else
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginRegister);
}
}
PRBool nsPluginTag::HasFlag(PRUint32 flag)
{
return (mFlags & flag) != 0;
}
PRUint32 nsPluginTag::Flags()
{
return mFlags;
}
PRBool nsPluginTag::IsEnabled()
{
return HasFlag(NS_PLUGIN_FLAG_ENABLED) && !HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
}
PRBool nsPluginTag::Equals(nsPluginTag *aPluginTag)
{
NS_ENSURE_TRUE(aPluginTag, PR_FALSE);
if ((!mName.Equals(aPluginTag->mName)) ||
(!mDescription.Equals(aPluginTag->mDescription)) ||
(mVariants != aPluginTag->mVariants))
return PR_FALSE;
if (mVariants && mMimeTypeArray && aPluginTag->mMimeTypeArray) {
for (PRInt32 i = 0; i < mVariants; i++) {
if (PL_strcmp(mMimeTypeArray[i], aPluginTag->mMimeTypeArray[i]) != 0)
return PR_FALSE;
}
}
return PR_TRUE;
}
void nsPluginTag::TryUnloadPlugin()
{
if (mEntryPoint) {
mEntryPoint->Shutdown();
mEntryPoint = nsnull;
}
// before we unload check if we are allowed to, see bug #61388
if (mLibrary && mCanUnloadLibrary) {
// NPAPI plugins can be unloaded now if they don't use XPConnect
if (!mXPConnected) {
// unload the plugin asynchronously by posting a PLEvent
nsPluginHost::PostPluginUnloadEvent(mLibrary);
}
else {
// add library to the unused library list to handle it later
if (mPluginHost)
mPluginHost->AddUnusedLibrary(mLibrary);
}
}
// we should zero it anyway, it is going to be unloaded by
// CleanUnsedLibraries before we need to call the library
// again so the calling code should not be fooled and reload
// the library fresh
mLibrary = nsnull;
// Remove mime types added to the category manager
// only if we were made 'active' by setting the host
if (mPluginHost) {
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
}
}
/* nsPluginInstanceTag */
nsPluginInstanceTag::nsPluginInstanceTag(nsPluginTag* aPluginTag,
nsIPluginInstance* aInstance,
const char * url,
PRBool aDefaultPlugin)
{
mNext = nsnull;
mPluginTag = aPluginTag;
mURL = PL_strdup(url);
mInstance = aInstance;
if (aInstance)
NS_ADDREF(aInstance);
mXPConnected = PR_FALSE;
mDefaultPlugin = aDefaultPlugin;
mStopped = PR_FALSE;
mllStopTime = LL_ZERO;
}
nsPluginInstanceTag::~nsPluginInstanceTag()
{
mPluginTag = nsnull;
if (mInstance) {
nsCOMPtr<nsIPluginInstanceOwner> owner;
mInstance->GetOwner(getter_AddRefs(owner));
if (owner)
owner->SetInstance(nsnull);
mInstance->InvalidateOwner();
NS_RELEASE(mInstance);
}
PL_strfree(mURL);
}
void nsPluginInstanceTag::setStopped(PRBool stopped)
{
mStopped = stopped;
if (mStopped) // plugin instance is told to stop
mllStopTime = PR_Now();
else
mllStopTime = LL_ZERO;
}
/* nsPluginInstanceTagList */
nsPluginInstanceTagList::nsPluginInstanceTagList()
{
mFirst = nsnull;
mLast = nsnull;
mCount = 0;
}
nsPluginInstanceTagList::~nsPluginInstanceTagList()
{
if (!mFirst)
return;
shutdown();
}
void nsPluginInstanceTagList::shutdown()
{
if (!mFirst)
return;
for (nsPluginInstanceTag * plugin = mFirst; plugin != nsnull;) {
nsPluginInstanceTag * next = plugin->mNext;
remove(plugin);
plugin = next;
}
mFirst = nsnull;
mLast = nsnull;
}
PRInt32 nsPluginInstanceTagList::add(nsPluginInstanceTag * plugin)
{
if (!mFirst) {
mFirst = plugin;
mLast = plugin;
mFirst->mNext = nsnull;
}
else {
mLast->mNext = plugin;
mLast = plugin;
}
mLast->mNext = nsnull;
mCount++;
return mCount;
}
PRBool nsPluginInstanceTagList::IsLastInstance(nsPluginInstanceTag * plugin)
{
if (!plugin)
return PR_FALSE;
if (!plugin->mPluginTag)
return PR_FALSE;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if ((p->mPluginTag == plugin->mPluginTag) && (p != plugin))
return PR_FALSE;
}
return PR_TRUE;
}
PRBool nsPluginInstanceTagList::remove(nsPluginInstanceTag * plugin)
{
if (!mFirst)
return PR_FALSE;
nsPluginInstanceTag * prev = nsnull;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p == plugin) {
PRBool lastInstance = IsLastInstance(p);
if (p == mFirst)
mFirst = p->mNext;
else
prev->mNext = p->mNext;
if (prev && !prev->mNext)
mLast = prev;
if (lastInstance) {
nsRefPtr<nsPluginTag> pluginTag = p->mPluginTag;
delete p;
if (pluginTag) {
nsresult rv;
nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
PRBool unloadPluginsASAP = PR_FALSE;
rv = pref->GetBoolPref("plugins.unloadASAP", &unloadPluginsASAP);
if (NS_SUCCEEDED(rv) && unloadPluginsASAP)
pluginTag->TryUnloadPlugin();
} else {
NS_ASSERTION(pluginTag, "pluginTag was not set, plugin not shutdown");
}
} else {
delete p;
}
mCount--;
return PR_TRUE;
}
prev = p;
}
return PR_FALSE;
}
// This method terminates all running instances of plugins and collects their
// documents to be returned through an array. This method is used
// when we are shutting down or when a plugins.refresh(1) happens.
// If aPluginTag is given, then only that plugin is terminated
void nsPluginInstanceTagList::stopRunning(nsISupportsArray* aReloadDocs,
nsPluginTag* aPluginTag)
{
if (!mFirst)
return;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!p->mStopped && p->mInstance &&
(!aPluginTag || aPluginTag == p->mPluginTag)) {
p->mInstance->SetWindow(nsnull);
p->mInstance->Stop();
p->setStopped(PR_TRUE);
// If we've been passed an array to return, lets collect all our documents,
// removing duplicates. These will be reframed (embedded) or reloaded (full-page) later
// to kickstart our instances.
if (aReloadDocs && p->mInstance) {
nsCOMPtr<nsIPluginInstanceOwner> owner;
p->mInstance->GetOwner(getter_AddRefs(owner));
if (owner) {
nsCOMPtr<nsIDocument> doc;
owner->GetDocument(getter_AddRefs(doc));
if (doc && aReloadDocs->IndexOf(doc) == -1) // don't allow for duplicates
aReloadDocs->AppendElement(doc);
}
}
}
}
}
void nsPluginInstanceTagList::removeAllStopped()
{
if (!mFirst)
return;
nsPluginInstanceTag * next = nsnull;
for (nsPluginInstanceTag * p = mFirst; p != nsnull;) {
next = p->mNext;
if (p->mStopped)
remove(p);
p = next;
}
return;
}
nsPluginInstanceTag * nsPluginInstanceTagList::find(nsIPluginInstance* instance)
{
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p->mInstance == instance)
return p;
}
return nsnull;
}
nsPluginInstanceTag * nsPluginInstanceTagList::find(const char * mimetype)
{
PRBool defaultplugin = (PL_strcmp(mimetype, "*") == 0);
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
// give it some special treatment for the default plugin first
// because we cannot tell the default plugin by asking instance for a mime type
if (defaultplugin && p->mDefaultPlugin)
return p;
if (!p->mInstance)
continue;
const char* mt;
nsresult rv = p->mInstance->GetMIMEType(&mt);
if (NS_FAILED(rv))
continue;
if (PL_strcasecmp(mt, mimetype) == 0)
return p;
}
return nsnull;
}
nsPluginInstanceTag * nsPluginInstanceTagList::findStopped(const char * url)
{
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!PL_strcmp(url, p->mURL) && p->mStopped)
return p;
}
return nsnull;
}
PRUint32 nsPluginInstanceTagList::getStoppedCount()
{
PRUint32 stoppedCount = 0;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p->mStopped)
stoppedCount++;
}
return stoppedCount;
}
nsPluginInstanceTag * nsPluginInstanceTagList::findOldestStopped()
{
nsPluginInstanceTag * res = nsnull;
PRInt64 llTime = LL_MAXINT;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!p->mStopped)
continue;
if (LL_CMP(p->mllStopTime, <, llTime)) {
llTime = p->mllStopTime;
res = p;
}
}
return res;
}

View File

@ -0,0 +1,172 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Aas <josh@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsPluginTags_h_
#define nsPluginTags_h_
#include "nscore.h"
#include "prtypes.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsIPluginTag.h"
#include "nsIPlugin.h"
#include "nsIPluginInstance.h"
#include "nsISupportsArray.h"
class nsPluginHost;
class PRLibrary;
class nsPluginInfo;
// Remember that flags are written out to pluginreg.dat, be careful
// changing their meaning.
#define NS_PLUGIN_FLAG_ENABLED 0x0001 // is this plugin enabled?
// no longer used 0x0002 // reuse only if regenerating pluginreg.dat
#define NS_PLUGIN_FLAG_FROMCACHE 0x0004 // this plugintag info was loaded from cache
#define NS_PLUGIN_FLAG_UNWANTED 0x0008 // this is an unwanted plugin
#define NS_PLUGIN_FLAG_BLOCKLISTED 0x0010 // this is a blocklisted plugin
// A linked-list of plugin information that is used for instantiating plugins
// and reflecting plugin information into JavaScript.
class nsPluginTag : public nsIPluginTag
{
public:
enum nsRegisterType {
ePluginRegister,
ePluginUnregister
};
NS_DECL_ISUPPORTS
NS_DECL_NSIPLUGINTAG
nsPluginTag(nsPluginTag* aPluginTag);
nsPluginTag(nsPluginInfo* aPluginInfo);
nsPluginTag(const char* aName,
const char* aDescription,
const char* aFileName,
const char* aFullPath,
const char* aVersion,
const char* const* aMimeTypes,
const char* const* aMimeDescriptions,
const char* const* aExtensions,
PRInt32 aVariants,
PRInt64 aLastModifiedTime = 0,
PRBool aCanUnload = PR_TRUE,
PRBool aArgsAreUTF8 = PR_FALSE);
~nsPluginTag();
void SetHost(nsPluginHost * aHost);
void TryUnloadPlugin();
void Mark(PRUint32 mask);
void UnMark(PRUint32 mask);
PRBool HasFlag(PRUint32 flag);
PRUint32 Flags();
PRBool Equals(nsPluginTag* aPluginTag);
PRBool IsEnabled();
void RegisterWithCategoryManager(PRBool aOverrideInternalTypes,
nsRegisterType aType = ePluginRegister);
nsRefPtr<nsPluginTag> mNext;
nsPluginHost *mPluginHost;
nsCString mName; // UTF-8
nsCString mDescription; // UTF-8
PRInt32 mVariants;
char **mMimeTypeArray;
nsTArray<nsCString> mMimeDescriptionArray; // UTF-8
char **mExtensionsArray;
PRLibrary *mLibrary;
nsCOMPtr<nsIPlugin> mEntryPoint;
PRPackedBool mCanUnloadLibrary;
PRPackedBool mXPConnected;
PRPackedBool mIsJavaPlugin;
PRPackedBool mIsNPRuntimeEnabledJavaPlugin;
nsCString mFileName; // UTF-8
nsCString mFullPath; // UTF-8
nsCString mVersion; // UTF-8
PRInt64 mLastModifiedTime;
private:
PRUint32 mFlags;
nsresult EnsureMembersAreUTF8();
};
struct nsPluginInstanceTag
{
nsPluginInstanceTag* mNext;
char* mURL;
nsRefPtr<nsPluginTag> mPluginTag;
nsIPluginInstance* mInstance;
PRTime mllStopTime;
PRPackedBool mStopped;
PRPackedBool mDefaultPlugin;
PRPackedBool mXPConnected;
// Array holding all opened stream listeners for this entry
nsCOMPtr <nsISupportsArray> mStreams;
nsPluginInstanceTag(nsPluginTag* aPluginTag,
nsIPluginInstance* aInstance,
const char * url,
PRBool aDefaultPlugin);
~nsPluginInstanceTag();
void setStopped(PRBool stopped);
};
class nsPluginInstanceTagList
{
public:
nsPluginInstanceTag *mFirst;
nsPluginInstanceTag *mLast;
PRInt32 mCount;
nsPluginInstanceTagList();
~nsPluginInstanceTagList();
void shutdown();
PRBool add(nsPluginInstanceTag *plugin);
PRBool remove(nsPluginInstanceTag *plugin);
nsPluginInstanceTag *find(nsIPluginInstance *instance);
nsPluginInstanceTag *find(const char *mimetype);
nsPluginInstanceTag *findStopped(const char *url);
PRUint32 getStoppedCount();
nsPluginInstanceTag *findOldestStopped();
void removeAllStopped();
void stopRunning(nsISupportsArray *aReloadDocs, nsPluginTag *aPluginTag);
PRBool IsLastInstance(nsPluginInstanceTag *plugin);
};
#endif // nsPluginTags_h_

View File

@ -52,18 +52,23 @@ interface nsIChannel;
* list is changed, or a cookie is rejected:
*
* topic : "cookie-changed"
* broadcast whenever the cookie list changes in some way. there
* are four possible data strings for this notification; one
* notification will be broadcast for each change, and will involve
* a single cookie.
* subject: an nsICookie2 interface pointer representing the cookie object
* that changed.
* broadcast whenever the cookie list changes in some way. see
* explanation of data strings below.
* subject: see below.
* data : "deleted"
* a cookie was deleted. the subject is the deleted cookie.
* a cookie was deleted. the subject is an nsICookie2 representing
* the deleted cookie.
* "added"
* a cookie was added. the subject is the added cookie.
* a cookie was added. the subject is an nsICookie2 representing
* the added cookie.
* "changed"
* a cookie was changed. the subject is the new cookie.
* a cookie was changed. the subject is an nsICookie2 representing
* the new cookie. (note that host, path, and name are invariant
* for a given cookie; other parameters may change.)
* "batch-deleted"
* a batch of cookies was deleted (for instance, as part of a purging
* operation). the subject is an nsIArray of nsICookie2's representing
* the deleted cookies.
* "cleared"
* the entire cookie list was cleared. the subject is null.
* "reload"
@ -85,9 +90,11 @@ interface nsICookieService : nsISupports
* @param aURI
* the URI of the document for which cookies are being queried.
* @param aChannel
* the channel used to load the document. this parameter may be null,
* but it is strongly recommended that a non-null value be provided to
* ensure that the cookie privacy preferences are honored.
* the channel used to load the document. this parameter should not
* be null, otherwise the cookies will not be returned if third-party
* cookies have been disabled by the user. (the channel is used
* to determine the originating URI of the document; if it is not
* provided, the cookies will be assumed third-party.)
*
* @return the resulting cookie string
*/
@ -105,9 +112,11 @@ interface nsICookieService : nsISupports
* the URI that the user originally typed in or clicked on to initiate
* the load of the document referenced by aURI.
* @param aChannel
* the channel used to load the document. this parameter may be null,
* but it is strongly recommended that a non-null value be provided to
* ensure that the cookie privacy preferences are honored.
* the channel used to load the document. this parameter should not
* be null, otherwise the cookies will not be returned if third-party
* cookies have been disabled by the user. (the channel is used
* to determine the originating URI of the document; if it is not
* provided, the cookies will be assumed third-party.)
*
* @return the resulting cookie string
*/
@ -123,9 +132,11 @@ interface nsICookieService : nsISupports
* @param aCookie
* the cookie string to set.
* @param aChannel
* the channel used to load the document. this parameter may be null,
* but it is strongly recommended that a non-null value be provided to
* ensure that the cookie privacy preferences are honored.
* the channel used to load the document. this parameter should not
* be null, otherwise the cookies will not be set if third-party
* cookies have been disabled by the user. (the channel is used
* to determine the originating URI of the document; if it is not
* provided, the cookies will be assumed third-party.)
*
* XXX should be able to allow null aPrompt, since nsIPrompt can be queryied
* from aChannel.
@ -151,9 +162,11 @@ interface nsICookieService : nsISupports
* the expiry information of the cookie (the Date header from the HTTP
* response).
* @param aChannel
* the channel used to load the document. this parameter may be null,
* but it is strongly recommended that a non-null value be provided to
* ensure that the cookie privacy preferences are honored.
* the channel used to load the document. this parameter should not
* be null, otherwise the cookies will not be set if third-party
* cookies have been disabled by the user. (the channel is used
* to determine the originating URI of the document; if it is not
* provided, the cookies will be assumed third-party.)
*/
void setCookieStringFromHttp(in nsIURI aURI, in nsIURI aFirstURI, in nsIPrompt aPrompt, in string aCookie, in string aServerTime, in nsIChannel aChannel);
};

View File

@ -55,7 +55,9 @@
#include "nsILineInputStream.h"
#include "nsIEffectiveTLDService.h"
#include "nsTArray.h"
#include "nsCOMArray.h"
#include "nsIMutableArray.h"
#include "nsArrayEnumerator.h"
#include "nsEnumeratorUtils.h"
#include "nsAutoPtr.h"
@ -85,12 +87,16 @@ static const char kCookieFileName[] = "cookies.sqlite";
#define COOKIES_SCHEMA_VERSION 2
static const PRInt64 kCookieStaleThreshold = 60 * PR_USEC_PER_SEC; // 1 minute in microseconds
static const PRInt64 kCookiePurgeAge = 30 * 24 * 60 * 60 * PR_USEC_PER_SEC; // 30 days in microseconds
static const char kOldCookieFileName[] = "cookies.txt";
#undef LIMIT
#define LIMIT(x, low, high, default) ((x) >= (low) && (x) <= (high) ? (x) : (default))
#undef ADD_TEN_PERCENT
#define ADD_TEN_PERCENT(i) ((i) + (i)/10)
// default limits for the cookie list. these can be tuned by the
// network.cookie.maxNumber and network.cookie.maxPerHost prefs respectively.
static const PRUint32 kMaxNumberOfCookies = 3000;
@ -116,6 +122,7 @@ static const PRUint32 BEHAVIOR_REJECT = 2;
static const char kPrefCookiesPermissions[] = "network.cookie.cookieBehavior";
static const char kPrefMaxNumberOfCookies[] = "network.cookie.maxNumber";
static const char kPrefMaxCookiesPerHost[] = "network.cookie.maxPerHost";
static const char kPrefCookiePurgeAge[] = "network.cookie.purgeAge";
// struct for temporarily storing cookie attributes during header parsing
struct nsCookieAttributes
@ -206,7 +213,13 @@ static PRLogModuleInfo *sCookieLog = PR_NewLogModule("cookie");
#define COOKIE_LOGFAILURE(a, b, c, d) LogFailure(a, b, c, d)
#define COOKIE_LOGSUCCESS(a, b, c, d, e) LogSuccess(a, b, c, d, e)
#define COOKIE_LOGEVICTED(a) LogEvicted(a)
#define COOKIE_LOGEVICTED(a) \
PR_BEGIN_MACRO \
if (PR_LOG_TEST(sCookieLog, PR_LOG_DEBUG)) \
LogEvicted(a); \
PR_END_MACRO
#define COOKIE_LOGSTRING(lvl, fmt) \
PR_BEGIN_MACRO \
PR_LOG(sCookieLog, lvl, fmt); \
@ -299,11 +312,6 @@ LogSuccess(PRBool aSetCookie, nsIURI *aHostURI, const char *aCookieString, nsCoo
static void
LogEvicted(nsCookie *aCookie)
{
// if logging isn't enabled, return now to save cycles
if (!PR_LOG_TEST(sCookieLog, PR_LOG_DEBUG)) {
return;
}
PR_LOG(sCookieLog, PR_LOG_DEBUG,("===== COOKIE EVICTED =====\n"));
LogCookie(aCookie);
@ -380,6 +388,7 @@ nsCookieService::nsCookieService()
, mCookiesPermissions(BEHAVIOR_ACCEPT)
, mMaxNumberOfCookies(kMaxNumberOfCookies)
, mMaxCookiesPerHost(kMaxCookiesPerHost)
, mCookiePurgeAge(kCookiePurgeAge)
{
}
@ -400,6 +409,7 @@ nsCookieService::Init()
prefBranch->AddObserver(kPrefCookiesPermissions, this, PR_TRUE);
prefBranch->AddObserver(kPrefMaxNumberOfCookies, this, PR_TRUE);
prefBranch->AddObserver(kPrefMaxCookiesPerHost, this, PR_TRUE);
prefBranch->AddObserver(kPrefCookiePurgeAge, this, PR_TRUE);
PrefChanged(prefBranch);
}
@ -691,6 +701,7 @@ nsCookieService::Observe(nsISupports *aSubject,
NS_ASSERTION(mDBState == &mDefaultDBState, "already in private state");
NS_ASSERTION(mPrivateDBState.cookieCount == 0, "private count not 0");
NS_ASSERTION(mPrivateDBState.cookieOldestTime == LL_MAXINT, "private time not reset");
NS_ASSERTION(mPrivateDBState.hostTable.Count() == 0, "private table not empty");
NS_ASSERTION(mPrivateDBState.dbConn == NULL, "private DB connection not null");
@ -706,6 +717,7 @@ nsCookieService::Observe(nsISupports *aSubject,
NS_ASSERTION(!mPrivateDBState.dbConn, "private DB connection not null");
mPrivateDBState.cookieCount = 0;
mPrivateDBState.cookieOldestTime = LL_MAXINT;
if (mPrivateDBState.hostTable.IsInitialized())
mPrivateDBState.hostTable.Clear();
@ -812,18 +824,20 @@ nsCookieService::NotifyRejected(nsIURI *aHostURI)
mObserverService->NotifyObservers(aHostURI, "cookie-rejected", nsnull);
}
// notify observers that the cookie list changed. there are four possible
// notify observers that the cookie list changed. there are five possible
// values for aData:
// "deleted" means a cookie was deleted. aCookie is the deleted cookie.
// "added" means a cookie was added. aCookie is the added cookie.
// "changed" means a cookie was altered. aCookie is the new cookie.
// "cleared" means the entire cookie list was cleared. aCookie is null.
// "deleted" means a cookie was deleted. aSubject is the deleted cookie.
// "added" means a cookie was added. aSubject is the added cookie.
// "changed" means a cookie was altered. aSubject is the new cookie.
// "cleared" means the entire cookie list was cleared. aSubject is null.
// "batch-deleted" means multiple cookies were deleted. aSubject is the list of
// cookies.
void
nsCookieService::NotifyChanged(nsICookie2 *aCookie,
nsCookieService::NotifyChanged(nsISupports *aSubject,
const PRUnichar *aData)
{
if (mObserverService)
mObserverService->NotifyObservers(aCookie, "cookie-changed", aData);
mObserverService->NotifyObservers(aSubject, "cookie-changed", aData);
}
/******************************************************************************
@ -843,6 +857,9 @@ nsCookieService::PrefChanged(nsIPrefBranch *aPrefBranch)
if (NS_SUCCEEDED(aPrefBranch->GetIntPref(kPrefMaxCookiesPerHost, &val)))
mMaxCookiesPerHost = (PRUint16) LIMIT(val, 1, 0xFFFF, kMaxCookiesPerHost);
if (NS_SUCCEEDED(aPrefBranch->GetIntPref(kPrefCookiePurgeAge, &val)))
mCookiePurgeAge = LIMIT(val, 0, PR_INT32_MAX, PR_INT32_MAX) * PR_USEC_PER_SEC;
}
/******************************************************************************
@ -938,7 +955,7 @@ nsCookieService::Add(const nsACString &aDomain,
return NS_ERROR_OUT_OF_MEMORY;
}
AddInternal(cookie, currentTimeInUsec / PR_USEC_PER_SEC, nsnull, nsnull, PR_TRUE);
AddInternal(cookie, currentTimeInUsec, nsnull, nsnull, PR_TRUE);
return NS_OK;
}
@ -1182,7 +1199,7 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
if (originalCookieCount == 0)
AddCookieToList(newCookie);
else
AddInternal(newCookie, currentTime, nsnull, nsnull, PR_TRUE);
AddInternal(newCookie, currentTimeInUsec, nsnull, nsnull, PR_TRUE);
}
COOKIE_LOGSTRING(PR_LOG_DEBUG, ("ImportCookies(): %ld cookies imported", mDBState->cookieCount));
@ -1199,25 +1216,28 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
static inline PRBool ispathdelimiter(char c) { return c == '/' || c == '?' || c == '#' || c == ';'; }
// Comparator class for sorting cookies before sending to a server.
class CompareCookiesForSendingComparator
class CompareCookiesForSending
{
public:
PRBool Equals(const nsCookie* aCookie1, const nsCookie* aCookie2) const {
return PR_FALSE; // CreationID is unique, so two id's can never be equal.
public:
PRBool Equals(const nsCookie* aCookie1, const nsCookie* aCookie2) const
{
// CreationID is unique, so two id's can never be equal.
return PR_FALSE;
}
PRBool LessThan(const nsCookie* aCookie1, const nsCookie* aCookie2) const {
PRBool LessThan(const nsCookie* aCookie1, const nsCookie* aCookie2) const
{
// compare by cookie path length in accordance with RFC2109
int rv = aCookie2->Path().Length() - aCookie1->Path().Length();
if (rv == 0) {
// when path lengths match, older cookies should be listed first. this is
// required for backwards compatibility since some websites erroneously
// depend on receiving cookies in the order in which they were sent to the
// browser! see bug 236772.
// note: CreationID is unique, so two id's can never be equal.
// we may have overflow problems returning the result directly, so we need branches
rv = (aCookie1->CreationID() > aCookie2->CreationID() ? 1 : -1);
}
return rv < 0;
PRInt32 result = aCookie2->Path().Length() - aCookie1->Path().Length();
if (result != 0)
return result < 0;
// when path lengths match, older cookies should be listed first. this is
// required for backwards compatibility since some websites erroneously
// depend on receiving cookies in the order in which they were sent to the
// browser! see bug 236772.
// note: CreationID is unique, so two id's can never be equal.
return aCookie1->CreationID() < aCookie2->CreationID();
}
};
@ -1358,7 +1378,7 @@ nsCookieService::GetCookieInternal(nsIURI *aHostURI,
// return cookies in order of path length; longest to shortest.
// this is required per RFC2109. if cookies match in length,
// then sort by creation time (see bug 236772).
foundCookieList.Sort(CompareCookiesForSendingComparator());
foundCookieList.Sort(CompareCookiesForSending());
nsCAutoString cookieData;
for (PRInt32 i = 0; i < count; ++i) {
@ -1481,7 +1501,7 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
// add the cookie to the list. AddInternal() takes care of logging.
// we get the current time again here, since it may have changed during prompting
AddInternal(cookie, PR_Now() / PR_USEC_PER_SEC, aHostURI, savedCookieHeader.get(), aFromHttp);
AddInternal(cookie, PR_Now(), aHostURI, savedCookieHeader.get(), aFromHttp);
return newCookie;
}
@ -1492,11 +1512,13 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
// reached). also performs list maintenance by removing expired cookies.
void
nsCookieService::AddInternal(nsCookie *aCookie,
PRInt64 aCurrentTime,
PRInt64 aCurrentTimeInUsec,
nsIURI *aHostURI,
const char *aCookieHeader,
PRBool aFromHttp)
{
PRInt64 currentTime = aCurrentTimeInUsec / PR_USEC_PER_SEC;
// if the new cookie is httponly, make sure we're not coming from script
if (!aFromHttp && aCookie->IsHttpOnly()) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "cookie is httponly; coming from script");
@ -1510,7 +1532,7 @@ nsCookieService::AddInternal(nsCookie *aCookie,
nsListIter matchIter;
PRBool foundCookie = FindCookie(aCookie->Host(), aCookie->Name(), aCookie->Path(),
matchIter, aCurrentTime);
matchIter, currentTime);
nsRefPtr<nsCookie> oldCookie;
if (foundCookie) {
@ -1525,7 +1547,7 @@ nsCookieService::AddInternal(nsCookie *aCookie,
RemoveCookieFromList(matchIter);
// check if the cookie has expired
if (aCookie->Expiry() <= aCurrentTime) {
if (aCookie->Expiry() <= currentTime) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "previously stored cookie was deleted");
NotifyChanged(oldCookie, NS_LITERAL_STRING("deleted").get());
return;
@ -1537,36 +1559,33 @@ nsCookieService::AddInternal(nsCookie *aCookie,
} else {
// check if cookie has already expired
if (aCookie->Expiry() <= aCurrentTime) {
if (aCookie->Expiry() <= currentTime) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "cookie has already expired");
return;
}
// check if we have to delete an old cookie.
nsEnumerationData data(aCurrentTime, LL_MAXINT);
nsEnumerationData data(currentTime, LL_MAXINT);
if (CountCookiesFromHostInternal(aCookie->RawHost(), data) >= mMaxCookiesPerHost) {
// remove the oldest cookie from host
oldCookie = data.iter.current;
COOKIE_LOGEVICTED(oldCookie);
RemoveCookieFromList(data.iter);
} else if (mDBState->cookieCount >= mMaxNumberOfCookies) {
// try to make room, by removing expired cookies
RemoveExpiredCookies(aCurrentTime);
// check if we still have to get rid of something
if (mDBState->cookieCount >= mMaxNumberOfCookies) {
// find the position of the oldest cookie, and remove it
data.oldestTime = LL_MAXINT;
FindOldestCookie(data);
oldCookie = data.iter.current;
RemoveCookieFromList(data.iter);
}
}
// if we deleted an old cookie, notify consumers
if (oldCookie) {
COOKIE_LOGEVICTED(oldCookie);
NotifyChanged(oldCookie, NS_LITERAL_STRING("deleted").get());
} else if (mDBState->cookieCount >= ADD_TEN_PERCENT(mMaxNumberOfCookies)) {
PRInt64 maxAge = aCurrentTimeInUsec - mDBState->cookieOldestTime;
PRInt64 purgeAge = ADD_TEN_PERCENT(mCookiePurgeAge);
if (maxAge >= purgeAge) {
// we're over both size and age limits by 10%; time to purge the table!
// do this by:
// 1) removing expired cookies;
// 2) evicting the balance of old cookies, until we reach the size limit.
// note that the cookieOldestTime indicator can be pessimistic - if it's
// older than the actual oldest cookie, we'll just purge more eagerly.
PurgeCookies(aCurrentTimeInUsec);
}
}
}
@ -2124,35 +2143,159 @@ nsCookieService::RemoveAllFromMemory()
// which releases all their respective children.
mDBState->hostTable.Clear();
mDBState->cookieCount = 0;
mDBState->cookieOldestTime = LL_MAXINT;
}
PLDHashOperator
removeExpiredCallback(nsCookieEntry *aEntry,
void *aArg)
// stores temporary data for enumerating over the hash entries,
// since enumeration is done using callback functions
struct nsPurgeData
{
const PRInt64 &currentTime = *static_cast<PRInt64*>(aArg);
nsPurgeData(PRInt64 aCurrentTime,
PRInt64 aPurgeTime,
nsTArray<nsListIter> &aPurgeList,
nsIMutableArray *aRemovedList)
: currentTime(aCurrentTime)
, purgeTime(aPurgeTime)
, oldestTime(LL_MAXINT)
, purgeList(aPurgeList)
, removedList(aRemovedList) {}
// the current time, in seconds
PRInt64 currentTime;
// lastAccessed time older than which cookies are eligible for purge
PRInt64 purgeTime;
// lastAccessed time of the oldest cookie found during purge, to update our indicator
PRInt64 oldestTime;
// list of cookies over the age limit, for purging
nsTArray<nsListIter> &purgeList;
// list of all cookies we've removed, for notification
nsIMutableArray *removedList;
};
// comparator class for lastaccessed times of cookies.
class CompareCookiesByAge {
public:
PRBool Equals(const nsListIter &a, const nsListIter &b) const
{
// CreationID is unique, so two id's can never be equal.
return PR_FALSE;
}
PRBool LessThan(const nsListIter &a, const nsListIter &b) const
{
// compare by LastAccessed time, and tiebreak by CreationID.
PRInt64 result = a.current->LastAccessed() - b.current->LastAccessed();
if (result != 0)
return result < 0;
return a.current->CreationID() < b.current->CreationID();
}
};
PLDHashOperator
purgeCookiesCallback(nsCookieEntry *aEntry,
void *aArg)
{
nsPurgeData &data = *static_cast<nsPurgeData*>(aArg);
for (nsListIter iter(aEntry, nsnull, aEntry->Head()); iter.current; ) {
if (iter.current->Expiry() <= currentTime)
// check if the cookie has expired
if (iter.current->Expiry() <= data.currentTime) {
nsCookie *cookie = iter.current;
data.removedList->AppendElement(cookie, PR_FALSE);
COOKIE_LOGEVICTED(cookie);
// remove from list. this takes care of updating the iterator for us
nsCookieService::gCookieService->RemoveCookieFromList(iter);
else
} else {
// check if the cookie is over the age limit
if (iter.current->LastAccessed() <= data.purgeTime) {
data.purgeList.AppendElement(iter);
} else if (iter.current->LastAccessed() < data.oldestTime) {
// reset our indicator
data.oldestTime = iter.current->LastAccessed();
}
++iter;
}
}
return PL_DHASH_NEXT;
}
// removes any expired cookies from memory
// purges expired and old cookies in a batch operation.
void
nsCookieService::RemoveExpiredCookies(PRInt64 aCurrentTime)
nsCookieService::PurgeCookies(PRInt64 aCurrentTimeInUsec)
{
NS_ASSERTION(mDBState->hostTable.Count() > 0, "table is empty");
#ifdef PR_LOGGING
PRUint32 initialCookieCount = mDBState->cookieCount;
#endif
mDBState->hostTable.EnumerateEntries(removeExpiredCallback, &aCurrentTime);
COOKIE_LOGSTRING(PR_LOG_DEBUG,
("RemoveExpiredCookies(): %ld purged; %ld remain",
initialCookieCount - mDBState->cookieCount, mDBState->cookieCount));
("PurgeCookies(): beginning purge with %ld cookies and %lld age",
mDBState->cookieCount, aCurrentTimeInUsec - mDBState->cookieOldestTime));
#endif
nsAutoTArray<nsListIter, kMaxNumberOfCookies> purgeList;
nsCOMPtr<nsIMutableArray> removedList = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (!removedList)
return;
nsPurgeData data(aCurrentTimeInUsec / PR_USEC_PER_SEC,
aCurrentTimeInUsec - mCookiePurgeAge, purgeList, removedList);
mDBState->hostTable.EnumerateEntries(purgeCookiesCallback, &data);
#ifdef PR_LOGGING
PRUint32 postExpiryCookieCount = mDBState->cookieCount;
#endif
// now we have a list of iterators for cookies over the age limit.
// sort them by age, and then we'll see how many to remove...
purgeList.Sort(CompareCookiesByAge());
// only remove old cookies until we reach the max cookie limit, no more.
PRUint32 excess = mDBState->cookieCount - mMaxNumberOfCookies;
if (purgeList.Length() > excess) {
// we're not purging everything in the list, so update our indicator
data.oldestTime = purgeList[excess].current->LastAccessed();
purgeList.SetLength(excess);
}
// traverse the list and remove cookies. the iterators we've stored
// in the list aren't stable under list mutation, so we need to do a
// fresh linked list traversal from the hash entryclass for each cookie.
for (PRUint32 i = 0; i < purgeList.Length(); ++i) {
nsListIter iter(purgeList[i].entry, nsnull, purgeList[i].entry->Head());
for (; iter.current; ++iter) {
if (iter.current == purgeList[i].current) {
// remove from list. this takes care of updating the iterator for us
nsCookie *cookie = iter.current;
removedList->AppendElement(cookie, PR_FALSE);
COOKIE_LOGEVICTED(cookie);
RemoveCookieFromList(iter);
break;
}
}
}
// take all the cookies in the removed list, and notify about them in one batch
NotifyChanged(removedList, NS_LITERAL_STRING("batch-deleted").get());
// reset the oldest time indicator
mDBState->cookieOldestTime = data.oldestTime;
COOKIE_LOGSTRING(PR_LOG_DEBUG,
("PurgeCookies(): %ld expired; %ld purged; %ld remain; %lld oldest age",
initialCookieCount - postExpiryCookieCount,
mDBState->cookieCount - postExpiryCookieCount,
mDBState->cookieCount,
aCurrentTimeInUsec - mDBState->cookieOldestTime));
}
// find whether a given cookie has been previously set. this is provided by the
@ -2379,6 +2522,10 @@ nsCookieService::AddCookieToList(nsCookie *aCookie, PRBool aWriteToDB)
entry->Head() = aCookie;
++mDBState->cookieCount;
// keep track of the oldest cookie, for when it comes time to purge
if (aCookie->LastAccessed() < mDBState->cookieOldestTime)
mDBState->cookieOldestTime = aCookie->LastAccessed();
// if it's a non-session cookie and hasn't just been read from the db, write it out.
if (aWriteToDB && !aCookie->IsSession() && mDBState->dbConn) {
// use our cached sqlite "insert" statement
@ -2426,24 +2573,3 @@ nsCookieService::UpdateCookieInList(nsCookie *aCookie, PRInt64 aLastAccessed)
}
}
static PLDHashOperator
findOldestCallback(nsCookieEntry *aEntry,
void *aArg)
{
nsEnumerationData *data = static_cast<nsEnumerationData*>(aArg);
for (nsListIter iter(aEntry, nsnull, aEntry->Head()); iter.current; ++iter) {
// check if we've found the oldest cookie so far
if (data->oldestTime > iter.current->LastAccessed()) {
data->oldestTime = iter.current->LastAccessed();
data->iter = iter;
}
}
return PL_DHASH_NEXT;
}
void
nsCookieService::FindOldestCookie(nsEnumerationData &aData)
{
NS_ASSERTION(mDBState->hostTable.Count() > 0, "table is empty");
mDBState->hostTable.EnumerateEntries(findOldestCallback, &aData);
}

View File

@ -144,10 +144,11 @@ class nsCookieEntry : public PLDHashEntryHdr
// conveniently switch state when entering or exiting private browsing.
struct DBState
{
DBState() : cookieCount(0) { }
DBState() : cookieCount(0), cookieOldestTime(LL_MAXINT) { }
nsTHashtable<nsCookieEntry> hostTable;
PRUint32 cookieCount;
PRInt64 cookieOldestTime;
nsCOMPtr<mozIStorageConnection> dbConn;
nsCOMPtr<mozIStorageStatement> stmtInsert;
nsCOMPtr<mozIStorageStatement> stmtDelete;
@ -187,7 +188,7 @@ class nsCookieService : public nsICookieService
void GetCookieInternal(nsIURI *aHostURI, nsIChannel *aChannel, PRBool aHttpBound, char **aCookie);
nsresult SetCookieStringInternal(nsIURI *aHostURI, nsIPrompt *aPrompt, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, PRBool aFromHttp);
PRBool SetCookieInternal(nsIURI *aHostURI, nsIChannel *aChannel, nsDependentCString &aCookieHeader, PRInt64 aServerTime, PRBool aFromHttp);
void AddInternal(nsCookie *aCookie, PRInt64 aCurrentTime, nsIURI *aHostURI, const char *aCookieHeader, PRBool aFromHttp);
void AddInternal(nsCookie *aCookie, PRInt64 aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, PRBool aFromHttp);
void RemoveCookieFromList(nsListIter &aIter);
PRBool AddCookieToList(nsCookie *aCookie, PRBool aWriteToDB = PR_TRUE);
void UpdateCookieInList(nsCookie *aCookie, PRInt64 aLastAccessed);
@ -199,12 +200,11 @@ class nsCookieService : public nsICookieService
static PRBool CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
static PRBool GetExpiry(nsCookieAttributes &aCookie, PRInt64 aServerTime, PRInt64 aCurrentTime);
void RemoveAllFromMemory();
void RemoveExpiredCookies(PRInt64 aCurrentTime);
void PurgeCookies(PRInt64 aCurrentTimeInUsec);
PRBool FindCookie(const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter, PRInt64 aCurrentTime);
void FindOldestCookie(nsEnumerationData &aData);
PRUint32 CountCookiesFromHostInternal(const nsACString &aHost, nsEnumerationData &aData);
void NotifyRejected(nsIURI *aHostURI);
void NotifyChanged(nsICookie2 *aCookie, const PRUnichar *aData);
void NotifyChanged(nsISupports *aSubject, const PRUnichar *aData);
protected:
// cached members.
@ -225,13 +225,14 @@ class nsCookieService : public nsICookieService
PRUint8 mCookiesPermissions; // BEHAVIOR_{ACCEPT, REJECTFOREIGN, REJECT}
PRUint16 mMaxNumberOfCookies;
PRUint16 mMaxCookiesPerHost;
PRInt64 mCookiePurgeAge;
// private static member, used to cache a ptr to nsCookieService,
// so we can make nsCookieService a singleton xpcom object.
static nsCookieService *gCookieService;
// this callback needs access to member functions
friend PLDHashOperator removeExpiredCallback(nsCookieEntry *aEntry, void *aArg);
friend PLDHashOperator purgeCookiesCallback(nsCookieEntry *aEntry, void *aArg);
};
#endif // nsCookieService_h__

View File

@ -759,41 +759,7 @@ main(PRInt32 argc, char *argv[])
GetACookie(cookieService, "http://creation.ordering.tests/", nsnull, getter_Copies(cookie));
rv[0] = CheckResult(cookie.get(), MUST_EQUAL, expected.get());
// test that cookies are evicted by order of lastAccessed time, if the limit on total cookies
// (3000) is reached
nsCAutoString host;
for (PRInt32 i = 0; i < 3010; ++i) {
host = NS_LITERAL_CSTRING("http://eviction.");
host.AppendInt(i);
host += NS_LITERAL_CSTRING(".tests/");
SetACookie(cookieService, host.get(), nsnull, "test=eviction", nsnull);
if (i == 9) {
// sleep a couple of seconds, to make sure the first 10 cookies are older than
// subsequent ones (timer resolution varies on different platforms).
PR_Sleep(2 * PR_TicksPerSecond());
}
}
rv[1] = NS_SUCCEEDED(cookieMgr->GetEnumerator(getter_AddRefs(enumerator)));
i = 0;
rv[2] = PR_FALSE; // init to failure in case we break from the while loop
while (NS_SUCCEEDED(enumerator->HasMoreElements(&more)) && more) {
nsCOMPtr<nsISupports> cookie;
if (NS_FAILED(enumerator->GetNext(getter_AddRefs(cookie)))) break;
++i;
// keep tabs on the third cookie, so we can check it later
nsCOMPtr<nsICookie2> cookie2(do_QueryInterface(cookie));
if (!cookie2) break;
nsCAutoString domain;
cookie2->GetRawHost(domain);
PRInt32 hostNumber;
PRInt32 numInts = PR_sscanf(domain.get(), "eviction.%ld.tests", &hostNumber);
if (numInts != 1 || hostNumber < 10) break;
}
rv[2] = i == 3000;
allTestsPassed = PrintResult(rv, 3) && allTestsPassed;
allTestsPassed = PrintResult(rv, 1) && allTestsPassed;
// XXX the following are placeholders: add these tests please!

View File

@ -113,7 +113,6 @@ const HTTP_412 = new HttpError(412, "Precondition Failed");
const HTTP_413 = new HttpError(413, "Request Entity Too Large");
const HTTP_414 = new HttpError(414, "Request-URI Too Long");
const HTTP_415 = new HttpError(415, "Unsupported Media Type");
const HTTP_416 = new HttpError(416, "Requested Range Not Satisfiable");
const HTTP_417 = new HttpError(417, "Expectation Failed");
const HTTP_500 = new HttpError(500, "Internal Server Error");
@ -2227,6 +2226,8 @@ ServerHandler.prototype =
dumpn("*** errorCode == " + errorCode);
response = new Response(connection);
if (e.customErrorHandling)
e.customErrorHandling(response);
this._handleError(errorCode, request, response);
return;
}
@ -2446,8 +2447,14 @@ ServerHandler.prototype =
if (end === undefined || end >= file.fileSize)
end = file.fileSize - 1;
if (start !== undefined && start >= file.fileSize)
if (start !== undefined && start >= file.fileSize) {
var HTTP_416 = new HttpError(416, "Requested Range Not Satisfiable");
HTTP_416.customErrorHandling = function(errorResponse)
{
maybeAddHeaders(file, metadata, errorResponse);
};
throw HTTP_416;
}
if (end < start)
{

View File

@ -0,0 +1 @@
Hello Kitty

View File

@ -0,0 +1 @@
X-SJS-Header: customized

View File

@ -65,6 +65,8 @@ var tests =
init_byterange11, start_byterange11, stop_byterange11),
new Test(PREFIX + "/empty.txt",
null, start_byterange12, stop_byterange12),
new Test(PREFIX + "/headers.txt",
init_byterange13, start_byterange13, null),
new Test(PREFIX + "/range.txt",
null, start_normal, stop_normal)
];
@ -289,3 +291,14 @@ function stop_byterange12(ch, cx, status, data)
{
do_check_eq(data.length, 0);
}
function init_byterange13(ch)
{
ch.setRequestHeader("Range", "bytes=9999999-", false);
}
function start_byterange13(ch, cx)
{
do_check_eq(ch.responseStatus, 416);
do_check_eq(ch.getResponseHeader("X-SJS-Header"), "customized");
}

View File

@ -222,18 +222,6 @@ nsHtml5Tokenizer::appendStrBuf(PRUnichar c)
strBuf[strBufLen++] = c;
}
void
nsHtml5Tokenizer::appendStrBufForceWrite(PRUnichar c)
{
if (strBufLen == strBuf.length) {
jArray<PRUnichar,PRInt32> newBuf = jArray<PRUnichar,PRInt32>(strBuf.length + NS_HTML5TOKENIZER_BUFFER_GROW_BY);
nsHtml5ArrayCopy::arraycopy(strBuf, newBuf, strBuf.length);
strBuf.release();
strBuf = newBuf;
}
strBuf[strBufLen++] = c;
}
nsString*
nsHtml5Tokenizer::strBufToString()
{
@ -413,8 +401,8 @@ void
nsHtml5Tokenizer::addAttributeWithValue()
{
if (!!attributeName) {
nsString* value = longStrBufToString();
attributes->addAttribute(attributeName, value);
nsString* val = longStrBufToString();
attributes->addAttribute(attributeName, val);
attributeName = nsnull;
}
}

View File

@ -160,7 +160,6 @@ class nsHtml5Tokenizer
void clearStrBufAndAppendForceWrite(PRUnichar c);
void clearStrBufForNextState();
void appendStrBuf(PRUnichar c);
void appendStrBufForceWrite(PRUnichar c);
protected:
nsString* strBufToString();
private:

View File

@ -2990,7 +2990,7 @@ nsHtml5TreeBuilder::resetTheInsertionMode()
} else if (nsHtml5Atoms::table == name) {
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
return;
} else if (kNameSpaceID_XHTML != node->ns) {
} else if (kNameSpaceID_XHTML != ns) {
foreignFlag = NS_HTML5TREE_BUILDER_IN_FOREIGN;
mode = NS_HTML5TREE_BUILDER_IN_BODY;
return;

View File

@ -198,7 +198,7 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState
void appendCommentToDocument(PRUnichar* buf, PRInt32 start, PRInt32 length);
void addAttributesToElement(nsIContent** element, nsHtml5HtmlAttributes* attributes);
void markMalformedIfScript(nsIContent** elt);
void start(PRBool fragment);
void start(PRBool fragmentMode);
void end();
void appendDoctypeToDocument(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier);
void elementPushed(PRInt32 ns, nsIAtom* name, nsIContent** node);

View File

@ -113,13 +113,19 @@ nsHtml5TreeOpExecutor::DidBuildModel(PRBool aTerminated)
return NS_OK;
}
static_cast<nsHtml5Parser*> (mParser.get())->DropStreamParser();
// This is comes from nsXMLContentSink
DidBuildModelImpl(aTerminated);
mDocument->ScriptLoader()->RemoveObserver(this);
ScrollToRef();
mDocument->RemoveObserver(this);
if (!mParser) {
// DidBuildModelImpl may cause mParser to be nulled out
// Return early to avoid unblocking the onload event too many times.
return NS_OK;
}
mDocument->EndLoad();
static_cast<nsHtml5Parser*> (mParser.get())->DropStreamParser();
DropParserAndPerfHint();
#ifdef GATHER_DOCWRITE_STATISTICS
printf("UNSAFE SCRIPTS: %d\n", sUnsafeDocWrites);

View File

@ -183,6 +183,9 @@ DEFAULT_GMAKE_FLAGS += MOZILLA_CLIENT=1
DEFAULT_GMAKE_FLAGS += NO_MDUPDATE=1
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ECC=1
DEFAULT_GMAKE_FLAGS += IMPORT_LIB_SUFFIX=".$(IMPORT_LIB_SUFFIX)"
ifndef MOZ_NATIVE_SQLITE
DEFAULT_GMAKE_FLAGS += SQLITE=$(call EXPAND_LIBNAME,mozsqlite3)
endif
ifdef NSS_DISABLE_DBM
DEFAULT_GMAKE_FLAGS += NSS_DISABLE_DBM=1
endif
@ -320,7 +323,7 @@ ifndef NSS_DISABLE_DBM
endif
$(NSSMAKE) -C $(NSS_SRCDIR)/security/nss/lib $(DEFAULT_GMAKE_FLAGS)
ifdef ENABLE_TESTS
# Need certutil binary for mochitest certificates generation
# Need certutil binary for mochitest certificates generation
$(NSSMAKE) -C $(NSS_SRCDIR)/security/nss/cmd/lib $(DEFAULT_GMAKE_FLAGS)
$(NSSMAKE) -C $(NSS_SRCDIR)/security/nss/cmd/certutil $(DEFAULT_GMAKE_FLAGS)
$(NSSMAKE) -C $(NSS_SRCDIR)/security/nss/cmd/pk12util $(DEFAULT_GMAKE_FLAGS)

View File

@ -92,6 +92,7 @@ ifdef USE_STATIC_LIBS
# can't do this in manifest.mn because OS_ARCH isn't defined there.
ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
SQLITE = $(LIB_PREFIX)sqlite3.$(LIB_SUFFIX)
DEFINES += -DNSS_USE_STATIC_LIBS
# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
@ -129,7 +130,7 @@ EXTRA_LIBS += \
$(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \
$(PKIXLIB) \
$(DBMLIB) \
$(DIST)/lib/$(LIB_PREFIX)sqlite3.$(LIB_SUFFIX) \
$(DIST)/lib/$(SQLITE) \
$(DIST)/lib/$(LIB_PREFIX)nssutil3.$(LIB_SUFFIX) \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.$(LIB_SUFFIX) \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.$(LIB_SUFFIX) \

View File

@ -53,11 +53,12 @@ RES = $(OBJDIR)/$(LIBRARY_NAME).res
RESNAME = $(LIBRARY_NAME).rc
ifdef NS_USE_GCC
SQLITE = -lsqlite3
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib \
-L$(NSSUTIL_LIB_DIR) \
-lnssutil3 \
-lsqlite3 \
$(SQLITE) \
-L$(NSPR_LIB_DIR) \
-lplc4 \
-lplds4 \
@ -65,8 +66,9 @@ EXTRA_SHARED_LIBS += \
$(NULL)
else # ! NS_USE_GCC
SQLITE = sqlite3.lib
EXTRA_SHARED_LIBS += \
$(DIST)/lib/sqlite3.lib \
$(DIST)/lib/$(SQLITE) \
$(DIST)/lib/nssutil3.lib \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
@ -79,11 +81,12 @@ else
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
SQLITE = -lsqlite3
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib \
-L$(NSSUTIL_LIB_DIR) \
-lnssutil3 \
-lsqlite3 \
$(SQLITE) \
-L$(NSPR_LIB_DIR) \
-lplc4 \
-lplds4 \

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