mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Merge last green mozilla-inbound changeset to mozilla-central
This commit is contained in:
commit
ede62c1ae5
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 });
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
@ -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: {},
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -69,6 +69,6 @@ function test() {
|
||||
finish();
|
||||
}
|
||||
newWin.addEventListener("tabviewshown", onTabViewShow, false);
|
||||
newWin.TabView.toggle();
|
||||
waitForFocus(function() { newWin.TabView.toggle(); });
|
||||
}, false);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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@
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -146,6 +146,7 @@ PluginProcessChild::Init()
|
||||
protectCurrentDirectory = false;
|
||||
}
|
||||
if (protectCurrentDirectory) {
|
||||
SanitizeEnvironmentVariables();
|
||||
NS_SetDllDirectory(L"");
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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@
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
12
layout/reftests/reftest-sanity/647192-1-ref.html
Normal file
12
layout/reftests/reftest-sanity/647192-1-ref.html
Normal 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>
|
16
layout/reftests/reftest-sanity/647192-1.html
Normal file
16
layout/reftests/reftest-sanity/647192-1.html
Normal 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>
|
33
layout/reftests/reftest-sanity/656041-1-ref.html
Normal file
33
layout/reftests/reftest-sanity/656041-1-ref.html
Normal 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>
|
33
layout/reftests/reftest-sanity/656041-1.html
Normal file
33
layout/reftests/reftest-sanity/656041-1.html
Normal 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>
|
@ -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).
|
||||
|
@ -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() {
|
||||
|
@ -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":
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -1438,6 +1438,10 @@ setting {
|
||||
-moz-margin-start: @margin_xnormal@;
|
||||
}
|
||||
|
||||
#sync-message {
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
/* content scrollbars */
|
||||
.scroller {
|
||||
opacity: 0;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.,
|
||||
|
@ -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
|
||||
|
@ -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 += \
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -98,7 +98,6 @@ EXPORTS_mozilla = \
|
||||
$(NULL)
|
||||
|
||||
ifeq (windows,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += nsSetDllDirectory.cpp
|
||||
CPPSRCS += nsCrashOnException.cpp
|
||||
endif
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
178
xpcom/build/BinaryPath.h
Normal 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 */
|
@ -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__
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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";
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user