145 lines
4.3 KiB
Text
145 lines
4.3 KiB
Text
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
|
*/
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
#import <CoreServices/CoreServices.h>
|
|
|
|
#include "MacAutoreleasePool.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsIComponentManager.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIWindowMediator.h"
|
|
#include "nsIWidget.h"
|
|
#include "nsICommandLineRunner.h"
|
|
#include "nsICommandLine.h"
|
|
#include "nsCommandLine.h"
|
|
#include "nsIDocShell.h"
|
|
#include "nsMacRemoteServer.h"
|
|
#include "nsXPCOM.h"
|
|
#include "RemoteUtils.h"
|
|
|
|
CFDataRef messageServerCallback(CFMessagePortRef aLocal, int32_t aMsgid,
|
|
CFDataRef aData, void* aInfo) {
|
|
// One of the clients submitted a structure.
|
|
static_cast<nsMacRemoteServer*>(aInfo)->HandleCommandLine(aData);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// aData contains serialized Dictionary, which in turn contains command line
|
|
// arguments
|
|
void nsMacRemoteServer::HandleCommandLine(CFDataRef aData) {
|
|
mozilla::MacAutoreleasePool pool;
|
|
|
|
if (aData) {
|
|
NSDictionary* dict =
|
|
[NSKeyedUnarchiver unarchiveObjectWithData:(NSData*)aData];
|
|
if (dict && [dict isKindOfClass:[NSDictionary class]]) {
|
|
NSArray* args = dict[@"args"];
|
|
if (!args) {
|
|
NS_ERROR("Wrong parameters passed to the Remote Server");
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsICommandLineRunner> cmdLine(new nsCommandLine());
|
|
|
|
// Converting Objective-C array into a C array,
|
|
// which nsICommandLineRunner understands.
|
|
int argc = [args count];
|
|
const char** argv = new const char*[argc];
|
|
for (int i = 0; i < argc; i++) {
|
|
const char* arg = [[args objectAtIndex:i] UTF8String];
|
|
argv[i] = arg;
|
|
}
|
|
|
|
nsresult rv =
|
|
cmdLine->Init(argc, argv, nullptr, nsICommandLine::STATE_REMOTE_AUTO);
|
|
|
|
// Cleaning up C array.
|
|
delete[] argv;
|
|
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Error initializing command line.");
|
|
return;
|
|
}
|
|
|
|
// Processing the command line, passed from a remote instance
|
|
// in the current instance.
|
|
cmdLine->Run();
|
|
|
|
NSNumber* raise = dict[@"raise"];
|
|
if (!raise || [raise boolValue]) {
|
|
// Activating the application brings the most recent window to the
|
|
// foreground.
|
|
ProcessSerialNumber psn;
|
|
if (::GetCurrentProcess(&psn) == noErr) {
|
|
::SetFrontProcess(&psn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
nsresult nsMacRemoteServer::Startup(const char* aAppName,
|
|
const char* aProfileName) {
|
|
// This is the first instance ever.
|
|
// Let's register a notification listener here,
|
|
// In case future instances would want to notify us about command line
|
|
// arguments passed to them. Note, that if mozilla process is restarting, we
|
|
// still need to register for notifications.
|
|
|
|
mozilla::MacAutoreleasePool pool;
|
|
|
|
nsString className;
|
|
BuildClassName(aAppName, aProfileName, className);
|
|
|
|
NSString* serverNameString = [NSString
|
|
stringWithCharacters:reinterpret_cast<const unichar*>(className.get())
|
|
length:className.Length()];
|
|
|
|
CFMessagePortContext context;
|
|
context.copyDescription = NULL;
|
|
context.info = this;
|
|
context.release = NULL;
|
|
context.retain = NULL;
|
|
context.version = NULL;
|
|
mMessageServer =
|
|
CFMessagePortCreateLocal(NULL, (CFStringRef)serverNameString,
|
|
messageServerCallback, &context, NULL);
|
|
if (!mMessageServer) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessageServer, 0);
|
|
if (!mRunLoopSource) {
|
|
CFRelease(mMessageServer);
|
|
mMessageServer = NULL;
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
CFRunLoopRef runLoop = CFRunLoopGetMain();
|
|
CFRunLoopAddSource(runLoop, mRunLoopSource, kCFRunLoopDefaultMode);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void nsMacRemoteServer::Shutdown() {
|
|
// 1) Invalidate server connection
|
|
if (mMessageServer) {
|
|
CFMessagePortInvalidate(mMessageServer);
|
|
}
|
|
|
|
// 2) Release run loop source
|
|
if (mRunLoopSource) {
|
|
CFRelease(mRunLoopSource);
|
|
mRunLoopSource = NULL;
|
|
}
|
|
|
|
// 3) Release server connection
|
|
if (mMessageServer) {
|
|
CFRelease(mMessageServer);
|
|
mMessageServer = NULL;
|
|
}
|
|
}
|