1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
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"
11 #include "nsICommandLineRunner.h"
12 #include "nsCommandLine.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
21 void nsUnixRemoteServer::SetStartupTokenOrTimestamp(
22 const nsACString
& aStartupToken
, uint32_t aTimestamp
) {
23 nsGTKToolkit
* toolkit
= nsGTKToolkit::GetToolkit();
28 if (!aStartupToken
.IsEmpty()) {
29 toolkit
->SetStartupToken(aStartupToken
);
32 toolkit
->SetFocusTimestamp(aTimestamp
);
35 static bool FindExtensionParameterInCommand(const char* aParameterName
,
36 const nsACString
& aCommand
,
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
;
51 aCommand
.EndReading(charEnd
);
52 nsACString::const_iterator idStart
= charStart
, idEnd
;
53 if (FindCharInReadable(aSeparator
, charStart
, charEnd
)) {
58 *aValue
= nsDependentCSubstring(idStart
, idEnd
);
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";
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
;
85 NS_NewNativeLocalFile(nsDependentCString(workingDir
), getter_AddRefs(lf
));
87 return "509 internal error";
90 const char** argv
= (const char**)malloc(sizeof(char*) * argc
);
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
;
108 nsDependentCString
cmd(argv
[0]);
109 FindExtensionParameterInCommand("STARTUP_TOKEN", cmd
, ' ',
114 rv
= cmdline
->Init(argc
, argv
, lf
, nsICommandLine::STATE_REMOTE_AUTO
);
118 return "509 internal error";
121 SetStartupTokenOrTimestamp(desktopStartupID
, aTimestamp
);
125 if (NS_ERROR_ABORT
== rv
) {
126 return "500 command not parseable";
130 return "509 internal error";
133 return "200 executed command";