Backed out changeset 48baafc34055 (bug 1789166) for causing mochitests failures....
[gecko.git] / toolkit / components / remote / nsMacRemoteServer.mm
blobf7c6ea234a3fc579360874d229259f193060908c
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 #import <Cocoa/Cocoa.h>
9 #import <CoreServices/CoreServices.h>
11 #include "MacAutoreleasePool.h"
12 #include "nsCOMPtr.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"
22 #include "nsXPCOM.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);
30   return NULL;
33 // aData contains serialized Dictionary, which in turn contains command line
34 // arguments
35 void nsMacRemoteServer::HandleCommandLine(CFDataRef aData) {
36   mozilla::MacAutoreleasePool pool;
38   if (aData) {
39     NSDictionary* dict =
40         [NSKeyedUnarchiver unarchiveObjectWithData:(NSData*)aData];
41     if (dict && [dict isKindOfClass:[NSDictionary class]]) {
42       NSArray* args = dict[@"args"];
43       if (!args) {
44         NS_ERROR("Wrong parameters passed to the Remote Server");
45         return;
46       }
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];
56         argv[i] = arg;
57       }
59       nsresult rv =
60           cmdLine->Init(argc, argv, nullptr, nsICommandLine::STATE_REMOTE_AUTO);
62       // Cleaning up C array.
63       delete[] argv;
65       if (NS_FAILED(rv)) {
66         NS_ERROR("Error initializing command line.");
67         return;
68       }
70       // Processing the command line, passed from a remote instance
71       // in the current instance.
72       cmdLine->Run();
74       // And bring the app's window to front.
75       [[NSRunningApplication currentApplication]
76           activateWithOptions:NSApplicationActivateIgnoringOtherApps];
77     }
78   }
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;
91   nsString className;
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;
100   context.info = this;
101   context.release = NULL;
102   context.retain = NULL;
103   context.version = NULL;
104   mMessageServer =
105       CFMessagePortCreateLocal(NULL, (CFStringRef)serverNameString,
106                                messageServerCallback, &context, NULL);
107   if (!mMessageServer) {
108     return NS_ERROR_FAILURE;
109   }
110   mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessageServer, 0);
111   if (!mRunLoopSource) {
112     CFRelease(mMessageServer);
113     mMessageServer = NULL;
114     return NS_ERROR_FAILURE;
115   }
116   CFRunLoopRef runLoop = CFRunLoopGetMain();
117   CFRunLoopAddSource(runLoop, mRunLoopSource, kCFRunLoopDefaultMode);
119   return NS_OK;
122 void nsMacRemoteServer::Shutdown() {
123   // 1) Invalidate server connection
124   if (mMessageServer) {
125     CFMessagePortInvalidate(mMessageServer);
126   }
128   // 2) Release run loop source
129   if (mRunLoopSource) {
130     CFRelease(mRunLoopSource);
131     mRunLoopSource = NULL;
132   }
134   // 3) Release server connection
135   if (mMessageServer) {
136     CFRelease(mMessageServer);
137     mMessageServer = NULL;
138   }