Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <algorithm> | 5 #include <algorithm> |
| 6 #include <string> | 6 #include <string> |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/base_paths.h" | 9 #include "base/base_paths.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 #include "chrome/browser/extensions/extension_system.h" | 23 #include "chrome/browser/extensions/extension_system.h" |
| 24 #include "chrome/browser/lifetime/application_lifetime.h" | 24 #include "chrome/browser/lifetime/application_lifetime.h" |
| 25 #include "chrome/browser/profiles/profile.h" | 25 #include "chrome/browser/profiles/profile.h" |
| 26 #include "chrome/browser/profiles/profile_info_cache.h" | 26 #include "chrome/browser/profiles/profile_info_cache.h" |
| 27 #include "chrome/browser/profiles/profile_manager.h" | 27 #include "chrome/browser/profiles/profile_manager.h" |
| 28 #include "chrome/browser/status_icons/status_icon.h" | 28 #include "chrome/browser/status_icons/status_icon.h" |
| 29 #include "chrome/browser/status_icons/status_tray.h" | 29 #include "chrome/browser/status_icons/status_tray.h" |
| 30 #include "chrome/browser/ui/browser.h" | 30 #include "chrome/browser/ui/browser.h" |
| 31 #include "chrome/browser/ui/browser_commands.h" | 31 #include "chrome/browser/ui/browser_commands.h" |
| 32 #include "chrome/browser/ui/browser_finder.h" | 32 #include "chrome/browser/ui/browser_finder.h" |
| 33 #include "chrome/browser/ui/browser_list.h" | |
| 33 #include "chrome/browser/ui/chrome_pages.h" | 34 #include "chrome/browser/ui/chrome_pages.h" |
| 34 #include "chrome/browser/ui/extensions/application_launch.h" | 35 #include "chrome/browser/ui/extensions/application_launch.h" |
| 35 #include "chrome/browser/ui/host_desktop.h" | 36 #include "chrome/browser/ui/host_desktop.h" |
| 36 #include "chrome/common/chrome_constants.h" | 37 #include "chrome/common/chrome_constants.h" |
| 37 #include "chrome/common/chrome_switches.h" | 38 #include "chrome/common/chrome_switches.h" |
| 38 #include "chrome/common/extensions/extension.h" | 39 #include "chrome/common/extensions/extension.h" |
| 39 #include "chrome/common/extensions/extension_constants.h" | 40 #include "chrome/common/extensions/extension_constants.h" |
| 40 #include "chrome/common/extensions/permissions/permission_set.h" | 41 #include "chrome/common/extensions/permissions/permission_set.h" |
| 41 #include "chrome/common/pref_names.h" | 42 #include "chrome/common/pref_names.h" |
| 42 #include "content/public/browser/notification_service.h" | 43 #include "content/public/browser/notification_service.h" |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 141 BackgroundModeManager::BackgroundModeManager( | 142 BackgroundModeManager::BackgroundModeManager( |
| 142 CommandLine* command_line, | 143 CommandLine* command_line, |
| 143 ProfileInfoCache* profile_cache) | 144 ProfileInfoCache* profile_cache) |
| 144 : profile_cache_(profile_cache), | 145 : profile_cache_(profile_cache), |
| 145 status_tray_(NULL), | 146 status_tray_(NULL), |
| 146 status_icon_(NULL), | 147 status_icon_(NULL), |
| 147 context_menu_(NULL), | 148 context_menu_(NULL), |
| 148 in_background_mode_(false), | 149 in_background_mode_(false), |
| 149 keep_alive_for_startup_(false), | 150 keep_alive_for_startup_(false), |
| 150 keep_alive_for_test_(false), | 151 keep_alive_for_test_(false), |
| 152 background_mode_suspended_(false), | |
| 153 keeping_alive_(false), | |
| 151 current_command_id_(0) { | 154 current_command_id_(0) { |
| 152 // We should never start up if there is no browser process or if we are | 155 // We should never start up if there is no browser process or if we are |
| 153 // currently quitting. | 156 // currently quitting. |
| 154 CHECK(g_browser_process != NULL); | 157 CHECK(g_browser_process != NULL); |
| 155 CHECK(!browser_shutdown::IsTryingToQuit()); | 158 CHECK(!browser_shutdown::IsTryingToQuit()); |
| 156 | 159 |
| 157 // Add self as an observer for the profile info cache so we know when profiles | 160 // Add self as an observer for the profile info cache so we know when profiles |
| 158 // are deleted and their names change. | 161 // are deleted and their names change. |
| 159 profile_cache_->AddObserver(this); | 162 profile_cache_->AddObserver(this); |
| 160 | 163 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 174 if (command_line->HasSwitch(switches::kNoStartupWindow)) { | 177 if (command_line->HasSwitch(switches::kNoStartupWindow)) { |
| 175 keep_alive_for_startup_ = true; | 178 keep_alive_for_startup_ = true; |
| 176 chrome::StartKeepAlive(); | 179 chrome::StartKeepAlive(); |
| 177 } | 180 } |
| 178 | 181 |
| 179 // If the -keep-alive-for-test flag is passed, then always keep chrome running | 182 // If the -keep-alive-for-test flag is passed, then always keep chrome running |
| 180 // in the background until the user explicitly terminates it. | 183 // in the background until the user explicitly terminates it. |
| 181 if (command_line->HasSwitch(switches::kKeepAliveForTest)) | 184 if (command_line->HasSwitch(switches::kKeepAliveForTest)) |
| 182 keep_alive_for_test_ = true; | 185 keep_alive_for_test_ = true; |
| 183 | 186 |
| 187 // If the --app-id or the --show-app-list flag is passed, then start with | |
| 188 // background mode suspended. It will be resumed when the first browser window | |
| 189 // is opened. | |
| 190 if (command_line->HasSwitch(switches::kAppId) || | |
| 191 command_line->HasSwitch(switches::kShowAppList)) { | |
| 192 SuspendBackgroundMode(); | |
|
benwells
2013/10/21 05:57:22
Relying on these two flags feels fragile. E.g. --l
Sam McNally
2013/10/21 06:45:35
Done.
| |
| 193 } | |
| 194 | |
| 184 if (ShouldBeInBackgroundMode()) | 195 if (ShouldBeInBackgroundMode()) |
| 185 StartBackgroundMode(); | 196 StartBackgroundMode(); |
| 186 | 197 |
| 187 // Listen for the application shutting down so we can decrement our KeepAlive | 198 // Listen for the application shutting down so we can decrement our KeepAlive |
| 188 // count. | 199 // count. |
| 189 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, | 200 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, |
| 190 content::NotificationService::AllSources()); | 201 content::NotificationService::AllSources()); |
| 202 BrowserList::AddObserver(this); | |
| 191 } | 203 } |
| 192 | 204 |
| 193 BackgroundModeManager::~BackgroundModeManager() { | 205 BackgroundModeManager::~BackgroundModeManager() { |
| 194 // Remove ourselves from the application observer list (only needed by unit | 206 // Remove ourselves from the application observer list (only needed by unit |
| 195 // tests since APP_TERMINATING is what does this in a real running system). | 207 // tests since APP_TERMINATING is what does this in a real running system). |
| 196 for (BackgroundModeInfoMap::iterator it = | 208 for (BackgroundModeInfoMap::iterator it = |
| 197 background_mode_data_.begin(); | 209 background_mode_data_.begin(); |
| 198 it != background_mode_data_.end(); | 210 it != background_mode_data_.end(); |
| 199 ++it) { | 211 ++it) { |
| 200 it->second->applications_->RemoveObserver(this); | 212 it->second->applications_->RemoveObserver(this); |
| 201 } | 213 } |
| 214 BrowserList::RemoveObserver(this); | |
| 202 | 215 |
| 203 // We're going away, so exit background mode (does nothing if we aren't in | 216 // We're going away, so exit background mode (does nothing if we aren't in |
| 204 // background mode currently). This is primarily needed for unit tests, | 217 // background mode currently). This is primarily needed for unit tests, |
| 205 // because in an actual running system we'd get an APP_TERMINATING | 218 // because in an actual running system we'd get an APP_TERMINATING |
| 206 // notification before being destroyed. | 219 // notification before being destroyed. |
| 207 EndBackgroundMode(); | 220 EndBackgroundMode(); |
| 208 } | 221 } |
| 209 | 222 |
| 210 // static | 223 // static |
| 211 void BackgroundModeManager::RegisterPrefs(PrefRegistrySimple* registry) { | 224 void BackgroundModeManager::RegisterPrefs(PrefRegistrySimple* registry) { |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 450 BackgroundModeData* bmd = background_mode_data_.begin()->second.get(); | 463 BackgroundModeData* bmd = background_mode_data_.begin()->second.get(); |
| 451 switch (command_id) { | 464 switch (command_id) { |
| 452 case IDC_ABOUT: | 465 case IDC_ABOUT: |
| 453 chrome::ShowAboutChrome(bmd->GetBrowserWindow()); | 466 chrome::ShowAboutChrome(bmd->GetBrowserWindow()); |
| 454 break; | 467 break; |
| 455 case IDC_TASK_MANAGER: | 468 case IDC_TASK_MANAGER: |
| 456 chrome::OpenTaskManager(bmd->GetBrowserWindow()); | 469 chrome::OpenTaskManager(bmd->GetBrowserWindow()); |
| 457 break; | 470 break; |
| 458 case IDC_EXIT: | 471 case IDC_EXIT: |
| 459 content::RecordAction(UserMetricsAction("Exit")); | 472 content::RecordAction(UserMetricsAction("Exit")); |
| 460 chrome::AttemptExit(); | 473 chrome::CloseAllBrowsers(); |
| 461 break; | 474 break; |
| 462 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: { | 475 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: { |
| 463 // Background mode must already be enabled (as otherwise this menu would | 476 // Background mode must already be enabled (as otherwise this menu would |
| 464 // not be visible). | 477 // not be visible). |
| 465 DCHECK(IsBackgroundModePrefEnabled()); | 478 DCHECK(IsBackgroundModePrefEnabled()); |
| 466 DCHECK(chrome::WillKeepAlive()); | 479 DCHECK(chrome::WillKeepAlive()); |
| 467 | 480 |
| 468 // Set the background mode pref to "disabled" - the resulting notification | 481 // Set the background mode pref to "disabled" - the resulting notification |
| 469 // will result in a call to DisableBackgroundMode(). | 482 // will result in a call to DisableBackgroundMode(). |
| 470 PrefService* service = g_browser_process->local_state(); | 483 PrefService* service = g_browser_process->local_state(); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 495 void BackgroundModeManager::StartBackgroundMode() { | 508 void BackgroundModeManager::StartBackgroundMode() { |
| 496 DCHECK(ShouldBeInBackgroundMode()); | 509 DCHECK(ShouldBeInBackgroundMode()); |
| 497 // Don't bother putting ourselves in background mode if we're already there | 510 // Don't bother putting ourselves in background mode if we're already there |
| 498 // or if background mode is disabled. | 511 // or if background mode is disabled. |
| 499 if (in_background_mode_) | 512 if (in_background_mode_) |
| 500 return; | 513 return; |
| 501 | 514 |
| 502 // Mark ourselves as running in background mode. | 515 // Mark ourselves as running in background mode. |
| 503 in_background_mode_ = true; | 516 in_background_mode_ = true; |
| 504 | 517 |
| 505 // Put ourselves in KeepAlive mode and create a status tray icon. | 518 UpdateKeepAliveAndTrayIcon(); |
| 506 chrome::StartKeepAlive(); | |
| 507 | |
| 508 // Display a status icon to exit Chrome. | |
| 509 InitStatusTrayIcon(); | |
| 510 | 519 |
| 511 content::NotificationService::current()->Notify( | 520 content::NotificationService::current()->Notify( |
| 512 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED, | 521 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED, |
| 513 content::Source<BackgroundModeManager>(this), | 522 content::Source<BackgroundModeManager>(this), |
| 514 content::Details<bool>(&in_background_mode_)); | 523 content::Details<bool>(&in_background_mode_)); |
| 515 } | 524 } |
| 516 | 525 |
| 517 void BackgroundModeManager::InitStatusTrayIcon() { | |
| 518 // Only initialize status tray icons for those profiles which actually | |
| 519 // have a background app running. | |
| 520 if (ShouldBeInBackgroundMode()) | |
| 521 CreateStatusTrayIcon(); | |
| 522 } | |
| 523 | |
| 524 void BackgroundModeManager::EndBackgroundMode() { | 526 void BackgroundModeManager::EndBackgroundMode() { |
| 525 if (!in_background_mode_) | 527 if (!in_background_mode_) |
| 526 return; | 528 return; |
| 527 in_background_mode_ = false; | 529 in_background_mode_ = false; |
| 528 | 530 |
| 529 // End KeepAlive mode and blow away our status tray icon. | 531 UpdateKeepAliveAndTrayIcon(); |
| 530 chrome::EndKeepAlive(); | |
| 531 | 532 |
| 532 RemoveStatusTrayIcon(); | |
| 533 content::NotificationService::current()->Notify( | 533 content::NotificationService::current()->Notify( |
| 534 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED, | 534 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED, |
| 535 content::Source<BackgroundModeManager>(this), | 535 content::Source<BackgroundModeManager>(this), |
| 536 content::Details<bool>(&in_background_mode_)); | 536 content::Details<bool>(&in_background_mode_)); |
| 537 } | 537 } |
| 538 | 538 |
| 539 void BackgroundModeManager::EnableBackgroundMode() { | 539 void BackgroundModeManager::EnableBackgroundMode() { |
| 540 DCHECK(IsBackgroundModePrefEnabled()); | 540 DCHECK(IsBackgroundModePrefEnabled()); |
| 541 // If background mode should be enabled, but isn't, turn it on. | 541 // If background mode should be enabled, but isn't, turn it on. |
| 542 if (!in_background_mode_ && ShouldBeInBackgroundMode()) { | 542 if (!in_background_mode_ && ShouldBeInBackgroundMode()) { |
| 543 StartBackgroundMode(); | 543 StartBackgroundMode(); |
| 544 EnableLaunchOnStartup(true); | 544 EnableLaunchOnStartup(true); |
| 545 } | 545 } |
| 546 } | 546 } |
| 547 | 547 |
| 548 void BackgroundModeManager::DisableBackgroundMode() { | 548 void BackgroundModeManager::DisableBackgroundMode() { |
| 549 DCHECK(!IsBackgroundModePrefEnabled()); | 549 DCHECK(!IsBackgroundModePrefEnabled()); |
| 550 // If background mode is currently enabled, turn it off. | 550 // If background mode is currently enabled, turn it off. |
| 551 if (in_background_mode_) { | 551 if (in_background_mode_) { |
| 552 EndBackgroundMode(); | 552 EndBackgroundMode(); |
| 553 EnableLaunchOnStartup(false); | 553 EnableLaunchOnStartup(false); |
| 554 } | 554 } |
| 555 } | 555 } |
| 556 | 556 |
| 557 void BackgroundModeManager::SuspendBackgroundMode() { | |
| 558 background_mode_suspended_ = true; | |
| 559 UpdateKeepAliveAndTrayIcon(); | |
| 560 } | |
| 561 | |
| 562 void BackgroundModeManager::ResumeBackgroundMode() { | |
| 563 background_mode_suspended_ = false; | |
| 564 UpdateKeepAliveAndTrayIcon(); | |
| 565 } | |
| 566 | |
| 567 void BackgroundModeManager::UpdateKeepAliveAndTrayIcon() { | |
| 568 if (in_background_mode_ && !background_mode_suspended_) { | |
| 569 if (!keeping_alive_) { | |
| 570 keeping_alive_ = true; | |
| 571 chrome::StartKeepAlive(); | |
| 572 } | |
| 573 CreateStatusTrayIcon(); | |
|
benwells
2013/10/21 05:57:22
Nit: early return instead of else.
Sam McNally
2013/10/21 06:45:35
Done.
| |
| 574 } else { | |
| 575 RemoveStatusTrayIcon(); | |
| 576 if (keeping_alive_) { | |
| 577 keeping_alive_ = false; | |
| 578 chrome::EndKeepAlive(); | |
| 579 } | |
| 580 } | |
| 581 } | |
| 582 | |
| 583 void BackgroundModeManager::OnBrowserAdded(Browser* browser) { | |
| 584 ResumeBackgroundMode(); | |
| 585 } | |
| 586 | |
| 557 int BackgroundModeManager::GetBackgroundAppCount() const { | 587 int BackgroundModeManager::GetBackgroundAppCount() const { |
| 558 int count = 0; | 588 int count = 0; |
| 559 // Walk the BackgroundModeData for all profiles and count the number of apps. | 589 // Walk the BackgroundModeData for all profiles and count the number of apps. |
| 560 for (BackgroundModeInfoMap::const_iterator it = | 590 for (BackgroundModeInfoMap::const_iterator it = |
| 561 background_mode_data_.begin(); | 591 background_mode_data_.begin(); |
| 562 it != background_mode_data_.end(); | 592 it != background_mode_data_.end(); |
| 563 ++it) { | 593 ++it) { |
| 564 count += it->second->GetBackgroundAppCount(); | 594 count += it->second->GetBackgroundAppCount(); |
| 565 } | 595 } |
| 566 DCHECK(count >= 0); | 596 DCHECK(count >= 0); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 577 return IsBackgroundModePrefEnabled() && | 607 return IsBackgroundModePrefEnabled() && |
| 578 (GetBackgroundAppCount() > 0 || keep_alive_for_test_); | 608 (GetBackgroundAppCount() > 0 || keep_alive_for_test_); |
| 579 } | 609 } |
| 580 | 610 |
| 581 void BackgroundModeManager::OnBackgroundAppInstalled( | 611 void BackgroundModeManager::OnBackgroundAppInstalled( |
| 582 const Extension* extension) { | 612 const Extension* extension) { |
| 583 // Background mode is disabled - don't do anything. | 613 // Background mode is disabled - don't do anything. |
| 584 if (!IsBackgroundModePrefEnabled()) | 614 if (!IsBackgroundModePrefEnabled()) |
| 585 return; | 615 return; |
| 586 | 616 |
| 587 // Check if we need a status tray icon and make one if we do (needed so we | 617 // Ensure we have a tray icon if appropriate (needed so we can display the |
| 588 // can display the app-installed notification below). | 618 // app-installed notification below). |
| 589 CreateStatusTrayIcon(); | 619 UpdateKeepAliveAndTrayIcon(); |
| 620 | |
| 621 // If we don't have a status icon or one could not be created succesfully, | |
| 622 // then we won't notify the user. | |
| 623 if (!status_icon_) | |
| 624 return; | |
| 590 | 625 |
| 591 // Notify the user that a background app has been installed. | 626 // Notify the user that a background app has been installed. |
| 592 if (extension) { // NULL when called by unit tests. | 627 if (extension) { // NULL when called by unit tests. |
| 593 DisplayAppInstalledNotification(extension); | 628 DisplayAppInstalledNotification(extension); |
| 594 } | 629 } |
| 595 } | 630 } |
| 596 | 631 |
| 597 void BackgroundModeManager::CheckReloadStatus( | 632 void BackgroundModeManager::CheckReloadStatus( |
| 598 const Extension* extension, | 633 const Extension* extension, |
| 599 bool* is_being_reloaded) { | 634 bool* is_being_reloaded) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 636 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); | 671 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); |
| 637 if (!status_icon_) | 672 if (!status_icon_) |
| 638 return; | 673 return; |
| 639 UpdateStatusTrayIconContextMenu(); | 674 UpdateStatusTrayIconContextMenu(); |
| 640 } | 675 } |
| 641 | 676 |
| 642 void BackgroundModeManager::UpdateStatusTrayIconContextMenu() { | 677 void BackgroundModeManager::UpdateStatusTrayIconContextMenu() { |
| 643 // If no status icon exists, it's either because one wasn't created when | 678 // If no status icon exists, it's either because one wasn't created when |
| 644 // it should have been which can happen when extensions load after the | 679 // it should have been which can happen when extensions load after the |
| 645 // profile has already been registered with the background mode manager. | 680 // profile has already been registered with the background mode manager. |
| 646 if (in_background_mode_ && !status_icon_) | 681 UpdateKeepAliveAndTrayIcon(); |
|
benwells
2013/10/21 05:57:22
This only happened before if !status_icon, and the
Sam McNally
2013/10/21 06:45:35
Done.
| |
| 647 CreateStatusTrayIcon(); | |
| 648 | 682 |
| 649 // If we don't have a status icon or one could not be created succesfully, | 683 // If we don't have a status icon or one could not be created succesfully, |
| 650 // then no need to continue the update. | 684 // then no need to continue the update. |
| 651 if (!status_icon_) | 685 if (!status_icon_) |
| 652 return; | 686 return; |
| 653 | 687 |
| 654 // We should only get here if we have a profile loaded, or if we're running | 688 // We should only get here if we have a profile loaded, or if we're running |
| 655 // in test mode. | 689 // in test mode. |
| 656 if (background_mode_data_.empty()) { | 690 if (background_mode_data_.empty()) { |
| 657 DCHECK(keep_alive_for_test_); | 691 DCHECK(keep_alive_for_test_); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 749 } | 783 } |
| 750 } | 784 } |
| 751 return profile_it; | 785 return profile_it; |
| 752 } | 786 } |
| 753 | 787 |
| 754 bool BackgroundModeManager::IsBackgroundModePrefEnabled() const { | 788 bool BackgroundModeManager::IsBackgroundModePrefEnabled() const { |
| 755 PrefService* service = g_browser_process->local_state(); | 789 PrefService* service = g_browser_process->local_state(); |
| 756 DCHECK(service); | 790 DCHECK(service); |
| 757 return service->GetBoolean(prefs::kBackgroundModeEnabled); | 791 return service->GetBoolean(prefs::kBackgroundModeEnabled); |
| 758 } | 792 } |
| OLD | NEW |