Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.mm

Issue 1186803003: Mac: Give packaged app windows their own window cycle list. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: extension || is_browser + cl format Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/ui/cocoa/apps/app_shim_menu_controller_mac.h" 5 #import "chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.h"
6 6
7 #include "base/command_line.h"
7 #include "base/mac/scoped_nsautorelease_pool.h" 8 #include "base/mac/scoped_nsautorelease_pool.h"
8 #include "base/strings/sys_string_conversions.h" 9 #include "base/strings/sys_string_conversions.h"
9 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/app/chrome_command_ids.h" 11 #include "chrome/app/chrome_command_ids.h"
11 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" 12 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
12 #include "chrome/browser/apps/app_window_registry_util.h" 13 #include "chrome/browser/apps/app_window_registry_util.h"
13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h" 15 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_finder.h" 16 #include "chrome/browser/ui/browser_finder.h"
16 #import "chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h" 17 #import "chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h"
18 #include "chrome/common/chrome_switches.h"
17 #include "chrome/grit/generated_resources.h" 19 #include "chrome/grit/generated_resources.h"
18 #include "extensions/browser/app_window/app_window.h" 20 #include "extensions/browser/app_window/app_window.h"
19 #include "extensions/common/extension.h" 21 #include "extensions/common/extension.h"
20 #include "ui/base/l10n/l10n_util.h" 22 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/l10n/l10n_util_mac.h" 23 #include "ui/base/l10n/l10n_util_mac.h"
22 24
25 using extensions::Extension;
26
23 namespace { 27 namespace {
24 28
29 // When an app window loses main status, AppKit may make another app window main
30 // instead. Rather than trying to predict what AppKit will do (which is hard),
31 // just protect against changes in the event queue that will clobber each other.
32 int g_window_cycle_sequence_number = 0;
33
34 // Whether Custom Cmd+` window cycling is enabled for apps.
35 bool IsAppWindowCyclingEnabled() {
36 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
37 if (command_line->HasSwitch(switches::kDisableAppWindowCycling))
38 return false;
39 if (command_line->HasSwitch(switches::kEnableAppWindowCycling))
40 return true;
41
42 return false; // Current default.
43 }
44
25 // Gets an item from the main menu given the tag of the top level item 45 // Gets an item from the main menu given the tag of the top level item
26 // |menu_tag| and the tag of the item |item_tag|. 46 // |menu_tag| and the tag of the item |item_tag|.
27 NSMenuItem* GetItemByTag(NSInteger menu_tag, NSInteger item_tag) { 47 NSMenuItem* GetItemByTag(NSInteger menu_tag, NSInteger item_tag) {
28 return [[[[NSApp mainMenu] itemWithTag:menu_tag] submenu] 48 return [[[[NSApp mainMenu] itemWithTag:menu_tag] submenu]
29 itemWithTag:item_tag]; 49 itemWithTag:item_tag];
30 } 50 }
31 51
32 // Finds a top level menu item using |menu_tag| and creates a new NSMenuItem 52 // Finds a top level menu item using |menu_tag| and creates a new NSMenuItem
33 // with the same title. 53 // with the same title.
34 NSMenuItem* NewTopLevelItemFrom(NSInteger menu_tag) { 54 NSMenuItem* NewTopLevelItemFrom(NSInteger menu_tag) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 DCHECK([alternate_item isAlternate]); 126 DCHECK([alternate_item isAlternate]);
107 } 127 }
108 128
109 // The alternate item visibility should always be in sync. 129 // The alternate item visibility should always be in sync.
110 DCHECK_EQ([alternate_item isHidden], [menu_item isHidden]); 130 DCHECK_EQ([alternate_item isHidden], [menu_item isHidden]);
111 [alternate_item setAlternate:visible]; 131 [alternate_item setAlternate:visible];
112 [alternate_item setHidden:!visible]; 132 [alternate_item setHidden:!visible];
113 [menu_item setHidden:!visible]; 133 [menu_item setHidden:!visible];
114 } 134 }
115 135
136 // Return the Extension (if any) associated with the given window. If it is not
137 // a platform app nor hosted app, but it is a browser, |is_browser| will be set
138 // to true (otherwise false).
139 const Extension* GetExtensionForNSWindow(NSWindow* window, bool* is_browser) {
140 const Extension* extension = nullptr;
141 Browser* browser = nullptr;
142
143 extensions::AppWindow* app_window =
144 AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile(window);
145 if (app_window) {
146 extension = app_window->GetExtension();
147 } else {
148 // If there is no corresponding AppWindow, this could be a hosted app, so
149 // check for a browser.
150 browser = chrome::FindBrowserWithWindow(window);
151 extension = apps::ExtensionAppShimHandler::MaybeGetAppForBrowser(browser);
152 }
153
154 *is_browser = extension == nullptr && browser != nullptr;
155 return extension;
156 }
157
158 // Sets or clears NSWindowCollectionBehaviorIgnoresCycle for |window|. Does not
159 // change NSWindowCollectionBehaviorParticipatesInCycle. That exists, e.g, for
160 // an NSPanel to override its default behavior, but this should only ever be
161 // called for Browser windows and App windows (which are not panels).
162 bool SetWindowParticipatesInCycle(NSWindow* window, bool participates) {
163 const NSWindowCollectionBehavior past_behavior = [window collectionBehavior];
164 NSWindowCollectionBehavior behavior = past_behavior;
165 if (participates)
166 behavior &= ~NSWindowCollectionBehaviorIgnoresCycle;
167 else
168 behavior |= NSWindowCollectionBehaviorIgnoresCycle;
169
170 // Often, there is no change. AppKit has no early exit since the value is
171 // derived partially from styleMask and other things, so do our own.
172 if (behavior == past_behavior)
173 return false;
174
175 [window setCollectionBehavior:behavior];
176 return true;
177 }
178
179 // Sets the window cycle list to |app_id|'s windows only.
180 void SetAppCyclesWindows(const std::string& app_id, int sequence_number) {
181 if (g_window_cycle_sequence_number != sequence_number)
182 return;
183
184 bool any_change = false;
185 for (NSWindow* window : [NSApp windows]) {
186 bool is_browser;
187 const Extension* extension = GetExtensionForNSWindow(window, &is_browser);
188 if (extension && extension->id() == app_id)
189 any_change = SetWindowParticipatesInCycle(window, true) || any_change;
Robert Sesek 2015/06/23 15:00:55 You could use |= instead of "|| any change" at the
tapted 2015/06/23 23:36:10 Done.
190 else if (extension || is_browser)
191 any_change = SetWindowParticipatesInCycle(window, false) || any_change;
192 }
193
194 // Without the following, -[NSApplication _getLockedWindowListForCycle] will
195 // happily return windows that were just set to ignore window cycling. Doing
196 // this seems to trick AppKit into updating the window cycle list. But it is a
197 // bit scary, so avoid it when there is no change. These attempts were based
198 // on the observation that clicking a window twice to switch focus would
199 // always work. Also tried (without luck):
200 // - [NSApp setWindowsNeedUpdate:YES],
201 // - Creating a deferred NSWindow and immediately releasing it,
202 // - Calling private methods like [NSApp _unlockWindowListForCycle],
203 // - [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined...
204 // (an attempt to tickle AppKit into an update of some kind),
205 // - Calling synchronously (i.e. not via PostTask) <- this was actually the
206 // initial attempt. Then, switching to PostTask didn't help with this
207 // quirk, but was useful for the sequence number stuff, and
208 // - Re-ordering collection behavior changes to ensure one window was always
209 // participating (i.e. all 'adds' before any 'removes').
210 if (any_change)
211 [[NSApp keyWindow] makeKeyAndOrderFront:nil];
212 }
213
214 // Sets the window cycle list to Chrome browser windows only.
215 void SetChromeCyclesWindows(int sequence_number) {
216 if (g_window_cycle_sequence_number != sequence_number)
217 return;
218
219 bool any_change = false;
220 for (NSWindow* window : [NSApp windows]) {
221 bool is_browser;
222 const Extension* extension = GetExtensionForNSWindow(window, &is_browser);
223 if (extension || is_browser) {
224 any_change =
225 SetWindowParticipatesInCycle(window, is_browser) || any_change;
Robert Sesek 2015/06/23 15:00:55 Same.
tapted 2015/06/23 23:36:10 Done.
226 }
227 }
228 if (any_change)
229 [[NSApp keyWindow] makeKeyAndOrderFront:nil];
230 }
231
116 } // namespace 232 } // namespace
117 233
118 // Used by AppShimMenuController to manage menu items that are a copy of a 234 // Used by AppShimMenuController to manage menu items that are a copy of a
119 // Chrome menu item but with a different action. This manages unsetting and 235 // Chrome menu item but with a different action. This manages unsetting and
120 // restoring the original item's key equivalent, so that we can use the same 236 // restoring the original item's key equivalent, so that we can use the same
121 // key equivalent in the copied item with a different action. If |resourceId_| 237 // key equivalent in the copied item with a different action. If |resourceId_|
122 // is non-zero, this will also update the title to include the app name. 238 // is non-zero, this will also update the title to include the app name.
123 // If the copy (menuItem) has no key equivalent, and the title does not have the 239 // If the copy (menuItem) has no key equivalent, and the title does not have the
124 // app name, then enableForApp and disable do not need to be called. I.e. the 240 // app name, then enableForApp and disable do not need to be called. I.e. the
125 // doppelganger just copies the item and sets a new action. 241 // doppelganger just copies the item and sets a new action.
(...skipping 16 matching lines...) Expand all
142 keyEquivalent:(NSString*)keyEquivalent; 258 keyEquivalent:(NSString*)keyEquivalent;
143 // Retain the source item given |menuTag| and |sourceItemTag|. Copy 259 // Retain the source item given |menuTag| and |sourceItemTag|. Copy
144 // the menu item given |menuTag| and |targetItemTag|. 260 // the menu item given |menuTag| and |targetItemTag|.
145 // This is useful when we want a doppelganger with a different source item. 261 // This is useful when we want a doppelganger with a different source item.
146 // For example, if there are conflicting key equivalents. 262 // For example, if there are conflicting key equivalents.
147 - (id)initWithMenuTag:(NSInteger)menuTag 263 - (id)initWithMenuTag:(NSInteger)menuTag
148 sourceItemTag:(NSInteger)sourceItemTag 264 sourceItemTag:(NSInteger)sourceItemTag
149 targetItemTag:(NSInteger)targetItemTag 265 targetItemTag:(NSInteger)targetItemTag
150 keyEquivalent:(NSString*)keyEquivalent; 266 keyEquivalent:(NSString*)keyEquivalent;
151 // Set the title using |resourceId_| and unset the source item's key equivalent. 267 // Set the title using |resourceId_| and unset the source item's key equivalent.
152 - (void)enableForApp:(const extensions::Extension*)app; 268 - (void)enableForApp:(const Extension*)app;
153 // Restore the source item's key equivalent. 269 // Restore the source item's key equivalent.
154 - (void)disable; 270 - (void)disable;
155 @end 271 @end
156 272
157 @implementation DoppelgangerMenuItem 273 @implementation DoppelgangerMenuItem
158 274
159 - (NSMenuItem*)menuItem { 275 - (NSMenuItem*)menuItem {
160 return menuItem_; 276 return menuItem_;
161 } 277 }
162 278
(...skipping 25 matching lines...) Expand all
188 if ((self = [super init])) { 304 if ((self = [super init])) {
189 menuItem_.reset([GetItemByTag(menuTag, targetItemTag) copy]); 305 menuItem_.reset([GetItemByTag(menuTag, targetItemTag) copy]);
190 sourceItem_.reset([GetItemByTag(menuTag, sourceItemTag) retain]); 306 sourceItem_.reset([GetItemByTag(menuTag, sourceItemTag) retain]);
191 DCHECK(menuItem_); 307 DCHECK(menuItem_);
192 DCHECK(sourceItem_); 308 DCHECK(sourceItem_);
193 sourceKeyEquivalent_.reset([[sourceItem_ keyEquivalent] copy]); 309 sourceKeyEquivalent_.reset([[sourceItem_ keyEquivalent] copy]);
194 } 310 }
195 return self; 311 return self;
196 } 312 }
197 313
198 - (void)enableForApp:(const extensions::Extension*)app { 314 - (void)enableForApp:(const Extension*)app {
199 // It seems that two menu items that have the same key equivalent must also 315 // It seems that two menu items that have the same key equivalent must also
200 // have the same action for the keyboard shortcut to work. (This refers to the 316 // have the same action for the keyboard shortcut to work. (This refers to the
201 // original keyboard shortcut, regardless of any overrides set in OSX). 317 // original keyboard shortcut, regardless of any overrides set in OSX).
202 // In order to let the app menu items have a different action, we remove the 318 // In order to let the app menu items have a different action, we remove the
203 // key equivalent of the original items and restore them later. 319 // key equivalent of the original items and restore them later.
204 [sourceItem_ setKeyEquivalent:@""]; 320 [sourceItem_ setKeyEquivalent:@""];
205 if (!resourceId_) 321 if (!resourceId_)
206 return; 322 return;
207 323
208 [menuItem_ setTitle:l10n_util::GetNSStringF(resourceId_, 324 [menuItem_ setTitle:l10n_util::GetNSStringF(resourceId_,
209 base::UTF8ToUTF16(app->name()))]; 325 base::UTF8ToUTF16(app->name()))];
210 } 326 }
211 327
212 - (void)disable { 328 - (void)disable {
213 // Restore the keyboard shortcut to Chrome. This just needs to be set back to 329 // Restore the keyboard shortcut to Chrome. This just needs to be set back to
214 // the original keyboard shortcut, regardless of any overrides in OSX. The 330 // the original keyboard shortcut, regardless of any overrides in OSX. The
215 // overrides still work as they are based on the title of the menu item. 331 // overrides still work as they are based on the title of the menu item.
216 [sourceItem_ setKeyEquivalent:sourceKeyEquivalent_]; 332 [sourceItem_ setKeyEquivalent:sourceKeyEquivalent_];
217 } 333 }
218 334
219 @end 335 @end
220 336
221 @interface AppShimMenuController () 337 @interface AppShimMenuController ()
222 // Construct the NSMenuItems for apps. 338 // Construct the NSMenuItems for apps.
223 - (void)buildAppMenuItems; 339 - (void)buildAppMenuItems;
224 // Register for NSWindow notifications. 340 // Register for NSWindow notifications.
225 - (void)registerEventHandlers; 341 - (void)registerEventHandlers;
226 // If the window is an app window, add or remove menu items. 342 // If the window is an app window, add or remove menu items.
227 - (void)windowMainStatusChanged:(NSNotification*)notification; 343 - (void)windowMainStatusChanged:(NSNotification*)notification;
344 // Called when |app| becomes the main window in the Chrome process.
345 - (void)appBecameMain:(const Extension*)app;
346 // Called when there is no main window, or if the main window is not an app.
347 - (void)chromeBecameMain;
228 // Add menu items for an app and hide Chrome menu items. 348 // Add menu items for an app and hide Chrome menu items.
229 - (void)addMenuItems:(const extensions::Extension*)app; 349 - (void)addMenuItems:(const Extension*)app;
230 // If the window belongs to the currently focused app, remove the menu items and 350 // If the window belongs to the currently focused app, remove the menu items and
231 // unhide Chrome menu items. 351 // unhide Chrome menu items.
232 - (void)removeMenuItems; 352 - (void)removeMenuItems;
233 // If the currently focused window belongs to a platform app, quit the app. 353 // If the currently focused window belongs to a platform app, quit the app.
234 - (void)quitCurrentPlatformApp; 354 - (void)quitCurrentPlatformApp;
235 // If the currently focused window belongs to a platform app, hide the app. 355 // If the currently focused window belongs to a platform app, hide the app.
236 - (void)hideCurrentPlatformApp; 356 - (void)hideCurrentPlatformApp;
237 // If the currently focused window belongs to a platform app, focus the app. 357 // If the currently focused window belongs to a platform app, focus the app.
238 - (void)focusCurrentPlatformApp; 358 - (void)focusCurrentPlatformApp;
239 @end 359 @end
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 // A Yosemite AppKit bug causes this notification to be sent during the 489 // A Yosemite AppKit bug causes this notification to be sent during the
370 // -dealloc for a specific NSWindow. Any autoreleases sent to that window 490 // -dealloc for a specific NSWindow. Any autoreleases sent to that window
371 // must be drained before the window finishes -dealloc. In this method, an 491 // must be drained before the window finishes -dealloc. In this method, an
372 // autorelease is sent by the invocation of [NSApp windows]. 492 // autorelease is sent by the invocation of [NSApp windows].
373 // http://crbug.com/406944. 493 // http://crbug.com/406944.
374 base::mac::ScopedNSAutoreleasePool pool; 494 base::mac::ScopedNSAutoreleasePool pool;
375 495
376 NSString* name = [notification name]; 496 NSString* name = [notification name];
377 if ([name isEqualToString:NSWindowDidBecomeMainNotification]) { 497 if ([name isEqualToString:NSWindowDidBecomeMainNotification]) {
378 id window = [notification object]; 498 id window = [notification object];
379 extensions::AppWindow* appWindow = 499 bool is_browser;
380 AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile( 500 const Extension* extension = GetExtensionForNSWindow(window, &is_browser);
381 window); 501 // Ignore is_browser: if a window becomes main that does not belong to an
382 502 // extension or browser, treat it the same as switching to a browser.
383 const extensions::Extension* extension = NULL; 503 if (extension)
384 // If there is no corresponding AppWindow, this could be a hosted app, so 504 [self appBecameMain:extension];
385 // check for a browser.
386 if (appWindow)
387 extension = appWindow->GetExtension();
388 else 505 else
389 extension = apps::ExtensionAppShimHandler::MaybeGetAppForBrowser( 506 [self chromeBecameMain];
390 chrome::FindBrowserWithWindow(window));
391
392 if (extension)
393 [self addMenuItems:extension];
394 else
395 [self removeMenuItems];
396 } else if ([name isEqualToString:NSWindowDidResignMainNotification]) { 507 } else if ([name isEqualToString:NSWindowDidResignMainNotification]) {
397 // When a window resigns main status, reset back to the Chrome menu. 508 // When a window resigns main status, reset back to the Chrome menu.
398 // In the past we've tried: 509 // In the past we've tried:
399 // - Only doing this when a window closes, but this would not be triggered 510 // - Only doing this when a window closes, but this would not be triggered
400 // when an app becomes hidden (Cmd+h), and there are no Chrome windows to 511 // when an app becomes hidden (Cmd+h), and there are no Chrome windows to
401 // become main. 512 // become main.
402 // - Scanning [NSApp windows] to predict whether we could 513 // - Scanning [NSApp windows] to predict whether we could
403 // expect another Chrome window to become main, and skip the reset. However, 514 // expect another Chrome window to become main, and skip the reset. However,
404 // panels need to do strange things during window close to ensure panels 515 // panels need to do strange things during window close to ensure panels
405 // never get chosen for key status over a browser window (which is likely 516 // never get chosen for key status over a browser window (which is likely
406 // because they are given an elevated [NSWindow level]). Trying to handle 517 // because they are given an elevated [NSWindow level]). Trying to handle
407 // this case is not robust. 518 // this case is not robust.
408 // 519 //
409 // Unfortunately, resetting the menu to Chrome 520 // Unfortunately, resetting the menu to Chrome
410 // unconditionally means that if another packaged app window becomes key, 521 // unconditionally means that if another packaged app window becomes key,
411 // the menu will flicker. TODO(tapted): Investigate restoring the logic when 522 // the menu will flicker. TODO(tapted): Investigate restoring the logic when
412 // the panel code is removed. 523 // the panel code is removed.
413 [self removeMenuItems]; 524 [self chromeBecameMain];
414 } else { 525 } else {
415 NOTREACHED(); 526 NOTREACHED();
416 } 527 }
417 } 528 }
418 529
419 - (void)addMenuItems:(const extensions::Extension*)app { 530 - (void)appBecameMain:(const Extension*)app {
420 NSString* appId = base::SysUTF8ToNSString(app->id()); 531 if (appId_ == app->id())
421 NSString* title = base::SysUTF8ToNSString(app->name());
422
423 if ([appId_ isEqualToString:appId])
424 return; 532 return;
425 533
534 if (!appId_.empty())
535 [self removeMenuItems];
536
537 appId_ = app->id();
538 [self addMenuItems:app];
539 if (IsAppWindowCyclingEnabled()) {
540 base::MessageLoop::current()->PostTask(
541 FROM_HERE, base::Bind(&SetAppCyclesWindows, appId_,
542 ++g_window_cycle_sequence_number));
543 }
544 }
545
546 - (void)chromeBecameMain {
547 if (appId_.empty())
548 return;
549
550 appId_.clear();
426 [self removeMenuItems]; 551 [self removeMenuItems];
427 appId_.reset([appId copy]); 552 if (IsAppWindowCyclingEnabled()) {
553 base::MessageLoop::current()->PostTask(
554 FROM_HERE,
555 base::Bind(&SetChromeCyclesWindows, ++g_window_cycle_sequence_number));
556 }
557 }
558
559 - (void)addMenuItems:(const Extension*)app {
560 DCHECK_EQ(appId_, app->id());
561 NSString* title = base::SysUTF8ToNSString(app->name());
428 562
429 // Hide Chrome menu items. 563 // Hide Chrome menu items.
430 NSMenu* mainMenu = [NSApp mainMenu]; 564 NSMenu* mainMenu = [NSApp mainMenu];
431 for (NSMenuItem* item in [mainMenu itemArray]) 565 for (NSMenuItem* item in [mainMenu itemArray])
432 [item setHidden:YES]; 566 [item setHidden:YES];
433 567
434 [aboutDoppelganger_ enableForApp:app]; 568 [aboutDoppelganger_ enableForApp:app];
435 [hideDoppelganger_ enableForApp:app]; 569 [hideDoppelganger_ enableForApp:app];
436 [quitDoppelganger_ enableForApp:app]; 570 [quitDoppelganger_ enableForApp:app];
437 [newDoppelganger_ enableForApp:app]; 571 [newDoppelganger_ enableForApp:app];
438 [openDoppelganger_ enableForApp:app]; 572 [openDoppelganger_ enableForApp:app];
439 [closeWindowDoppelganger_ enableForApp:app]; 573 [closeWindowDoppelganger_ enableForApp:app];
440 574
441 [appMenuItem_ setTitle:appId]; 575 [appMenuItem_ setTitle:base::SysUTF8ToNSString(appId_)];
442 [[appMenuItem_ submenu] setTitle:title]; 576 [[appMenuItem_ submenu] setTitle:title];
443 577
444 [mainMenu addItem:appMenuItem_]; 578 [mainMenu addItem:appMenuItem_];
445 [mainMenu addItem:fileMenuItem_]; 579 [mainMenu addItem:fileMenuItem_];
446 580
447 SetItemWithTagVisible(editMenuItem_, 581 SetItemWithTagVisible(editMenuItem_,
448 IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE, 582 IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE,
449 app->is_hosted_app(), true); 583 app->is_hosted_app(), true);
450 SetItemWithTagVisible(editMenuItem_, IDC_FIND_MENU, app->is_hosted_app(), 584 SetItemWithTagVisible(editMenuItem_, IDC_FIND_MENU, app->is_hosted_app(),
451 false); 585 false);
452 [mainMenu addItem:editMenuItem_]; 586 [mainMenu addItem:editMenuItem_];
453 587
454 if (app->is_hosted_app()) { 588 if (app->is_hosted_app()) {
455 [mainMenu addItem:viewMenuItem_]; 589 [mainMenu addItem:viewMenuItem_];
456 [mainMenu addItem:historyMenuItem_]; 590 [mainMenu addItem:historyMenuItem_];
457 } 591 }
458 [mainMenu addItem:windowMenuItem_]; 592 [mainMenu addItem:windowMenuItem_];
459 } 593 }
460 594
461 - (void)removeMenuItems { 595 - (void)removeMenuItems {
462 if (!appId_)
463 return;
464
465 appId_.reset();
466
467 NSMenu* mainMenu = [NSApp mainMenu]; 596 NSMenu* mainMenu = [NSApp mainMenu];
468 [mainMenu removeItem:appMenuItem_]; 597 [mainMenu removeItem:appMenuItem_];
469 [mainMenu removeItem:fileMenuItem_]; 598 [mainMenu removeItem:fileMenuItem_];
470 if ([mainMenu indexOfItem:viewMenuItem_] >= 0) 599 if ([mainMenu indexOfItem:viewMenuItem_] >= 0)
471 [mainMenu removeItem:viewMenuItem_]; 600 [mainMenu removeItem:viewMenuItem_];
472 if ([mainMenu indexOfItem:historyMenuItem_] >= 0) 601 if ([mainMenu indexOfItem:historyMenuItem_] >= 0)
473 [mainMenu removeItem:historyMenuItem_]; 602 [mainMenu removeItem:historyMenuItem_];
474 [mainMenu removeItem:editMenuItem_]; 603 [mainMenu removeItem:editMenuItem_];
475 [mainMenu removeItem:windowMenuItem_]; 604 [mainMenu removeItem:windowMenuItem_];
476 605
(...skipping 10 matching lines...) Expand all
487 } 616 }
488 617
489 - (void)quitCurrentPlatformApp { 618 - (void)quitCurrentPlatformApp {
490 extensions::AppWindow* appWindow = 619 extensions::AppWindow* appWindow =
491 AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile( 620 AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile(
492 [NSApp keyWindow]); 621 [NSApp keyWindow]);
493 if (appWindow) { 622 if (appWindow) {
494 apps::ExtensionAppShimHandler::QuitAppForWindow(appWindow); 623 apps::ExtensionAppShimHandler::QuitAppForWindow(appWindow);
495 } else { 624 } else {
496 Browser* browser = chrome::FindBrowserWithWindow([NSApp keyWindow]); 625 Browser* browser = chrome::FindBrowserWithWindow([NSApp keyWindow]);
497 const extensions::Extension* extension = 626 const Extension* extension =
498 apps::ExtensionAppShimHandler::MaybeGetAppForBrowser(browser); 627 apps::ExtensionAppShimHandler::MaybeGetAppForBrowser(browser);
499 if (extension) 628 if (extension)
500 apps::ExtensionAppShimHandler::QuitHostedAppForWindow(browser->profile(), 629 apps::ExtensionAppShimHandler::QuitHostedAppForWindow(browser->profile(),
501 extension->id()); 630 extension->id());
502 } 631 }
503 } 632 }
504 633
505 - (void)hideCurrentPlatformApp { 634 - (void)hideCurrentPlatformApp {
506 extensions::AppWindow* appWindow = 635 extensions::AppWindow* appWindow =
507 AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile( 636 AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile(
508 [NSApp keyWindow]); 637 [NSApp keyWindow]);
509 if (appWindow) { 638 if (appWindow) {
510 apps::ExtensionAppShimHandler::HideAppForWindow(appWindow); 639 apps::ExtensionAppShimHandler::HideAppForWindow(appWindow);
511 } else { 640 } else {
512 Browser* browser = chrome::FindBrowserWithWindow([NSApp keyWindow]); 641 Browser* browser = chrome::FindBrowserWithWindow([NSApp keyWindow]);
513 const extensions::Extension* extension = 642 const Extension* extension =
514 apps::ExtensionAppShimHandler::MaybeGetAppForBrowser(browser); 643 apps::ExtensionAppShimHandler::MaybeGetAppForBrowser(browser);
515 if (extension) 644 if (extension)
516 apps::ExtensionAppShimHandler::HideHostedApp(browser->profile(), 645 apps::ExtensionAppShimHandler::HideHostedApp(browser->profile(),
517 extension->id()); 646 extension->id());
518 } 647 }
519 } 648 }
520 649
521 - (void)focusCurrentPlatformApp { 650 - (void)focusCurrentPlatformApp {
522 extensions::AppWindow* appWindow = 651 extensions::AppWindow* appWindow =
523 AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile( 652 AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile(
524 [NSApp keyWindow]); 653 [NSApp keyWindow]);
525 if (appWindow) 654 if (appWindow)
526 apps::ExtensionAppShimHandler::FocusAppForWindow(appWindow); 655 apps::ExtensionAppShimHandler::FocusAppForWindow(appWindow);
527 } 656 }
528 657
529 @end 658 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698