OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "chrome/browser/app_controller_mac.h" | 5 #import "chrome/browser/app_controller_mac.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/sys_string_conversions.h" | 9 #include "base/sys_string_conversions.h" |
10 #include "chrome/app/chrome_dll_resource.h" | 10 #include "chrome/app/chrome_dll_resource.h" |
11 #include "chrome/browser/browser.h" | 11 #include "chrome/browser/browser.h" |
12 #include "chrome/browser/browser_init.h" | 12 #include "chrome/browser/browser_init.h" |
13 #include "chrome/browser/browser_list.h" | 13 #include "chrome/browser/browser_list.h" |
14 #include "chrome/browser/browser_shutdown.h" | 14 #include "chrome/browser/browser_shutdown.h" |
15 #import "chrome/browser/cocoa/bookmark_menu_bridge.h" | 15 #import "chrome/browser/cocoa/bookmark_menu_bridge.h" |
16 #include "chrome/browser/command_updater.h" | 16 #include "chrome/browser/command_updater.h" |
17 #include "chrome/browser/profile_manager.h" | 17 #include "chrome/browser/profile_manager.h" |
18 #include "chrome/common/temp_scaffolding_stubs.h" | 18 #include "chrome/common/temp_scaffolding_stubs.h" |
19 | 19 |
20 @interface AppController(PRIVATE) | 20 @interface AppController(PRIVATE) |
21 - (void)initMenuState; | 21 - (void)initMenuState; |
22 - (void)getUrl:(NSAppleEventDescriptor*)event | 22 - (void)getUrl:(NSAppleEventDescriptor*)event |
23 withReply:(NSAppleEventDescriptor*)reply; | 23 withReply:(NSAppleEventDescriptor*)reply; |
| 24 - (void)openFiles:(NSAppleEventDescriptor*)event |
| 25 withReply:(NSAppleEventDescriptor*)reply; |
24 @end | 26 @end |
25 | 27 |
26 @implementation AppController | 28 @implementation AppController |
27 | 29 |
28 - (void)awakeFromNib { | 30 - (void)awakeFromNib { |
29 // Set up the command updater for when there are no windows open | 31 // Set up the command updater for when there are no windows open |
30 [self initMenuState]; | 32 [self initMenuState]; |
31 bookmarkMenuBridge_ = new BookmarkMenuBridge(); | 33 bookmarkMenuBridge_ = new BookmarkMenuBridge(); |
32 } | 34 } |
33 | 35 |
34 - (void)applicationDidFinishLaunching:(NSNotification*)notify { | 36 - (void)applicationDidFinishLaunching:(NSNotification*)notify { |
35 // Hold an extra ref to the BrowserProcess singleton so it doesn't go away | 37 // Hold an extra ref to the BrowserProcess singleton so it doesn't go away |
36 // when all the browser windows get closed. We'll release it on quit which | 38 // when all the browser windows get closed. We'll release it on quit which |
37 // will be the signal to exit. | 39 // will be the signal to exit. |
38 DCHECK(g_browser_process); | 40 DCHECK(g_browser_process); |
39 g_browser_process->AddRefModule(); | 41 g_browser_process->AddRefModule(); |
40 | 42 |
41 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; | 43 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; |
42 [em setEventHandler:self | 44 [em setEventHandler:self |
43 andSelector:@selector(getUrl:withReply:) | 45 andSelector:@selector(getUrl:withReply:) |
44 forEventClass:kInternetEventClass | 46 forEventClass:kInternetEventClass |
45 andEventID:kAEGetURL]; | 47 andEventID:kAEGetURL]; |
46 [em setEventHandler:self | 48 [em setEventHandler:self |
47 andSelector:@selector(getUrl:withReply:) | 49 andSelector:@selector(getUrl:withReply:) |
48 forEventClass:'WWW!' // A particularly ancient AppleEvent that dates | 50 forEventClass:'WWW!' // A particularly ancient AppleEvent that dates |
49 andEventID:'OURL']; // back to the Spyglass days. | 51 andEventID:'OURL']; // back to the Spyglass days. |
| 52 [em setEventHandler:self |
| 53 andSelector:@selector(openFiles:withReply:) |
| 54 forEventClass:kCoreEventClass |
| 55 andEventID:kAEOpenDocuments]; |
50 } | 56 } |
51 | 57 |
52 - (void)dealloc { | 58 - (void)dealloc { |
53 delete bookmarkMenuBridge_; | 59 delete bookmarkMenuBridge_; |
54 delete menuState_; | 60 delete menuState_; |
55 [super dealloc]; | 61 [super dealloc]; |
56 } | 62 } |
57 | 63 |
58 // We can't use the standard terminate: method because it will abruptly exit | 64 // We can't use the standard terminate: method because it will abruptly exit |
59 // the app and leave things on the stack in an unfinalized state. We need to | 65 // the app and leave things on the stack in an unfinalized state. We need to |
60 // post a quit message to our run loop so the stack can gracefully unwind. | 66 // post a quit message to our run loop so the stack can gracefully unwind. |
61 - (IBAction)quit:(id)sender { | 67 - (IBAction)quit:(id)sender { |
62 // TODO(pinkerton): | 68 // TODO(pinkerton): |
63 // since we have to roll it ourselves, ask the delegate (ourselves, really) | 69 // since we have to roll it ourselves, ask the delegate (ourselves, really) |
64 // if we should terminate. For example, we might not want to if the user | 70 // if we should terminate. For example, we might not want to if the user |
65 // has ongoing downloads or multiple windows/tabs open. However, this would | 71 // has ongoing downloads or multiple windows/tabs open. However, this would |
66 // require posting UI and may require spinning up another run loop to | 72 // require posting UI and may require spinning up another run loop to |
67 // handle it. If it says to continue, post the quit message, otherwise | 73 // handle it. If it says to continue, post the quit message, otherwise |
68 // go back to normal. | 74 // go back to normal. |
69 | 75 |
70 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; | 76 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; |
71 [em removeEventHandlerForEventClass:kInternetEventClass | 77 [em removeEventHandlerForEventClass:kInternetEventClass |
72 andEventID:kAEGetURL]; | 78 andEventID:kAEGetURL]; |
73 [em removeEventHandlerForEventClass:'WWW!' | 79 [em removeEventHandlerForEventClass:'WWW!' |
74 andEventID:'OURL']; | 80 andEventID:'OURL']; |
| 81 [em removeEventHandlerForEventClass:kCoreEventClass |
| 82 andEventID:kAEOpenDocuments]; |
75 | 83 |
76 // TODO(pinkerton): Not sure where this should live, including it here | 84 // TODO(pinkerton): Not sure where this should live, including it here |
77 // causes all sorts of asserts from the open renderers. On Windows, it | 85 // causes all sorts of asserts from the open renderers. On Windows, it |
78 // lives in Browser::OnWindowClosing, but that's not appropriate on Mac | 86 // lives in Browser::OnWindowClosing, but that's not appropriate on Mac |
79 // since we don't shut down when we reach zero windows. | 87 // since we don't shut down when we reach zero windows. |
80 // browser_shutdown::OnShutdownStarting(browser_shutdown::WINDOW_CLOSE); | 88 // browser_shutdown::OnShutdownStarting(browser_shutdown::WINDOW_CLOSE); |
81 | 89 |
82 // Close all the windows. | 90 // Close all the windows. |
83 BrowserList::CloseAllBrowsers(true); | 91 BrowserList::CloseAllBrowsers(true); |
84 | 92 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 NSString* urlStr = [[event paramDescriptorForKeyword:keyDirectObject] | 191 NSString* urlStr = [[event paramDescriptorForKeyword:keyDirectObject] |
184 stringValue]; | 192 stringValue]; |
185 | 193 |
186 GURL gurl(base::SysNSStringToUTF8(urlStr)); | 194 GURL gurl(base::SysNSStringToUTF8(urlStr)); |
187 std::vector<GURL> gurlVector; | 195 std::vector<GURL> gurlVector; |
188 gurlVector.push_back(gurl); | 196 gurlVector.push_back(gurl); |
189 | 197 |
190 OpenURLs(gurlVector); | 198 OpenURLs(gurlVector); |
191 } | 199 } |
192 | 200 |
193 - (void)application:(NSApplication*)sender | 201 - (void)openFiles:(NSAppleEventDescriptor*)event |
194 openFiles:(NSArray*)filenames { | 202 withReply:(NSAppleEventDescriptor*)reply { |
| 203 // Ordinarily we'd use the NSApplication delegate method |
| 204 // -application:openFiles:, but Cocoa tries to be smart and it sends files |
| 205 // specified on the command line into that delegate method. That's too smart |
| 206 // for us (our setup isn't done by the time Cocoa triggers the delegate method |
| 207 // and we crash). Since all we want are files dropped on the app icon, and we |
| 208 // have cross-platform code to handle the command-line files anyway, an Apple |
| 209 // Event handler fits the bill just right. |
| 210 NSAppleEventDescriptor* fileList = |
| 211 [event paramDescriptorForKeyword:keyDirectObject]; |
| 212 if (!fileList) |
| 213 return; |
195 std::vector<GURL> gurlVector; | 214 std::vector<GURL> gurlVector; |
196 | 215 |
197 for (NSString* filename in filenames) { | 216 for (NSInteger i = 1; i <= [fileList numberOfItems]; ++i) { |
198 NSURL* fileURL = [NSURL fileURLWithPath:filename]; | 217 NSAppleEventDescriptor* fileAliasDesc = [fileList descriptorAtIndex:i]; |
199 GURL gurl(base::SysNSStringToUTF8([fileURL absoluteString])); | 218 if (!fileAliasDesc) |
| 219 continue; |
| 220 NSAppleEventDescriptor* fileURLDesc = |
| 221 [fileAliasDesc coerceToDescriptorType:typeFileURL]; |
| 222 if (!fileURLDesc) |
| 223 continue; |
| 224 NSData* fileURLData = [fileURLDesc data]; |
| 225 if (!fileURLData) |
| 226 continue; |
| 227 GURL gurl(std::string((char*)[fileURLData bytes], [fileURLData length])); |
200 gurlVector.push_back(gurl); | 228 gurlVector.push_back(gurl); |
201 } | 229 } |
202 | 230 |
203 OpenURLs(gurlVector); | 231 OpenURLs(gurlVector); |
204 } | 232 } |
205 | 233 |
206 @end | 234 @end |
OLD | NEW |