Merge last green mozilla-inbound changeset to mozilla-central

This commit is contained in:
Matt Brubeck 2011-06-15 08:25:48 -07:00
commit ede62c1ae5
65 changed files with 1133 additions and 539 deletions

View File

@ -91,29 +91,20 @@ include $(topsrcdir)/config/rules.mk
else
# Build a binary bootstrapping with XRE_main
ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
else
PROGRAM = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
endif
CPPSRCS = nsBrowserApp.cpp
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
LIBS += $(DIST)/bin/XUL
TK_LIBS := $(TK_LIBS)
else
EXTRA_DSO_LIBS += xul
endif
DEFINES += -DXPCOM_GLUE
STL_FLAGS=
LIBS += \
$(STATIC_COMPONENTS_LINKER_PATH) \
$(EXTRA_DSO_LIBS) \
$(XPCOM_GLUE_LDOPTS) \
$(NSPR_LIBS) \
$(XPCOM_STANDALONE_GLUE_LDOPTS) \
$(NULL)
ifdef MOZ_JPROF
@ -194,18 +185,9 @@ endif
ifneq (,$(filter-out OS2 WINNT,$(OS_ARCH)))
$(MOZ_APP_NAME):: $(topsrcdir)/build/unix/mozilla.in $(GLOBAL_DEPS)
cat $< | sed -e "s|%MOZAPPDIR%|$(installdir)|" \
-e "s|%MOZ_APP_DISPLAYNAME%|$(MOZ_APP_DISPLAYNAME)|" > $@
chmod +x $@
libs::
cp -p $(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/bin/$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
libs:: $(MOZ_APP_NAME)
$(INSTALL) $< $(DIST)/bin
install:: $(MOZ_APP_NAME)
$(SYSINSTALL) $< $(DESTDIR)$(bindir)
GARBAGE += $(MOZ_APP_NAME)
GARBAGE += $(addprefix $(DIST)/bin/defaults/pref/, firefox.js)
endif
@ -273,7 +255,7 @@ libs repackage:: $(PROGRAM) application.ini
rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
ifdef LIBXUL_SDK
cp $(LIBXUL_DIST)/bin/$(XR_STUB_NAME) $(DIST)/$(APP_NAME).app/Contents/MacOS/firefox-bin
cp $(LIBXUL_DIST)/bin/$(XR_STUB_NAME) $(DIST)/$(APP_NAME).app/Contents/MacOS/firefox
else
$(RM) $(DIST)/$(APP_NAME).app/Contents/MacOS/$(PROGRAM)
rsync -aL $(PROGRAM) $(DIST)/$(APP_NAME).app/Contents/MacOS

View File

@ -143,7 +143,7 @@
</dict>
</array>
<key>CFBundleExecutable</key>
<string>firefox-bin</string>
<string>firefox</string>
<key>CFBundleGetInfoString</key>
<string>%APP_NAME% %APP_VERSION%</string>
<key>CFBundleIconFile</key>

View File

@ -36,6 +36,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsXPCOMGlue.h"
#include "nsXULAppAPI.h"
#ifdef XP_WIN
#include <windows.h>
@ -44,6 +45,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "plstr.h"
#include "prprf.h"
@ -54,11 +56,14 @@
#include "nsStringGlue.h"
#ifdef XP_WIN
// we want to use the DLL blocklist if possible
#define XRE_WANT_DLL_BLOCKLIST
// we want a wmain entry point
#include "nsWindowsWMain.cpp"
#define snprintf _snprintf
#define strcasecmp _stricmp
#endif
#include "BinaryPath.h"
#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
static void Output(const char *fmt, ... )
{
@ -85,12 +90,12 @@ static PRBool IsArg(const char* arg, const char* s)
{
if (*++arg == '-')
++arg;
return !PL_strcasecmp(arg, s);
return !strcasecmp(arg, s);
}
#if defined(XP_WIN) || defined(XP_OS2)
if (*arg == '/')
return !PL_strcasecmp(++arg, s);
return !strcasecmp(++arg, s);
#endif
return PR_FALSE;
@ -106,22 +111,46 @@ public:
~ScopedLogging() { NS_LogTerm(); }
};
int main(int argc, char* argv[])
{
ScopedLogging log;
XRE_GetFileFromPathType XRE_GetFileFromPath;
XRE_CreateAppDataType XRE_CreateAppData;
XRE_FreeAppDataType XRE_FreeAppData;
#ifdef XRE_HAS_DLL_BLOCKLIST
XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
#endif
XRE_mainType XRE_main;
static const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
{ "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
{ "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
#ifdef XRE_HAS_DLL_BLOCKLIST
{ "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
#endif
{ "XRE_main", (NSFuncPtr*) &XRE_main },
{ nsnull, nsnull }
};
static int do_main(const char *exePath, int argc, char* argv[])
{
nsCOMPtr<nsILocalFile> appini;
nsresult rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(appini));
#ifdef XP_WIN
// exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
// encoded path, so it is safe to convert it
nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), PR_FALSE,
getter_AddRefs(appini));
#else
nsresult rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_FALSE,
getter_AddRefs(appini));
#endif
if (NS_FAILED(rv)) {
Output("Couldn't calculate the application directory.");
return 255;
}
appini->SetNativeLeafName(NS_LITERAL_CSTRING("application.ini"));
// Allow firefox.exe to launch XULRunner apps via -app <application.ini>
// Note that -app must be the *first* argument.
char *appEnv = nsnull;
const char *appDataFile = PR_GetEnv("XUL_APP_FILE");
const char *appDataFile = getenv("XUL_APP_FILE");
if (appDataFile && *appDataFile) {
rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
if (NS_FAILED(rv)) {
@ -141,8 +170,12 @@ int main(int argc, char* argv[])
return 255;
}
appEnv = PR_smprintf("XUL_APP_FILE=%s", argv[2]);
PR_SetEnv(appEnv);
char appEnv[MAXPATHLEN];
snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]);
if (putenv(appEnv)) {
Output("Couldn't set %s.\n", appEnv);
return 255;
}
argv[2] = argv[0];
argv += 2;
argc -= 2;
@ -157,7 +190,62 @@ int main(int argc, char* argv[])
int result = XRE_main(argc, argv, appData);
XRE_FreeAppData(appData);
if (appEnv)
PR_smprintf_free(appEnv);
return result;
}
int main(int argc, char* argv[])
{
char exePath[MAXPATHLEN];
nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
if (NS_FAILED(rv)) {
Output("Couldn't calculate the application directory.\n");
return 255;
}
char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
if (!lastSlash || (lastSlash - exePath > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
return 255;
strcpy(++lastSlash, XPCOM_DLL);
#ifdef XP_WIN
// GetProcessIoCounters().ReadOperationCount seems to have little to
// do with actual read operations. It reports 0 or 1 at this stage
// in the program. Luckily 1 coincides with when prefetch is
// enabled. If Windows prefetch didn't happen we can do our own
// faster dll preloading.
IO_COUNTERS ioCounters;
if (GetProcessIoCounters(GetCurrentProcess(), &ioCounters)
&& !ioCounters.ReadOperationCount)
#endif
{
XPCOMGlueEnablePreload();
}
rv = XPCOMGlueStartup(exePath);
if (NS_FAILED(rv)) {
Output("Couldn't load XPCOM.\n");
return 255;
}
rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
if (NS_FAILED(rv)) {
Output("Couldn't load XRE functions.\n");
return 255;
}
#ifdef XRE_HAS_DLL_BLOCKLIST
XRE_SetupDllBlocklist();
#endif
int result;
{
ScopedLogging log;
result = do_main(exePath, argc, argv);
}
XPCOMGlueShutdown();
return result;
}

View File

@ -86,10 +86,6 @@ function GroupItem(listOfEls, options) {
this.keepProportional = false;
this._frozenItemSizeData = {};
// Double click tracker
this._lastClick = 0;
this._lastClickPositions = null;
// Variable: _activeTab
// The <TabItem> for the groupItem's active tab.
this._activeTab = null;
@ -786,7 +782,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
return (groupItem != self && !groupItem.getChildren().length);
});
let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
group.newTab();
group.newTab(null, { closedLastTab: true });
}
this.destroy();
@ -1651,28 +1647,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
_addHandlers: function GroupItem__addHandlers(container) {
let self = this;
// Create new tab and zoom in on it after a double click
container.mousedown(function(e) {
if (!Utils.isLeftClick(e) || self.$titlebar[0] == e.target ||
self.$titlebar.contains(e.target)) {
self._lastClick = 0;
self._lastClickPositions = null;
return;
}
if (Date.now() - self._lastClick <= UI.DBLCLICK_INTERVAL &&
(self._lastClickPositions.x - UI.DBLCLICK_OFFSET) <= e.clientX &&
(self._lastClickPositions.x + UI.DBLCLICK_OFFSET) >= e.clientX &&
(self._lastClickPositions.y - UI.DBLCLICK_OFFSET) <= e.clientY &&
(self._lastClickPositions.y + UI.DBLCLICK_OFFSET) >= e.clientY) {
self.newTab();
self._lastClick = 0;
self._lastClickPositions = null;
} else {
self._lastClick = Date.now();
self._lastClickPositions = new Point(e.clientX, e.clientY);
}
});
var dropIndex = false;
var dropSpaceTimer = null;
@ -1791,14 +1765,16 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
// ----------
// Function: newTab
// Creates a new tab within this groupItem.
newTab: function GroupItem_newTab(url) {
UI.setActive(this, { dontSetActiveTabInGroup: true });
let newTab = gBrowser.loadOneTab(url || "about:blank", {inBackground: true});
// Parameters:
// url - the new tab should open this url as well
// options - the options object
// closedLastTab - boolean indicates the last tab has just been closed
newTab: function GroupItem_newTab(url, options) {
if (options && options.closedLastTab)
UI.closedLastTabInTabView = true;
// TabItems will have handled the new tab and added the tabItem property.
// We don't have to check if it's an app tab (and therefore wouldn't have a
// TabItem), since we've just created it.
newTab._tabViewTabItem.zoomIn(!url);
UI.setActive(this, { dontSetActiveTabInGroup: true });
gBrowser.loadOneTab(url || "about:blank", { inBackground: false });
},
// ----------

View File

@ -380,7 +380,7 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
}
} else {
// create tab by double click is handled in UI_init().
if (!TabItems.creatingNewOrphanTab)
if (!UI.creatingNewOrphanTab)
GroupItems.newTab(self, {immediately: true});
}
@ -564,7 +564,7 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
});
group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
}
group.newTab();
group.newTab(null, { closedLastTab: true });
}
// when "TabClose" event is fired, the browser tab is about to close and our
// item "close" is fired before the browser tab actually get closed.
@ -666,6 +666,8 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
}
if (self.parent && self.parent.expanded)
self.parent.collapse();
self._sendToSubscribers("zoomedIn");
}
let animateZoom = gPrefBranch.getBoolPref("animate_zoom");
@ -804,7 +806,6 @@ let TabItems = {
_lastUpdateTime: Date.now(),
_eventListeners: [],
_pauseUpdateForTest: false,
creatingNewOrphanTab: false,
tempCanvas: null,
_reconnectingPaused: false,
tabItemPadding: {},

View File

@ -139,6 +139,14 @@ let UI = {
// Used to prevent keypress being handled after quitting search mode.
ignoreKeypressForSearch: false,
// Variable: creatingNewOrphanTab
// Used to keep track of whether we are creating a new oprhan tab or not.
creatingNewOrphanTab: false,
// Variable: _lastOpenedTab
// Used to keep track of the last opened tab.
_lastOpenedTab: null,
// ----------
// Function: toString
// Prints [UI] for debug use
@ -196,20 +204,21 @@ let UI = {
(self._lastClickPositions.y - self.DBLCLICK_OFFSET) <= e.clientY &&
(self._lastClickPositions.y + self.DBLCLICK_OFFSET) >= e.clientY) {
self.setActive(null);
TabItems.creatingNewOrphanTab = true;
let newTab =
gBrowser.loadOneTab("about:blank", { inBackground: true });
self.creatingNewOrphanTab = true;
let box =
new Rect(e.clientX - Math.floor(TabItems.tabWidth/2),
e.clientY - Math.floor(TabItems.tabHeight/2),
TabItems.tabWidth, TabItems.tabHeight);
let newTab =
gBrowser.loadOneTab("about:blank", { inBackground: false });
newTab._tabViewTabItem.setBounds(box, true);
newTab._tabViewTabItem.pushAway(true);
self.setActive(newTab._tabViewTabItem);
TabItems.creatingNewOrphanTab = false;
self.creatingNewOrphanTab = false;
// the bounds of tab item is set and we can zoom in now.
newTab._tabViewTabItem.zoomIn(true);
self._lastClick = 0;
@ -727,6 +736,8 @@ let UI = {
// if it's an app tab, add it to all the group items
if (tab.pinned)
GroupItems.addAppTab(tab);
else if (self.isTabViewVisible())
self._lastOpenedTab = tab;
};
// TabClose
@ -861,30 +872,40 @@ let UI = {
// Function: onTabSelect
// Called when the user switches from one tab to another outside of the TabView UI.
onTabSelect: function UI_onTabSelect(tab) {
let currentTab = this._currentTab;
this._currentTab = tab;
// if the last visible tab has just been closed, don't show the chrome UI.
if (this.isTabViewVisible() &&
(this._closedLastVisibleTab || this._closedSelectedTabInTabView ||
this.restoredClosedTab)) {
if (this.restoredClosedTab) {
// when the tab view UI is being displayed, update the thumb for the
// restored closed tab after the page load
tab.linkedBrowser.addEventListener("load", function (event) {
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
TabItems._update(tab);
}, true);
if (this.isTabViewVisible()) {
if (!this.restoredClosedTab && this._lastOpenedTab == tab &&
tab._tabViewTabItem) {
if (!this.creatingNewOrphanTab)
tab._tabViewTabItem.zoomIn(true);
this._lastOpenedTab = null;
return;
}
if (this._closedLastVisibleTab ||
(this._closedSelectedTabInTabView && !this.closedLastTabInTabView) ||
this.restoredClosedTab) {
if (this.restoredClosedTab) {
// when the tab view UI is being displayed, update the thumb for the
// restored closed tab after the page load
tab.linkedBrowser.addEventListener("load", function (event) {
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
TabItems._update(tab);
}, true);
}
this._closedLastVisibleTab = false;
this._closedSelectedTabInTabView = false;
this.closedLastTabInTabView = false;
this.restoredClosedTab = false;
return;
}
this._closedLastVisibleTab = false;
this._closedSelectedTabInTabView = false;
this.restoredClosedTab = false;
return;
}
// reset these vars, just in case.
this._closedLastVisibleTab = false;
this._closedSelectedTabInTabView = false;
this.closedLastTabInTabView = false;
this.restoredClosedTab = false;
this._lastOpenedTab = null;
// if TabView is visible but we didn't just close the last tab or
// selected tab, show chrome.
@ -896,12 +917,7 @@ let UI = {
if (this._currentTab != tab)
return;
let oldItem = null;
let newItem = null;
if (currentTab && currentTab._tabViewTabItem)
oldItem = currentTab._tabViewTabItem;
// update the tab bar for the new tab's group
if (tab && tab._tabViewTabItem) {
if (!TabItems.reconnectingPaused()) {
@ -1499,14 +1515,14 @@ let UI = {
return (!groupItem.hidden && groupItem.getChildren().length > 0);
});
// no pinned tabs, no visible groups and no orphaned tabs: open a new
// group. open a blank tab and return
// group, a blank tab and return
if (!unhiddenGroups.length && !GroupItems.getOrphanedTabs().length) {
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
return (!groupItem.hidden && !groupItem.getChildren().length);
});
let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
if (!gBrowser._numPinnedTabs) {
group.newTab();
group.newTab(null, { closedLastTab: true });
return;
}
}

View File

@ -36,20 +36,23 @@ function test3() {
ok(!contentWindow.isSearchEnabled(), "The search is disabled")
is(gBrowser.tabs.length, 1, "There is one tab before cmd/ctrl + t is pressed");
EventUtils.synthesizeKey("t", { accelKey: true }, contentWindow);
is(gBrowser.tabs.length, 2, "There are two tabs after cmd/ctrl + t is pressed");
gBrowser.tabs[0].linkedBrowser.loadURI("about:robots");
gBrowser.tabs[1].linkedBrowser.loadURI("http://example.com/");
whenTabViewIsHidden(function() {
is(gBrowser.tabs.length, 2, "There are two tabs after cmd/ctrl + t is pressed");
afterAllTabsLoaded(function () {
showTabView(test4);
gBrowser.tabs[0].linkedBrowser.loadURI("about:robots");
gBrowser.tabs[1].linkedBrowser.loadURI("http://example.com/");
afterAllTabsLoaded(function () {
showTabView(test4);
});
});
EventUtils.synthesizeKey("t", { accelKey: true }, contentWindow);
}
function test4() {
is(gBrowser.tabs.length, 2, "There are two tabs");
let onTabClose = function() {
gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, true);
executeSoon(function() {
@ -59,7 +62,7 @@ function test4() {
is(gBrowser.tabs.length, 2, "There are two tabs after restoring one");
gBrowser.tabs[0].linkedBrowser.loadURI("about:blank");
gBrowser.removeTab(gBrowser.tabs[1]);
gBrowser.selectedTab = gBrowser.tabs[0];
test8();
});
};
@ -69,14 +72,14 @@ function test4() {
// below key combination shouldn't trigger actions in tabview UI
function test8() {
let newTab = gBrowser.loadOneTab("about:blank", { inBackground: true });
showTabView(function() {
is(gBrowser.tabs.length, 2, "There are two tabs before cmd/ctrl + w is pressed");
EventUtils.synthesizeKey("w", { accelKey: true }, contentWindow);
is(gBrowser.tabs.length, 2, "There are two tabs after cmd/ctrl + w is pressed");
is(gBrowser.tabs.length, 2, "There are two tabs before cmd/ctrl + w is pressed");
EventUtils.synthesizeKey("w", { accelKey: true }, contentWindow);
is(gBrowser.tabs.length, 2, "There are two tabs after cmd/ctrl + w is pressed");
gBrowser.removeTab(newTab);
test9();
gBrowser.removeTab(gBrowser.tabs[1]);
test9();
});
}
function test9() {

View File

@ -69,6 +69,6 @@ function test() {
finish();
}
newWin.addEventListener("tabviewshown", onTabViewShow, false);
newWin.TabView.toggle();
waitForFocus(function() { newWin.TabView.toggle(); });
}, false);
}

View File

@ -9,6 +9,12 @@ let contentElement;
function test() {
waitForExplicitFinish();
registerCleanupFunction(function() {
if (gBrowser.tabs.length > 1)
gBrowser.removeTab(gBrowser.tabs[1]);
hideTabView(function() {});
});
showTabView(function() {
contentWindow = TabView.getContentWindow();
contentElement = contentWindow.document.getElementById("content");
@ -24,9 +30,10 @@ function test1() {
showTabView(function() {
is(contentWindow.GroupItems.getOrphanedTabs().length, 1,
"An orphaned tab is created");
orphanedTab = contentWindow.GroupItems.getOrphanedTabs()[0].tab;
test2();
hideTabView(function() {
gBrowser.selectedTab = originalTab;
finish();
});
});
});
@ -36,29 +43,10 @@ function test1() {
mouseClick(contentElement, 0);
}
function test2() {
let groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200);
is(groupItem.getChildren().length, 0, "The group is empty");
hideTabView(function() {
is(groupItem.getChildren().length, 1, "A tab is created inside the group");
gBrowser.selectedTab = originalTab;
gBrowser.removeTab(orphanedTab);
gBrowser.removeTab(groupItem.getChildren()[0].tab);
finish();
});
// first click
mouseClick(groupItem.container, 0);
// second click
mouseClick(groupItem.container, 0);
}
function mouseClick(targetElement, buttonCode) {
EventUtils.sendMouseEvent(
{ type: "mousedown", button: buttonCode }, targetElement, contentWindow);
EventUtils.sendMouseEvent(
{ type: "mouseup", button: buttonCode }, targetElement, contentWindow);
}

View File

@ -64,11 +64,8 @@ function part1(win) {
ok(!contentWindow.UI.getActiveOrphanTab(), "There is no active orphan tab.");
ok(win.TabView.isVisible(), "Tab View is visible.");
win.gBrowser.tabContainer.addEventListener("TabSelect", function() {
win.gBrowser.tabContainer.removeEventListener("TabSelect", arguments.callee, false);
executeSoon(part4);
}, false);
whenTabViewIsHidden(part4, win);
win.document.getElementById("cmd_newNavigatorTab").doCommand();
}

View File

@ -35,7 +35,6 @@ function test() {
let tabItem = gBrowser.tabs[0]._tabViewTabItem;
cw.GroupItems.updateActiveGroupItemAndTabBar(tabItem);
gBrowser.removeTab(gBrowser.tabs[1]);
assertNumberOfGroups(1);
assertNumberOfTabs(1);
@ -69,9 +68,10 @@ function test() {
// simulate double click with left mouse button
let container = groupItem.container;
simulateDoubleClick(container);
assertNumberOfTabs(2);
assertNumberOfTabs(1);
whenTabViewIsHidden(finishTest);
groupItem.close();
hideTabView(finishTest);
}
waitForExplicitFinish();

View File

@ -0,0 +1,86 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let origTab = gBrowser.visibleTabs[0];
let contentWindow;
function test() {
waitForExplicitFinish();
test1();
}
// Open a new tab when the active tab item belongs to a group item.
function test1() {
registerCleanupFunction(function () TabView.hide());
showTabView(function() {
ok(origTab._tabViewTabItem.parent, "The original tab belongs to a group");
contentWindow = TabView.getContentWindow();
contentWindow.UI.setActive(origTab._tabViewTabItem);
testCreateTabAndThen(test2);
});
}
// Open a new tab when the active tab item is nothing.
function test2() {
showTabView(function() {
contentWindow.UI.setActive(null, { onlyRemoveActiveTab: true });
testCreateTabAndThen(test3);
});
}
// Open a new tab when the active tab item is an orphan tab.
function test3() {
showTabView(function() {
let groupItem = origTab._tabViewTabItem.parent;
let tabItems = groupItem.getChildren();
is(tabItems.length, 3, "There are 3 tab items in the group");
let lastTabItem = tabItems[tabItems.length - 1];
groupItem.remove(lastTabItem);
let orphanedTabs = contentWindow.GroupItems.getOrphanedTabs();
is(orphanedTabs.length, 1, "There should be 1 orphan tab");
is(orphanedTabs[0], lastTabItem, "The tab item is the same as the orphan tab");
contentWindow.UI.setActive(lastTabItem);
testCreateTabAndThen(function() {
hideTabView(finish);
});
});
}
function testCreateTabAndThen(callback) {
ok(TabView.isVisible(), "Tab View is visible");
// detect tab open and zoomed in event.
let onTabOpen = function(event) {
gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, false);
// ensure that the default tabview listener is called before so the
// tab._tabViewTabItem exists
executeSoon(function() {
let tab = event.target;
tabItem = tab._tabViewTabItem;
ok(tabItem, "Tab item is available after tab open");
registerCleanupFunction(function () gBrowser.removeTab(tab))
tabItem.addSubscriber(tabItem, "zoomedIn", function() {
tabItem.removeSubscriber(tabItem, "zoomedIn");
is(gBrowser.selectedTab, tab,
"The selected tab is the same as the newly opened tab");
executeSoon(callback);
});
});
}
gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, false);
// use the menu item (the same as pressing cmd/ctrl + t)
document.getElementById("menu_newNavigatorTab").doCommand();
}

View File

@ -50,33 +50,35 @@ function onTabViewLoadedAndShown() {
}
// Create a second tab
gBrowser.addTab("about:robots");
gBrowser.loadOneTab("about:robots", { inBackground: false });
is(gBrowser.tabs.length, 2, "we now have 2 tabs");
registerCleanupFunction(function() {
gBrowser.removeTab(gBrowser.tabs[1]);
});
afterAllTabsLoaded(function() {
// Get normal tab urls
for (let a = 0; a < gBrowser.tabs.length; a++)
normalURLs.push(gBrowser.tabs[a].linkedBrowser.currentURI.spec);
showTabView(function() {
// Get normal tab urls
for (let a = 0; a < gBrowser.tabs.length; a++)
normalURLs.push(gBrowser.tabs[a].linkedBrowser.currentURI.spec);
// verify that we're all set up for our test
verifyNormal();
// verify that we're all set up for our test
verifyNormal();
// go into private browsing and make sure Tab View becomes hidden
togglePBAndThen(function() {
ok(!TabView.isVisible(), "Tab View is no longer visible");
verifyPB();
// exit private browsing and make sure Tab View is shown again
// go into private browsing and make sure Tab View becomes hidden
togglePBAndThen(function() {
ok(TabView.isVisible(), "Tab View is visible again");
verifyNormal();
ok(!TabView.isVisible(), "Tab View is no longer visible");
verifyPB();
hideTabView(onTabViewHidden);
// exit private browsing and make sure Tab View is shown again
togglePBAndThen(function() {
ok(TabView.isVisible(), "Tab View is visible again");
verifyNormal();
hideTabView(onTabViewHidden);
});
});
});
});
});
}

View File

@ -315,6 +315,7 @@ WARNINGS_AS_ERRORS = @WARNINGS_AS_ERRORS@
MOZ_OPTIMIZE = @MOZ_OPTIMIZE@
MOZ_OPTIMIZE_FLAGS = @MOZ_OPTIMIZE_FLAGS@
MOZ_PGO_OPTIMIZE_FLAGS = @MOZ_PGO_OPTIMIZE_FLAGS@
MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@
MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@

View File

@ -422,8 +422,13 @@ ifdef MODULE_OPTIMIZE_FLAGS
CFLAGS += $(MODULE_OPTIMIZE_FLAGS)
CXXFLAGS += $(MODULE_OPTIMIZE_FLAGS)
else
ifneq (,$(if $(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE),$(MOZ_PGO_OPTIMIZE_FLAGS)))
CFLAGS += $(MOZ_PGO_OPTIMIZE_FLAGS)
CXXFLAGS += $(MOZ_PGO_OPTIMIZE_FLAGS)
else
CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
endif # neq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
endif # MODULE_OPTIMIZE_FLAGS
else
CFLAGS += $(MOZ_OPTIMIZE_FLAGS)

View File

@ -2224,10 +2224,12 @@ ia64*-hpux*)
esac
# If we're building with --enable-profiling, we need a frame pointer.
if test -z "$MOZ_PROFILING"; then
MOZ_OPTIMIZE_FLAGS="-O3 -fomit-frame-pointer"
MOZ_FRAMEPTR_FLAGS="-fomit-frame-pointer"
else
MOZ_OPTIMIZE_FLAGS="-O3 -fno-omit-frame-pointer"
MOZ_FRAMEPTR_FLAGS="-fno-omit-frame-pointer"
fi
MOZ_PGO_OPTIMIZE_FLAGS="-O3 $MOZ_FRAMEPTR_FLAGS"
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK $MOZ_FRAMEPTR_FLAGS"
MOZ_DEBUG_FLAGS="-g"
fi
@ -7275,6 +7277,7 @@ AC_SUBST(MOZ_OPTIMIZE)
AC_SUBST(MOZ_OPTIMIZE_FLAGS)
AC_SUBST(MOZ_OPTIMIZE_LDFLAGS)
AC_SUBST(MOZ_OPTIMIZE_SIZE_TWEAK)
AC_SUBST(MOZ_PGO_OPTIMIZE_FLAGS)
dnl ========================================================
dnl = Enable generation of debug symbols

View File

@ -128,8 +128,13 @@ nsSMILInstanceTime::HandleChangedInterval(
PRBool aBeginObjectChanged,
PRBool aEndObjectChanged)
{
NS_ABORT_IF_FALSE(mBaseInterval,
"Got call to HandleChangedInterval on an independent instance time.");
// It's possible a sequence of notifications might cause our base interval to
// be updated and then deleted. Furthermore, the delete might happen whilst
// we're still in the queue to be notified of the change. In any case, if we
// don't have a base interval, just ignore the change.
if (!mBaseInterval)
return;
NS_ABORT_IF_FALSE(mCreator, "Base interval is set but creator is not.");
if (mVisited) {

View File

@ -40,9 +40,7 @@
nsSMILInterval::nsSMILInterval()
:
mBeginFixed(PR_FALSE),
mEndFixed(PR_FALSE),
mBeginObjectChanged(PR_FALSE),
mEndObjectChanged(PR_FALSE)
mEndFixed(PR_FALSE)
{
}
@ -51,9 +49,7 @@ nsSMILInterval::nsSMILInterval(const nsSMILInterval& aOther)
mBegin(aOther.mBegin),
mEnd(aOther.mEnd),
mBeginFixed(PR_FALSE),
mEndFixed(PR_FALSE),
mBeginObjectChanged(PR_FALSE),
mEndObjectChanged(PR_FALSE)
mEndFixed(PR_FALSE)
{
NS_ABORT_IF_FALSE(aOther.mDependentTimes.IsEmpty(),
"Attempting to copy-construct an interval with dependent times, "
@ -74,18 +70,6 @@ nsSMILInterval::~nsSMILInterval()
"Unlink was not called");
}
void
nsSMILInterval::NotifyChanged(const nsSMILTimeContainer* aContainer)
{
for (PRInt32 i = mDependentTimes.Length() - 1; i >= 0; --i) {
mDependentTimes[i]->HandleChangedInterval(aContainer,
mBeginObjectChanged,
mEndObjectChanged);
}
mBeginObjectChanged = PR_FALSE;
mEndObjectChanged = PR_FALSE;
}
void
nsSMILInterval::Unlink(PRBool aFiltered)
{
@ -131,11 +115,7 @@ nsSMILInterval::SetBegin(nsSMILInstanceTime& aBegin)
NS_ABORT_IF_FALSE(!mBeginFixed,
"Attempting to set begin time but the begin point is fixed");
if (mBegin == &aBegin)
return;
mBegin = &aBegin;
mBeginObjectChanged = PR_TRUE;
}
void
@ -144,11 +124,7 @@ nsSMILInterval::SetEnd(nsSMILInstanceTime& aEnd)
NS_ABORT_IF_FALSE(!mEndFixed,
"Attempting to set end time but the end point is fixed");
if (mEnd == &aEnd)
return;
mEnd = &aEnd;
mEndObjectChanged = PR_TRUE;
}
void
@ -193,6 +169,12 @@ nsSMILInterval::RemoveDependentTime(const nsSMILInstanceTime& aTime)
NS_ABORT_IF_FALSE(found, "Couldn't find instance time to delete.");
}
void
nsSMILInterval::GetDependentTimes(InstanceTimeList& aTimes)
{
aTimes = mDependentTimes;
}
PRBool
nsSMILInterval::IsDependencyChainLink() const
{

View File

@ -56,7 +56,6 @@ public:
nsSMILInterval();
nsSMILInterval(const nsSMILInterval& aOther);
~nsSMILInterval();
void NotifyChanged(const nsSMILTimeContainer* aContainer);
void Unlink(PRBool aFiltered = PR_FALSE);
const nsSMILInstanceTime* Begin() const
@ -86,8 +85,11 @@ public:
void FixBegin();
void FixEnd();
typedef nsTArray<nsRefPtr<nsSMILInstanceTime> > InstanceTimeList;
void AddDependentTime(nsSMILInstanceTime& aTime);
void RemoveDependentTime(const nsSMILInstanceTime& aTime);
void GetDependentTimes(InstanceTimeList& aTimes);
// Cue for assessing if this interval can be filtered
PRBool IsDependencyChainLink() const;
@ -96,8 +98,6 @@ private:
nsRefPtr<nsSMILInstanceTime> mBegin;
nsRefPtr<nsSMILInstanceTime> mEnd;
typedef nsTArray<nsRefPtr<nsSMILInstanceTime> > InstanceTimeList;
// nsSMILInstanceTimes to notify when this interval is changed or deleted.
InstanceTimeList mDependentTimes;
@ -112,21 +112,6 @@ private:
// OBJECT returned for that end point and its TIME value will not change.
PRPackedBool mBeginFixed;
PRPackedBool mEndFixed;
// When change notifications are passed around the timing model we try to
// filter out all changes where there is no observable difference to an
// instance time. Changes that may produce an observable difference are:
//
// * Changes to the time of an interval endpoint
// * Changes in the relative times of different time containers
// * Changes to the dependency chain (which may affect the animation sandwich)
//
// The nsSMILTimeValueSpec can detect the first two changes by recalculating
// the time but in order to help detect the third change we simply set a flag
// whenever the mBegin or mEnd pointers are changed. These flags are reset
// when the next change notification is sent.
PRPackedBool mBeginObjectChanged;
PRPackedBool mEndObjectChanged;
};
#endif // NS_SMILINTERVAL_H_

View File

@ -551,7 +551,10 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly)
case STATE_ACTIVE:
{
ApplyEarlyEnd(sampleTime);
// Ending early will change the interval but we don't notify dependents
// of the change until we have closed off the current interval (since we
// don't want dependencies to un-end our early end).
PRBool didApplyEarlyEnd = ApplyEarlyEnd(sampleTime);
if (mCurrentInterval->End()->Time() <= sampleTime) {
nsSMILInterval newInterval;
@ -567,15 +570,23 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly)
}
mCurrentRepeatIteration = 0;
mOldIntervals.AppendElement(mCurrentInterval.forget());
// We must update mOldIntervals before calling SampleFillValue
SampleFillValue();
if (mElementState == STATE_WAITING) {
mCurrentInterval = new nsSMILInterval(newInterval);
}
// We are now in a consistent state to dispatch notifications
if (didApplyEarlyEnd) {
NotifyChangedInterval(
mOldIntervals[mOldIntervals.Length() - 1], PR_FALSE, PR_TRUE);
}
if (mElementState == STATE_WAITING) {
NotifyNewInterval();
}
FilterHistory();
stateChanged = PR_TRUE;
} else {
NS_ABORT_IF_FALSE(!didApplyEarlyEnd,
"We got an early end, but didn't end");
nsSMILTime beginTime = mCurrentInterval->Begin()->Time().GetMillis();
NS_ASSERTION(aContainerTime >= beginTime,
"Sample time should not precede current interval");
@ -626,7 +637,7 @@ nsSMILTimedElement::HandleContainerTimeChange()
// the nsSMILTimeValueSpec we'll check if anything has changed and if not, we
// won't go any further.
if (mElementState == STATE_WAITING || mElementState == STATE_ACTIVE) {
NotifyChangedInterval();
NotifyChangedInterval(mCurrentInterval, PR_FALSE, PR_FALSE);
}
}
@ -1237,13 +1248,15 @@ nsSMILTimedElement::ClearIntervalProgress()
mOldIntervals.Clear();
}
void
PRBool
nsSMILTimedElement::ApplyEarlyEnd(const nsSMILTimeValue& aSampleTime)
{
// This should only be called within DoSampleAt as a helper function
NS_ABORT_IF_FALSE(mElementState == STATE_ACTIVE,
"Unexpected state to try to apply an early end");
PRBool updated = PR_FALSE;
// Only apply an early end if we're not already ending.
if (mCurrentInterval->End()->Time() > aSampleTime) {
nsSMILInstanceTime* earlyEnd = CheckForEarlyEnd(aSampleTime);
@ -1258,9 +1271,10 @@ nsSMILTimedElement::ApplyEarlyEnd(const nsSMILTimeValue& aSampleTime)
} else {
mCurrentInterval->SetEnd(*earlyEnd);
}
NotifyChangedInterval();
updated = PR_TRUE;
}
}
return updated;
}
namespace
@ -1815,22 +1829,23 @@ nsSMILTimedElement::UpdateCurrentInterval(PRBool aForceChangeNotice)
} else {
PRBool changed = PR_FALSE;
PRBool beginChanged = PR_FALSE;
PRBool endChanged = PR_FALSE;
if (mElementState != STATE_ACTIVE &&
!updatedInterval.Begin()->SameTimeAndBase(
*mCurrentInterval->Begin())) {
mCurrentInterval->SetBegin(*updatedInterval.Begin());
changed = PR_TRUE;
beginChanged = PR_TRUE;
}
if (!updatedInterval.End()->SameTimeAndBase(*mCurrentInterval->End())) {
mCurrentInterval->SetEnd(*updatedInterval.End());
changed = PR_TRUE;
endChanged = PR_TRUE;
}
if (changed || aForceChangeNotice) {
NotifyChangedInterval();
if (beginChanged || endChanged || aForceChangeNotice) {
NotifyChangedInterval(mCurrentInterval, beginChanged, endChanged);
}
}
@ -1844,7 +1859,7 @@ nsSMILTimedElement::UpdateCurrentInterval(PRBool aForceChangeNotice)
if (!mCurrentInterval->End()->SameTimeAndBase(*mCurrentInterval->Begin()))
{
mCurrentInterval->SetEnd(*mCurrentInterval->Begin());
NotifyChangedInterval();
NotifyChangedInterval(mCurrentInterval, PR_FALSE, PR_TRUE);
}
// The transition to the postactive state will take place on the next
// sample (along with firing end events, clearing intervals etc.)
@ -2023,18 +2038,27 @@ nsSMILTimedElement::NotifyNewInterval()
}
void
nsSMILTimedElement::NotifyChangedInterval()
nsSMILTimedElement::NotifyChangedInterval(nsSMILInterval* aInterval,
PRBool aBeginObjectChanged,
PRBool aEndObjectChanged)
{
NS_ABORT_IF_FALSE(mCurrentInterval,
"Attempting to notify dependents of a changed interval but the interval "
"is not set--perhaps we should be deleting the interval instead?");
NS_ABORT_IF_FALSE(aInterval, "Null interval for change notification");
nsSMILTimeContainer* container = GetTimeContainer();
if (container) {
container->SyncPauseTime();
}
mCurrentInterval->NotifyChanged(container);
// Copy the instance times list since notifying the instance times can result
// in a chain reaction whereby our own interval gets deleted along with its
// instance times.
InstanceTimeList times;
aInterval->GetDependentTimes(times);
for (PRUint32 i = 0; i < times.Length(); ++i) {
times[i]->HandleChangedInterval(container, aBeginObjectChanged,
aEndObjectChanged);
}
}
void

View File

@ -423,8 +423,10 @@ protected:
* applied at the last possible moment (i.e. if they are at
* or before the current sample time) and only if the
* current interval is not already ending.
* @return PR_TRUE if the end time of the current interval was updated,
* PR_FALSE otherwise.
*/
void ApplyEarlyEnd(const nsSMILTimeValue& aSampleTime);
PRBool ApplyEarlyEnd(const nsSMILTimeValue& aSampleTime);
/**
* Clears certain state in response to the element restarting.
@ -504,8 +506,17 @@ protected:
void RegisterMilestone();
PRBool GetNextMilestone(nsSMILMilestone& aNextMilestone) const;
// Notification methods. Note that these notifications can result in nested
// calls to this same object. Therefore,
// (i) we should not perform notification until this object is in
// a consistent state to receive callbacks, and
// (ii) after calling these methods we must assume that the state of the
// element may have changed.
void NotifyNewInterval();
void NotifyChangedInterval();
void NotifyChangedInterval(nsSMILInterval* aInterval,
PRBool aBeginObjectChanged,
PRBool aEndObjectChanged);
void FireTimeEventAsync(PRUint32 aMsg, PRInt32 aDetail);
const nsSMILInstanceTime* GetEffectiveBeginInstance() const;
const nsSMILInterval* GetPreviousInterval() const;

View File

@ -146,6 +146,7 @@ PluginProcessChild::Init()
protectCurrentDirectory = false;
}
if (protectCurrentDirectory) {
SanitizeEnvironmentVariables();
NS_SetDllDirectory(L"");
}

View File

@ -34,19 +34,33 @@ var numWindows = 0;
/* Called when our popup loads. */
function testWindow(w)
{
// w.location.search == '?true' if we expect the bars to be on, and
// '?false' otherwise.
var e = w.location.search == '?true';
is(w.menubar.visible, e, "menubar");
is(w.toolbar.visible, e, "toolbar");
is(w.personalbar.visible, e, "personalbar");
is(w.scrollbars.visible, e, "scrollbars");
// If dom.disable_window_open_feature.X is true, then we can't disable
// feature X when we call window.open from content. So to check that our popup
// has the right bars shown, we need to check that it obeys first the pref
// and then the arguments to window.open, if applicable.
// You can't turn these off even if you try, so check that they're true.
is(w.locationbar.visible, true, "locationbar");
is(w.statusbar.visible, true, "statusbar");
function checkFeature(feature, prefname) {
if (prefname === undefined)
prefname = feature;
if (SpecialPowers.getBoolPref('dom.disable_window_open_feature.' + prefname)) {
is(w[feature].visible, true, feature + ' should always be true.');
}
else {
// w.location.search == '?true' if we expect the bars to be on, and
// '?false' otherwise.
var enabled = w.location.search == '?true';
is(w[feature].visible, enabled, feature + ' should follow window.open settings.');
}
}
checkFeature('menubar');
checkFeature('toolbar');
checkFeature('personalbar');
checkFeature('scrollbars');
checkFeature('statusbar', 'status');
checkFeature('locationbar', 'location');
w.close();

View File

@ -77,6 +77,8 @@
#endif
#endif
using namespace mozilla;
#ifdef CAIRO_HAS_D2D_SURFACE
#include "gfxD2DSurface.h"
@ -85,8 +87,6 @@
#include "nsIMemoryReporter.h"
#include "nsMemory.h"
using namespace mozilla;
class D2DCacheReporter :
public nsIMemoryReporter
{

View File

@ -73,6 +73,7 @@ main(int argc, char* argv[])
// avoid it for unsupported plugins. See PluginProcessChild::Init for
// the details.
if (proctype != GeckoProcessType_Plugin) {
mozilla::SanitizeEnvironmentVariables();
mozilla::NS_SetDllDirectory(L"");
}
#endif

View File

@ -145,6 +145,7 @@ FAIL_ON_WARNINGS = @FAIL_ON_WARNINGS@
MOZ_OPTIMIZE = @MOZ_OPTIMIZE@
MOZ_OPTIMIZE_FLAGS = @MOZ_OPTIMIZE_FLAGS@
MOZ_PGO_OPTIMIZE_FLAGS = @MOZ_PGO_OPTIMIZE_FLAGS@
MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@
MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@

View File

@ -422,8 +422,13 @@ ifdef MODULE_OPTIMIZE_FLAGS
CFLAGS += $(MODULE_OPTIMIZE_FLAGS)
CXXFLAGS += $(MODULE_OPTIMIZE_FLAGS)
else
ifneq (,$(if $(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE),$(MOZ_PGO_OPTIMIZE_FLAGS)))
CFLAGS += $(MOZ_PGO_OPTIMIZE_FLAGS)
CXXFLAGS += $(MOZ_PGO_OPTIMIZE_FLAGS)
else
CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
endif # neq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
endif # MODULE_OPTIMIZE_FLAGS
else
CFLAGS += $(MOZ_OPTIMIZE_FLAGS)

View File

@ -2140,10 +2140,12 @@ ia64*-hpux*)
esac
# If we're building with --enable-profiling, we need a frame pointer.
if test -z "$MOZ_PROFILING"; then
MOZ_OPTIMIZE_FLAGS="-O3 -fomit-frame-pointer"
MOZ_FRAMEPTR_FLAGS="-fomit-frame-pointer"
else
MOZ_OPTIMIZE_FLAGS="-O3 -fno-omit-frame-pointer"
MOZ_FRAMEPTR_FLAGS="-fno-omit-frame-pointer"
fi
MOZ_PGO_OPTIMIZE_FLAGS="-O3 $MOZ_FRAMEPTR_FLAGS"
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK $MOZ_FRAMEPTR_FLAGS"
MOZ_DEBUG_FLAGS="-g"
fi
@ -4729,6 +4731,7 @@ AC_SUBST(MOZ_OPTIMIZE)
AC_SUBST(MOZ_OPTIMIZE_FLAGS)
AC_SUBST(MOZ_OPTIMIZE_LDFLAGS)
AC_SUBST(MOZ_OPTIMIZE_SIZE_TWEAK)
AC_SUBST(MOZ_PGO_OPTIMIZE_FLAGS)
dnl ========================================================
dnl = Enable generation of debug symbols

View File

@ -2026,7 +2026,7 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// metadata about this scroll box to the compositor process.
nsDisplayScrollInfoLayer* layerItem = new (aBuilder) nsDisplayScrollInfoLayer(
aBuilder, mScrolledFrame, mOuter);
set.Content()->AppendNewToBottom(layerItem);
set.BorderBackground()->AppendNewToBottom(layerItem);
}
nsRect clip;

View File

@ -0,0 +1,12 @@
<html><head>
<style>
div {
outline: 1px solid black;
}
</style>
</head><body>
You should see no red, only green<br>
<div style="overflow: scroll; height: 200px; z-index: 2; position: relative; background-color: lime;"></div>
</div>
</body></html>

View File

@ -0,0 +1,16 @@
<html><head>
<style>
div {
outline: 1px solid black;
}
</style>
</head><body>
You should see no red, only green<br>
<div style="overflow: scroll; height: 200px; z-index: 2; position: relative; background-color: red;"></div>
<div class="displayport" reftest-displayport-h="500" style="overflow: scroll; position: relative; margin-top: -200px; height: 200px;">
<div style="z-index: 10; position: absolute; width: 100%; height: 500px; bottom: -300px;">
<div style="height: 200px; background-color: lime;"></div>
</div>
</div>
</body></html>

View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Reftest</title>
<style type="text/css">
ul {
position: absolute;
top: 50px;
bottom: 0px;
left: 0;
right: 0;
overflow: auto;
}
li {
height: 2000px;
}
a {
float: left;
color: black;
border: solid black 1px;
}
</style>
</head>
<body>
<ul>
<li>
<a href="#"> </a>
</li>
</ul>
</body>
</html>

View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Reftest</title>
<style type="text/css">
ul {
position: absolute;
top: 50px;
bottom: 0px;
left: 0;
right: 0;
overflow: auto;
}
li {
height: 2000px;
}
a {
float: left;
color: black;
border: solid black 1px;
}
</style>
</head>
<body>
<ul class="displayport">
<li>
<a href="#"> </a>
</li>
</ul>
</body>
</html>

View File

@ -89,6 +89,8 @@ needs-focus == data:text/plain, about:blank
# Sanity check of viewport+displayport overrides
fails-if(!browserIsRemote) == test-displayport.html test-displayport-ref.html # bug 593168
skip-if(!browserIsRemote) != test-displayport-2.html test-displayport-ref.html # bug 593168
skip-if(!browserIsRemote) == 647192-1.html 647192-1-ref.html
skip-if(!browserIsRemote) == 656041-1.html 656041-1-ref.html
# IPC Position-fixed frames/layers test
# Fixed layers are temporarily disabled (bug 656167).

View File

@ -2734,13 +2734,18 @@ Tab.prototype = {
if ("delayLoad" in aParams && aParams.delayLoad)
return;
try {
let flags = aParams.flags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
let postData = aParams.postData ? aParams.postData.value : null;
browser.loadURIWithFlags(aURI, flags, aParams.referrerURI, aParams.charset, postData);
} catch(e) {
dump("Error: " + e + "\n");
}
// Give the browser binding a chance to attach completely before trying to
// load. Trying to load an invalid about: page from a remote browser causes
// a crash when trying to display the warning dialog.
setTimeout(function() {
try {
let flags = aParams.flags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
let postData = aParams.postData ? aParams.postData.value : null;
browser.loadURIWithFlags(aURI, flags, aParams.referrerURI, aParams.charset, postData);
} catch(e) {
dump("Error: " + e + "\n");
}
}, 0);
},
destroy: function destroy() {

View File

@ -1021,7 +1021,7 @@ var FormSubmitObserver = {
addMessageListener("Browser:TabClose", this);
},
receiveMessage: function findHandlerReceiveMessage(aMessage) {
receiveMessage: function receiveMessage(aMessage) {
let json = aMessage.json;
switch (aMessage.name) {
case "Browser:TabOpen":

View File

@ -96,7 +96,7 @@ SSLExceptions.prototype = {
var req = new XMLHttpRequest();
try {
if(aURI) {
if (aURI) {
req.open("GET", aURI.prePath, false);
req.channel.notificationCallbacks = this;
req.send(null);

View File

@ -346,7 +346,7 @@ function start() {
}
}
if (matchingLocale != chrome.getSelectedLocale("browser"))
if (matchingLocale && matchingLocale != chrome.getSelectedLocale("browser"))
LocaleUI.language = matchingLocale;
else {
LocaleUI._language = chrome.getSelectedLocale("browser");

View File

@ -1438,6 +1438,10 @@ setting {
-moz-margin-start: @margin_xnormal@;
}
#sync-message {
padding-bottom: 2em;
}
/* content scrollbars */
.scroller {
opacity: 0;

View File

@ -3151,9 +3151,9 @@ pref("image.http.accept", "image/png,image/*;q=0.8,*/*;q=0.5");
// compressed data.
pref("image.mem.discardable", true);
// Prevents images from automatically being decoded on load, instead allowing
// them to be decoded on demand when they are drawn.
pref("image.mem.decodeondraw", false);
// Prevents images from automatically being decoded when loaded in background
// tabs, instead allowing them to be decoded on demand when they are drawn.
pref("image.mem.decodeondraw", true);
// Minimum timeout for image discarding (in milliseconds). The actual time in
// which an image must inactive for it to be discarded will vary between this

View File

@ -325,7 +325,12 @@ nsStandardURL::~nsStandardURL()
}
#ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
static void DumpLeakedURLs()
struct DumpLeakedURLs {
DumpLeakedURLs() {}
~DumpLeakedURLs();
};
DumpLeakedURLs::~DumpLeakedURLs()
{
if (!PR_CLIST_IS_EMPTY(&gAllURLs)) {
printf("Leaked URLs:\n");
@ -363,8 +368,12 @@ nsStandardURL::ShutdownGlobalObjects()
NS_IF_RELEASE(gCharsetMgr);
#ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
if (gInitialized)
atexit(DumpLeakedURLs);
if (gInitialized) {
// This instanciates a dummy class, and will trigger the class
// destructor when libxul is unloaded. This is equivalent to atexit(),
// but gracefully handles dlclose().
static DumpLeakedURLs d;
}
#endif
}

View File

@ -196,9 +196,6 @@ static const char* const kDumpFileAfterText[] = {
*/
CViewSourceHTML::CViewSourceHTML()
{
mSyntaxHighlight = PR_FALSE;
mWrapLongLines = PR_FALSE;
mTabSize = -1;
mSyntaxHighlight =
Preferences::GetBool("view_source.syntax_highlight", PR_TRUE);

View File

@ -390,7 +390,10 @@ nsresult nsProfileLock::LockWithSymlink(const nsACString& lockFilePath, PRBool a
if (!setupPidLockCleanup++)
{
// Clean up on normal termination.
atexit(RemovePidLockFilesExiting);
// This instanciates a dummy class, and will trigger the class
// destructor when libxul is unloaded. This is equivalent to atexit(),
// but gracefully handles dlclose().
static RemovePidLockFilesExiting r;
// Clean up on abnormal termination, using POSIX sigaction.
// Don't arm a handler if the signal is being ignored, e.g.,

View File

@ -99,14 +99,12 @@ private:
LHANDLE mLockFileHandle;
#elif defined (XP_UNIX)
static void RemovePidLockFilesExiting()
{
// We can't implement this function with a default parameter on
// RemovePidLockFiles(aFatalSignal) since we register
// atexit(RemovePidLockFilesExiting).
RemovePidLockFiles(PR_FALSE);
}
struct RemovePidLockFilesExiting {
RemovePidLockFilesExiting() {}
~RemovePidLockFilesExiting() {
RemovePidLockFiles(PR_FALSE);
}
};
static void RemovePidLockFiles(PRBool aFatalSignal);
static void FatalSignalHandler(int signo

View File

@ -92,6 +92,7 @@ endif
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
CPPSRCS += nsNativeAppSupportWin.cpp
CPPSRCS += nsWindowsDllBlocklist.cpp
DEFINES += -DWIN32_LEAN_AND_MEAN -DUNICODE -D_UNICODE
EXPORTS = nsWindowsDllInterceptor.h
else
@ -191,6 +192,7 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/dom/ipc \
-I$(topsrcdir)/toolkit/crashreporter \
-I$(topsrcdir)/dom/base \
-I$(topsrcdir)/xpcom/build \
$(NULL)
LOCAL_INCLUDES += \

View File

@ -251,6 +251,7 @@ static char **gQtOnlyArgv;
#endif /* MOZ_X11 */
#include "nsGTKToolkit.h"
#endif
#include "BinaryPath.h"
// Save literal putenv string to environment variable.
static void
@ -1435,141 +1436,10 @@ RemoteCommandLine(const char* aDesktopStartupID)
}
#endif // MOZ_ENABLE_XREMOTE
#ifdef XP_MACOSX
static char const *gBinaryPath;
#endif
nsresult
XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult)
{
nsresult rv;
nsCOMPtr<nsILocalFile> lf;
// We need to use platform-specific hackery to find the
// path of this executable. This is copied, with some modifications, from
// nsGREDirServiceProvider.cpp
#ifdef XP_WIN
PRUnichar exePath[MAXPATHLEN];
if (!::GetModuleFileNameW(0, exePath, MAXPATHLEN))
return NS_ERROR_FAILURE;
rv = NS_NewLocalFile(nsDependentString(exePath), PR_TRUE,
getter_AddRefs(lf));
if (NS_FAILED(rv))
return rv;
#elif defined(XP_MACOSX)
if (gBinaryPath)
return NS_NewNativeLocalFile(nsDependentCString(gBinaryPath), PR_FALSE,
aResult);
NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(lf));
nsCOMPtr<nsILocalFileMac> lfm (do_QueryInterface(lf));
if (!lfm)
return NS_ERROR_FAILURE;
// Works even if we're not bundled.
CFBundleRef appBundle = CFBundleGetMainBundle();
if (!appBundle)
return NS_ERROR_FAILURE;
CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle);
if (!executableURL)
return NS_ERROR_FAILURE;
rv = lfm->InitWithCFURL(executableURL);
CFRelease(executableURL);
if (NS_FAILED(rv))
return rv;
// Callers expect a normalized path.
lfm->Normalize();
#elif defined(XP_UNIX)
struct stat fileStat;
char exePath[MAXPATHLEN];
char tmpPath[MAXPATHLEN];
rv = NS_ERROR_FAILURE;
// on unix, there is no official way to get the path of the current binary.
// instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
// multiple applications, we will try a series of techniques:
//
// 1) look for /proc/<pid>/exe which is a symlink to the executable on newer
// Linux kernels
// 2) use realpath() on argv[0], which works unless we're loaded from the
// PATH
// 3) manually walk through the PATH and look for ourself
// 4) give up
// #ifdef __linux__
// Commented out because it used to not work because it used to not deal
// with readlink not null-terminating the buffer.
#if 0
int r = readlink("/proc/self/exe", exePath, MAXPATHLEN);
if (r > 0 && r < MAXPATHLEN) {
exePath[r] = '\0';
if (stat(exePath, &fileStat) == 0) {
rv = NS_OK;
}
}
#endif
if (NS_FAILED(rv) &&
realpath(argv0, exePath) && stat(exePath, &fileStat) == 0) {
rv = NS_OK;
}
if (NS_FAILED(rv)) {
const char *path = getenv("PATH");
if (!path)
return NS_ERROR_FAILURE;
char *pathdup = strdup(path);
if (!pathdup)
return NS_ERROR_OUT_OF_MEMORY;
PRBool found = PR_FALSE;
char *newStr = pathdup;
char *token;
while ( (token = nsCRT::strtok(newStr, ":", &newStr)) ) {
sprintf(tmpPath, "%s/%s", token, argv0);
if (realpath(tmpPath, exePath) && stat(exePath, &fileStat) == 0) {
found = PR_TRUE;
break;
}
}
free(pathdup);
if (!found)
return NS_ERROR_FAILURE;
}
rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE,
getter_AddRefs(lf));
if (NS_FAILED(rv))
return rv;
#elif defined(XP_OS2)
PPIB ppib;
PTIB ptib;
char exePath[MAXPATHLEN];
DosGetInfoBlocks( &ptib, &ppib);
DosQueryModuleName( ppib->pib_hmte, MAXPATHLEN, exePath);
rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE,
getter_AddRefs(lf));
if (NS_FAILED(rv))
return rv;
#else
#error Oops, you need platform-specific code here
#endif
NS_ADDREF(*aResult = lf);
return NS_OK;
return mozilla::BinaryPath::GetFile(argv0, aResult);
}
#define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200)
@ -2821,16 +2691,6 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
NS_ENSURE_TRUE(aAppData, 2);
#ifdef XP_MACOSX
// The xulrunner stub executable tricks CFBundleGetMainBundle on
// purpose into lying about the main bundle path. It will set
// XRE_BINARY_PATH to inform us of our real location.
gBinaryPath = getenv("XRE_BINARY_PATH");
if (gBinaryPath && !*gBinaryPath)
gBinaryPath = nsnull;
#endif
// Check for application.ini overrides
const char* override = nsnull;
ar = CheckArg("override", PR_TRUE, &override);
@ -3750,14 +3610,6 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD);
SaveWordToEnvIfUnset("XRE_PROFILE_NAME", profileName);
#ifdef XP_MACOSX
if (gBinaryPath) {
static char kEnvVar[MAXPATHLEN];
sprintf(kEnvVar, "XRE_BINARY_PATH=%s", gBinaryPath);
PR_SetEnv(kEnvVar);
}
#endif
#ifdef MOZ_WIDGET_GTK2
MOZ_gdk_display_close(display);
#endif

View File

@ -40,6 +40,12 @@
#include <stdio.h>
#ifdef XRE_WANT_DLL_BLOCKLIST
#define XRE_SetupDllBlocklist SetupDllBlocklist
#else
#include "nsXULAppAPI.h"
#endif
#include "nsAutoPtr.h"
#include "prlog.h"
@ -208,7 +214,7 @@ continue_loading:
WindowsDllInterceptor NtDllIntercept;
void
SetupDllBlocklist()
XRE_SetupDllBlocklist()
{
NtDllIntercept.Init("ntdll.dll");

View File

@ -76,6 +76,7 @@ FreeAllocStrings(int argc, char **argv)
int wmain(int argc, WCHAR **argv)
{
#ifndef XRE_DONT_PROTECT_DLL_LOAD
mozilla::SanitizeEnvironmentVariables();
mozilla::NS_SetDllDirectory(L"");
#endif

View File

@ -1365,7 +1365,7 @@ NS_TraceMallocStartup(int logfd)
log_header(logfd);
}
atexit(NS_TraceMallocShutdown);
RegisterTraceMallocShutdown();
tmlock = PR_NewLock();
(void) tm_get_thread(); /* ensure index initialization while it's easy */

View File

@ -54,6 +54,22 @@
extern "C" const char* nsGetTypeName(void* ptr);
extern "C" void NS_TraceMallocShutdown();
struct TraceMallocShutdown {
TraceMallocShutdown() {}
~TraceMallocShutdown() {
NS_TraceMallocShutdown();
}
};
extern "C" void RegisterTraceMallocShutdown() {
// This instanciates the dummy class above, and will trigger the class
// destructor when libxul is unloaded. This is equivalent to atexit(),
// but gracefully handles dlclose().
static TraceMallocShutdown t;
}
class IUnknown {
public:
virtual long QueryInterface() = 0;

View File

@ -61,7 +61,6 @@ using namespace mozilla;
const float kAccessoryViewPadding = 5;
const int kSaveTypeControlTag = 1;
const char kLastTypeIndexPref[] = "filepicker.lastTypeIndex";
static PRBool gCallSecretHiddenFileAPI = PR_FALSE;
const char kShowHiddenFilesPref[] = "filepicker.showHiddenFiles";
@ -143,10 +142,6 @@ nsFilePicker::InitNative(nsIWidget *aParent, const nsAString& aTitle,
{
mTitle = aTitle;
mMode = aMode;
// read in initial type index from prefs
mSelectedTypeIndex =
Preferences::GetInt(kLastTypeIndexPref, mSelectedTypeIndex);
}
NSView* nsFilePicker::GetAccessoryView()
@ -511,8 +506,6 @@ nsFilePicker::PutLocalFile(const nsString& inTitle, const nsString& inDefaultNam
NSPopUpButton* popupButton = [accessoryView viewWithTag:kSaveTypeControlTag];
if (popupButton) {
mSelectedTypeIndex = [popupButton indexOfSelectedItem];
// save out to prefs for initializing other file picker instances
Preferences::SetInt(kLastTypeIndexPref, mSelectedTypeIndex);
}
NSURL* fileURL = [thePanel URL];
@ -542,10 +535,15 @@ nsFilePicker::GetFilterList()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (mFilters.Length() <= (PRUint32)mSelectedTypeIndex) {
if (!mFilters.Length()) {
return nil;
}
if (mFilters.Length() <= (PRUint32)mSelectedTypeIndex) {
NS_WARNING("An out of range index has been selected. Using the first index instead.");
mSelectedTypeIndex = 0;
}
const nsString& filterWide = mFilters[mSelectedTypeIndex];
if (!filterWide.Length()) {
return nil;

View File

@ -98,7 +98,6 @@ EXPORTS_mozilla = \
$(NULL)
ifeq (windows,$(MOZ_WIDGET_TOOLKIT))
CPPSRCS += nsSetDllDirectory.cpp
CPPSRCS += nsCrashOnException.cpp
endif

View File

@ -1,91 +0,0 @@
/* -*- Mode: C++; tab-width: 8; 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
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ehsan Akhgari <ehsan@mozilla.com> (Original Author)
*
* 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 XP_WIN
#error This file only makes sense on Windows.
#endif
#include <windows.h>
#include <stdlib.h>
#include "nsSetDllDirectory.h"
void
SanitizeEnvironmentVariables()
{
DWORD bufferSize = GetEnvironmentVariableW(L"PATH", NULL, 0);
if (bufferSize) {
wchar_t* originalPath = new wchar_t[bufferSize];
if (bufferSize - 1 == GetEnvironmentVariableW(L"PATH", originalPath, bufferSize)) {
bufferSize = ExpandEnvironmentStringsW(originalPath, NULL, 0);
if (bufferSize) {
wchar_t* newPath = new wchar_t[bufferSize];
if (ExpandEnvironmentStringsW(originalPath,
newPath,
bufferSize)) {
SetEnvironmentVariableW(L"PATH", newPath);
}
delete[] newPath;
}
}
delete[] originalPath;
}
}
namespace mozilla {
XPCOM_API(void)
NS_SetDllDirectory(const WCHAR *aDllDirectory)
{
typedef BOOL
(WINAPI *pfnSetDllDirectory) (LPCWSTR);
static pfnSetDllDirectory setDllDirectory = nsnull;
if (!setDllDirectory) {
setDllDirectory = reinterpret_cast<pfnSetDllDirectory>
(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetDllDirectoryW"));
// If it's the first time we're running this function, sanitize the
// environment variables too.
SanitizeEnvironmentVariables();
}
if (setDllDirectory) {
setDllDirectory(aDllDirectory);
}
}
}

View File

@ -43,13 +43,48 @@
#error This file only makes sense on Windows.
#endif
#include <windows.h>
#include <nscore.h>
#include <stdlib.h>
namespace mozilla {
static void SanitizeEnvironmentVariables()
{
DWORD bufferSize = GetEnvironmentVariableW(L"PATH", NULL, 0);
if (bufferSize) {
wchar_t* originalPath = new wchar_t[bufferSize];
if (bufferSize - 1 == GetEnvironmentVariableW(L"PATH", originalPath, bufferSize)) {
bufferSize = ExpandEnvironmentStringsW(originalPath, NULL, 0);
if (bufferSize) {
wchar_t* newPath = new wchar_t[bufferSize];
if (ExpandEnvironmentStringsW(originalPath,
newPath,
bufferSize)) {
SetEnvironmentVariableW(L"PATH", newPath);
}
delete[] newPath;
}
}
delete[] originalPath;
}
}
// Sets the directory from which DLLs can be loaded if the SetDllDirectory OS
// API is available.
XPCOM_API(void) NS_SetDllDirectory(const WCHAR *aDllDirectory);
// You must call SanitizeEnvironmentVariables before this function when calling
// it the first time.
static inline void NS_SetDllDirectory(const WCHAR *aDllDirectory)
{
typedef BOOL
(WINAPI *pfnSetDllDirectory) (LPCWSTR);
pfnSetDllDirectory setDllDirectory = nsnull;
setDllDirectory = reinterpret_cast<pfnSetDllDirectory>
(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetDllDirectoryW"));
if (setDllDirectory) {
setDllDirectory(aDllDirectory);
}
}
}

178
xpcom/build/BinaryPath.h Normal file
View File

@ -0,0 +1,178 @@
/* ***** 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
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mike Hommey <mh@glandium.org>
*
* 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 mozilla_BinaryPath_h
#define mozilla_BinaryPath_h
#include "nsXPCOMPrivate.h" // for MAXPATHLEN
#include "prtypes.h"
#ifdef XP_WIN
#include <windows.h>
#elif defined(XP_MACOSX)
#include <CoreFoundation/CoreFoundation.h>
#elif defined(XP_UNIX)
#include <sys/stat.h>
#endif
namespace mozilla {
class BinaryPath {
public:
#ifdef XP_WIN
static nsresult Get(const char *argv0, char aResult[MAXPATHLEN])
{
PRUnichar wide_path[MAXPATHLEN];
nsresult rv = GetW(argv0, wide_path);
if (NS_FAILED(rv))
return rv;
WideCharToMultiByte(CP_UTF8, 0, wide_path, -1,
aResult, MAXPATHLEN, NULL, NULL);
return NS_OK;
}
private:
static nsresult GetW(const char *argv0, PRUnichar aResult[MAXPATHLEN])
{
if (::GetModuleFileNameW(0, aResult, MAXPATHLEN))
return NS_OK;
return NS_ERROR_FAILURE;
}
#elif defined(XP_MACOSX)
static nsresult Get(const char *argv0, char aResult[MAXPATHLEN])
{
// Works even if we're not bundled.
CFBundleRef appBundle = CFBundleGetMainBundle();
if (!appBundle)
return NS_ERROR_FAILURE;
CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle);
if (!executableURL)
return NS_ERROR_FAILURE;
nsresult rv;
if (CFURLGetFileSystemRepresentation(executableURL, false, (UInt8 *)aResult, MAXPATHLEN))
rv = NS_OK;
else
rv = NS_ERROR_FAILURE;
CFRelease(executableURL);
return rv;
}
#elif defined(XP_UNIX)
static nsresult Get(const char *argv0, char aResult[MAXPATHLEN])
{
struct stat fileStat;
// on unix, there is no official way to get the path of the current binary.
// instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
// multiple applications, we will try a series of techniques:
//
// 1) use realpath() on argv[0], which works unless we're loaded from the
// PATH
// 2) manually walk through the PATH and look for ourself
// 3) give up
if (realpath(argv0, aResult) && stat(aResult, &fileStat) == 0)
return NS_OK;
const char *path = getenv("PATH");
if (!path)
return NS_ERROR_FAILURE;
char *pathdup = strdup(path);
if (!pathdup)
return NS_ERROR_OUT_OF_MEMORY;
PRBool found = PR_FALSE;
char *token = strtok(pathdup, ":");
while (token) {
char tmpPath[MAXPATHLEN];
sprintf(tmpPath, "%s/%s", token, argv0);
if (realpath(tmpPath, aResult) && stat(aResult, &fileStat) == 0) {
found = PR_TRUE;
break;
}
token = strtok(NULL, ":");
}
free(pathdup);
if (found)
return NS_OK;
return NS_ERROR_FAILURE;
}
#elif defined(XP_OS2)
static nsresult Get(const char *argv0, char aResult[MAXPATHLEN])
{
PPIB ppib;
PTIB ptib;
DosGetInfoBlocks( &ptib, &ppib);
DosQueryModuleName(ppib->pib_hmte, MAXPATHLEN, aResult);
}
#else
#error Oops, you need platform-specific code here
#endif
public:
static nsresult GetFile(const char *argv0, nsILocalFile* *aResult)
{
nsCOMPtr<nsILocalFile> lf;
#ifdef XP_WIN
PRUnichar exePath[MAXPATHLEN];
nsresult rv = GetW(argv0, exePath);
#else
char exePath[MAXPATHLEN];
nsresult rv = Get(argv0, exePath);
#endif
if (NS_FAILED(rv))
return rv;
#ifdef XP_WIN
rv = NS_NewLocalFile(nsDependentString(exePath), PR_TRUE,
getter_AddRefs(lf));
#else
rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE,
getter_AddRefs(lf));
#endif
if (NS_FAILED(rv))
return rv;
NS_ADDREF(*aResult = lf);
return NS_OK;
}
};
}
#endif /* mozilla_BinaryPath_h */

View File

@ -562,4 +562,11 @@ XRE_API(bool,
XRE_API(void,
XRE_InstallX11ErrorHandler, ())
#if defined(_MSC_VER) && defined(_M_IX86)
#define XRE_HAS_DLL_BLOCKLIST
XRE_API(void,
XRE_SetupDllBlocklist, ())
#endif
#endif // _nsXULAppAPI_h__

View File

@ -48,7 +48,7 @@ XPCOMGlueLoad(const char *xpcomFile, GetFrozenFunctionsFunc *func NS_OUTPARAM);
NS_HIDDEN_(void)
XPCOMGlueUnload();
typedef void (*DependentLibsCallback)(const char *aDependentLib);
typedef void (*DependentLibsCallback)(const char *aDependentLib, PRBool do_preload);
NS_HIDDEN_(void)
XPCOMGlueLoadDependentLibs(const char *xpcomDir, DependentLibsCallback cb);

View File

@ -21,6 +21,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mike Hommey <mh@glandium.org>
*
* 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
@ -38,6 +39,15 @@
#include "nsGlueLinking.h"
#include "nsXPCOMGlue.h"
#include "nscore.h"
#ifdef LINUX
#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#include <elf.h>
#include <limits.h>
#endif
#include <dlfcn.h>
#include <stdlib.h>
@ -51,6 +61,54 @@
#define LEADING_UNDERSCORE
#endif
#ifdef NS_TRACE_MALLOC
extern "C" {
NS_EXPORT_(__ptr_t) __libc_malloc(size_t);
NS_EXPORT_(__ptr_t) __libc_calloc(size_t, size_t);
NS_EXPORT_(__ptr_t) __libc_realloc(__ptr_t, size_t);
NS_EXPORT_(void) __libc_free(__ptr_t);
NS_EXPORT_(__ptr_t) __libc_memalign(size_t, size_t);
NS_EXPORT_(__ptr_t) __libc_valloc(size_t);
}
static __ptr_t (*_malloc)(size_t) = __libc_malloc;
static __ptr_t (*_calloc)(size_t, size_t) = __libc_calloc;
static __ptr_t (*_realloc)(__ptr_t, size_t) = __libc_realloc;
static void (*_free)(__ptr_t) = __libc_free;
static __ptr_t (*_memalign)(size_t, size_t) = __libc_memalign;
static __ptr_t (*_valloc)(size_t) = __libc_valloc;
NS_EXPORT_(__ptr_t) malloc(size_t size)
{
return _malloc(size);
}
NS_EXPORT_(__ptr_t) calloc(size_t nmemb, size_t size)
{
return _calloc(nmemb, size);
}
NS_EXPORT_(__ptr_t) realloc(__ptr_t ptr, size_t size)
{
return _realloc(ptr, size);
}
NS_EXPORT_(void) free(__ptr_t ptr)
{
_free(ptr);
}
NS_EXPORT_(__ptr_t) memalign(size_t boundary, size_t size)
{
return _memalign(boundary, size);
}
NS_EXPORT_(__ptr_t) valloc(size_t size)
{
return _valloc(size);
}
#endif /* NS_TRACE_MALLOC */
struct DependentLib
{
void *libHandle;
@ -73,9 +131,69 @@ AppendDependentLib(void *libHandle)
sTop = d;
}
#ifdef LINUX
static const unsigned int bufsize = 4096;
#ifdef HAVE_64BIT_OS
typedef Elf64_Ehdr Elf_Ehdr;
typedef Elf64_Phdr Elf_Phdr;
static const unsigned char ELFCLASS = ELFCLASS64;
typedef Elf64_Off Elf_Off;
#else
typedef Elf32_Ehdr Elf_Ehdr;
typedef Elf32_Phdr Elf_Phdr;
static const unsigned char ELFCLASS = ELFCLASS32;
typedef Elf32_Off Elf_Off;
#endif
static void
ReadDependentCB(const char *aDependentLib)
preload(const char *file)
{
union {
char buf[bufsize];
Elf_Ehdr ehdr;
} elf;
int fd = open(file, O_RDONLY);
if (fd < 0)
return;
// Read ELF header (ehdr) and program header table (phdr).
// We check that the ELF magic is found, that the ELF class matches
// our own, and that the program header table as defined in the ELF
// headers fits in the buffer we read.
if ((read(fd, elf.buf, bufsize) <= 0) ||
(memcmp(elf.buf, ELFMAG, 4)) ||
(elf.ehdr.e_ident[EI_CLASS] != ELFCLASS) ||
(elf.ehdr.e_phoff + elf.ehdr.e_phentsize * elf.ehdr.e_phnum >= bufsize)) {
close(fd);
return;
}
// The program header table contains segment definitions. One such
// segment type is PT_LOAD, which describes how the dynamic loader
// is going to map the file in memory. We use that information to
// find the biggest offset from the library that will be mapped in
// memory.
Elf_Phdr *phdr = (Elf_Phdr *)&elf.buf[elf.ehdr.e_phoff];
Elf_Off end = 0;
for (int phnum = elf.ehdr.e_phnum; phnum; phdr++, phnum--)
if ((phdr->p_type == PT_LOAD) &&
(end < phdr->p_offset + phdr->p_filesz))
end = phdr->p_offset + phdr->p_filesz;
// Let the kernel read ahead what the dynamic loader is going to
// map in memory soon after.
if (end > 0) {
readahead(fd, 0, end);
}
close(fd);
}
#endif
static void
ReadDependentCB(const char *aDependentLib, PRBool do_preload)
{
#ifdef LINUX
if (do_preload)
preload(aDependentLib);
#endif
void *libHandle = dlopen(aDependentLib, RTLD_GLOBAL | RTLD_LAZY);
if (!libHandle)
return;
@ -97,6 +215,15 @@ XPCOMGlueLoad(const char *xpcomFile, GetFrozenFunctionsFunc *func)
snprintf(lastSlash, MAXPATHLEN - strlen(xpcomDir), "/" XUL_DLL);
sXULLibHandle = dlopen(xpcomDir, RTLD_GLOBAL | RTLD_LAZY);
#ifdef NS_TRACE_MALLOC
_malloc = (__ptr_t(*)(size_t)) dlsym(sXULLibHandle, "malloc");
_calloc = (__ptr_t(*)(size_t, size_t)) dlsym(sXULLibHandle, "calloc");
_realloc = (__ptr_t(*)(__ptr_t, size_t)) dlsym(sXULLibHandle, "realloc");
_free = (void(*)(__ptr_t)) dlsym(sXULLibHandle, "free");
_memalign = (__ptr_t(*)(size_t, size_t)) dlsym(sXULLibHandle, "memalign");
_valloc = (__ptr_t(*)(size_t)) dlsym(sXULLibHandle, "valloc");
#endif
}
}
@ -139,6 +266,14 @@ XPCOMGlueUnload()
}
if (sXULLibHandle) {
#ifdef NS_TRACE_MALLOC
_malloc = __libc_malloc;
_calloc = __libc_calloc;
_realloc = __libc_realloc;
_free = __libc_free;
_memalign = __libc_memalign;
_valloc = __libc_valloc;
#endif
dlclose(sXULLibHandle);
sXULLibHandle = nsnull;
}

View File

@ -68,7 +68,7 @@ AppendDependentLib(HMODULE libHandle)
}
static void
ReadDependentCB(const char *aDependentLib)
ReadDependentCB(const char *aDependentLib, PRBool do_preload)
{
CHAR pszError[_MAX_PATH];
ULONG ulrc = NO_ERROR;

View File

@ -21,6 +21,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mike Hommey <mh@glandium.org>
*
* 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
@ -45,11 +46,131 @@
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <mach/machine.h>
#include <mach-o/fat.h>
#include <mach-o/loader.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <limits.h>
#if defined(__i386__)
static const uint32_t CPU_TYPE = CPU_TYPE_X86;
#elif defined(__x86_64__)
static const uint32_t CPU_TYPE = CPU_TYPE_X86_64;
#elif defined(__ppc__)
static const uint32_t CPU_TYPE = CPU_TYPE_POWERPC;
#elif defined(__ppc64__)
static const uint32_t CPU_TYPE = CPU_TYPE_POWERPC64;
#else
#error Unsupported CPU type
#endif
#ifdef HAVE_64BIT_OS
#undef LC_SEGMENT
#define LC_SEGMENT LC_SEGMENT_64
#undef MH_MAGIC
#define MH_MAGIC MH_MAGIC_64
#define cpu_mach_header mach_header_64
#define segment_command segment_command_64
#else
#define cpu_mach_header mach_header
#endif
class ScopedMMap
{
public:
ScopedMMap(const char *file): buf(NULL) {
fd = open(file, O_RDONLY);
if (fd < 0)
return;
struct stat st;
if (fstat(fd, &st) < 0)
return;
size = st.st_size;
buf = (char *)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
}
~ScopedMMap() {
if (buf)
munmap(buf, size);
if (fd >= 0)
close(fd);
}
operator char *() { return buf; }
int getFd() { return fd; }
private:
int fd;
char *buf;
size_t size;
};
static void
preload(const char *file)
{
ScopedMMap buf(file);
char *base = buf;
if (!base)
return;
// An OSX binary might either be a fat (universal) binary or a
// Mach-O binary. A fat binary actually embeds several Mach-O
// binaries. If we have a fat binary, find the offset where the
// Mach-O binary for our CPU type can be found.
struct fat_header *fh = (struct fat_header *)base;
if (OSSwapBigToHostInt32(fh->magic) == FAT_MAGIC) {
uint32_t nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);
struct fat_arch *arch = (struct fat_arch *)&buf[sizeof(struct fat_header)];
for (; nfat_arch; arch++, nfat_arch--) {
if (OSSwapBigToHostInt32(arch->cputype) == CPU_TYPE) {
base += OSSwapBigToHostInt32(arch->offset);
break;
}
}
if (base == buf)
return;
}
// Check Mach-O magic in the Mach header
struct cpu_mach_header *mh = (struct cpu_mach_header *)base;
if (mh->magic != MH_MAGIC)
return;
// The Mach header is followed by a sequence of load commands.
// Each command has a header containing the command type and the
// command size. LD_SEGMENT commands describes how the dynamic
// loader is going to map the file in memory. We use that
// information to find the biggest offset from the library that
// will be mapped in memory.
char *cmd = &base[sizeof(struct cpu_mach_header)];
off_t end = 0;
for (uint32_t ncmds = mh->ncmds; ncmds; ncmds--) {
struct segment_command *sh = (struct segment_command *)cmd;
if (sh->cmd != LC_SEGMENT)
continue;
if (end < sh->fileoff + sh->filesize)
end = sh->fileoff + sh->filesize;
cmd += sh->cmdsize;
}
// Let the kernel read ahead what the dynamic loader is going to
// map in memory soon after. The F_RDADVISE fcntl is equivalent
// to Linux' readahead() system call.
if (end > 0) {
struct radvisory ra;
ra.ra_offset = (base - buf);
ra.ra_count = end;
fcntl(buf.getFd(), F_RDADVISE, &ra);
}
}
static const mach_header* sXULLibImage;
static void
ReadDependentCB(const char *aDependentLib)
ReadDependentCB(const char *aDependentLib, PRBool do_preload)
{
if (do_preload)
preload(aDependentLib);
(void) NSAddImage(aDependentLib,
NSADDIMAGE_OPTION_RETURN_ON_ERROR |
NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);

View File

@ -70,11 +70,34 @@ AppendDependentLib(HINSTANCE libHandle)
}
static void
ReadDependentCB(const char *aDependentLib)
preload(LPCWSTR dll)
{
HANDLE fd = CreateFileW(dll, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
char buf[64 * 1024];
if (fd == INVALID_HANDLE_VALUE)
return;
DWORD dwBytesRead;
// Do dummy reads to trigger kernel-side readhead via FILE_FLAG_SEQUENTIAL_SCAN.
// Abort when underfilling because during testing the buffers are read fully
// A buffer that's not keeping up would imply that readahead isn't working right
while (ReadFile(fd, buf, sizeof(buf), &dwBytesRead, NULL) && dwBytesRead == sizeof(buf))
/* Nothing */;
CloseHandle(fd);
}
static void
ReadDependentCB(const char *aDependentLib, PRBool do_preload)
{
wchar_t wideDependentLib[MAX_PATH];
MultiByteToWideChar(CP_UTF8, 0, aDependentLib, -1, wideDependentLib, MAX_PATH);
if (do_preload)
preload(wideDependentLib);
HINSTANCE h =
LoadLibraryExW(wideDependentLib, NULL, MOZ_LOADLIBRARY_FLAGS);

View File

@ -55,6 +55,13 @@
#endif
static XPCOMFunctions xpcomFunctions;
static PRBool do_preload = PR_FALSE;
extern "C"
void XPCOMGlueEnablePreload()
{
do_preload = PR_TRUE;
}
extern "C"
nsresult XPCOMGlueStartup(const char* xpcomFile)
@ -128,7 +135,7 @@ XPCOMGlueLoadDependentLibs(const char *xpcomDir, DependentLibsCallback cb)
snprintf(buffer2, sizeof(buffer2),
"%s" XPCOM_FILE_PATH_SEPARATOR "%s",
xpcomDir, buffer);
cb(buffer2);
cb(buffer2, do_preload);
}
fclose(flist);

View File

@ -47,6 +47,12 @@
* The following functions are only available in the standalone glue.
*/
/**
* Enabled preloading of dynamically loaded libraries
*/
extern "C" NS_HIDDEN_(void)
XPCOMGlueEnablePreload();
/**
* Initialize the XPCOM glue by dynamically linking against the XPCOM
* shared library indicated by xpcomFile.

View File

@ -51,7 +51,7 @@ MOZILLA_INTERNAL_API = 1
# work around bug 408258
ifdef GNU_CC
ifneq ($(OS_ARCH), Darwin)
MODULE_OPTIMIZE_FLAGS = -O3 -fno-strict-aliasing
MODULE_OPTIMIZE_FLAGS = $(MOZ_OPTIMIZE_FLAGS) -fno-strict-aliasing
endif
endif

View File

@ -317,6 +317,13 @@ sub do_copyfile
}
}
unlink("$destpath$destname$destsuffix") if ( -e "$destpath$destname$destsuffix");
# If source is a symbolic link pointing in the same directory, create a
# symbolic link
if ((-l "$srcpath$srcname$srcsuffix") && (readlink("$srcpath$srcname$srcsuffix") !~ /\//)) {
symlink(readlink("$srcpath$srcname$srcsuffix"), "$destpath$destname$destsuffix") ||
die "Error: copy of symbolic link $srcpath$srcname$srcsuffix failed ($package, $component, $lineno): $!. Exiting...\n";
return;
}
copy ("$srcpath$srcname$srcsuffix", "$destpath$destname$destsuffix") ||
die "Error: copy of file $srcpath$srcname$srcsuffix failed ($package, $component, $lineno): $!. Exiting...\n";