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

Side by Side Diff: chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc

Issue 790043002: Hosted apps on OS X now act more like a native app. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@creating-app-shims-2
Patch Set: Refactored code and addressed comments Created 6 years 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 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" 5 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
6 6
7 #include "apps/app_lifetime_monitor_factory.h" 7 #include "apps/app_lifetime_monitor_factory.h"
8 #include "apps/launcher.h" 8 #include "apps/launcher.h"
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h" 11 #include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h"
12 #include "chrome/browser/browser_process.h" 12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chrome_notification_types.h" 13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/extensions/launch_util.h"
14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/profiles/profile_manager.h" 16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/ui/browser_list.h"
18 #include "chrome/browser/ui/browser_window.h"
16 #include "chrome/browser/ui/extensions/application_launch.h" 19 #include "chrome/browser/ui/extensions/application_launch.h"
17 #include "chrome/browser/ui/extensions/extension_enable_flow.h" 20 #include "chrome/browser/ui/extensions/extension_enable_flow.h"
18 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h" 21 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
jackhou1 2014/12/12 00:48:29 Do you still need this #include?
mitchellj 2014/12/12 03:46:23 Acknowledged.
19 #include "chrome/browser/web_applications/web_app_mac.h" 23 #include "chrome/browser/web_applications/web_app_mac.h"
20 #include "chrome/common/extensions/extension_constants.h" 24 #include "chrome/common/extensions/extension_constants.h"
21 #include "chrome/common/extensions/extension_metrics.h" 25 #include "chrome/common/extensions/extension_metrics.h"
22 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 26 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
23 #include "chrome/common/mac/app_shim_messages.h" 27 #include "chrome/common/mac/app_shim_messages.h"
24 #include "components/crx_file/id_util.h" 28 #include "components/crx_file/id_util.h"
25 #include "content/public/browser/notification_details.h" 29 #include "content/public/browser/notification_details.h"
26 #include "content/public/browser/notification_service.h" 30 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/notification_source.h" 31 #include "content/public/browser/notification_source.h"
28 #include "extensions/browser/app_window/app_window.h" 32 #include "extensions/browser/app_window/app_window.h"
29 #include "extensions/browser/app_window/app_window_registry.h" 33 #include "extensions/browser/app_window/app_window_registry.h"
30 #include "extensions/browser/app_window/native_app_window.h" 34 #include "extensions/browser/app_window/native_app_window.h"
31 #include "extensions/browser/extension_host.h" 35 #include "extensions/browser/extension_host.h"
36 #include "extensions/browser/extension_prefs.h"
32 #include "extensions/browser/extension_registry.h" 37 #include "extensions/browser/extension_registry.h"
33 #include "extensions/common/constants.h" 38 #include "extensions/common/constants.h"
34 #include "ui/base/cocoa/focus_window_set.h" 39 #include "ui/base/cocoa/focus_window_set.h"
35 40
36 using extensions::AppWindow; 41 using extensions::AppWindow;
37 using extensions::AppWindowRegistry; 42 using extensions::AppWindowRegistry;
38 using extensions::ExtensionRegistry; 43 using extensions::ExtensionRegistry;
39 44
40 namespace { 45 namespace {
41 46
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 ++it) { 80 ++it) {
76 native_windows.insert((*it)->GetNativeWindow()); 81 native_windows.insert((*it)->GetNativeWindow());
77 } 82 }
78 // Allow workspace switching. For the browser process, we can reasonably rely 83 // Allow workspace switching. For the browser process, we can reasonably rely
79 // on OS X to switch spaces for us and honor relevant user settings. But shims 84 // on OS X to switch spaces for us and honor relevant user settings. But shims
80 // don't have windows, so we have to do it ourselves. 85 // don't have windows, so we have to do it ourselves.
81 ui::FocusWindowSet(native_windows); 86 ui::FocusWindowSet(native_windows);
82 return true; 87 return true;
83 } 88 }
84 89
90 bool FocusHostedAppWindows(std::set<Browser*>& browsers) {
91 if (browsers.empty())
92 return false;
93
94 std::set<gfx::NativeWindow> native_windows;
95 for (const Browser* browser : browsers) {
jackhou1 2014/12/12 00:48:28 No braces on one-line for-loop.
mitchellj 2014/12/12 03:46:23 Done.
96 native_windows.insert(browser->window()->GetNativeWindow());
97 }
98
99 ui::FocusWindowSet(native_windows);
100 return true;
101 }
102
85 // Attempts to launch a packaged app, prompting the user to enable it if 103 // Attempts to launch a packaged app, prompting the user to enable it if
86 // necessary. The prompt is shown in its own window. 104 // necessary. The prompt is shown in its own window.
87 // This class manages its own lifetime. 105 // This class manages its own lifetime.
88 class EnableViaPrompt : public ExtensionEnableFlowDelegate { 106 class EnableViaPrompt : public ExtensionEnableFlowDelegate {
89 public: 107 public:
90 EnableViaPrompt(Profile* profile, 108 EnableViaPrompt(Profile* profile,
91 const std::string& extension_id, 109 const std::string& extension_id,
92 const base::Callback<void()>& callback) 110 const base::Callback<void()>& callback)
93 : profile_(profile), 111 : profile_(profile),
94 extension_id_(extension_id), 112 extension_id_(extension_id),
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 AppWindowList ExtensionAppShimHandler::Delegate::GetWindows( 179 AppWindowList ExtensionAppShimHandler::Delegate::GetWindows(
162 Profile* profile, 180 Profile* profile,
163 const std::string& extension_id) { 181 const std::string& extension_id) {
164 return AppWindowRegistry::Get(profile)->GetAppWindowsForApp(extension_id); 182 return AppWindowRegistry::Get(profile)->GetAppWindowsForApp(extension_id);
165 } 183 }
166 184
167 const extensions::Extension* 185 const extensions::Extension*
168 ExtensionAppShimHandler::Delegate::GetAppExtension( 186 ExtensionAppShimHandler::Delegate::GetAppExtension(
169 Profile* profile, 187 Profile* profile,
170 const std::string& extension_id) { 188 const std::string& extension_id) {
171 ExtensionRegistry* registry = ExtensionRegistry::Get(profile); 189 return ExtensionAppShimHandler::GetAppExtension(profile, extension_id);
172 const extensions::Extension* extension =
173 registry->GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
174 return extension &&
175 (extension->is_platform_app() || extension->is_hosted_app())
176 ? extension
177 : NULL;
178 } 190 }
179 191
180 void ExtensionAppShimHandler::Delegate::EnableExtension( 192 void ExtensionAppShimHandler::Delegate::EnableExtension(
181 Profile* profile, 193 Profile* profile,
182 const std::string& extension_id, 194 const std::string& extension_id,
183 const base::Callback<void()>& callback) { 195 const base::Callback<void()>& callback) {
184 (new EnableViaPrompt(profile, extension_id, callback))->Run(); 196 (new EnableViaPrompt(profile, extension_id, callback))->Run();
185 } 197 }
186 198
187 void ExtensionAppShimHandler::Delegate::LaunchApp( 199 void ExtensionAppShimHandler::Delegate::LaunchApp(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 : delegate_(new Delegate), 234 : delegate_(new Delegate),
223 weak_factory_(this) { 235 weak_factory_(this) {
224 // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with 236 // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with
225 // AppShimHostManager. Since PROFILE_CREATED is not fired until 237 // AppShimHostManager. Since PROFILE_CREATED is not fired until
226 // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch 238 // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch
227 // notifications for all profiles. 239 // notifications for all profiles.
228 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, 240 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
229 content::NotificationService::AllBrowserContextsAndSources()); 241 content::NotificationService::AllBrowserContextsAndSources());
230 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 242 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
231 content::NotificationService::AllBrowserContextsAndSources()); 243 content::NotificationService::AllBrowserContextsAndSources());
244 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY,
245 content::NotificationService::AllBrowserContextsAndSources());
246 BrowserList::AddObserver(this);
232 } 247 }
233 248
234 ExtensionAppShimHandler::~ExtensionAppShimHandler() {} 249 ExtensionAppShimHandler::~ExtensionAppShimHandler() {
250 BrowserList::RemoveObserver(this);
251 }
235 252
236 AppShimHandler::Host* ExtensionAppShimHandler::FindHost( 253 AppShimHandler::Host* ExtensionAppShimHandler::FindHost(
237 Profile* profile, 254 Profile* profile,
238 const std::string& app_id) { 255 const std::string& app_id) {
239 HostMap::iterator it = hosts_.find(make_pair(profile, app_id)); 256 HostMap::iterator it = hosts_.find(make_pair(profile, app_id));
240 return it == hosts_.end() ? NULL : it->second; 257 return it == hosts_.end() ? NULL : it->second;
241 } 258 }
242 259
243 // static 260 // static
244 void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) { 261 void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) {
245 ExtensionAppShimHandler* handler = GetInstance(); 262 ExtensionAppShimHandler* handler = GetInstance();
246 Host* host = handler->FindHost( 263 Host* host = handler->FindHost(
247 Profile::FromBrowserContext(app_window->browser_context()), 264 Profile::FromBrowserContext(app_window->browser_context()),
248 app_window->extension_id()); 265 app_window->extension_id());
249 if (host) { 266 if (host) {
250 handler->OnShimQuit(host); 267 handler->OnShimQuit(host);
251 } else { 268 } else {
252 // App shims might be disabled or the shim is still starting up. 269 // App shims might be disabled or the shim is still starting up.
253 AppWindowRegistry::Get( 270 AppWindowRegistry::Get(
254 Profile::FromBrowserContext(app_window->browser_context())) 271 Profile::FromBrowserContext(app_window->browser_context()))
255 ->CloseAllAppWindowsForApp(app_window->extension_id()); 272 ->CloseAllAppWindowsForApp(app_window->extension_id());
256 } 273 }
257 } 274 }
258 275
276 // static
277 void ExtensionAppShimHandler::QuitHostedAppForWindow(
jackhou1 2014/12/12 00:48:28 I don't think you need to check is_hosted_app here
mitchellj 2014/12/12 03:46:23 Done.
278 Browser* browser,
279 const extensions::Extension* extension) {
280 ExtensionAppShimHandler* handler = GetInstance();
281 Host* host = handler->FindHost(
282 Profile::FromBrowserContext(browser->profile()), extension->id());
283 if (host && extension->is_hosted_app()) {
284 handler->OnShimQuit(host);
285 }
286 }
287
259 void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) { 288 void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) {
260 ExtensionAppShimHandler* handler = GetInstance(); 289 ExtensionAppShimHandler* handler = GetInstance();
261 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 290 Profile* profile = Profile::FromBrowserContext(app_window->browser_context());
262 Host* host = handler->FindHost(profile, app_window->extension_id()); 291 Host* host = handler->FindHost(profile, app_window->extension_id());
263 if (host) 292 if (host)
264 host->OnAppHide(); 293 host->OnAppHide();
265 else 294 else
266 SetAppHidden(profile, app_window->extension_id(), true); 295 SetAppHidden(profile, app_window->extension_id(), true);
267 } 296 }
268 297
298 void ExtensionAppShimHandler::HideHostedApp(Profile* profile,
299 const std::string& app_id) {
300 ExtensionAppShimHandler* handler = GetInstance();
301 Host* host = handler->FindHost(profile, app_id);
302 if (host)
303 host->OnAppHide();
304 else
305 handler->SetHostedAppHidden(profile, app_id, true);
306 }
307
308 void ExtensionAppShimHandler::SetHostedAppHidden(Profile* profile,
309 const std::string& app_id,
310 bool hidden) {
311 const AppBrowserMap::iterator it = app_browser_windows_.find(app_id);
312 if (it == app_browser_windows_.end())
313 return;
314
315 for (const Browser* browser : it->second) {
316 if (!browser->is_app() ||
jackhou1 2014/12/12 00:48:29 Can this ever happen? All the Browser*s in the map
mitchellj 2014/12/12 03:46:23 This is correct. I've removed the first condition
317 web_app::GetExtensionIdFromApplicationName(browser->app_name()) !=
318 app_id) {
319 continue;
320 }
321
322 if (hidden)
323 browser->window()->Hide();
324 else
325 browser->window()->Show();
326 }
327 }
328
269 void ExtensionAppShimHandler::FocusAppForWindow(AppWindow* app_window) { 329 void ExtensionAppShimHandler::FocusAppForWindow(AppWindow* app_window) {
270 ExtensionAppShimHandler* handler = GetInstance(); 330 ExtensionAppShimHandler* handler = GetInstance();
271 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 331 Profile* profile = Profile::FromBrowserContext(app_window->browser_context());
272 const std::string& app_id = app_window->extension_id(); 332 const std::string& app_id = app_window->extension_id();
273 Host* host = handler->FindHost(profile, app_id); 333 Host* host = handler->FindHost(profile, app_id);
274 if (host) { 334 if (host) {
275 handler->OnShimFocus(host, 335 handler->OnShimFocus(host,
276 APP_SHIM_FOCUS_NORMAL, 336 APP_SHIM_FOCUS_NORMAL,
277 std::vector<base::FilePath>()); 337 std::vector<base::FilePath>());
278 } else { 338 } else {
279 FocusWindows(AppWindowRegistry::Get(profile)->GetAppWindowsForApp(app_id)); 339 FocusWindows(AppWindowRegistry::Get(profile)->GetAppWindowsForApp(app_id));
280 } 340 }
281 } 341 }
282 342
283 // static 343 // static
344 const extensions::Extension* ExtensionAppShimHandler::GetAppExtension(
345 Profile* profile,
346 const std::string& extension_id) {
347 if (!profile)
348 return NULL;
349
350 ExtensionRegistry* registry = ExtensionRegistry::Get(profile);
351 const extensions::Extension* extension =
352 registry->GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
353 return extension &&
354 (extension->is_platform_app() || extension->is_hosted_app())
355 ? extension
356 : NULL;
357 }
358
359 // static
284 bool ExtensionAppShimHandler::ActivateAndRequestUserAttentionForWindow( 360 bool ExtensionAppShimHandler::ActivateAndRequestUserAttentionForWindow(
285 AppWindow* app_window) { 361 AppWindow* app_window) {
286 ExtensionAppShimHandler* handler = GetInstance(); 362 ExtensionAppShimHandler* handler = GetInstance();
287 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 363 Profile* profile = Profile::FromBrowserContext(app_window->browser_context());
288 Host* host = handler->FindHost(profile, app_window->extension_id()); 364 Host* host = handler->FindHost(profile, app_window->extension_id());
289 if (host) { 365 if (host) {
290 // Bring the window to the front without showing it. 366 // Bring the window to the front without showing it.
291 AppWindowRegistry::Get(profile)->AppWindowActivated(app_window); 367 AppWindowRegistry::Get(profile)->AppWindowActivated(app_window);
292 host->OnAppRequestUserAttention(APP_SHIM_ATTENTION_INFORMATIONAL); 368 host->OnAppRequestUserAttention(APP_SHIM_ATTENTION_INFORMATIONAL);
293 return true; 369 return true;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 } 468 }
393 469
394 // TODO(jeremya): Handle the case that launching the app fails. Probably we 470 // TODO(jeremya): Handle the case that launching the app fails. Probably we
395 // need to watch for 'app successfully launched' or at least 'background page 471 // need to watch for 'app successfully launched' or at least 'background page
396 // exists/was created' and time out with failure if we don't see that sign of 472 // exists/was created' and time out with failure if we don't see that sign of
397 // life within a certain window. 473 // life within a certain window.
398 const extensions::Extension* extension = 474 const extensions::Extension* extension =
399 delegate_->GetAppExtension(profile, app_id); 475 delegate_->GetAppExtension(profile, app_id);
400 if (extension) { 476 if (extension) {
401 delegate_->LaunchApp(profile, extension, files); 477 delegate_->LaunchApp(profile, extension, files);
402 // If it's a hosted app, just kill it immediately after opening for now. 478 // If it's a hosted app and a tabbed application, let the shim terminate
jackhou1 2014/12/12 00:48:29 s/and a tabbed application/that opens in a tab/
mitchellj 2014/12/12 03:46:23 Acknowledged.
403 if (extension->is_hosted_app()) 479 // immediately.
480 if (extension->is_hosted_app() &&
481 extensions::GetLaunchType(extensions::ExtensionPrefs::Get(profile),
482 extension) ==
483 extensions::LAUNCH_TYPE_REGULAR) {
404 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); 484 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST);
485 }
405 return; 486 return;
406 } 487 }
407 488
408 delegate_->EnableExtension( 489 delegate_->EnableExtension(
409 profile, app_id, 490 profile, app_id,
410 base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled, 491 base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled,
411 weak_factory_.GetWeakPtr(), 492 weak_factory_.GetWeakPtr(),
412 host->GetProfilePath(), app_id, files)); 493 host->GetProfilePath(), app_id, files));
413 } 494 }
414 495
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 } 528 }
448 } 529 }
449 530
450 void ExtensionAppShimHandler::OnShimFocus( 531 void ExtensionAppShimHandler::OnShimFocus(
451 Host* host, 532 Host* host,
452 AppShimFocusType focus_type, 533 AppShimFocusType focus_type,
453 const std::vector<base::FilePath>& files) { 534 const std::vector<base::FilePath>& files) {
454 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 535 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath()));
455 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 536 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath());
456 537
457 const AppWindowList windows = 538 bool windows_focused;
458 delegate_->GetWindows(profile, host->GetAppId()); 539 const std::string& app_id = host->GetAppId();
459 bool windows_focused = FocusWindows(windows); 540 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) {
541 std::vector<content::WebContents*> items;
jackhou1 2014/12/12 00:48:28 Is |items| ever used?
mitchellj 2014/12/12 03:46:23 Oops, forgot to remove it when I changed the signa
542 AppBrowserMap::iterator it = app_browser_windows_.find(app_id);
543 if (it == app_browser_windows_.end())
544 return;
jackhou1 2014/12/12 00:48:28 Blank line after return.
mitchellj 2014/12/12 03:46:23 Done.
545 windows_focused = FocusHostedAppWindows(it->second);
546 } else {
547 const AppWindowList windows =
548 delegate_->GetWindows(profile, host->GetAppId());
549 windows_focused = FocusWindows(windows);
550 }
460 551
461 if (focus_type == APP_SHIM_FOCUS_NORMAL || 552 if (focus_type == APP_SHIM_FOCUS_NORMAL ||
462 (focus_type == APP_SHIM_FOCUS_REOPEN && windows_focused)) { 553 (focus_type == APP_SHIM_FOCUS_REOPEN && windows_focused)) {
463 return; 554 return;
464 } 555 }
465 556
466 const extensions::Extension* extension = 557 const extensions::Extension* extension =
467 delegate_->GetAppExtension(profile, host->GetAppId()); 558 delegate_->GetAppExtension(profile, host->GetAppId());
468 if (extension) { 559 if (extension) {
469 delegate_->LaunchApp(profile, extension, files); 560 delegate_->LaunchApp(profile, extension, files);
470 } else { 561 } else {
471 // Extensions may have been uninstalled or disabled since the shim 562 // Extensions may have been uninstalled or disabled since the shim
472 // started. 563 // started.
473 host->OnAppClosed(); 564 host->OnAppClosed();
474 } 565 }
475 } 566 }
476 567
477 void ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) { 568 void ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) {
478 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 569 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath()));
479 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 570 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath());
480 571
481 SetAppHidden(profile, host->GetAppId(), hidden); 572 const std::string& app_id = host->GetAppId();
573 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) {
574 ExtensionAppShimHandler* handler = GetInstance();
575 handler->SetHostedAppHidden(profile, app_id, hidden);
jackhou1 2014/12/12 00:48:28 You can call SetHostedAppHidden directly here sinc
mitchellj 2014/12/12 03:46:23 Done.
576 } else {
577 SetAppHidden(profile, app_id, hidden);
578 }
482 } 579 }
483 580
484 void ExtensionAppShimHandler::OnShimQuit(Host* host) { 581 void ExtensionAppShimHandler::OnShimQuit(Host* host) {
485 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 582 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath()));
486 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 583 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath());
487 584
488 const std::string& app_id = host->GetAppId(); 585 const std::string& app_id = host->GetAppId();
489 const AppWindowList windows = delegate_->GetWindows(profile, app_id); 586 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) {
490 for (AppWindowRegistry::const_iterator it = windows.begin(); 587 std::vector<content::WebContents*> items;
491 it != windows.end(); 588 AppBrowserMap::iterator it = app_browser_windows_.find(app_id);
492 ++it) { 589 if (it == app_browser_windows_.end())
493 (*it)->GetBaseWindow()->Close(); 590 return;
591
592 for (const Browser* browser : it->second) {
jackhou1 2014/12/12 00:48:29 No braces here.
mitchellj 2014/12/12 03:46:23 Done.
593 browser->window()->Close();
594 }
595 } else {
596 const AppWindowList windows = delegate_->GetWindows(profile, app_id);
597 for (AppWindowRegistry::const_iterator it = windows.begin();
598 it != windows.end(); ++it) {
599 (*it)->GetBaseWindow()->Close();
600 }
494 } 601 }
495 // Once the last window closes, flow will end up in OnAppDeactivated via 602 // Once the last window closes, flow will end up in OnAppDeactivated via
496 // AppLifetimeMonitor. 603 // AppLifetimeMonitor.
604 // Otherwise, once the last window closes for a hosted app, OnBrowserRemoved
605 // will call OnAppDeactivated.
497 } 606 }
498 607
499 void ExtensionAppShimHandler::set_delegate(Delegate* delegate) { 608 void ExtensionAppShimHandler::set_delegate(Delegate* delegate) {
500 delegate_.reset(delegate); 609 delegate_.reset(delegate);
501 } 610 }
502 611
503 void ExtensionAppShimHandler::Observe( 612 void ExtensionAppShimHandler::Observe(
504 int type, 613 int type,
505 const content::NotificationSource& source, 614 const content::NotificationSource& source,
506 const content::NotificationDetails& details) { 615 const content::NotificationDetails& details) {
507 Profile* profile = content::Source<Profile>(source).ptr();
508 if (profile->IsOffTheRecord())
509 return;
510
511 switch (type) { 616 switch (type) {
512 case chrome::NOTIFICATION_PROFILE_CREATED: { 617 case chrome::NOTIFICATION_PROFILE_CREATED: {
618 Profile* profile = content::Source<Profile>(source).ptr();
619 if (profile->IsOffTheRecord())
620 return;
621
513 AppLifetimeMonitorFactory::GetForProfile(profile)->AddObserver(this); 622 AppLifetimeMonitorFactory::GetForProfile(profile)->AddObserver(this);
514 break; 623 break;
515 } 624 }
516 case chrome::NOTIFICATION_PROFILE_DESTROYED: { 625 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
626 Profile* profile = content::Source<Profile>(source).ptr();
627 if (profile->IsOffTheRecord())
628 return;
629
517 AppLifetimeMonitorFactory::GetForProfile(profile)->RemoveObserver(this); 630 AppLifetimeMonitorFactory::GetForProfile(profile)->RemoveObserver(this);
518 // Shut down every shim associated with this profile. 631 // Shut down every shim associated with this profile.
519 for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { 632 for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) {
520 // Increment the iterator first as OnAppClosed may call back to 633 // Increment the iterator first as OnAppClosed may call back to
521 // OnShimClose and invalidate the iterator. 634 // OnShimClose and invalidate the iterator.
522 HostMap::iterator current = it++; 635 HostMap::iterator current = it++;
523 if (profile->IsSameProfile(current->first.first)) { 636 if (profile->IsSameProfile(current->first.first)) {
524 Host* host = current->second; 637 Host* host = current->second;
525 host->OnAppClosed(); 638 host->OnAppClosed();
526 } 639 }
527 } 640 }
528 break; 641 break;
529 } 642 }
643 case chrome::NOTIFICATION_BROWSER_WINDOW_READY: {
644 Browser* browser = content::Source<Browser>(source).ptr();
645 // Don't keep track of browsers that are not associated with an app.
646 if (!browser->is_app())
jackhou1 2014/12/12 00:48:29 This should also check that the Extension is a hos
mitchellj 2014/12/12 03:46:23 Done.
647 return;
648
649 std::string app_id =
650 web_app::GetExtensionIdFromApplicationName(browser->app_name());
651 BrowserSet& browsers = app_browser_windows_[app_id];
652 browsers.insert(browser);
653 if (browsers.size() == 1)
654 OnAppActivated(browser->profile(), app_id);
655
656 break;
657 }
530 default: { 658 default: {
531 NOTREACHED(); // Unexpected notification. 659 NOTREACHED(); // Unexpected notification.
532 break; 660 break;
533 } 661 }
534 } 662 }
535 } 663 }
536 664
537 void ExtensionAppShimHandler::OnAppStart(Profile* profile, 665 void ExtensionAppShimHandler::OnAppStart(Profile* profile,
538 const std::string& app_id) {} 666 const std::string& app_id) {}
539 667
(...skipping 22 matching lines...) Expand all
562 690
563 if (hosts_.empty()) 691 if (hosts_.empty())
564 delegate_->MaybeTerminate(); 692 delegate_->MaybeTerminate();
565 } 693 }
566 694
567 void ExtensionAppShimHandler::OnAppStop(Profile* profile, 695 void ExtensionAppShimHandler::OnAppStop(Profile* profile,
568 const std::string& app_id) {} 696 const std::string& app_id) {}
569 697
570 void ExtensionAppShimHandler::OnChromeTerminating() {} 698 void ExtensionAppShimHandler::OnChromeTerminating() {}
571 699
700 // The BrowserWindow may be NULL when this is called.
701 // Therefore we listen for the notification
702 // chrome::NOTIFICATION_BROWSER_WINDOW_READY and then call OnAppActivited.
jackhou1 2014/12/12 00:48:28 OnAppActivated
mitchellj 2014/12/12 03:46:23 Done.
703 // If this notification is removed, check that OnBrowserAdded is called after
704 // the BrowserWindow is ready.
705 void ExtensionAppShimHandler::OnBrowserAdded(Browser* browser) {
706 }
707
708 void ExtensionAppShimHandler::OnBrowserRemoved(Browser* browser) {
709 if (!browser->is_app())
710 return;
711
712 std::string app_id =
713 web_app::GetExtensionIdFromApplicationName(browser->app_name());
714 const extensions::Extension* extension =
715 GetAppExtension(browser->profile(), app_id);
716 if (!extension)
717 return;
718
719 AppBrowserMap::iterator it = app_browser_windows_.find(app_id);
720 if (it != app_browser_windows_.end()) {
721 BrowserSet& browsers = it->second;
722 browsers.erase(browser);
723 if (browsers.empty())
724 OnAppDeactivated(browser->profile(), app_id);
725 }
726 }
727
572 } // namespace apps 728 } // namespace apps
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698