зеркало из https://github.com/mozilla/gecko-dev.git
Bug 531552: Force handling of at-launch open-url and open-file Apple Events to happen during command line construction so that we can put them on the command line and don't open unnecessary windows. r=benwa
This commit is contained in:
Родитель
06648d8171
Коммит
c09529f48b
|
@ -64,6 +64,21 @@
|
|||
#include "nsIStandaloneNativeMenu.h"
|
||||
#include "nsILocalFileMac.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCommandLineServiceMac.h"
|
||||
|
||||
class AutoAutoreleasePool {
|
||||
public:
|
||||
AutoAutoreleasePool()
|
||||
{
|
||||
mLocalPool = [[NSAutoreleasePool alloc] init];
|
||||
}
|
||||
~AutoAutoreleasePool()
|
||||
{
|
||||
[mLocalPool release];
|
||||
}
|
||||
private:
|
||||
NSAutoreleasePool *mLocalPool;
|
||||
};
|
||||
|
||||
@interface MacApplicationDelegate : NSObject
|
||||
{
|
||||
|
@ -92,7 +107,7 @@ SetupMacApplicationDelegate()
|
|||
|
||||
// this is called during startup, outside an event loop, and therefore
|
||||
// needs an autorelease pool to avoid cocoa object leakage (bug 559075)
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
AutoAutoreleasePool pool;
|
||||
|
||||
// This call makes it so that application:openFile: doesn't get bogus calls
|
||||
// from Cocoa doing its own parsing of the argument string. And yes, we need
|
||||
|
@ -104,8 +119,6 @@ SetupMacApplicationDelegate()
|
|||
MacApplicationDelegate *delegate = [[MacApplicationDelegate alloc] init];
|
||||
[NSApp setDelegate:delegate];
|
||||
|
||||
[pool release];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
|
@ -128,6 +141,11 @@ SetupMacApplicationDelegate()
|
|||
forEventClass:'WWW!'
|
||||
andEventID:'OURL'];
|
||||
|
||||
[aeMgr setEventHandler:self
|
||||
andSelector:@selector(handleAppleEvent:withReplyEvent:)
|
||||
forEventClass:kCoreEventClass
|
||||
andEventID:kAEOpenDocuments];
|
||||
|
||||
if (![NSApp windowsMenu]) {
|
||||
// If the application has a windows menu, it will keep it up to date and
|
||||
// prepend the window list to the Dock menu automatically.
|
||||
|
@ -148,6 +166,7 @@ SetupMacApplicationDelegate()
|
|||
NSAppleEventManager *aeMgr = [NSAppleEventManager sharedAppleEventManager];
|
||||
[aeMgr removeEventHandlerForEventClass:kInternetEventClass andEventID:kAEGetURL];
|
||||
[aeMgr removeEventHandlerForEventClass:'WWW!' andEventID:'OURL'];
|
||||
[aeMgr removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
|
||||
[super dealloc];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
|
@ -175,10 +194,20 @@ SetupMacApplicationDelegate()
|
|||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
NSString *escapedPath = [filename stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
NSURL *url = [NSURL fileURLWithPath:filename];
|
||||
if (!url)
|
||||
return NO;
|
||||
|
||||
NSString *urlString = [url absoluteString];
|
||||
if (!urlString)
|
||||
return NO;
|
||||
|
||||
// Add the URL to any command line we're currently setting up.
|
||||
if (CommandLineServiceMac::AddURLToCurrentCommandLine([urlString UTF8String]))
|
||||
return YES;
|
||||
|
||||
nsCOMPtr<nsILocalFileMac> inFile;
|
||||
nsresult rv = NS_NewLocalFileWithCFURL((CFURLRef)[NSURL URLWithString:escapedPath], PR_TRUE, getter_AddRefs(inFile));
|
||||
nsresult rv = NS_NewLocalFileWithCFURL((CFURLRef)url, PR_TRUE, getter_AddRefs(inFile));
|
||||
if (NS_FAILED(rv))
|
||||
return NO;
|
||||
|
||||
|
@ -307,6 +336,8 @@ SetupMacApplicationDelegate()
|
|||
if (!event)
|
||||
return;
|
||||
|
||||
AutoAutoreleasePool pool;
|
||||
|
||||
if (([event eventClass] == kInternetEventClass && [event eventID] == kAEGetURL) ||
|
||||
([event eventClass] == 'WWW!' && [event eventID] == 'OURL')) {
|
||||
NSString* urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
|
||||
|
@ -320,6 +351,10 @@ SetupMacApplicationDelegate()
|
|||
return;
|
||||
}
|
||||
|
||||
// Add the URL to any command line we're currently setting up.
|
||||
if (CommandLineServiceMac::AddURLToCurrentCommandLine([urlString UTF8String]))
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsICommandLineRunner> cmdLine(do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
|
||||
if (!cmdLine) {
|
||||
NS_ERROR("Couldn't create command line!");
|
||||
|
@ -335,6 +370,26 @@ SetupMacApplicationDelegate()
|
|||
return;
|
||||
rv = cmdLine->Run();
|
||||
}
|
||||
else if ([event eventClass] == kCoreEventClass && [event eventID] == kAEOpenDocuments) {
|
||||
NSAppleEventDescriptor* fileListDescriptor = [event paramDescriptorForKeyword:keyDirectObject];
|
||||
if (!fileListDescriptor)
|
||||
return;
|
||||
|
||||
// Descriptor list indexing is one-based...
|
||||
NSInteger numberOfFiles = [fileListDescriptor numberOfItems];
|
||||
for (NSInteger i = 1; i <= numberOfFiles; i++) {
|
||||
NSString* urlString = [[fileListDescriptor descriptorAtIndex:i] stringValue];
|
||||
if (!urlString)
|
||||
continue;
|
||||
|
||||
// We need a path, not a URL
|
||||
NSURL* url = [NSURL URLWithString:urlString];
|
||||
if (!url)
|
||||
continue;
|
||||
|
||||
[self application:NSApp openFile:[url path]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -3565,6 +3565,10 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
|||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Set up ability to respond to system (Apple) events. This must be
|
||||
// done before setting up the command line service.
|
||||
SetupMacApplicationDelegate();
|
||||
|
||||
// we re-initialize the command-line service and do appleevents munging
|
||||
// after we are sure that we're not restarting
|
||||
cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
|
||||
|
@ -3575,9 +3579,6 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
|||
rv = cmdLine->Init(gArgc, gArgv,
|
||||
workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
|
||||
NS_ENSURE_SUCCESS(rv, 1);
|
||||
|
||||
// Set up ability to respond to system (Apple) events.
|
||||
SetupMacApplicationDelegate();
|
||||
#endif
|
||||
|
||||
MOZ_SPLASHSCREEN_UPDATE(70);
|
||||
|
|
|
@ -51,6 +51,8 @@ static char** sArgs = NULL;
|
|||
static int sArgsAllocated = 0;
|
||||
static int sArgsUsed = 0;
|
||||
|
||||
static PRBool sBuildingCommandLine = PR_FALSE;
|
||||
|
||||
void AddToCommandLine(const char* inArgText)
|
||||
{
|
||||
if (sArgsUsed >= sArgsAllocated - 1) {
|
||||
|
@ -81,6 +83,8 @@ void SetupMacCommandLine(int& argc, char**& argv, PRBool forRestart)
|
|||
sArgs[0] = NULL;
|
||||
sArgsUsed = 0;
|
||||
|
||||
sBuildingCommandLine = PR_TRUE;
|
||||
|
||||
// Copy args, stripping anything we don't want.
|
||||
for (int arg = 0; arg < argc; arg++) {
|
||||
char* flag = argv[arg];
|
||||
|
@ -89,10 +93,27 @@ void SetupMacCommandLine(int& argc, char**& argv, PRBool forRestart)
|
|||
AddToCommandLine(flag);
|
||||
}
|
||||
|
||||
// Force processing of any pending Apple Events while we're building the
|
||||
// command line. The handlers will append to the command line rather than
|
||||
// act directly so there is no chance we'll process them during a XUL window
|
||||
// load and accidentally open unnecessary windows and home pages.
|
||||
const EventTypeSpec kAppleEventList[] = {
|
||||
{ kEventClassAppleEvent, kEventAppleEvent },
|
||||
};
|
||||
EventRef carbonEvent;
|
||||
while (::ReceiveNextEvent(GetEventTypeCount(kAppleEventList),
|
||||
kAppleEventList,
|
||||
kEventDurationNoWait,
|
||||
PR_TRUE,
|
||||
&carbonEvent) == noErr) {
|
||||
::AEProcessEvent(carbonEvent);
|
||||
::ReleaseEvent(carbonEvent);
|
||||
}
|
||||
|
||||
// If the process will be relaunched, the child should be in the foreground
|
||||
// if the parent is in the foreground. This will be communicated in a
|
||||
// command-line argument to the child.
|
||||
if (forRestart) {
|
||||
// If the process will be relaunched, the child should be in the foreground
|
||||
// if the parent is in the foreground. This will be communicated in a
|
||||
// command-line argument to the child.
|
||||
Boolean isForeground = false;
|
||||
ProcessSerialNumber psnSelf, psnFront;
|
||||
if (::GetCurrentProcess(&psnSelf) == noErr &&
|
||||
|
@ -103,8 +124,22 @@ void SetupMacCommandLine(int& argc, char**& argv, PRBool forRestart)
|
|||
}
|
||||
}
|
||||
|
||||
sBuildingCommandLine = PR_FALSE;
|
||||
|
||||
argc = sArgsUsed;
|
||||
argv = sArgs;
|
||||
}
|
||||
|
||||
PRBool AddURLToCurrentCommandLine(const char* aURL)
|
||||
{
|
||||
if (!sBuildingCommandLine) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
AddToCommandLine("-url");
|
||||
AddToCommandLine(aURL);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
} // namespace CommandLineServiceMac
|
||||
|
|
|
@ -42,6 +42,11 @@
|
|||
|
||||
namespace CommandLineServiceMac {
|
||||
void SetupMacCommandLine(int& argc, char**& argv, PRBool forRestart);
|
||||
|
||||
// Add a URL to the command line currently being set up via
|
||||
// SetupMacCommandLine. Returns false if no command line is
|
||||
// being set up or the addition fails for any other reason.
|
||||
PRBool AddURLToCurrentCommandLine(const char* aURL);
|
||||
}
|
||||
|
||||
#endif // nsCommandLineServiceMac_h_
|
||||
|
|
Загрузка…
Ссылка в новой задаче