summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firefox.sh.in4
-rw-r--r--firefox.spec9
-rw-r--r--mozilla-1080319.patch870
3 files changed, 880 insertions, 3 deletions
diff --git a/firefox.sh.in b/firefox.sh.in
index 36d608f..2a0dfc9 100644
--- a/firefox.sh.in
+++ b/firefox.sh.in
@@ -168,9 +168,9 @@ FEDORA_LANGPACK_CONFIG="$MOZ_EXTENSIONS_PROFILE_DIR/.fedora-langpack-install"
# MOZ_DISABLE_LANGPACKS disables language packs completely
MOZILLA_DOWN=0
if ! [ $MOZ_DISABLE_LANGPACKS ] || [ $MOZ_DISABLE_LANGPACKS -eq 0 ]; then
- if [ -x $MOZ_DIST_BIN/mozilla-xremote-client ]; then
+ if [ -x $MOZ_DIST_BIN/$MOZ_FIREFOX_FILE ]; then
# Is firefox running?
- $MOZ_DIST_BIN/mozilla-xremote-client -a firefox 'ping()' > /dev/null 2>&1
+ $MOZ_DIST_BIN/$MOZ_FIREFOX_FILE -remote 'ping()' > /dev/null 2>&1
MOZILLA_DOWN=$?
fi
fi
diff --git a/firefox.spec b/firefox.spec
index ce98c11..917d6f7 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -107,7 +107,7 @@
Summary: Mozilla Firefox Web browser
Name: firefox
Version: 36.0
-Release: 2%{?pre_tag}%{?dist}
+Release: 3%{?pre_tag}%{?dist}
URL: http://www.mozilla.org/projects/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+
Group: Applications/Internet
@@ -144,6 +144,7 @@ Patch221: firefox-fedora-ua.patch
# Upstream patches
Patch301: mozilla-1129859-dictfix2.patch
+Patch302: mozilla-1080319.patch
# Gtk3 upstream patches
Patch404: mozilla-1101582.patch
@@ -298,6 +299,7 @@ cd %{tarballdir}
# Upstream patches
%patch301 -p1 -b .dict-fix
+%patch302 -p1 -b .1080319
%if %{toolkit_gtk3}
%patch404 -p1 -b .1101582
@@ -763,6 +765,11 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
#---------------------------------------------------------------------
%changelog
+* Thu Mar 5 2015 Martin Stransky <stransky@redhat.com> - 36.0-3
+- Added back the removed "-remote" option
+- Fixed rhbz#1198965 - mozilla-xremote-client has been removed,
+ langpack installation may be broken
+
* Tue Mar 3 2015 Martin Stransky <stransky@redhat.com> - 36.0-2
- Enable Skia for all arches (rhbz#1197007)
diff --git a/mozilla-1080319.patch b/mozilla-1080319.patch
new file mode 100644
index 0000000..20bbb50
--- /dev/null
+++ b/mozilla-1080319.patch
@@ -0,0 +1,870 @@
+diff --git a/browser/components/nsBrowserContentHandler.js b/browser/components/nsBrowserContentHandler.js
+index 5b9f9b1..6909621 100644
+--- a/browser/components/nsBrowserContentHandler.js
++++ b/browser/components/nsBrowserContentHandler.js
+@@ -337,16 +337,96 @@ nsBrowserContentHandler.prototype = {
+ if (cmdLine.handleFlag("browser", false)) {
+ // Passing defaultArgs, so use NO_EXTERNAL_URIS
+ openWindow(null, this.chromeURL, "_blank",
+ "chrome,dialog=no,all" + this.getFeatures(cmdLine),
+ this.defaultArgs, NO_EXTERNAL_URIS);
+ cmdLine.preventDefault = true;
+ }
+
++ try {
++ var remoteCommand = cmdLine.handleFlagWithParam("remote", true);
++ }
++ catch (e) {
++ throw NS_ERROR_ABORT;
++ }
++
++ if (remoteCommand != null) {
++ try {
++ var a = /^\s*(\w+)\(([^\)]*)\)\s*$/.exec(remoteCommand);
++ var remoteVerb;
++ if (a) {
++ remoteVerb = a[1].toLowerCase();
++ var remoteParams = [];
++ var sepIndex = a[2].lastIndexOf(",");
++ if (sepIndex == -1)
++ remoteParams[0] = a[2];
++ else {
++ remoteParams[0] = a[2].substring(0, sepIndex);
++ remoteParams[1] = a[2].substring(sepIndex + 1);
++ }
++ }
++
++ switch (remoteVerb) {
++ case "openurl":
++ case "openfile":
++ // openURL(<url>)
++ // openURL(<url>,new-window)
++ // openURL(<url>,new-tab)
++
++ // First param is the URL, second param (if present) is the "target"
++ // (tab, window)
++ var url = remoteParams[0];
++ var target = nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW;
++ if (remoteParams[1]) {
++ var targetParam = remoteParams[1].toLowerCase()
++ .replace(/^\s*|\s*$/g, "");
++ if (targetParam == "new-tab")
++ target = nsIBrowserDOMWindow.OPEN_NEWTAB;
++ else if (targetParam == "new-window")
++ target = nsIBrowserDOMWindow.OPEN_NEWWINDOW;
++ else {
++ // The "target" param isn't one of our supported values, so
++ // assume it's part of a URL that contains commas.
++ url += "," + remoteParams[1];
++ }
++ }
++
++ var uri = resolveURIInternal(cmdLine, url);
++ handURIToExistingBrowser(uri, target, cmdLine);
++ break;
++
++ case "xfedocommand":
++ // xfeDoCommand(openBrowser)
++ if (remoteParams[0].toLowerCase() != "openbrowser")
++ throw NS_ERROR_ABORT;
++
++ // Passing defaultArgs, so use NO_EXTERNAL_URIS
++ openWindow(null, this.chromeURL, "_blank",
++ "chrome,dialog=no,all" + this.getFeatures(cmdLine),
++ this.defaultArgs, NO_EXTERNAL_URIS);
++ break;
++
++ default:
++ // Somebody sent us a remote command we don't know how to process:
++ // just abort.
++ throw "Unknown remote command.";
++ }
++
++ cmdLine.preventDefault = true;
++ }
++ catch (e) {
++ Components.utils.reportError(e);
++ // If we had a -remote flag but failed to process it, throw
++ // NS_ERROR_ABORT so that the xremote code knows to return a failure
++ // back to the handling code.
++ throw NS_ERROR_ABORT;
++ }
++ }
++
+ var uriparam;
+ try {
+ while ((uriparam = cmdLine.handleFlagWithParam("new-window", false))) {
+ var uri = resolveURIInternal(cmdLine, uriparam);
+ if (!shouldLoadURI(uri))
+ continue;
+ openWindow(null, this.chromeURL, "_blank",
+ "chrome,dialog=no,all" + this.getFeatures(cmdLine),
+diff --git a/toolkit/components/remote/nsXRemoteService.cpp b/toolkit/components/remote/nsXRemoteService.cpp
+index 41a40e4..532cc48 100644
+--- a/toolkit/components/remote/nsXRemoteService.cpp
++++ b/toolkit/components/remote/nsXRemoteService.cpp
+@@ -35,16 +35,17 @@
+
+ #include <X11/Xlib.h>
+ #include <X11/Xatom.h>
+
+ using namespace mozilla;
+
+ #define MOZILLA_VERSION_PROP "_MOZILLA_VERSION"
+ #define MOZILLA_LOCK_PROP "_MOZILLA_LOCK"
++#define MOZILLA_COMMAND_PROP "_MOZILLA_COMMAND"
+ #define MOZILLA_RESPONSE_PROP "_MOZILLA_RESPONSE"
+ #define MOZILLA_USER_PROP "_MOZILLA_USER"
+ #define MOZILLA_PROFILE_PROP "_MOZILLA_PROFILE"
+ #define MOZILLA_PROGRAM_PROP "_MOZILLA_PROGRAM"
+ #define MOZILLA_COMMANDLINE_PROP "_MOZILLA_COMMANDLINE"
+
+ const unsigned char kRemoteVersion[] = "5.1";
+
+@@ -55,26 +56,28 @@ const unsigned char kRemoteVersion[] = "5.1";
+ #else
+ #define TO_LITTLE_ENDIAN32(x) (x)
+ #endif
+
+ // Minimize the roundtrips to the X server by getting all the atoms at once
+ static const char *XAtomNames[] = {
+ MOZILLA_VERSION_PROP,
+ MOZILLA_LOCK_PROP,
++ MOZILLA_COMMAND_PROP,
+ MOZILLA_RESPONSE_PROP,
+ MOZILLA_USER_PROP,
+ MOZILLA_PROFILE_PROP,
+ MOZILLA_PROGRAM_PROP,
+ MOZILLA_COMMANDLINE_PROP
+ };
+ static Atom XAtoms[MOZ_ARRAY_LENGTH(XAtomNames)];
+
+ Atom nsXRemoteService::sMozVersionAtom;
+ Atom nsXRemoteService::sMozLockAtom;
++Atom nsXRemoteService::sMozCommandAtom;
+ Atom nsXRemoteService::sMozResponseAtom;
+ Atom nsXRemoteService::sMozUserAtom;
+ Atom nsXRemoteService::sMozProfileAtom;
+ Atom nsXRemoteService::sMozProgramAtom;
+ Atom nsXRemoteService::sMozCommandLineAtom;
+
+ nsXRemoteService * nsXRemoteService::sRemoteImplementation = 0;
+
+@@ -174,17 +177,17 @@ bool
+ nsXRemoteService::HandleNewProperty(XID aWindowId, Display* aDisplay,
+ Time aEventTime,
+ Atom aChangedAtom,
+ nsIWeakReference* aDomWindow)
+ {
+
+ nsCOMPtr<nsIDOMWindow> window (do_QueryReferent(aDomWindow));
+
+- if (aChangedAtom == sMozCommandLineAtom) {
++ if (aChangedAtom == sMozCommandAtom || aChangedAtom == sMozCommandLineAtom) {
+ // We got a new command atom.
+ int result;
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ char *data = 0;
+
+ result = XGetWindowProperty (aDisplay,
+@@ -206,17 +209,21 @@ nsXRemoteService::HandleNewProperty(XID aWindowId, Display* aDisplay,
+ if (result != Success)
+ return false;
+
+ // Failed to get the data off the window or it was the wrong type?
+ if (!data || !TO_LITTLE_ENDIAN32(*reinterpret_cast<int32_t*>(data)))
+ return false;
+
+ // cool, we got the property data.
+- const char *response = HandleCommandLine(data, window, aEventTime);
++ const char *response = nullptr;
++ if (aChangedAtom == sMozCommandAtom)
++ response = HandleCommand(data, window, aEventTime);
++ else if (aChangedAtom == sMozCommandLineAtom)
++ response = HandleCommandLine(data, window, aEventTime);
+
+ // put the property onto the window as the response
+ XChangeProperty (aDisplay, aWindowId,
+ sMozResponseAtom, XA_STRING,
+ 8, PropModeReplace,
+ (const unsigned char *)response,
+ strlen (response));
+ XFree(data);
+@@ -232,16 +239,71 @@ nsXRemoteService::HandleNewProperty(XID aWindowId, Display* aDisplay,
+ // someone locked the window
+ return true;
+ }
+
+ return false;
+ }
+
+ const char*
++nsXRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow,
++ uint32_t aTimestamp)
++{
++ nsresult rv;
++
++ nsCOMPtr<nsICommandLineRunner> cmdline
++ (do_CreateInstance("@mozilla.org/toolkit/command-line;1", &rv));
++ if (NS_FAILED(rv))
++ return "509 internal error";
++
++ // 1) Make sure that it looks remotely valid with parens
++ // 2) Treat ping() immediately and specially
++
++ nsAutoCString command(aCommand);
++ int32_t p1, p2;
++ p1 = command.FindChar('(');
++ p2 = command.FindChar(')');
++
++ if (p1 == kNotFound || p2 == kNotFound || p1 == 0 || p2 < p1) {
++ return "500 command not parseable";
++ }
++
++ command.Truncate(p1);
++ command.Trim(" ", true, true);
++ ToLowerCase(command);
++
++ if (!command.EqualsLiteral("ping")) {
++ nsAutoCString desktopStartupID;
++ nsDependentCString cmd(aCommand);
++ FindExtensionParameterInCommand("DESKTOP_STARTUP_ID",
++ cmd, '\n',
++ &desktopStartupID);
++
++ const char* argv[3] = {"dummyappname", "-remote", aCommand};
++ rv = cmdline->Init(3, argv, nullptr, nsICommandLine::STATE_REMOTE_EXPLICIT);
++ if (NS_FAILED(rv))
++ return "509 internal error";
++
++ if (aWindow)
++ cmdline->SetWindowContext(aWindow);
++
++ if (sRemoteImplementation)
++ sRemoteImplementation->SetDesktopStartupIDOrTimestamp(desktopStartupID, aTimestamp);
++
++ rv = cmdline->Run();
++ if (NS_ERROR_ABORT == rv)
++ return "500 command not parseable";
++ if (NS_FAILED(rv))
++ return "509 internal error";
++ }
++
++ return "200 executed command";
++}
++
++const char*
+ nsXRemoteService::HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow,
+ uint32_t aTimestamp)
+ {
+ nsresult rv;
+
+ nsCOMPtr<nsICommandLineRunner> cmdline
+ (do_CreateInstance("@mozilla.org/toolkit/command-line;1", &rv));
+ if (NS_FAILED(rv))
+@@ -311,14 +373,15 @@ nsXRemoteService::EnsureAtoms(void)
+ return;
+
+ XInternAtoms(mozilla::DefaultXDisplay(), const_cast<char**>(XAtomNames),
+ ArrayLength(XAtomNames), False, XAtoms);
+
+ int i = 0;
+ sMozVersionAtom = XAtoms[i++];
+ sMozLockAtom = XAtoms[i++];
++ sMozCommandAtom = XAtoms[i++];
+ sMozResponseAtom = XAtoms[i++];
+ sMozUserAtom = XAtoms[i++];
+ sMozProfileAtom = XAtoms[i++];
+ sMozProgramAtom = XAtoms[i++];
+ sMozCommandLineAtom = XAtoms[i++];
+ }
+diff --git a/toolkit/components/remote/nsXRemoteService.h b/toolkit/components/remote/nsXRemoteService.h
+index 7186336..144a4ec 100644
+--- a/toolkit/components/remote/nsXRemoteService.h
++++ b/toolkit/components/remote/nsXRemoteService.h
+@@ -36,27 +36,31 @@ protected:
+ nsIWeakReference* aDomWindow);
+
+ void XRemoteBaseStartup(const char *aAppName, const char *aProfileName);
+
+ void HandleCommandsFor(Window aWindowId);
+ static nsXRemoteService *sRemoteImplementation;
+ private:
+ void EnsureAtoms();
++ static const char* HandleCommand(char* aCommand, nsIDOMWindow* aWindow,
++ uint32_t aTimestamp);
++
+ static const char* HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow,
+ uint32_t aTimestamp);
+
+ virtual void SetDesktopStartupIDOrTimestamp(const nsACString& aDesktopStartupID,
+ uint32_t aTimestamp) = 0;
+
+ nsCString mAppName;
+ nsCString mProfileName;
+
+ static Atom sMozVersionAtom;
+ static Atom sMozLockAtom;
++ static Atom sMozCommandAtom;
+ static Atom sMozResponseAtom;
+ static Atom sMozUserAtom;
+ static Atom sMozProfileAtom;
+ static Atom sMozProgramAtom;
+ static Atom sMozCommandLineAtom;
+ };
+
+ #endif // NSXREMOTESERVICE_H
+diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
+index db8667c..8d840ed 100644
+--- a/toolkit/xre/nsAppRunner.cpp
++++ b/toolkit/xre/nsAppRunner.cpp
+@@ -1609,16 +1609,76 @@ DumpVersion()
+ printf("%s ", gAppData->vendor);
+ printf("%s %s", gAppData->name, gAppData->version);
+ if (gAppData->copyright)
+ printf(", %s", gAppData->copyright);
+ printf("\n");
+ }
+
+ #ifdef MOZ_ENABLE_XREMOTE
++// use int here instead of a PR type since it will be returned
++// from main - just to keep types consistent
++static int
++HandleRemoteArgument(const char* remote, const char* aDesktopStartupID)
++{
++ nsresult rv;
++ ArgResult ar;
++
++ const char *profile = 0;
++ nsAutoCString program(gAppData->name);
++ ToLowerCase(program);
++ const char *username = getenv("LOGNAME");
++
++ ar = CheckArg("p", false, &profile);
++ if (ar == ARG_BAD) {
++ PR_fprintf(PR_STDERR, "Error: argument -p requires a profile name\n");
++ return 1;
++ }
++
++ const char *temp = nullptr;
++ ar = CheckArg("a", false, &temp);
++ if (ar == ARG_BAD) {
++ PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
++ return 1;
++ } else if (ar == ARG_FOUND) {
++ program.Assign(temp);
++ }
++
++ ar = CheckArg("u", false, &username);
++ if (ar == ARG_BAD) {
++ PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
++ return 1;
++ }
++
++ XRemoteClient client;
++ rv = client.Init();
++ if (NS_FAILED(rv)) {
++ PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
++ return 1;
++ }
++
++ nsXPIDLCString response;
++ bool success = false;
++ rv = client.SendCommand(program.get(), username, profile, remote,
++ aDesktopStartupID, getter_Copies(response), &success);
++ // did the command fail?
++ if (NS_FAILED(rv)) {
++ PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n",
++ response ? response.get() : "No response included");
++ return 1;
++ }
++
++ if (!success) {
++ PR_fprintf(PR_STDERR, "Error: No running window found\n");
++ return 2;
++ }
++
++ return 0;
++}
++
+ static RemoteResult
+ RemoteCommandLine(const char* aDesktopStartupID)
+ {
+ nsresult rv;
+ ArgResult ar;
+
+ nsAutoCString program(gAppData->remotingName);
+ ToLowerCase(program);
+@@ -3600,21 +3660,31 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
+ if (mDisableRemote) {
+ newInstance = true;
+ } else {
+ e = PR_GetEnv("MOZ_NEW_INSTANCE");
+ newInstance = (e && *e);
+ }
+ }
+
++ const char* xremotearg;
++ ArgResult ar = CheckArg("remote", true, &xremotearg);
++ if (ar == ARG_BAD) {
++ PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
++ return 1;
++ }
++ const char* desktopStartupIDPtr =
++ mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get();
++ if (ar) {
++ *aExitFlag = true;
++ return HandleRemoteArgument(xremotearg, desktopStartupIDPtr);
++ }
++
+ if (!newInstance) {
+ // Try to remote the entire command line. If this fails, start up normally.
+- const char* desktopStartupIDPtr =
+- mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get();
+-
+ RemoteResult rr = RemoteCommandLine(desktopStartupIDPtr);
+ if (rr == REMOTE_FOUND) {
+ *aExitFlag = true;
+ return 0;
+ }
+ else if (rr == REMOTE_ARG_BAD)
+ return 1;
+ }
+diff --git a/widget/xremoteclient/XRemoteClient.cpp b/widget/xremoteclient/XRemoteClient.cpp
+index dc63704..3ece6dc 100644
+--- a/widget/xremoteclient/XRemoteClient.cpp
++++ b/widget/xremoteclient/XRemoteClient.cpp
+@@ -21,16 +21,17 @@
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <limits.h>
+ #include <X11/Xatom.h>
+
+ #define MOZILLA_VERSION_PROP "_MOZILLA_VERSION"
+ #define MOZILLA_LOCK_PROP "_MOZILLA_LOCK"
++#define MOZILLA_COMMAND_PROP "_MOZILLA_COMMAND"
+ #define MOZILLA_COMMANDLINE_PROP "_MOZILLA_COMMANDLINE"
+ #define MOZILLA_RESPONSE_PROP "_MOZILLA_RESPONSE"
+ #define MOZILLA_USER_PROP "_MOZILLA_USER"
+ #define MOZILLA_PROFILE_PROP "_MOZILLA_PROFILE"
+ #define MOZILLA_PROGRAM_PROP "_MOZILLA_PROGRAM"
+
+ #ifdef IS_BIG_ENDIAN
+ #define TO_LITTLE_ENDIAN32(x) \
+@@ -56,16 +57,17 @@ static int (*sOldHandler)(Display *, XErrorEvent *);
+ static bool sGotBadWindow;
+
+ XRemoteClient::XRemoteClient()
+ {
+ mDisplay = 0;
+ mInitialized = false;
+ mMozVersionAtom = 0;
+ mMozLockAtom = 0;
++ mMozCommandAtom = 0;
+ mMozResponseAtom = 0;
+ mMozWMStateAtom = 0;
+ mMozUserAtom = 0;
+ mLockData = 0;
+ if (!sRemoteLm)
+ sRemoteLm = PR_NewLogModule("XRemoteClient");
+ PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::XRemoteClient"));
+ }
+@@ -76,16 +78,17 @@ XRemoteClient::~XRemoteClient()
+ if (mInitialized)
+ Shutdown();
+ }
+
+ // Minimize the roundtrips to the X-server
+ static const char *XAtomNames[] = {
+ MOZILLA_VERSION_PROP,
+ MOZILLA_LOCK_PROP,
++ MOZILLA_COMMAND_PROP,
+ MOZILLA_RESPONSE_PROP,
+ "WM_STATE",
+ MOZILLA_USER_PROP,
+ MOZILLA_PROFILE_PROP,
+ MOZILLA_PROGRAM_PROP,
+ MOZILLA_COMMANDLINE_PROP
+ };
+ static Atom XAtoms[ARRAY_LENGTH(XAtomNames)];
+@@ -105,16 +108,17 @@ XRemoteClient::Init()
+
+ // get our atoms
+ XInternAtoms(mDisplay, const_cast<char**>(XAtomNames),
+ ARRAY_LENGTH(XAtomNames), False, XAtoms);
+
+ int i = 0;
+ mMozVersionAtom = XAtoms[i++];
+ mMozLockAtom = XAtoms[i++];
++ mMozCommandAtom = XAtoms[i++];
+ mMozResponseAtom = XAtoms[i++];
+ mMozWMStateAtom = XAtoms[i++];
+ mMozUserAtom = XAtoms[i++];
+ mMozProfileAtom = XAtoms[i++];
+ mMozProgramAtom = XAtoms[i++];
+ mMozCommandLineAtom = XAtoms[i++];
+
+ mInitialized = true;
+@@ -135,44 +139,72 @@ XRemoteClient::Shutdown (void)
+ mDisplay = 0;
+ mInitialized = false;
+ if (mLockData) {
+ free(mLockData);
+ mLockData = 0;
+ }
+ }
+
++nsresult
++XRemoteClient::SendCommand (const char *aProgram, const char *aUsername,
++ const char *aProfile, const char *aCommand,
++ const char* aDesktopStartupID,
++ char **aResponse, bool *aWindowFound)
++{
++ PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::SendCommand"));
++
++ return SendCommandInternal(aProgram, aUsername, aProfile,
++ aCommand, 0, nullptr,
++ aDesktopStartupID,
++ aResponse, aWindowFound);
++}
++
++nsresult
++XRemoteClient::SendCommandLine (const char *aProgram, const char *aUsername,
++ const char *aProfile,
++ int32_t argc, char **argv,
++ const char* aDesktopStartupID,
++ char **aResponse, bool *aWindowFound)
++{
++ PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::SendCommandLine"));
++
++ return SendCommandInternal(aProgram, aUsername, aProfile,
++ nullptr, argc, argv,
++ aDesktopStartupID,
++ aResponse, aWindowFound);
++}
++
+ static int
+ HandleBadWindow(Display *display, XErrorEvent *event)
+ {
+ if (event->error_code == BadWindow) {
+ sGotBadWindow = true;
+ return 0; // ignored
+ }
+ else {
+ return (*sOldHandler)(display, event);
+ }
+ }
+
+ nsresult
+-XRemoteClient::SendCommandLine (const char *aProgram, const char *aUsername,
+- const char *aProfile,
+- int32_t argc, char **argv,
+- const char* aDesktopStartupID,
+- char **aResponse, bool *aWindowFound)
++XRemoteClient::SendCommandInternal(const char *aProgram, const char *aUsername,
++ const char *aProfile, const char *aCommand,
++ int32_t argc, char **argv,
++ const char* aDesktopStartupID,
++ char **aResponse, bool *aWindowFound)
+ {
+- PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::SendCommandLine"));
+-
+ *aWindowFound = false;
++ bool isCommandLine = !aCommand;
+
+ // FindBestWindow() iterates down the window hierarchy, so catch X errors
+ // when windows get destroyed before being accessed.
+ sOldHandler = XSetErrorHandler(HandleBadWindow);
+
+- Window w = FindBestWindow(aProgram, aUsername, aProfile);
++ Window w = FindBestWindow(aProgram, aUsername, aProfile, isCommandLine);
+
+ nsresult rv = NS_OK;
+
+ if (w) {
+ // ok, let the caller know that we at least found a window.
+ *aWindowFound = true;
+
+ // Ignore BadWindow errors up to this point. The last request from
+@@ -186,18 +218,24 @@ XRemoteClient::SendCommandLine (const char *aProgram, const char *aUsername,
+
+ bool destroyed = false;
+
+ // get the lock on the window
+ rv = GetLock(w, &destroyed);
+
+ if (NS_SUCCEEDED(rv)) {
+ // send our command
+- rv = DoSendCommandLine(w, argc, argv, aDesktopStartupID, aResponse,
+- &destroyed);
++ if (isCommandLine) {
++ rv = DoSendCommandLine(w, argc, argv, aDesktopStartupID, aResponse,
++ &destroyed);
++ }
++ else {
++ rv = DoSendCommand(w, aCommand, aDesktopStartupID, aResponse,
++ &destroyed);
++ }
+
+ // if the window was destroyed, don't bother trying to free the
+ // lock.
+ if (!destroyed)
+ FreeLock(w); // doesn't really matter what this returns
+
+ }
+ }
+@@ -405,17 +443,18 @@ XRemoteClient::GetLock(Window aWindow, bool *aDestroyed)
+ (unsigned int) aWindow));
+ }
+
+ return rv;
+ }
+
+ Window
+ XRemoteClient::FindBestWindow(const char *aProgram, const char *aUsername,
+- const char *aProfile)
++ const char *aProfile,
++ bool aSupportsCommandLine)
+ {
+ Window root = RootWindowOfScreen(DefaultScreenOfDisplay(mDisplay));
+ Window bestWindow = 0;
+ Window root2, parent, *kids;
+ unsigned int nkids;
+
+ // Get a list of the children of the root window, walk the list
+ // looking for the best window that fits the criteria.
+@@ -450,17 +489,17 @@ XRemoteClient::FindBestWindow(const char *aProgram, const char *aUsername,
+ &data_return);
+
+ if (!data_return)
+ continue;
+
+ double version = PR_strtod((char*) data_return, nullptr);
+ XFree(data_return);
+
+- if (!(version >= 5.1 && version < 6))
++ if (aSupportsCommandLine && !(version >= 5.1 && version < 6))
+ continue;
+
+ data_return = 0;
+
+ if (status != Success || type == None)
+ continue;
+
+ // If someone passed in a program name, check it against this one
+@@ -594,16 +633,56 @@ XRemoteClient::FreeLock(Window aWindow)
+ return NS_ERROR_FAILURE;
+ }
+
+ if (data)
+ XFree(data);
+ return NS_OK;
+ }
+
++nsresult
++XRemoteClient::DoSendCommand(Window aWindow, const char *aCommand,
++ const char* aDesktopStartupID,
++ char **aResponse, bool *aDestroyed)
++{
++ *aDestroyed = false;
++
++ PR_LOG(sRemoteLm, PR_LOG_DEBUG,
++ ("(writing " MOZILLA_COMMAND_PROP " \"%s\" to 0x%x)\n",
++ aCommand, (unsigned int) aWindow));
++
++ // We add the DESKTOP_STARTUP_ID setting as an extra line of
++ // the command string. Firefox ignores all lines but the first.
++ static char desktopStartupPrefix[] = "\nDESKTOP_STARTUP_ID=";
++
++ int32_t len = strlen(aCommand);
++ if (aDesktopStartupID) {
++ len += sizeof(desktopStartupPrefix) - 1 + strlen(aDesktopStartupID);
++ }
++ char* buffer = (char*)malloc(len + 1);
++ if (!buffer)
++ return NS_ERROR_OUT_OF_MEMORY;
++
++ strcpy(buffer, aCommand);
++ if (aDesktopStartupID) {
++ strcat(buffer, desktopStartupPrefix);
++ strcat(buffer, aDesktopStartupID);
++ }
++
++ XChangeProperty (mDisplay, aWindow, mMozCommandAtom, XA_STRING, 8,
++ PropModeReplace, (unsigned char *)buffer, len);
++
++ free(buffer);
++
++ if (!WaitForResponse(aWindow, aResponse, aDestroyed, mMozCommandAtom))
++ return NS_ERROR_FAILURE;
++
++ return NS_OK;
++}
++
+ /* like strcpy, but return the char after the final null */
+ static char*
+ estrcpy(const char* s, char* d)
+ {
+ while (*s)
+ *d++ = *s++;
+
+ *d++ = '\0';
+@@ -786,16 +865,16 @@ XRemoteClient::WaitForResponse(Window aWindow, char **aResponse,
+ }
+
+ else if (event.xany.type == PropertyNotify &&
+ event.xproperty.window == aWindow &&
+ event.xproperty.state == PropertyDelete &&
+ event.xproperty.atom == aCommandAtom) {
+ PR_LOG(sRemoteLm, PR_LOG_DEBUG,
+ ("(server 0x%x has accepted "
+- MOZILLA_COMMANDLINE_PROP ".)\n",
++ MOZILLA_COMMAND_PROP ".)\n",
+ (unsigned int) aWindow));
+ }
+
+ }
+
+ return accepted;
+ }
+diff --git a/widget/xremoteclient/XRemoteClient.h b/widget/xremoteclient/XRemoteClient.h
+index 840716a..db1f804f 100644
+--- a/widget/xremoteclient/XRemoteClient.h
++++ b/widget/xremoteclient/XRemoteClient.h
+@@ -10,44 +10,60 @@
+
+ class XRemoteClient : public nsRemoteClient
+ {
+ public:
+ XRemoteClient();
+ ~XRemoteClient();
+
+ virtual nsresult Init();
++ virtual nsresult SendCommand(const char *aProgram, const char *aUsername,
++ const char *aProfile, const char *aCommand,
++ const char* aDesktopStartupID,
++ char **aResponse, bool *aSucceeded);
+ virtual nsresult SendCommandLine(const char *aProgram, const char *aUsername,
+ const char *aProfile,
+ int32_t argc, char **argv,
+ const char* aDesktopStartupID,
+ char **aResponse, bool *aSucceeded);
+ void Shutdown();
+
+ private:
+
+ Window CheckWindow (Window aWindow);
+ Window CheckChildren (Window aWindow);
+ nsresult GetLock (Window aWindow, bool *aDestroyed);
+ nsresult FreeLock (Window aWindow);
+ Window FindBestWindow (const char *aProgram,
+ const char *aUsername,
+- const char *aProfile);
++ const char *aProfile,
++ bool aSupportsCommandLine);
++ nsresult SendCommandInternal(const char *aProgram, const char *aUsername,
++ const char *aProfile, const char *aCommand,
++ int32_t argc, char **argv,
++ const char* aDesktopStartupID,
++ char **aResponse, bool *aWindowFound);
++ nsresult DoSendCommand (Window aWindow,
++ const char *aCommand,
++ const char* aDesktopStartupID,
++ char **aResponse,
++ bool *aDestroyed);
+ nsresult DoSendCommandLine(Window aWindow,
+ int32_t argc, char **argv,
+ const char* aDesktopStartupID,
+ char **aResponse,
+ bool *aDestroyed);
+ bool WaitForResponse (Window aWindow, char **aResponse,
+ bool *aDestroyed, Atom aCommandAtom);
+
+ Display *mDisplay;
+
+ Atom mMozVersionAtom;
+ Atom mMozLockAtom;
++ Atom mMozCommandAtom;
+ Atom mMozCommandLineAtom;
+ Atom mMozResponseAtom;
+ Atom mMozWMStateAtom;
+ Atom mMozUserAtom;
+ Atom mMozProfileAtom;
+ Atom mMozProgramAtom;
+
+ char *mLockData;
+diff --git a/widget/xremoteclient/nsRemoteClient.h b/widget/xremoteclient/nsRemoteClient.h
+index 6d90d69..050aba4 100644
+--- a/widget/xremoteclient/nsRemoteClient.h
++++ b/widget/xremoteclient/nsRemoteClient.h
+@@ -18,43 +18,62 @@ class nsRemoteClient
+ {
+ public:
+ /**
+ * Initializes the client
+ */
+ virtual nsresult Init() = 0;
+
+ /**
+- * Send a complete command line to a running instance.
++ * Sends a command to a running instance.
+ *
+ * @param aProgram This is the preferred program that we want to use
+ * for this particular command.
+ *
++ * @param aNoProgramFallback This boolean attribute tells the client
++ * code that if the preferred program isn't found that it should
++ * fail not send the command to another server.
++ *
+ * @param aUsername This allows someone to only talk to an instance
+ * of the server that's running under a particular username. If
+ * this isn't specified here it's pulled from the LOGNAME
+ * environmental variable if it's set.
+ *
+ * @param aProfile This allows you to specify a particular server
+ * running under a named profile. If it is not specified the
+ * profile is not checked.
+ *
+- * @param argc The number of command-line arguments.
+- *
+- * @param argv The command-line arguments.
+- *
++ * @param aCommand This is the command that is passed to the server.
++ * Please see the additional information located at:
++ * http://www.mozilla.org/unix/remote.html
++ *
+ * @param aDesktopStartupID the contents of the DESKTOP_STARTUP_ID environment
+ * variable defined by the Startup Notification specification
+ * http://standards.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt
+ *
+ * @param aResponse If there is a response, it will be here. This
+ * includes error messages. The string is allocated using stdlib
+ * string functions, so free it with free().
+ *
+ * @return true if succeeded, false if no running instance was found.
++ */
++ virtual nsresult SendCommand(const char *aProgram, const char *aUsername,
++ const char *aProfile, const char *aCommand,
++ const char* aDesktopStartupID,
++ char **aResponse, bool *aSucceeded) = 0;
++
++ /**
++ * Send a complete command line to a running instance.
++ *
++ * @param aDesktopStartupID the contents of the DESKTOP_STARTUP_ID environment
++ * variable defined by the Startup Notification specification
++ * http://standards.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt
++ *
++ * @see sendCommand
++ * @param argc The number of command-line arguments.
+ *
+ */
+ virtual nsresult SendCommandLine(const char *aProgram, const char *aUsername,
+ const char *aProfile,
+ int32_t argc, char **argv,
+ const char* aDesktopStartupID,
+ char **aResponse, bool *aSucceeded) = 0;
+ };
bgstack15