Commit 2451b25a authored by avi's avatar avi Committed by Commit bot

Make GlobalErrorService's ownership model slightly less insane.

GlobalErrorService ownership was crazy; sometimes the error objects contained were owned, and sometimes they weren't. This separates the two cases into clear statements of ownership, and deprecates the case where the error objects are unowned.

BUG=555865,673578

Review-Url: https://codereview.chromium.org/2409443002
Cr-Commit-Position: refs/heads/master@{#438192}
parent 9c60403f
...@@ -360,13 +360,14 @@ void ExtensionDisabledGlobalError::OnShutdown( ...@@ -360,13 +360,14 @@ void ExtensionDisabledGlobalError::OnShutdown(
} }
void ExtensionDisabledGlobalError::RemoveGlobalError() { void ExtensionDisabledGlobalError::RemoveGlobalError() {
GlobalErrorServiceFactory::GetForProfile(service_->profile()) std::unique_ptr<GlobalError> ptr =
->RemoveGlobalError(this); GlobalErrorServiceFactory::GetForProfile(service_->profile())
->RemoveGlobalError(this);
registrar_.RemoveAll(); registrar_.RemoveAll();
registry_observer_.RemoveAll(); registry_observer_.RemoveAll();
// Delete this object after any running tasks, so that the extension dialog // Delete this object after any running tasks, so that the extension dialog
// still has it as a delegate to finish the current tasks. // still has it as a delegate to finish the current tasks.
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, ptr.release());
} }
// Globals -------------------------------------------------------------------- // Globals --------------------------------------------------------------------
...@@ -382,7 +383,7 @@ void AddExtensionDisabledErrorWithIcon(base::WeakPtr<ExtensionService> service, ...@@ -382,7 +383,7 @@ void AddExtensionDisabledErrorWithIcon(base::WeakPtr<ExtensionService> service,
const Extension* extension = service->GetInstalledExtension(extension_id); const Extension* extension = service->GetInstalledExtension(extension_id);
if (extension) { if (extension) {
GlobalErrorServiceFactory::GetForProfile(service->profile()) GlobalErrorServiceFactory::GetForProfile(service->profile())
->AddGlobalError(new ExtensionDisabledGlobalError( ->AddGlobalError(base::MakeUnique<ExtensionDisabledGlobalError>(
service.get(), extension, is_remote_install, icon)); service.get(), extension, is_remote_install, icon));
} }
} }
......
...@@ -313,7 +313,7 @@ ExternalInstallError::ExternalInstallError( ...@@ -313,7 +313,7 @@ ExternalInstallError::ExternalInstallError(
ExternalInstallError::~ExternalInstallError() { ExternalInstallError::~ExternalInstallError() {
if (global_error_.get()) if (global_error_.get())
error_service_->RemoveGlobalError(global_error_.get()); error_service_->RemoveUnownedGlobalError(global_error_.get());
} }
void ExternalInstallError::OnInstallPromptDone( void ExternalInstallError::OnInstallPromptDone(
...@@ -439,7 +439,7 @@ void ExternalInstallError::OnDialogReady( ...@@ -439,7 +439,7 @@ void ExternalInstallError::OnDialogReady(
if (alert_type_ == BUBBLE_ALERT) { if (alert_type_ == BUBBLE_ALERT) {
global_error_.reset(new ExternalInstallBubbleAlert(this, prompt_.get())); global_error_.reset(new ExternalInstallBubbleAlert(this, prompt_.get()));
error_service_->AddGlobalError(global_error_.get()); error_service_->AddUnownedGlobalError(global_error_.get());
if (!manager_->has_currently_visible_install_alert()) { if (!manager_->has_currently_visible_install_alert()) {
// |browser| is nullptr during unit tests, so call // |browser| is nullptr during unit tests, so call
...@@ -454,7 +454,7 @@ void ExternalInstallError::OnDialogReady( ...@@ -454,7 +454,7 @@ void ExternalInstallError::OnDialogReady(
} else { } else {
DCHECK(alert_type_ == MENU_ALERT); DCHECK(alert_type_ == MENU_ALERT);
global_error_.reset(new ExternalInstallMenuAlert(this)); global_error_.reset(new ExternalInstallMenuAlert(this));
error_service_->AddGlobalError(global_error_.get()); error_service_->AddUnownedGlobalError(global_error_.get());
} }
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <stddef.h> #include <stddef.h>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "chrome/app/chrome_command_ids.h" #include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/extensions/warning_badge_service_factory.h" #include "chrome/browser/extensions/warning_badge_service_factory.h"
...@@ -154,12 +155,10 @@ void WarningBadgeService::ShowBadge(bool show) { ...@@ -154,12 +155,10 @@ void WarningBadgeService::ShowBadge(bool show) {
ErrorBadge::GetMenuItemCommandID()); ErrorBadge::GetMenuItemCommandID());
// Activate or hide the warning badge in case the current state is incorrect. // Activate or hide the warning badge in case the current state is incorrect.
if (error && !show) { if (error && !show)
service->RemoveGlobalError(error); service->RemoveGlobalError(error);
delete error; else if (!error && show)
} else if (!error && show) { service->AddGlobalError(base::MakeUnique<ErrorBadge>(this));
service->AddGlobalError(new ErrorBadge(this));
}
} }
} // namespace extensions } // namespace extensions
...@@ -23,7 +23,8 @@ RecoveryInstallGlobalError::RecoveryInstallGlobalError(Profile* profile) ...@@ -23,7 +23,8 @@ RecoveryInstallGlobalError::RecoveryInstallGlobalError(Profile* profile)
: elevation_needed_(false), : elevation_needed_(false),
profile_(profile), profile_(profile),
has_shown_bubble_view_(false) { has_shown_bubble_view_(false) {
GlobalErrorServiceFactory::GetForProfile(profile_)->AddGlobalError(this); GlobalErrorServiceFactory::GetForProfile(profile_)->AddUnownedGlobalError(
this);
PrefService* pref = g_browser_process->local_state(); PrefService* pref = g_browser_process->local_state();
if (pref->FindPreference(prefs::kRecoveryComponentNeedsElevation)) { if (pref->FindPreference(prefs::kRecoveryComponentNeedsElevation)) {
...@@ -46,7 +47,8 @@ RecoveryInstallGlobalError::~RecoveryInstallGlobalError() { ...@@ -46,7 +47,8 @@ RecoveryInstallGlobalError::~RecoveryInstallGlobalError() {
} }
void RecoveryInstallGlobalError::Shutdown() { void RecoveryInstallGlobalError::Shutdown() {
GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError(this); GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveUnownedGlobalError(
this);
} }
GlobalError::Severity RecoveryInstallGlobalError::GetSeverity() { GlobalError::Severity RecoveryInstallGlobalError::GetSeverity() {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "base/debug/leak_annotations.h" #include "base/debug/leak_annotations.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h" #include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h" #include "base/metrics/sparse_histogram.h"
...@@ -544,7 +545,7 @@ void DisplaySRTPrompt(const base::FilePath& download_path) { ...@@ -544,7 +545,7 @@ void DisplaySRTPrompt(const base::FilePath& download_path) {
// Ownership of |global_error| is passed to the service. The error removes // Ownership of |global_error| is passed to the service. The error removes
// itself from the service and self-destructs when done. // itself from the service and self-destructs when done.
global_error_service->AddGlobalError(global_error); global_error_service->AddGlobalError(base::WrapUnique(global_error));
bool show_bubble = true; bool show_bubble = true;
PrefService* local_state = g_browser_process->local_state(); PrefService* local_state = g_browser_process->local_state();
......
...@@ -221,8 +221,8 @@ void SRTGlobalError::MaybeExecuteSRT() { ...@@ -221,8 +221,8 @@ void SRTGlobalError::MaybeExecuteSRT() {
return; return;
} }
// At this point, this object owns itself, since ownership has been taken back // At this point, this object owns itself, since ownership has been taken back
// from the global_error_service_ in the call to RemoveGlobalError. This means // from the global_error_service_ in the call to OnUserInteractionStarted.
// that it is safe to use base::Unretained here. // This means that it is safe to use base::Unretained here.
BrowserThread::PostBlockingPoolTask( BrowserThread::PostBlockingPoolTask(
FROM_HERE, FROM_HERE,
base::Bind( base::Bind(
...@@ -262,7 +262,7 @@ void SRTGlobalError::OnUserinteractionStarted( ...@@ -262,7 +262,7 @@ void SRTGlobalError::OnUserinteractionStarted(
RecordSRTPromptHistogram(histogram_value); RecordSRTPromptHistogram(histogram_value);
interacted_ = true; interacted_ = true;
if (global_error_service_) { if (global_error_service_) {
global_error_service_->RemoveGlobalError(this); global_error_service_->RemoveGlobalError(this).release();
global_error_service_ = nullptr; global_error_service_ = nullptr;
} }
} }
......
...@@ -30,7 +30,7 @@ SyncGlobalError::SyncGlobalError( ...@@ -30,7 +30,7 @@ SyncGlobalError::SyncGlobalError(
DCHECK(sync_service_); DCHECK(sync_service_);
error_controller_->AddObserver(this); error_controller_->AddObserver(this);
if (!switches::IsMaterialDesignUserMenu()) if (!switches::IsMaterialDesignUserMenu())
global_error_service_->AddGlobalError(this); global_error_service_->AddUnownedGlobalError(this);
} }
SyncGlobalError::~SyncGlobalError() { SyncGlobalError::~SyncGlobalError() {
...@@ -40,7 +40,7 @@ SyncGlobalError::~SyncGlobalError() { ...@@ -40,7 +40,7 @@ SyncGlobalError::~SyncGlobalError() {
void SyncGlobalError::Shutdown() { void SyncGlobalError::Shutdown() {
if (!switches::IsMaterialDesignUserMenu()) if (!switches::IsMaterialDesignUserMenu())
global_error_service_->RemoveGlobalError(this); global_error_service_->RemoveUnownedGlobalError(this);
error_controller_->RemoveObserver(this); error_controller_->RemoveObserver(this);
error_controller_ = nullptr; error_controller_ = nullptr;
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/callback_helpers.h" #include "base/callback_helpers.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
...@@ -484,7 +485,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionButtonUiTest, ...@@ -484,7 +485,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionButtonUiTest,
// up the overflow container's bounds (crbug.com/511326). // up the overflow container's bounds (crbug.com/511326).
GlobalErrorService* error_service = GlobalErrorService* error_service =
GlobalErrorServiceFactory::GetForProfile(profile()); GlobalErrorServiceFactory::GetForProfile(profile());
error_service->AddGlobalError(new MenuError()); error_service->AddGlobalError(base::MakeUnique<MenuError>());
// It's probably excessive to test every level of the overflow here. Test // It's probably excessive to test every level of the overflow here. Test
// having all actions overflowed, some actions overflowed, and one action // having all actions overflowed, some actions overflowed, and one action
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include <algorithm> #include <algorithm>
#include "base/stl_util.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/global_error/global_error.h" #include "chrome/browser/ui/global_error/global_error.h"
...@@ -18,18 +17,32 @@ ...@@ -18,18 +17,32 @@
GlobalErrorService::GlobalErrorService(Profile* profile) : profile_(profile) { GlobalErrorService::GlobalErrorService(Profile* profile) : profile_(profile) {
} }
GlobalErrorService::~GlobalErrorService() { GlobalErrorService::~GlobalErrorService() {}
base::STLDeleteElements(&errors_);
void GlobalErrorService::AddGlobalError(std::unique_ptr<GlobalError> error) {
DCHECK(error);
GlobalError* error_ptr = error.get();
owned_errors_[error_ptr] = std::move(error);
AddUnownedGlobalError(error_ptr);
} }
void GlobalErrorService::AddGlobalError(GlobalError* error) { void GlobalErrorService::AddUnownedGlobalError(GlobalError* error) {
DCHECK(error); DCHECK(error);
errors_.push_back(error); all_errors_.push_back(error);
NotifyErrorsChanged(error); NotifyErrorsChanged(error);
} }
void GlobalErrorService::RemoveGlobalError(GlobalError* error) { std::unique_ptr<GlobalError> GlobalErrorService::RemoveGlobalError(
errors_.erase(std::find(errors_.begin(), errors_.end(), error)); GlobalError* error_ptr) {
std::unique_ptr<GlobalError> ptr = std::move(owned_errors_[error_ptr]);
owned_errors_.erase(error_ptr);
RemoveUnownedGlobalError(error_ptr);
return ptr;
}
void GlobalErrorService::RemoveUnownedGlobalError(GlobalError* error) {
DCHECK(owned_errors_.find(error) == owned_errors_.end());
all_errors_.erase(std::find(all_errors_.begin(), all_errors_.end(), error));
GlobalErrorBubbleViewBase* bubble = error->GetBubbleView(); GlobalErrorBubbleViewBase* bubble = error->GetBubbleView();
if (bubble) if (bubble)
bubble->CloseBubbleView(); bubble->CloseBubbleView();
...@@ -38,23 +51,19 @@ void GlobalErrorService::RemoveGlobalError(GlobalError* error) { ...@@ -38,23 +51,19 @@ void GlobalErrorService::RemoveGlobalError(GlobalError* error) {
GlobalError* GlobalErrorService::GetGlobalErrorByMenuItemCommandID( GlobalError* GlobalErrorService::GetGlobalErrorByMenuItemCommandID(
int command_id) const { int command_id) const {
for (GlobalErrorList::const_iterator for (const auto& error : all_errors_)
it = errors_.begin(); it != errors_.end(); ++it) {
GlobalError* error = *it;
if (error->HasMenuItem() && command_id == error->MenuItemCommandID()) if (error->HasMenuItem() && command_id == error->MenuItemCommandID())
return error; return error;
}
return NULL; return nullptr;
} }
GlobalError* GlobalError*
GlobalErrorService::GetHighestSeverityGlobalErrorWithAppMenuItem() const { GlobalErrorService::GetHighestSeverityGlobalErrorWithAppMenuItem() const {
GlobalError::Severity highest_severity = GlobalError::SEVERITY_LOW; GlobalError::Severity highest_severity = GlobalError::SEVERITY_LOW;
GlobalError* highest_severity_error = NULL; GlobalError* highest_severity_error = nullptr;
for (GlobalErrorList::const_iterator for (const auto& error : all_errors_) {
it = errors_.begin(); it != errors_.end(); ++it) {
GlobalError* error = *it;
if (error->HasMenuItem()) { if (error->HasMenuItem()) {
if (!highest_severity_error || error->GetSeverity() > highest_severity) { if (!highest_severity_error || error->GetSeverity() > highest_severity) {
highest_severity = error->GetSeverity(); highest_severity = error->GetSeverity();
...@@ -67,13 +76,11 @@ GlobalErrorService::GetHighestSeverityGlobalErrorWithAppMenuItem() const { ...@@ -67,13 +76,11 @@ GlobalErrorService::GetHighestSeverityGlobalErrorWithAppMenuItem() const {
} }
GlobalError* GlobalErrorService::GetFirstGlobalErrorWithBubbleView() const { GlobalError* GlobalErrorService::GetFirstGlobalErrorWithBubbleView() const {
for (GlobalErrorList::const_iterator for (const auto& error : all_errors_) {
it = errors_.begin(); it != errors_.end(); ++it) {
GlobalError* error = *it;
if (error->HasBubbleView() && !error->HasShownBubbleView()) if (error->HasBubbleView() && !error->HasShownBubbleView())
return error; return error;
} }
return NULL; return nullptr;
} }
void GlobalErrorService::NotifyErrorsChanged(GlobalError* error) { void GlobalErrorService::NotifyErrorsChanged(GlobalError* error) {
...@@ -81,7 +88,7 @@ void GlobalErrorService::NotifyErrorsChanged(GlobalError* error) { ...@@ -81,7 +88,7 @@ void GlobalErrorService::NotifyErrorsChanged(GlobalError* error) {
// notifications to both it and its off-the-record profile to update // notifications to both it and its off-the-record profile to update
// incognito windows as well. // incognito windows as well.
std::vector<Profile*> profiles_to_notify; std::vector<Profile*> profiles_to_notify;
if (profile_ != NULL) { if (profile_) {
profiles_to_notify.push_back(profile_); profiles_to_notify.push_back(profile_);
if (profile_->IsOffTheRecord()) if (profile_->IsOffTheRecord())
profiles_to_notify.push_back(profile_->GetOriginalProfile()); profiles_to_notify.push_back(profile_->GetOriginalProfile());
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_UI_GLOBAL_ERROR_GLOBAL_ERROR_SERVICE_H_ #ifndef CHROME_BROWSER_UI_GLOBAL_ERROR_GLOBAL_ERROR_SERVICE_H_
#define CHROME_BROWSER_UI_GLOBAL_ERROR_GLOBAL_ERROR_SERVICE_H_ #define CHROME_BROWSER_UI_GLOBAL_ERROR_GLOBAL_ERROR_SERVICE_H_
#include <map>
#include <memory>
#include <vector> #include <vector>
#include "base/macros.h" #include "base/macros.h"
...@@ -21,7 +23,7 @@ class Profile; ...@@ -21,7 +23,7 @@ class Profile;
class GlobalErrorService : public KeyedService { class GlobalErrorService : public KeyedService {
public: public:
// Type used to represent the list of currently active errors. // Type used to represent the list of currently active errors.
typedef std::vector<GlobalError*> GlobalErrorList; using GlobalErrorList = std::vector<GlobalError*>;
// Constructs a GlobalErrorService object for the given profile. The profile // Constructs a GlobalErrorService object for the given profile. The profile
// maybe NULL for tests. // maybe NULL for tests.
...@@ -29,14 +31,24 @@ class GlobalErrorService : public KeyedService { ...@@ -29,14 +31,24 @@ class GlobalErrorService : public KeyedService {
~GlobalErrorService() override; ~GlobalErrorService() override;
// Adds the given error to the list of global errors and displays it on // Adds the given error to the list of global errors and displays it on
// browswer windows. If no browser windows are open then the error is // browser windows. If no browser windows are open then the error is
// displayed once a browser window is opened. This class takes ownership of // displayed once a browser window is opened.
// the error. void AddGlobalError(std::unique_ptr<GlobalError> error);
void AddGlobalError(GlobalError* error);
// Hides the given error and removes it from the list of global errors.
// Hides the given error and removes it from the list of global errors. Caller // Ownership is returned to the caller.
// then takes ownership of the error and is responsible for deleting it. std::unique_ptr<GlobalError> RemoveGlobalError(GlobalError* error);
void RemoveGlobalError(GlobalError* error);
// DEPRECATED; DO NOT USE!
// http://crbug.com/673578
//
// These functions allow adding and removing of a GlobalError that is not
// owned by the GlobalErrorService. In this case, the error's lifetime must
// exceed that of the GlobalErrorService.
//
// Do not add more uses of these functions, and remove existing uses.
void AddUnownedGlobalError(GlobalError* error);
void RemoveUnownedGlobalError(GlobalError* error);
// Gets the error with the given command ID or NULL if no such error exists. // Gets the error with the given command ID or NULL if no such error exists.
// This class maintains ownership of the returned error. // This class maintains ownership of the returned error.
...@@ -51,7 +63,7 @@ class GlobalErrorService : public KeyedService { ...@@ -51,7 +63,7 @@ class GlobalErrorService : public KeyedService {
GlobalError* GetFirstGlobalErrorWithBubbleView() const; GlobalError* GetFirstGlobalErrorWithBubbleView() const;
// Gets all errors. // Gets all errors.
const GlobalErrorList& errors() { return errors_; } const GlobalErrorList& errors() { return all_errors_; }
// Post a notification that a global error has changed and that the error UI // Post a notification that a global error has changed and that the error UI
// should update it self. Pass NULL for the given error to mean all error UIs // should update it self. Pass NULL for the given error to mean all error UIs
...@@ -59,7 +71,8 @@ class GlobalErrorService : public KeyedService { ...@@ -59,7 +71,8 @@ class GlobalErrorService : public KeyedService {
void NotifyErrorsChanged(GlobalError* error); void NotifyErrorsChanged(GlobalError* error);
private: private:
GlobalErrorList errors_; GlobalErrorList all_errors_;
std::map<GlobalError*, std::unique_ptr<GlobalError>> owned_errors_;
Profile* profile_; Profile* profile_;
DISALLOW_COPY_AND_ASSIGN(GlobalErrorService); DISALLOW_COPY_AND_ASSIGN(GlobalErrorService);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/global_error/global_error.h" #include "chrome/browser/ui/global_error/global_error.h"
...@@ -71,7 +72,7 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, ShowBubbleView) { ...@@ -71,7 +72,7 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, ShowBubbleView) {
GlobalErrorService* service = GlobalErrorService* service =
GlobalErrorServiceFactory::GetForProfile(browser()->profile()); GlobalErrorServiceFactory::GetForProfile(browser()->profile());
service->AddGlobalError(error); service->AddGlobalError(base::WrapUnique(error));
EXPECT_EQ(error, service->GetFirstGlobalErrorWithBubbleView()); EXPECT_EQ(error, service->GetFirstGlobalErrorWithBubbleView());
EXPECT_FALSE(error->HasShownBubbleView()); EXPECT_FALSE(error->HasShownBubbleView());
...@@ -92,7 +93,7 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, CloseBubbleView) { ...@@ -92,7 +93,7 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, CloseBubbleView) {
GlobalErrorService* service = GlobalErrorService* service =
GlobalErrorServiceFactory::GetForProfile(browser()->profile()); GlobalErrorServiceFactory::GetForProfile(browser()->profile());
service->AddGlobalError(error); service->AddGlobalError(base::WrapUnique(error));
EXPECT_EQ(error, service->GetFirstGlobalErrorWithBubbleView()); EXPECT_EQ(error, service->GetFirstGlobalErrorWithBubbleView());
EXPECT_FALSE(error->HasShownBubbleView()); EXPECT_FALSE(error->HasShownBubbleView());
...@@ -113,6 +114,10 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, CloseBubbleView) { ...@@ -113,6 +114,10 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, CloseBubbleView) {
// Test that bubble is silently dismissed if it is showing when the GlobalError // Test that bubble is silently dismissed if it is showing when the GlobalError
// instance is removed from the profile. // instance is removed from the profile.
//
// This uses the deprecated "unowned" API to the GlobalErrorService to maintain
// coverage. When those calls are eventually removed (http://crbug.com/673578)
// these uses should be switched to the non-deprecated API.
#if defined(OS_WIN) || defined(OS_LINUX) #if defined(OS_WIN) || defined(OS_LINUX)
// http://crbug.com/396473 // http://crbug.com/396473
#define MAYBE_BubbleViewDismissedOnRemove DISABLED_BubbleViewDismissedOnRemove #define MAYBE_BubbleViewDismissedOnRemove DISABLED_BubbleViewDismissedOnRemove
...@@ -125,7 +130,7 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, ...@@ -125,7 +130,7 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest,
GlobalErrorService* service = GlobalErrorService* service =
GlobalErrorServiceFactory::GetForProfile(browser()->profile()); GlobalErrorServiceFactory::GetForProfile(browser()->profile());
service->AddGlobalError(error.get()); service->AddUnownedGlobalError(error.get());
EXPECT_EQ(error.get(), service->GetFirstGlobalErrorWithBubbleView()); EXPECT_EQ(error.get(), service->GetFirstGlobalErrorWithBubbleView());
error->ShowBubbleView(browser()); error->ShowBubbleView(browser());
...@@ -135,8 +140,7 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, ...@@ -135,8 +140,7 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest,
// Removing |error| from profile should dismiss the bubble view without // Removing |error| from profile should dismiss the bubble view without
// calling |error->BubbleViewDidClose|. // calling |error->BubbleViewDidClose|.
service->RemoveGlobalError(error.get()); service->RemoveUnownedGlobalError(error.get());
content::RunAllPendingInMessageLoop(); content::RunAllPendingInMessageLoop();
EXPECT_EQ(1, error->bubble_view_close_count()); EXPECT_EQ(1, error->bubble_view_close_count());
// |error| is no longer owned by service and will be deleted.
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/ui/global_error/global_error.h" #include "chrome/browser/ui/global_error/global_error.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -76,12 +77,12 @@ TEST(GlobalErrorServiceTest, AddError) { ...@@ -76,12 +77,12 @@ TEST(GlobalErrorServiceTest, AddError) {
EXPECT_EQ(0u, service->errors().size()); EXPECT_EQ(0u, service->errors().size());
BaseError* error1 = new BaseError; BaseError* error1 = new BaseError;
service->AddGlobalError(error1); service->AddGlobalError(base::WrapUnique(error1));
EXPECT_EQ(1u, service->errors().size()); EXPECT_EQ(1u, service->errors().size());
EXPECT_EQ(error1, service->errors()[0]); EXPECT_EQ(error1, service->errors()[0]);
BaseError* error2 = new BaseError; BaseError* error2 = new BaseError;
service->AddGlobalError(error2); service->AddGlobalError(base::WrapUnique(error2));
EXPECT_EQ(2u, service->errors().size()); EXPECT_EQ(2u, service->errors().size());
EXPECT_EQ(error1, service->errors()[0]); EXPECT_EQ(error1, service->errors()[0]);
EXPECT_EQ(error2, service->errors()[1]); EXPECT_EQ(error2, service->errors()[1]);
...@@ -96,18 +97,22 @@ TEST(GlobalErrorServiceTest, AddError) { ...@@ -96,18 +97,22 @@ TEST(GlobalErrorServiceTest, AddError) {
TEST(GlobalErrorServiceTest, RemoveError) { TEST(GlobalErrorServiceTest, RemoveError) {
std::unique_ptr<GlobalErrorService> service(new GlobalErrorService(NULL)); std::unique_ptr<GlobalErrorService> service(new GlobalErrorService(NULL));
BaseError error1; BaseError error1;
service->AddGlobalError(&error1); service->AddUnownedGlobalError(&error1);
BaseError error2; BaseError error2;
service->AddGlobalError(&error2); service->AddUnownedGlobalError(&error2);
EXPECT_EQ(2u, service->errors().size()); EXPECT_EQ(2u, service->errors().size());
service->RemoveGlobalError(&error1); service->RemoveUnownedGlobalError(&error1);
EXPECT_EQ(1u, service->errors().size()); EXPECT_EQ(1u, service->errors().size());
EXPECT_EQ(&error2, service->errors()[0]); EXPECT_EQ(&error2, service->errors()[0]);
service->RemoveGlobalError(&error2); service->RemoveUnownedGlobalError(&error2);
EXPECT_EQ(0u, service->errors().size()); EXPECT_EQ(0u, service->errors().size());
// Ensure that deleting the service does not delete the error objects. // Ensure that deleting the service does not delete the error objects.
//
// NB: If the service _does_ delete the error objects, then it called the
// delete operator on a stack-allocated object, which is undefined behavior,
// which we can't really use to prove anything. :(
EXPECT_EQ(2, BaseError::count()); EXPECT_EQ(2, BaseError::count());
service.reset(); service.reset();
EXPECT_EQ(2, BaseError::count()); EXPECT_EQ(2, BaseError::count());
...@@ -120,16 +125,16 @@ TEST(GlobalErrorServiceTest, GetMenuItem) { ...@@ -120,16 +125,16 @@ TEST(GlobalErrorServiceTest, GetMenuItem) {
MenuError* error3 = new MenuError(3, GlobalError::SEVERITY_HIGH); MenuError* error3 = new MenuError(3, GlobalError::SEVERITY_HIGH);
GlobalErrorService service(NULL); GlobalErrorService service(NULL);
service.AddGlobalError(error1); service.AddGlobalError(base::WrapUnique(error1));
service.AddGlobalError(error2); service.AddGlobalError(base::WrapUnique(error2));
service.AddGlobalError(error3); service.AddGlobalError(base::WrapUnique(error3));
EXPECT_EQ(error2, service.GetGlobalErrorByMenuItemCommandID(2)); EXPECT_EQ(error2, service.GetGlobalErrorByMenuItemCommandID(2));
EXPECT_EQ(error3, service.GetGlobalErrorByMenuItemCommandID(3)); EXPECT_EQ(error3, service.GetGlobalErrorByMenuItemCommandID(3));
EXPECT_EQ(NULL, service.GetGlobalErrorByMenuItemCommandID(4)); EXPECT_EQ(NULL, service.GetGlobalErrorByMenuItemCommandID(4));
} }
// Test getting the error with the higest severity. // Test getting the error with the highest severity.
TEST(GlobalErrorServiceTest, HighestSeverity) { TEST(GlobalErrorServiceTest, HighestSeverity) {
MenuError* error1 = new MenuError(1, GlobalError::SEVERITY_LOW); MenuError* error1 = new MenuError(1, GlobalError::SEVERITY_LOW);
MenuError* error2 = new MenuError(2, GlobalError::SEVERITY_MEDIUM); MenuError* error2 = new MenuError(2, GlobalError::SEVERITY_MEDIUM);
...@@ -138,18 +143,17 @@ TEST(GlobalErrorServiceTest, HighestSeverity) { ...@@ -138,18 +143,17 @@ TEST(GlobalErrorServiceTest, HighestSeverity) {
GlobalErrorService service(NULL); GlobalErrorService service(NULL);
EXPECT_EQ(NULL, service.GetHighestSeverityGlobalErrorWithAppMenuItem()); EXPECT_EQ(NULL, service.GetHighestSeverityGlobalErrorWithAppMenuItem());
service.AddGlobalError(error1); service.AddGlobalError(base::WrapUnique(error1));
EXPECT_EQ(error1, service.GetHighestSeverityGlobalErrorWithAppMenuItem()); EXPECT_EQ(error1, service.GetHighestSeverityGlobalErrorWithAppMenuItem());
service.AddGlobalError(error2); service.AddGlobalError(base::WrapUnique(error2));
EXPECT_EQ(error2, service.GetHighestSeverityGlobalErrorWithAppMenuItem()); EXPECT_EQ(error2, service.GetHighestSeverityGlobalErrorWithAppMenuItem());
service.AddGlobalError(error3); service.AddGlobalError(base::WrapUnique(error3));
EXPECT_EQ(error3, service.GetHighestSeverityGlobalErrorWithAppMenuItem()); EXPECT_EQ(error3, service.GetHighestSeverityGlobalErrorWithAppMenuItem());
// Remove the highest-severity error. // Remove the highest-severity error.
service.RemoveGlobalError(error3); service.RemoveGlobalError(error3);
delete error3;
// Now error2 should be the next highest severity error. // Now error2 should be the next highest severity error.
EXPECT_EQ(error2, service.GetHighestSeverityGlobalErrorWithAppMenuItem()); EXPECT_EQ(error2, service.GetHighestSeverityGlobalErrorWithAppMenuItem());
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chrome/browser/ui/toolbar/app_menu_model.h" #include "chrome/browser/ui/toolbar/app_menu_model.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "chrome/app/chrome_command_ids.h" #include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/defaults.h" #include "chrome/browser/defaults.h"
#include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/prefs/browser_prefs.h"
...@@ -179,13 +180,11 @@ TEST_F(AppMenuModelTest, GlobalError) { ...@@ -179,13 +180,11 @@ TEST_F(AppMenuModelTest, GlobalError) {
GlobalErrorServiceFactory::GetForProfile(browser()->profile()); GlobalErrorServiceFactory::GetForProfile(browser()->profile());
ProfileOAuth2TokenServiceFactory::GetForProfile(browser()->profile()); ProfileOAuth2TokenServiceFactory::GetForProfile(browser()->profile());
const int command1 = 1234567; const int command1 = 1234567;
// AddGlobalError takes ownership of error1.
MenuError* error1 = new MenuError(command1); MenuError* error1 = new MenuError(command1);
service->AddGlobalError(error1); service->AddGlobalError(base::WrapUnique(error1));
const int command2 = 1234568; const int command2 = 1234568;
// AddGlobalError takes ownership of error2.
MenuError* error2 = new MenuError(command2); MenuError* error2 = new MenuError(command2);
service->AddGlobalError(error2); service->AddGlobalError(base::WrapUnique(error2));
AppMenuModel model(this, browser()); AppMenuModel model(this, browser());
int index1 = model.GetIndexOfCommandId(command1); int index1 = model.GetIndexOfCommandId(command1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment