Bug 1943650 - Command-line --help output misformatted after --dbus-service. r=emilio
[gecko.git] / toolkit / components / remote / nsUnixRemoteServer.cpp
blobaaeb30cb000bfaf166601b940535bb64d5905e44
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "nsUnixRemoteServer.h"
9 #include "nsGTKToolkit.h"
10 #include "nsCOMPtr.h"
11 #include "nsICommandLineRunner.h"
12 #include "nsCommandLine.h"
13 #include "nsIFile.h"
15 // Set desktop startup ID to the passed ID, if there is one, so that any created
16 // windows get created with the right window manager metadata, and any windows
17 // that get new tabs and are activated also get the right WM metadata.
18 // The timestamp will be used if there is no desktop startup ID, or if we're
19 // raising an existing window rather than showing a new window for the first
20 // time.
21 void nsUnixRemoteServer::SetStartupTokenOrTimestamp(
22 const nsACString& aStartupToken, uint32_t aTimestamp) {
23 nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
24 if (!toolkit) {
25 return;
28 if (!aStartupToken.IsEmpty()) {
29 toolkit->SetStartupToken(aStartupToken);
32 toolkit->SetFocusTimestamp(aTimestamp);
35 static bool FindExtensionParameterInCommand(const char* aParameterName,
36 const nsACString& aCommand,
37 char aSeparator,
38 nsACString* aValue) {
39 nsAutoCString searchFor;
40 searchFor.Append(aSeparator);
41 searchFor.Append(aParameterName);
42 searchFor.Append('=');
44 nsACString::const_iterator start, end;
45 aCommand.BeginReading(start);
46 aCommand.EndReading(end);
47 if (!FindInReadable(searchFor, start, end)) return false;
49 nsACString::const_iterator charStart, charEnd;
50 charStart = end;
51 aCommand.EndReading(charEnd);
52 nsACString::const_iterator idStart = charStart, idEnd;
53 if (FindCharInReadable(aSeparator, charStart, charEnd)) {
54 idEnd = charStart;
55 } else {
56 idEnd = charEnd;
58 *aValue = nsDependentCSubstring(idStart, idEnd);
59 return true;
62 const char* nsUnixRemoteServer::HandleCommandLine(
63 mozilla::Span<const char> aBuffer, uint32_t aTimestamp) {
64 nsCOMPtr<nsICommandLineRunner> cmdline(new nsCommandLine());
66 // the commandline property is constructed as an array of int32_t
67 // followed by a series of null-terminated strings:
69 // [argc][offsetargv0][offsetargv1...]<workingdir>\0<argv[0]>\0argv[1]...\0
70 // (offset is from the beginning of the buffer)
71 if (aBuffer.size() < sizeof(uint32_t)) {
72 return "500 command not parseable";
75 uint32_t argc =
76 TO_LITTLE_ENDIAN32(*reinterpret_cast<const uint32_t*>(aBuffer.data()));
77 uint32_t offsetFilelist = ((argc + 1) * sizeof(uint32_t));
78 if (offsetFilelist >= aBuffer.size()) {
79 return "500 command not parseable";
81 const char* workingDir = aBuffer.data() + offsetFilelist;
83 nsCOMPtr<nsIFile> lf;
84 nsresult rv =
85 NS_NewNativeLocalFile(nsDependentCString(workingDir), getter_AddRefs(lf));
86 if (NS_FAILED(rv)) {
87 return "509 internal error";
90 const char** argv = (const char**)malloc(sizeof(char*) * argc);
91 if (!argv) {
92 return "509 internal error";
95 const uint32_t* offset =
96 reinterpret_cast<const uint32_t*>(aBuffer.data()) + 1;
97 nsAutoCString desktopStartupID;
99 for (unsigned int i = 0; i < argc; ++i) {
100 uint32_t argvOffset = TO_LITTLE_ENDIAN32(offset[i]);
101 if (argvOffset >= aBuffer.size()) {
102 return "500 command not parseable";
105 argv[i] = aBuffer.data() + argvOffset;
107 if (i == 0) {
108 nsDependentCString cmd(argv[0]);
109 FindExtensionParameterInCommand("STARTUP_TOKEN", cmd, ' ',
110 &desktopStartupID);
114 rv = cmdline->Init(argc, argv, lf, nsICommandLine::STATE_REMOTE_AUTO);
116 free(argv);
117 if (NS_FAILED(rv)) {
118 return "509 internal error";
121 SetStartupTokenOrTimestamp(desktopStartupID, aTimestamp);
123 rv = cmdline->Run();
125 if (NS_ERROR_ABORT == rv) {
126 return "500 command not parseable";
129 if (NS_FAILED(rv)) {
130 return "509 internal error";
133 return "200 executed command";