From a3e5347321a645dede559f21fe60b7f432de8d01 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Thu, 5 Mar 2015 14:10:30 +0100 Subject: Added back the removed -remote option, Fixed rhbz#1198965 - mozilla-xremote-client has been removed, langpack installation may be broken --- firefox.sh.in | 4 +- firefox.spec | 9 +- mozilla-1080319.patch | 870 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 880 insertions(+), 3 deletions(-) create mode 100644 mozilla-1080319.patch 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 - 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 - 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() ++ // openURL(,new-window) ++ // openURL(,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 + #include + + 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 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(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 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 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(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 + #include + #include + #include + #include + + #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(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; + }; -- cgit