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 #import <Cocoa/Cocoa.h>
9 #import <CoreServices/CoreServices.h>
11 #include "MacAutoreleasePool.h"
13 #include "nsIComponentManager.h"
14 #include "nsIServiceManager.h"
15 #include "nsIWindowMediator.h"
16 #include "nsIWidget.h"
17 #include "nsICommandLineRunner.h"
18 #include "nsICommandLine.h"
19 #include "nsCommandLine.h"
20 #include "nsIDocShell.h"
21 #include "nsMacRemoteServer.h"
23 #include "RemoteUtils.h"
25 CFDataRef messageServerCallback(CFMessagePortRef aLocal, int32_t aMsgid,
26 CFDataRef aData, void* aInfo) {
27 // One of the clients submitted a structure.
28 static_cast<nsMacRemoteServer*>(aInfo)->HandleCommandLine(aData);
33 // aData contains serialized Dictionary, which in turn contains command line
35 void nsMacRemoteServer::HandleCommandLine(CFDataRef aData) {
36 mozilla::MacAutoreleasePool pool;
40 [NSKeyedUnarchiver unarchiveObjectWithData:(NSData*)aData];
41 if (dict && [dict isKindOfClass:[NSDictionary class]]) {
42 NSArray* args = dict[@"args"];
44 NS_ERROR("Wrong parameters passed to the Remote Server");
48 nsCOMPtr<nsICommandLineRunner> cmdLine(new nsCommandLine());
50 // Converting Objective-C array into a C array,
51 // which nsICommandLineRunner understands.
52 int argc = [args count];
53 const char** argv = new const char*[argc];
54 for (int i = 0; i < argc; i++) {
55 const char* arg = [[args objectAtIndex:i] UTF8String];
60 cmdLine->Init(argc, argv, nullptr, nsICommandLine::STATE_REMOTE_AUTO);
62 // Cleaning up C array.
66 NS_ERROR("Error initializing command line.");
70 // Processing the command line, passed from a remote instance
71 // in the current instance.
74 // And bring the app's window to front.
75 [[NSRunningApplication currentApplication]
76 activateWithOptions:NSApplicationActivateIgnoringOtherApps];
81 nsresult nsMacRemoteServer::Startup(const char* aAppName,
82 const char* aProfileName) {
83 // This is the first instance ever.
84 // Let's register a notification listener here,
85 // In case future instances would want to notify us about command line
86 // arguments passed to them. Note, that if mozilla process is restarting, we
87 // still need to register for notifications.
89 mozilla::MacAutoreleasePool pool;
92 BuildClassName(aAppName, aProfileName, className);
94 NSString* serverNameString = [NSString
95 stringWithCharacters:reinterpret_cast<const unichar*>(className.get())
96 length:className.Length()];
98 CFMessagePortContext context;
99 context.copyDescription = NULL;
101 context.release = NULL;
102 context.retain = NULL;
103 context.version = NULL;
105 CFMessagePortCreateLocal(NULL, (CFStringRef)serverNameString,
106 messageServerCallback, &context, NULL);
107 if (!mMessageServer) {
108 return NS_ERROR_FAILURE;
110 mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessageServer, 0);
111 if (!mRunLoopSource) {
112 CFRelease(mMessageServer);
113 mMessageServer = NULL;
114 return NS_ERROR_FAILURE;
116 CFRunLoopRef runLoop = CFRunLoopGetMain();
117 CFRunLoopAddSource(runLoop, mRunLoopSource, kCFRunLoopDefaultMode);
122 void nsMacRemoteServer::Shutdown() {
123 // 1) Invalidate server connection
124 if (mMessageServer) {
125 CFMessagePortInvalidate(mMessageServer);
128 // 2) Release run loop source
129 if (mRunLoopSource) {
130 CFRelease(mRunLoopSource);
131 mRunLoopSource = NULL;
134 // 3) Release server connection
135 if (mMessageServer) {
136 CFRelease(mMessageServer);
137 mMessageServer = NULL;