diff options
author | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-25 04:25:45 +0000 |
---|---|---|
committer | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-25 04:25:45 +0000 |
commit | c6b207c6c4290a06000fabd9b09a96614d3ae118 (patch) | |
tree | 6c3f284de26c7a88415bba43f465e32282700d01 | |
parent | 02eb89fb03a303cb2b745063e6d852feb3bc5c5e (diff) | |
download | chromium_src-c6b207c6c4290a06000fabd9b09a96614d3ae118.zip chromium_src-c6b207c6c4290a06000fabd9b09a96614d3ae118.tar.gz chromium_src-c6b207c6c4290a06000fabd9b09a96614d3ae118.tar.bz2 |
Cocoa: Close bubble if its GlobalError object is removed
This is the Cocoa version of this change:
https://chromiumcodereview.appspot.com/9190009
BUG=109728
TEST=
Review URL: http://codereview.chromium.org/9254019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118994 0039d316-1c4b-4281-b951-d872f2087c98
35 files changed, 385 insertions, 307 deletions
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc index eb93b6c..e1e8e46 100644 --- a/chrome/browser/automation/testing_automation_provider.cc +++ b/chrome/browser/automation/testing_automation_provider.cc @@ -3440,9 +3440,9 @@ void TestingAutomationProvider::PerformProtectorAction( return; } if (action == "apply_change") - protector_service->ApplyChange(); + protector_service->ApplyChange(browser); else if (action == "discard_change") - protector_service->DiscardChange(); + protector_service->DiscardChange(browser); else return reply.SendError("Invalid 'action' value"); reply.SendSuccess(NULL); diff --git a/chrome/browser/extensions/extension_global_error.cc b/chrome/browser/extensions/extension_global_error.cc index f499317..dfcb016 100644 --- a/chrome/browser/extensions/extension_global_error.cc +++ b/chrome/browser/extensions/extension_global_error.cc @@ -15,8 +15,7 @@ ExtensionGlobalError::ExtensionGlobalError( base::WeakPtr<ExtensionService> extension_service) - : current_browser_(NULL), - should_delete_self_on_close_(true), + : should_delete_self_on_close_(true), extension_service_(extension_service), external_extension_ids_(new ExtensionIdSet), blacklisted_extension_ids_(new ExtensionIdSet), @@ -79,11 +78,6 @@ bool ExtensionGlobalError::HasBubbleView() { return true; } -void ExtensionGlobalError::ShowBubbleView(Browser* browser) { - current_browser_ = browser; - GlobalError::ShowBubbleView(browser); -} - string16 ExtensionGlobalError::GetBubbleViewTitle() { return l10n_util::GetStringUTF16(IDS_EXTENSION_ALERT_TITLE); } @@ -133,23 +127,23 @@ string16 ExtensionGlobalError::GetBubbleViewCancelButtonLabel() { return l10n_util::GetStringUTF16(IDS_EXTENSION_ALERT_ITEM_DETAILS); } -void ExtensionGlobalError::BubbleViewDidClose() { +void ExtensionGlobalError::OnBubbleViewDidClose(Browser* browser) { if (!closed_callback_.is_null()) { - closed_callback_.Run(*this, current_browser_); + closed_callback_.Run(*this, browser); } if (should_delete_self_on_close_) { delete this; } } -void ExtensionGlobalError::BubbleViewAcceptButtonPressed() { +void ExtensionGlobalError::BubbleViewAcceptButtonPressed(Browser* browser) { if (!accept_callback_.is_null()) { - accept_callback_.Run(*this, current_browser_); + accept_callback_.Run(*this, browser); } } -void ExtensionGlobalError::BubbleViewCancelButtonPressed() { +void ExtensionGlobalError::BubbleViewCancelButtonPressed(Browser* browser) { if (!cancel_callback_.is_null()) { - cancel_callback_.Run(*this, current_browser_); + cancel_callback_.Run(*this, browser); } } diff --git a/chrome/browser/extensions/extension_global_error.h b/chrome/browser/extensions/extension_global_error.h index 7730125..6d8423f 100644 --- a/chrome/browser/extensions/extension_global_error.h +++ b/chrome/browser/extensions/extension_global_error.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -81,17 +81,15 @@ class ExtensionGlobalError : public GlobalError { virtual string16 MenuItemLabel() OVERRIDE; virtual void ExecuteMenuItem(Browser* browser) OVERRIDE; virtual bool HasBubbleView() OVERRIDE; - virtual void ShowBubbleView(Browser* browser) OVERRIDE; virtual string16 GetBubbleViewTitle() OVERRIDE; virtual string16 GetBubbleViewMessage() OVERRIDE; virtual string16 GetBubbleViewAcceptButtonLabel() OVERRIDE; virtual string16 GetBubbleViewCancelButtonLabel() OVERRIDE; - virtual void BubbleViewDidClose() OVERRIDE; - virtual void BubbleViewAcceptButtonPressed() OVERRIDE; - virtual void BubbleViewCancelButtonPressed() OVERRIDE; + virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE; + virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE; + virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE; private: - Browser* current_browser_; // The browser passed to ShowBubbleView(). bool should_delete_self_on_close_; base::WeakPtr<ExtensionService> extension_service_; scoped_ptr<ExtensionIdSet> external_extension_ids_; diff --git a/chrome/browser/extensions/extension_global_error_badge.cc b/chrome/browser/extensions/extension_global_error_badge.cc index 8124dc8..6efd04b 100644 --- a/chrome/browser/extensions/extension_global_error_badge.cc +++ b/chrome/browser/extensions/extension_global_error_badge.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -63,13 +63,15 @@ string16 ExtensionGlobalErrorBadge::GetBubbleViewCancelButtonLabel() { return string16(); } -void ExtensionGlobalErrorBadge::BubbleViewDidClose() { +void ExtensionGlobalErrorBadge::OnBubbleViewDidClose(Browser* browser) { } -void ExtensionGlobalErrorBadge::BubbleViewAcceptButtonPressed() { +void ExtensionGlobalErrorBadge::BubbleViewAcceptButtonPressed( + Browser* browser) { NOTREACHED(); } -void ExtensionGlobalErrorBadge::BubbleViewCancelButtonPressed() { +void ExtensionGlobalErrorBadge::BubbleViewCancelButtonPressed( + Browser* browser) { NOTREACHED(); } diff --git a/chrome/browser/extensions/extension_global_error_badge.h b/chrome/browser/extensions/extension_global_error_badge.h index f49ce4b..613fc93 100644 --- a/chrome/browser/extensions/extension_global_error_badge.h +++ b/chrome/browser/extensions/extension_global_error_badge.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -34,9 +34,9 @@ class ExtensionGlobalErrorBadge : public GlobalError { virtual string16 GetBubbleViewMessage() OVERRIDE; virtual string16 GetBubbleViewAcceptButtonLabel() OVERRIDE; virtual string16 GetBubbleViewCancelButtonLabel() OVERRIDE; - virtual void BubbleViewDidClose() OVERRIDE; - virtual void BubbleViewAcceptButtonPressed() OVERRIDE; - virtual void BubbleViewCancelButtonPressed() OVERRIDE; + virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE; + virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE; + virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(ExtensionGlobalErrorBadge); diff --git a/chrome/browser/protector/base_setting_change.cc b/chrome/browser/protector/base_setting_change.cc index 3ee61d4..805d48b 100644 --- a/chrome/browser/protector/base_setting_change.cc +++ b/chrome/browser/protector/base_setting_change.cc @@ -21,10 +21,10 @@ bool BaseSettingChange::Init(Profile* profile) { return true; } -void BaseSettingChange::Apply() { +void BaseSettingChange::Apply(Browser* browser) { } -void BaseSettingChange::Discard() { +void BaseSettingChange::Discard(Browser* browser) { } void BaseSettingChange::Timeout() { diff --git a/chrome/browser/protector/base_setting_change.h b/chrome/browser/protector/base_setting_change.h index 0d1cdff..098d6f1 100644 --- a/chrome/browser/protector/base_setting_change.h +++ b/chrome/browser/protector/base_setting_change.h @@ -12,6 +12,7 @@ #include "base/basictypes.h" #include "base/string16.h" +class Browser; class Profile; class TemplateURL; @@ -30,11 +31,13 @@ class BaseSettingChange { // base method. virtual bool Init(Profile* profile); - // Persists new setting if needed. - virtual void Apply(); + // Persists new setting if needed. |browser| is the Browser instance from + // which the user action originates. + virtual void Apply(Browser* browser); - // Restores old setting if needed. - virtual void Discard(); + // Restores old setting if needed. |browser| is the Browser instance from + // which the user action originates. + virtual void Discard(Browser* browser); // Indicates that user has ignored this change and timeout has passed. virtual void Timeout(); diff --git a/chrome/browser/protector/default_search_provider_change.cc b/chrome/browser/protector/default_search_provider_change.cc index d7b29a8..6818f49 100644 --- a/chrome/browser/protector/default_search_provider_change.cc +++ b/chrome/browser/protector/default_search_provider_change.cc @@ -89,8 +89,8 @@ class DefaultSearchProviderChange : public BaseSettingChange, // BaseSettingChange overrides: virtual bool Init(Profile* profile) OVERRIDE; - virtual void Apply() OVERRIDE; - virtual void Discard() OVERRIDE; + virtual void Apply(Browser* browser) OVERRIDE; + virtual void Discard(Browser* browser) OVERRIDE; virtual void Timeout() OVERRIDE; virtual int GetBadgeIconID() const OVERRIDE; virtual int GetMenuItemIconID() const OVERRIDE; @@ -121,7 +121,7 @@ class DefaultSearchProviderChange : public BaseSettingChange, scoped_ptr<TemplateURL>* search_provider); // Opens the Search engine settings page in a new tab. - void OpenSearchEngineSettings(); + void OpenSearchEngineSettings(Browser* browser); // Returns the TemplateURLService instance for the Profile this change is // related to. @@ -232,7 +232,7 @@ bool DefaultSearchProviderChange::Init(Profile* profile) { return true; } -void DefaultSearchProviderChange::Apply() { +void DefaultSearchProviderChange::Apply(Browser* browser) { UMA_HISTOGRAM_ENUMERATION( kProtectorHistogramSearchProviderApplied, new_histogram_id_, @@ -243,11 +243,11 @@ void DefaultSearchProviderChange::Apply() { GetTemplateURLService()->SetDefaultSearchProvider(new_search_provider_); } else { // Open settings page in case the new setting is invalid. - OpenSearchEngineSettings(); + OpenSearchEngineSettings(browser); } } -void DefaultSearchProviderChange::Discard() { +void DefaultSearchProviderChange::Discard(Browser* browser) { UMA_HISTOGRAM_ENUMERATION( kProtectorHistogramSearchProviderDiscarded, new_histogram_id_, @@ -256,7 +256,7 @@ void DefaultSearchProviderChange::Discard() { GetTemplateURLService()->RemoveObserver(this); if (is_fallback_) { // Open settings page in case the old setting is invalid. - OpenSearchEngineSettings(); + OpenSearchEngineSettings(browser); } // Nothing to do otherwise since we have already set the search engine // to |old_id_| in |Init|. @@ -385,10 +385,10 @@ const TemplateURL* DefaultSearchProviderChange::SetDefaultSearchProvider( return new_default_provider; } -void DefaultSearchProviderChange::OpenSearchEngineSettings() { +void DefaultSearchProviderChange::OpenSearchEngineSettings(Browser* browser) { ProtectorServiceFactory::GetForProfile(profile())->OpenTab( GURL(std::string(chrome::kChromeUISettingsURL) + - chrome::kSearchEnginesSubPage)); + chrome::kSearchEnginesSubPage), browser); } TemplateURLService* DefaultSearchProviderChange::GetTemplateURLService() { diff --git a/chrome/browser/protector/default_search_provider_change_browsertest.cc b/chrome/browser/protector/default_search_provider_change_browsertest.cc index 1bb7e50..7a87af7 100644 --- a/chrome/browser/protector/default_search_provider_change_browsertest.cc +++ b/chrome/browser/protector/default_search_provider_change_browsertest.cc @@ -121,7 +121,7 @@ class DefaultSearchProviderChangeTest : public InProcessBrowserTest { void ExpectSettingsOpened(const std::string& subpage) { GURL settings_url(chrome::kChromeUISettingsURL + subpage); - EXPECT_CALL(*mock_protector_service_, OpenTab(settings_url)); + EXPECT_CALL(*mock_protector_service_, OpenTab(settings_url, browser())); } void ExpectHistogramCount(const std::string& name, @@ -181,14 +181,14 @@ IN_PROC_BROWSER_TEST_F(DefaultSearchProviderChangeTest, BackupValid) { change->GetDiscardButtonText()); // Discard does nothing - backup was already active. - change->Discard(); + change->Discard(browser()); EXPECT_EQ(FindTemplateURL(http_example_info), turl_service_->GetDefaultSearchProvider()); ExpectHistogramCount(kProtectorHistogramSearchProviderDiscarded, SEARCH_ENGINE_OTHER, 1); // Verify that Apply switches back to |current_url|. - change->Apply(); + change->Apply(browser()); EXPECT_EQ(FindTemplateURL(http_example_com), turl_service_->GetDefaultSearchProvider()); ExpectHistogramCount(kProtectorHistogramSearchProviderApplied, @@ -278,12 +278,12 @@ IN_PROC_BROWSER_TEST_F(DefaultSearchProviderChangeTest, BackupInvalid) { // Verify that search engine settings are opened by Discard. ExpectSettingsOpened(chrome::kSearchEnginesSubPage); - change->Discard(); + change->Discard(browser()); EXPECT_EQ(FindTemplateURL(prepopulated_url_->url()->url()), turl_service_->GetDefaultSearchProvider()); // Verify that Apply switches back to |current_url|. - change->Apply(); + change->Apply(browser()); EXPECT_EQ(FindTemplateURL(http_example_com), turl_service_->GetDefaultSearchProvider()); } @@ -332,12 +332,12 @@ IN_PROC_BROWSER_TEST_F(DefaultSearchProviderChangeTest, // Verify that search engine settings are opened by Discard. ExpectSettingsOpened(chrome::kSearchEnginesSubPage); - change->Discard(); + change->Discard(browser()); EXPECT_EQ(FindTemplateURL(prepopulated_url_->url()->url()), turl_service_->GetDefaultSearchProvider()); // Verify that Apply switches back to |current_url|. - change->Apply(); + change->Apply(browser()); EXPECT_EQ(FindTemplateURL(http_example_com), turl_service_->GetDefaultSearchProvider()); } @@ -373,13 +373,13 @@ IN_PROC_BROWSER_TEST_F(DefaultSearchProviderChangeTest, change->GetDiscardButtonText()); // Discard does nothing - backup was already active. - change->Discard(); + change->Discard(browser()); EXPECT_EQ(FindTemplateURL(http_example_info), turl_service_->GetDefaultSearchProvider()); // Verify that search engine settings are opened by Apply (no other changes). ExpectSettingsOpened(chrome::kSearchEnginesSubPage); - change->Apply(); + change->Apply(browser()); EXPECT_EQ(FindTemplateURL(http_example_info), turl_service_->GetDefaultSearchProvider()); } @@ -415,7 +415,7 @@ IN_PROC_BROWSER_TEST_F(DefaultSearchProviderChangeTest, // Verify that search engine settings are opened by Discard. ExpectSettingsOpened(chrome::kSearchEnginesSubPage); - change->Discard(); + change->Discard(browser()); EXPECT_EQ(FindTemplateURL(prepopulated_url_->url()->url()), turl_service_->GetDefaultSearchProvider()); } @@ -454,7 +454,7 @@ IN_PROC_BROWSER_TEST_F(DefaultSearchProviderChangeTest, // Verify that search engine settings are opened by Discard. ExpectSettingsOpened(chrome::kSearchEnginesSubPage); - change->Discard(); + change->Discard(browser()); EXPECT_EQ(current_url, turl_service_->GetDefaultSearchProvider()); } @@ -518,12 +518,12 @@ IN_PROC_BROWSER_TEST_F(DefaultSearchProviderChangeTest, // Verify that search engine settings are opened by Apply. ExpectSettingsOpened(chrome::kSearchEnginesSubPage); - change->Apply(); + change->Apply(browser()); EXPECT_EQ(FindTemplateURL(http_example_info), turl_service_->GetDefaultSearchProvider()); // Discard does nothing - backup was already active. - change->Discard(); + change->Discard(browser()); EXPECT_EQ(FindTemplateURL(http_example_info), turl_service_->GetDefaultSearchProvider()); } diff --git a/chrome/browser/protector/mock_protector_service.h b/chrome/browser/protector/mock_protector_service.h index a32bb92..bc2c36f 100644 --- a/chrome/browser/protector/mock_protector_service.h +++ b/chrome/browser/protector/mock_protector_service.h @@ -26,13 +26,13 @@ class MockProtectorService : public ProtectorService { MOCK_CONST_METHOD0(IsShowingChange, bool()); MOCK_METHOD0(DismissChange, void()); - MOCK_METHOD0(ApplyChange, void()); - MOCK_METHOD0(DiscardChange, void()); + MOCK_METHOD1(ApplyChange, void(Browser*)); + MOCK_METHOD1(DiscardChange, void(Browser*)); - MOCK_METHOD1(OpenTab, void(const GURL&)); + MOCK_METHOD2(OpenTab, void(const GURL&, Browser*)); - MOCK_METHOD0(OnApplyChange, void()); - MOCK_METHOD0(OnDiscardChange, void()); + MOCK_METHOD1(OnApplyChange, void(Browser*)); + MOCK_METHOD1(OnDiscardChange, void(Browser*)); MOCK_METHOD0(OnDecisionTimeout, void()); MOCK_METHOD0(OnRemovedFromProfile, void()); diff --git a/chrome/browser/protector/mock_setting_change.h b/chrome/browser/protector/mock_setting_change.h index 3f151ea..c665ced 100644 --- a/chrome/browser/protector/mock_setting_change.h +++ b/chrome/browser/protector/mock_setting_change.h @@ -20,8 +20,8 @@ class MockSettingChange : public BaseSettingChange { virtual bool Init(Profile* profile) OVERRIDE; MOCK_METHOD1(MockInit, bool(Profile* profile)); - MOCK_METHOD0(Apply, void()); - MOCK_METHOD0(Discard, void()); + MOCK_METHOD1(Apply, void(Browser*)); + MOCK_METHOD1(Discard, void(Browser*)); MOCK_METHOD0(Timeout, void()); MOCK_CONST_METHOD0(GetBadgeIconID, int()); diff --git a/chrome/browser/protector/protector_service.cc b/chrome/browser/protector/protector_service.cc index 2464c0e..214be7db 100644 --- a/chrome/browser/protector/protector_service.cc +++ b/chrome/browser/protector/protector_service.cc @@ -44,15 +44,15 @@ bool ProtectorService::IsShowingChange() const { return change_.get() != NULL; } -void ProtectorService::ApplyChange() { +void ProtectorService::ApplyChange(Browser* browser) { DCHECK(IsShowingChange()); - change_->Apply(); + change_->Apply(browser); DismissChange(); } -void ProtectorService::DiscardChange() { +void ProtectorService::DiscardChange(Browser* browser) { DCHECK(IsShowingChange()); - change_->Discard(); + change_->Discard(browser); DismissChange(); } @@ -62,12 +62,9 @@ void ProtectorService::DismissChange() { DCHECK(!IsShowingChange()); } -void ProtectorService::OpenTab(const GURL& url) { - if (!error_.get() || !error_->browser()) { - LOG(WARNING) << "Don't have browser to show tab in."; - return; - } - error_->browser()->ShowSingletonTab(url); +void ProtectorService::OpenTab(const GURL& url, Browser* browser) { + DCHECK(browser); + browser->ShowSingletonTab(url); } void ProtectorService::Shutdown() { @@ -75,16 +72,16 @@ void ProtectorService::Shutdown() { DismissChange(); } -void ProtectorService::OnApplyChange() { +void ProtectorService::OnApplyChange(Browser* browser) { DVLOG(1) << "Apply change"; DCHECK(IsShowingChange()); - change_->Apply(); + change_->Apply(browser); } -void ProtectorService::OnDiscardChange() { +void ProtectorService::OnDiscardChange(Browser* browser) { DVLOG(1) << "Discard change"; DCHECK(IsShowingChange()); - change_->Discard(); + change_->Discard(browser); } void ProtectorService::OnDecisionTimeout() { diff --git a/chrome/browser/protector/protector_service.h b/chrome/browser/protector/protector_service.h index 28e1b6f..aae385c 100644 --- a/chrome/browser/protector/protector_service.h +++ b/chrome/browser/protector/protector_service.h @@ -43,14 +43,16 @@ class ProtectorService : public ProfileKeyedService, virtual void DismissChange(); // Persists the change that is currently active and removes global error. - virtual void ApplyChange(); + // |browser| is the Browser instance from which the user action originates. + virtual void ApplyChange(Browser* browser); // Discards the change that is currently active and removes global error. - virtual void DiscardChange(); + // |browser| is the Browser instance from which the user action originates. + virtual void DiscardChange(Browser* browser); // Opens a tab with specified URL in the browser window we've shown error // bubble for. - virtual void OpenTab(const GURL& url); + virtual void OpenTab(const GURL& url, Browser* browser); // Returns the Profile instance we've shown error bubble for. Profile* profile() { return profile_; } @@ -62,8 +64,8 @@ class ProtectorService : public ProfileKeyedService, virtual void Shutdown() OVERRIDE; // SettingsChangeGlobalErrorDelegate implementation. - virtual void OnApplyChange() OVERRIDE; - virtual void OnDiscardChange() OVERRIDE; + virtual void OnApplyChange(Browser* browser) OVERRIDE; + virtual void OnDiscardChange(Browser* browser) OVERRIDE; virtual void OnDecisionTimeout() OVERRIDE; virtual void OnRemovedFromProfile() OVERRIDE; diff --git a/chrome/browser/protector/protector_service_browsertest.cc b/chrome/browser/protector/protector_service_browsertest.cc index 951dabb..610af7e 100644 --- a/chrome/browser/protector/protector_service_browsertest.cc +++ b/chrome/browser/protector/protector_service_browsertest.cc @@ -11,12 +11,13 @@ #include "chrome/browser/protector/settings_change_global_error.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/global_error.h" +#include "chrome/browser/ui/global_error_bubble_view_base.h" #include "chrome/browser/ui/global_error_service.h" #include "chrome/browser/ui/global_error_service_factory.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" -using ::testing::Invoke; +using ::testing::InvokeWithoutArgs; using ::testing::NiceMock; using ::testing::Return; @@ -78,8 +79,8 @@ IN_PROC_BROWSER_TEST_F(ProtectorServiceTest, ShowAndApply) { protector_service_->ShowChange(mock_change_); ui_test_utils::RunAllPendingInMessageLoop(); ExpectGlobalErrorActive(true); - EXPECT_CALL(*mock_change_, Apply()); - protector_service_->ApplyChange(); + EXPECT_CALL(*mock_change_, Apply(browser())); + protector_service_->ApplyChange(browser()); ui_test_utils::RunAllPendingInMessageLoop(); ExpectGlobalErrorActive(false); } @@ -91,11 +92,11 @@ IN_PROC_BROWSER_TEST_F(ProtectorServiceTest, ShowAndApplyManually) { protector_service_->ShowChange(mock_change_); ui_test_utils::RunAllPendingInMessageLoop(); ExpectGlobalErrorActive(true); - EXPECT_CALL(*mock_change_, Apply()); + EXPECT_CALL(*mock_change_, Apply(browser())); // Pressing Cancel applies the change. GlobalError* error = GetGlobalError(); - error->BubbleViewCancelButtonPressed(); - error->BubbleViewDidClose(); + error->BubbleViewCancelButtonPressed(browser()); + error->GetBubbleView()->CloseBubbleView(); ui_test_utils::RunAllPendingInMessageLoop(); ExpectGlobalErrorActive(false); } @@ -107,8 +108,8 @@ IN_PROC_BROWSER_TEST_F(ProtectorServiceTest, ShowAndDiscard) { protector_service_->ShowChange(mock_change_); ui_test_utils::RunAllPendingInMessageLoop(); ExpectGlobalErrorActive(true); - EXPECT_CALL(*mock_change_, Discard()); - protector_service_->DiscardChange(); + EXPECT_CALL(*mock_change_, Discard(browser())); + protector_service_->DiscardChange(browser()); ui_test_utils::RunAllPendingInMessageLoop(); ExpectGlobalErrorActive(false); } @@ -120,11 +121,11 @@ IN_PROC_BROWSER_TEST_F(ProtectorServiceTest, ShowAndDiscardManually) { protector_service_->ShowChange(mock_change_); ui_test_utils::RunAllPendingInMessageLoop(); ExpectGlobalErrorActive(true); - EXPECT_CALL(*mock_change_, Discard()); + EXPECT_CALL(*mock_change_, Discard(browser())); // Pressing Apply discards the change. GlobalError* error = GetGlobalError(); - error->BubbleViewAcceptButtonPressed(); - error->BubbleViewDidClose(); + error->BubbleViewAcceptButtonPressed(browser()); + error->GetBubbleView()->CloseBubbleView(); ui_test_utils::RunAllPendingInMessageLoop(); ExpectGlobalErrorActive(false); } @@ -135,11 +136,15 @@ IN_PROC_BROWSER_TEST_F(ProtectorServiceTest, BubbleClosedInsideApply) { protector_service_->ShowChange(mock_change_); ui_test_utils::RunAllPendingInMessageLoop(); ExpectGlobalErrorActive(true); + GlobalError* error = GetGlobalError(); - EXPECT_CALL(*mock_change_, Apply()). - WillOnce(Invoke(error, &GlobalError::BubbleViewDidClose)); + GlobalErrorBubbleViewBase* bubble_view = error->GetBubbleView(); + EXPECT_TRUE(bubble_view); + EXPECT_CALL(*mock_change_, Apply(browser())).WillOnce(InvokeWithoutArgs( + bubble_view, &GlobalErrorBubbleViewBase::CloseBubbleView)); + // Pressing Cancel applies the change. - error->BubbleViewCancelButtonPressed(); + error->BubbleViewCancelButtonPressed(browser()); ui_test_utils::RunAllPendingInMessageLoop(); ExpectGlobalErrorActive(false); } diff --git a/chrome/browser/protector/settings_change_global_error.cc b/chrome/browser/protector/settings_change_global_error.cc index 4d22142..e9b2194 100644 --- a/chrome/browser/protector/settings_change_global_error.cc +++ b/chrome/browser/protector/settings_change_global_error.cc @@ -34,7 +34,6 @@ SettingsChangeGlobalError::SettingsChangeGlobalError( : change_(change), delegate_(delegate), profile_(NULL), - browser_(NULL), closed_by_button_(false), ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { DCHECK(delegate_); @@ -70,8 +69,7 @@ int SettingsChangeGlobalError::MenuItemIconResourceID() { void SettingsChangeGlobalError::ExecuteMenuItem(Browser* browser) { // Cancel previously posted tasks. weak_factory_.InvalidateWeakPtrs(); - browser_ = browser; - ShowBubbleView(browser_); + ShowBubbleView(browser); } bool SettingsChangeGlobalError::HasBubbleView() { @@ -103,14 +101,16 @@ string16 SettingsChangeGlobalError::GetBubbleViewCancelButtonLabel() { return change_->GetApplyButtonText(); } -void SettingsChangeGlobalError::BubbleViewAcceptButtonPressed() { +void SettingsChangeGlobalError::BubbleViewAcceptButtonPressed( + Browser* browser) { closed_by_button_ = true; - delegate_->OnDiscardChange(); + delegate_->OnDiscardChange(browser); } -void SettingsChangeGlobalError::BubbleViewCancelButtonPressed() { +void SettingsChangeGlobalError::BubbleViewCancelButtonPressed( + Browser* browser) { closed_by_button_ = true; - delegate_->OnApplyChange(); + delegate_->OnApplyChange(browser); } void SettingsChangeGlobalError::RemoveFromProfile() { @@ -120,8 +120,7 @@ void SettingsChangeGlobalError::RemoveFromProfile() { delegate_->OnRemovedFromProfile(); } -void SettingsChangeGlobalError::BubbleViewDidClose() { - browser_ = NULL; +void SettingsChangeGlobalError::OnBubbleViewDidClose(Browser* browser) { if (!closed_by_button_) { BrowserThread::PostDelayedTask( BrowserThread::UI, FROM_HERE, @@ -155,13 +154,13 @@ void SettingsChangeGlobalError::AddToProfile(Profile* profile) { void SettingsChangeGlobalError::Show() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(profile_); - browser_ = BrowserList::GetLastActiveWithProfile(profile_); - if (!browser_ && profile_->HasOffTheRecordProfile()) { - browser_ = BrowserList::GetLastActiveWithProfile( + Browser* browser = BrowserList::GetLastActiveWithProfile(profile_); + if (!browser && profile_->HasOffTheRecordProfile()) { + browser = BrowserList::GetLastActiveWithProfile( profile_->GetOffTheRecordProfile()); } - if (browser_) - ShowBubbleView(browser_); + if (browser) + ShowBubbleView(browser); } void SettingsChangeGlobalError::OnInactiveTimeout() { diff --git a/chrome/browser/protector/settings_change_global_error.h b/chrome/browser/protector/settings_change_global_error.h index 2065e52..1542443 100644 --- a/chrome/browser/protector/settings_change_global_error.h +++ b/chrome/browser/protector/settings_change_global_error.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -38,9 +38,6 @@ class SettingsChangeGlobalError : public GlobalError { // Removes global error from its profile. void RemoveFromProfile(); - // Browser that the bubble has been last time shown for. - Browser* browser() const { return browser_; } - // GlobalError implementation. virtual bool HasBadge() OVERRIDE; virtual int GetBadgeResourceID() OVERRIDE; @@ -55,9 +52,9 @@ class SettingsChangeGlobalError : public GlobalError { virtual string16 GetBubbleViewMessage() OVERRIDE; virtual string16 GetBubbleViewAcceptButtonLabel() OVERRIDE; virtual string16 GetBubbleViewCancelButtonLabel() OVERRIDE; - virtual void BubbleViewDidClose() OVERRIDE; - virtual void BubbleViewAcceptButtonPressed() OVERRIDE; - virtual void BubbleViewCancelButtonPressed() OVERRIDE; + virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE; + virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE; + virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE; private: // Helper called on the UI thread to add this global error to the default @@ -80,9 +77,6 @@ class SettingsChangeGlobalError : public GlobalError { // Profile that we have been added to. Profile* profile_; - // Browser that we have been shown for. - Browser* browser_; - // True if user has dismissed the bubble by clicking on one of the buttons. bool closed_by_button_; diff --git a/chrome/browser/protector/settings_change_global_error_delegate.h b/chrome/browser/protector/settings_change_global_error_delegate.h index cf21d2a..34cc9a8 100644 --- a/chrome/browser/protector/settings_change_global_error_delegate.h +++ b/chrome/browser/protector/settings_change_global_error_delegate.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,6 +8,8 @@ #include "base/basictypes.h" +class Browser; + namespace protector { // Interface for notifications about settings change error bubble closing. @@ -16,10 +18,10 @@ class SettingsChangeGlobalErrorDelegate { virtual ~SettingsChangeGlobalErrorDelegate() {} // Called if user clicks "Apply change" button. - virtual void OnApplyChange() = 0; + virtual void OnApplyChange(Browser* browser) = 0; // Called if user clicks "Discard change" button. - virtual void OnDiscardChange() = 0; + virtual void OnDiscardChange(Browser* browser) = 0; // Called if user clicked outside the bubble and timeout for its reshow // has passed. diff --git a/chrome/browser/sync/sync_global_error.cc b/chrome/browser/sync/sync_global_error.cc index c55e05b..1dba4c5 100644 --- a/chrome/browser/sync/sync_global_error.cc +++ b/chrome/browser/sync/sync_global_error.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -72,14 +72,14 @@ string16 SyncGlobalError::GetBubbleViewCancelButtonLabel() { return string16(); } -void SyncGlobalError::BubbleViewDidClose() { +void SyncGlobalError::OnBubbleViewDidClose(Browser* browser) { } -void SyncGlobalError::BubbleViewAcceptButtonPressed() { +void SyncGlobalError::BubbleViewAcceptButtonPressed(Browser* browser) { service_->ShowErrorUI(); } -void SyncGlobalError::BubbleViewCancelButtonPressed() { +void SyncGlobalError::BubbleViewCancelButtonPressed(Browser* browser) { NOTREACHED(); } diff --git a/chrome/browser/sync/sync_global_error.h b/chrome/browser/sync/sync_global_error.h index 27c6d63..c58dc99 100644 --- a/chrome/browser/sync/sync_global_error.h +++ b/chrome/browser/sync/sync_global_error.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -33,9 +33,9 @@ class SyncGlobalError : public GlobalError, virtual string16 GetBubbleViewMessage() OVERRIDE; virtual string16 GetBubbleViewAcceptButtonLabel() OVERRIDE; virtual string16 GetBubbleViewCancelButtonLabel() OVERRIDE; - virtual void BubbleViewDidClose() OVERRIDE; - virtual void BubbleViewAcceptButtonPressed() OVERRIDE; - virtual void BubbleViewCancelButtonPressed() OVERRIDE; + virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE; + virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE; + virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE; // ProfileSyncServiceObserver implementation. virtual void OnStateChanged() OVERRIDE; diff --git a/chrome/browser/sync/sync_global_error_unittest.cc b/chrome/browser/sync/sync_global_error_unittest.cc index e795dc5..683fe59 100644 --- a/chrome/browser/sync/sync_global_error_unittest.cc +++ b/chrome/browser/sync/sync_global_error_unittest.cc @@ -9,6 +9,7 @@ #include "chrome/browser/signin/signin_manager.h" #include "chrome/browser/sync/profile_sync_service_mock.h" #include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/browser_with_test_window_test.h" #include "content/test/test_browser_thread.h" #include "testing/gmock/include/gmock/gmock-actions.h" #include "testing/gmock/include/gmock/gmock.h" @@ -24,6 +25,7 @@ namespace { // Utility function to test that SyncGlobalError behaves correct for the given // error condition. void VerifySyncGlobalErrorResult(NiceMock<ProfileSyncServiceMock>* service, + Browser* browser, SyncGlobalError* error, GoogleServiceAuthError::State error_state, bool is_signed_in, @@ -56,19 +58,19 @@ void VerifySyncGlobalErrorResult(NiceMock<ProfileSyncServiceMock>* service, // Test message handler. if (is_error) { EXPECT_CALL(*service, ShowErrorUI()); - error->ExecuteMenuItem(NULL); + error->ExecuteMenuItem(browser); EXPECT_CALL(*service, ShowErrorUI()); - error->BubbleViewAcceptButtonPressed(); - error->BubbleViewDidClose(); + error->BubbleViewAcceptButtonPressed(browser); + error->BubbleViewDidClose(browser); } } } // namespace +typedef BrowserWithTestWindowTest SyncGlobalErrorTest; + // Test that SyncGlobalError shows an error if a passphrase is required. -TEST(SyncGlobalErrorTest, PassphraseGlobalError) { - MessageLoopForUI message_loop; - content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); +TEST_F(SyncGlobalErrorTest, PassphraseGlobalError) { scoped_ptr<Profile> profile( ProfileSyncServiceMock::MakeSignedInTestingProfile()); NiceMock<ProfileSyncServiceMock> service(profile.get()); @@ -79,15 +81,13 @@ TEST(SyncGlobalErrorTest, PassphraseGlobalError) { EXPECT_CALL(service, IsPassphraseRequiredForDecryption()) .WillRepeatedly(Return(true)); VerifySyncGlobalErrorResult( - &service, &error, GoogleServiceAuthError::NONE, true, true); + &service, browser(), &error, GoogleServiceAuthError::NONE, true, true); } // Test that SyncGlobalError shows an error for conditions that can be resolved // by the user and suppresses errors for conditions that cannot be resolved by // the user. -TEST(SyncGlobalErrorTest, AuthStateGlobalError) { - MessageLoopForUI message_loop; - content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); +TEST_F(SyncGlobalErrorTest, AuthStateGlobalError) { scoped_ptr<Profile> profile( ProfileSyncServiceMock::MakeSignedInTestingProfile()); NiceMock<ProfileSyncServiceMock> service(profile.get()); @@ -115,9 +115,9 @@ TEST(SyncGlobalErrorTest, AuthStateGlobalError) { }; for (size_t i = 0; i < sizeof(table)/sizeof(*table); ++i) { - VerifySyncGlobalErrorResult( - &service, &error, table[i].error_state, true, table[i].is_error); - VerifySyncGlobalErrorResult( - &service, &error, table[i].error_state, false, false); + VerifySyncGlobalErrorResult(&service, browser(), &error, + table[i].error_state, true, table[i].is_error); + VerifySyncGlobalErrorResult(&service, browser(), &error, + table[i].error_state, false, false); } } diff --git a/chrome/browser/ui/cocoa/global_error_bubble_controller.h b/chrome/browser/ui/cocoa/global_error_bubble_controller.h index 9c61c8b..75a2ef5 100644 --- a/chrome/browser/ui/cocoa/global_error_bubble_controller.h +++ b/chrome/browser/ui/cocoa/global_error_bubble_controller.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,18 +8,26 @@ #import <Cocoa/Cocoa.h> +#include "base/memory/weak_ptr.h" #import "chrome/browser/ui/cocoa/base_bubble_controller.h" +class Browser; class GlobalError; @class GTMUILocalizerAndLayoutTweaker; @class GTMWidthBasedTweaker; +class Profile; + +namespace GlobalErrorBubbleControllerInternal { +class Bridge; +} // This is a bubble view shown from the wrench menu to display information // about a global error. @interface GlobalErrorBubbleController : BaseBubbleController { @private - // |error_| can be NULL after -close is called. - GlobalError* error_; + base::WeakPtr<GlobalError> error_; + scoped_ptr<GlobalErrorBubbleControllerInternal::Bridge> bridge_; + Browser* browser_; IBOutlet NSImageView* iconView_; IBOutlet NSTextField* title_; @@ -33,6 +41,8 @@ class GlobalError; - (IBAction)onAccept:(id)sender; - (IBAction)onCancel:(id)sender; +- (void)close; + @end #endif // CHROME_BROWSER_UI_COCOA_GLOBAL_ERROR_BUBBLE_CONTROLLER_H_ diff --git a/chrome/browser/ui/cocoa/global_error_bubble_controller.mm b/chrome/browser/ui/cocoa/global_error_bubble_controller.mm index 1315e08..1d1c4d4 100644 --- a/chrome/browser/ui/cocoa/global_error_bubble_controller.mm +++ b/chrome/browser/ui/cocoa/global_error_bubble_controller.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -14,7 +14,10 @@ #import "chrome/browser/ui/cocoa/l10n_util.h" #import "chrome/browser/ui/cocoa/info_bubble_view.h" #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" -#import "chrome/browser/ui/global_error.h" +#include "chrome/browser/ui/global_error.h" +#include "chrome/browser/ui/global_error_bubble_view_base.h" +#include "chrome/browser/ui/global_error_service.h" +#include "chrome/browser/ui/global_error_service_factory.h" #include "grit/generated_resources.h" #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" #include "ui/base/l10n/l10n_util.h" @@ -28,10 +31,28 @@ const CGFloat kWrenchBubblePointOffsetY = 6; } // namespace +namespace GlobalErrorBubbleControllerInternal { + +// This is the bridge to the C++ GlobalErrorBubbleViewBase object. +class Bridge : public GlobalErrorBubbleViewBase { + public: + Bridge(GlobalErrorBubbleController* controller) : controller_(controller) { + } + + private: + virtual void CloseBubbleView() OVERRIDE { + [controller_ close]; + } + + GlobalErrorBubbleController* controller_; // Weak, owns this. +}; + +} // namespace GlobalErrorBubbleControllerInternal + @implementation GlobalErrorBubbleController -+ (void)showForBrowser:(Browser*)browser - error:(GlobalError*)error { ++ (GlobalErrorBubbleViewBase*)showForBrowser:(Browser*)browser + error:(const base::WeakPtr<GlobalError>&)error { NSWindow* parentWindow = browser->window()->GetNativeHandle(); BrowserWindowController* bwc = [BrowserWindowController browserWindowControllerForWindow:parentWindow]; @@ -45,7 +66,12 @@ const CGFloat kWrenchBubblePointOffsetY = 6; relativeToView:wrenchButton offset:offset]; bubble->error_ = error; + bubble->bridge_.reset(new GlobalErrorBubbleControllerInternal::Bridge( + bubble)); + bubble->browser_ = browser; [bubble showWindow:nil]; + + return bubble->bridge_.get(); } - (void)awakeFromNib { @@ -96,8 +122,8 @@ const CGFloat kWrenchBubblePointOffsetY = 6; - (void)close { if (error_) - error_->BubbleViewDidClose(); - error_ = NULL; + error_->BubbleViewDidClose(browser_); + bridge_.reset(); BrowserWindowController* bwc = [BrowserWindowController browserWindowControllerForWindow:[self parentWindow]]; [bwc releaseBarVisibilityForOwner:self withAnimation:YES delay:NO]; @@ -105,17 +131,21 @@ const CGFloat kWrenchBubblePointOffsetY = 6; } - (IBAction)onAccept:(id)sender { - error_->BubbleViewAcceptButtonPressed(); + if (error_) + error_->BubbleViewAcceptButtonPressed(browser_); [self close]; } - (IBAction)onCancel:(id)sender { - error_->BubbleViewCancelButtonPressed(); + if (error_) + error_->BubbleViewCancelButtonPressed(browser_); [self close]; } @end -void GlobalError::ShowBubbleView(Browser* browser, GlobalError* error) { - [GlobalErrorBubbleController showForBrowser:browser error:error]; +GlobalErrorBubbleViewBase* GlobalErrorBubbleViewBase::ShowBubbleView( + Browser* browser, + const base::WeakPtr<GlobalError>& error) { + return [GlobalErrorBubbleController showForBrowser:browser error:error]; } diff --git a/chrome/browser/ui/global_error.cc b/chrome/browser/ui/global_error.cc index f2cf17c..a282df7 100644 --- a/chrome/browser/ui/global_error.cc +++ b/chrome/browser/ui/global_error.cc @@ -1,14 +1,17 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/global_error.h" #include "base/logging.h" +#include "chrome/browser/ui/global_error_bubble_view_base.h" #include "grit/theme_resources.h" #include "grit/theme_resources_standard.h" -GlobalError::GlobalError() : has_shown_bubble_view_(false) { +GlobalError::GlobalError() + : has_shown_bubble_view_(false), + bubble_view_(NULL) { } GlobalError::~GlobalError() { @@ -28,9 +31,20 @@ bool GlobalError::HasShownBubbleView() { void GlobalError::ShowBubbleView(Browser* browser) { has_shown_bubble_view_ = true; - ShowBubbleView(browser, this); + bubble_view_ = + GlobalErrorBubbleViewBase::ShowBubbleView(browser, AsWeakPtr()); +} + +GlobalErrorBubbleViewBase* GlobalError::GetBubbleView() { + return bubble_view_; } int GlobalError::GetBubbleViewIconResourceID() { return IDR_INPUT_ALERT; } + +void GlobalError::BubbleViewDidClose(Browser* browser) { + DCHECK(browser); + bubble_view_ = NULL; + OnBubbleViewDidClose(browser); +} diff --git a/chrome/browser/ui/global_error.h b/chrome/browser/ui/global_error.h index 6352037..fb579f8 100644 --- a/chrome/browser/ui/global_error.h +++ b/chrome/browser/ui/global_error.h @@ -7,12 +7,14 @@ #pragma once #include "base/basictypes.h" +#include "base/memory/weak_ptr.h" #include "base/string16.h" class Browser; +class GlobalErrorBubbleViewBase; // This object describes a single global error. -class GlobalError { +class GlobalError : public base::SupportsWeakPtr<GlobalError> { public: GlobalError(); virtual ~GlobalError(); @@ -38,7 +40,9 @@ class GlobalError { // Returns true if the bubble view has been shown. virtual bool HasShownBubbleView(); // Called to show the bubble view. - virtual void ShowBubbleView(Browser* browser); + void ShowBubbleView(Browser* browser); + // Returns the bubble view. + virtual GlobalErrorBubbleViewBase* GetBubbleView(); // Returns the resource ID for bubble view icon. virtual int GetBubbleViewIconResourceID(); // Returns the title for the bubble view. @@ -50,19 +54,23 @@ class GlobalError { // Returns the cancel button label for the bubble view. To hide the cancel // button return an empty string. virtual string16 GetBubbleViewCancelButtonLabel() = 0; - // Called when the bubble view is closed unless the bubble is closed as the - // result of |this| being removed from GlobalErrorService. - virtual void BubbleViewDidClose() = 0; - // Called when the user clicks on the accept button. - virtual void BubbleViewAcceptButtonPressed() = 0; - // Called when teh user clicks the cancel button. - virtual void BubbleViewCancelButtonPressed() = 0; + // Called when the bubble view is closed. |browser| is the Browser that the + // bubble view was shown on. + void BubbleViewDidClose(Browser* browser); + // Notifies subclasses that the bubble view is closed. |browser| is the + // Browser that the bubble view was shown on. + virtual void OnBubbleViewDidClose(Browser* browser) = 0; + // Called when the user clicks on the accept button. |browser| is the + // Browser that the bubble view was shown on. + virtual void BubbleViewAcceptButtonPressed(Browser* browser) = 0; + // Called when the user clicks the cancel button. |browser| is the + // Browser that the bubble view was shown on. + virtual void BubbleViewCancelButtonPressed(Browser* browser) = 0; private: - static void ShowBubbleView(Browser* browser, GlobalError* error); - bool has_shown_bubble_view_; + GlobalErrorBubbleViewBase* bubble_view_; DISALLOW_COPY_AND_ASSIGN(GlobalError); }; diff --git a/chrome/browser/ui/global_error_bubble_view_base.h b/chrome/browser/ui/global_error_bubble_view_base.h new file mode 100644 index 0000000..ce7cfbb --- /dev/null +++ b/chrome/browser/ui/global_error_bubble_view_base.h @@ -0,0 +1,27 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_GLOBAL_ERROR_BUBBLE_VIEW_BASE_H_ +#define CHROME_BROWSER_UI_GLOBAL_ERROR_BUBBLE_VIEW_BASE_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/memory/weak_ptr.h" + +class Browser; +class GlobalError; + +class GlobalErrorBubbleViewBase { + public: + static GlobalErrorBubbleViewBase* ShowBubbleView( + Browser* browser, + const base::WeakPtr<GlobalError>& error); + + virtual ~GlobalErrorBubbleViewBase() {} + + // Close the bubble view. + virtual void CloseBubbleView() = 0; +}; + +#endif // CHROME_BROWSER_UI_GLOBAL_ERROR_BUBBLE_VIEW_BASE_H_ diff --git a/chrome/browser/ui/global_error_service.cc b/chrome/browser/ui/global_error_service.cc index ed24f47..491ba51 100644 --- a/chrome/browser/ui/global_error_service.cc +++ b/chrome/browser/ui/global_error_service.cc @@ -9,6 +9,7 @@ #include "base/stl_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/global_error.h" +#include "chrome/browser/ui/global_error_bubble_view_base.h" #include "chrome/common/chrome_notification_types.h" #include "content/public/browser/notification_service.h" @@ -26,6 +27,9 @@ void GlobalErrorService::AddGlobalError(GlobalError* error) { void GlobalErrorService::RemoveGlobalError(GlobalError* error) { errors_.erase(std::find(errors_.begin(), errors_.end(), error)); + GlobalErrorBubbleViewBase* bubble = error->GetBubbleView(); + if (bubble) + bubble->CloseBubbleView(); NotifyErrorsChanged(error); } diff --git a/chrome/browser/ui/global_error_service_browsertest.cc b/chrome/browser/ui/global_error_service_browsertest.cc index 37932cb..63197f2 100644 --- a/chrome/browser/ui/global_error_service_browsertest.cc +++ b/chrome/browser/ui/global_error_service_browsertest.cc @@ -7,6 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/global_error.h" +#include "chrome/browser/ui/global_error_bubble_view_base.h" #include "chrome/browser/ui/global_error_service_factory.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" @@ -54,12 +55,12 @@ class BubbleViewError : public GlobalError { virtual string16 GetBubbleViewCancelButtonLabel() OVERRIDE { return string16(); } - virtual void BubbleViewDidClose() OVERRIDE { + virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE { + EXPECT_TRUE(browser); ++bubble_view_close_count_; } - - virtual void BubbleViewAcceptButtonPressed() OVERRIDE {} - virtual void BubbleViewCancelButtonPressed() OVERRIDE {} + virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE {} + virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE {} private: int bubble_view_close_count_; @@ -92,8 +93,33 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, ShowBubbleView) { EXPECT_EQ(0, error->bubble_view_close_count()); } -// TODO(sail): enable on Mac once http://crbug.com/109728 is fixed. -#if !defined(OS_MACOSX) +// Test that GlobalErrorBubbleViewBase::CloseBubbleView correctly closes the +// bubble view. +IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, CloseBubbleView) { + // This will be deleted by the GlobalErrorService. + BubbleViewError* error = new BubbleViewError; + + GlobalErrorService* service = + GlobalErrorServiceFactory::GetForProfile(browser()->profile()); + service->AddGlobalError(error); + + EXPECT_EQ(error, service->GetFirstGlobalErrorWithBubbleView()); + EXPECT_FALSE(error->HasShownBubbleView()); + EXPECT_EQ(0, error->bubble_view_close_count()); + + // Creating a second browser window should show the bubble view. + CreateBrowser(browser()->profile()); + EXPECT_EQ(NULL, service->GetFirstGlobalErrorWithBubbleView()); + EXPECT_TRUE(error->HasShownBubbleView()); + EXPECT_EQ(0, error->bubble_view_close_count()); + + // Explicitly close the bubble view. + EXPECT_TRUE(error->GetBubbleView()); + error->GetBubbleView()->CloseBubbleView(); + ui_test_utils::RunAllPendingInMessageLoop(); + EXPECT_EQ(1, error->bubble_view_close_count()); +} + // Test that bubble is silently dismissed if it is showing when the GlobalError // instance is removed from the profile. IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, @@ -113,7 +139,7 @@ IN_PROC_BROWSER_TEST_F(GlobalErrorServiceBrowserTest, // Removing |error| from profile should dismiss the bubble view without // calling |error->BubbleViewDidClose|. service->RemoveGlobalError(error.get()); - EXPECT_EQ(0, error->bubble_view_close_count()); + ui_test_utils::RunAllPendingInMessageLoop(); + EXPECT_EQ(1, error->bubble_view_close_count()); // |error| is no longer owned by service and will be deleted. } -#endif diff --git a/chrome/browser/ui/global_error_service_unittest.cc b/chrome/browser/ui/global_error_service_unittest.cc index 2c16bc2..4613506 100644 --- a/chrome/browser/ui/global_error_service_unittest.cc +++ b/chrome/browser/ui/global_error_service_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -41,7 +41,6 @@ class BaseError : public GlobalError { virtual void ExecuteMenuItem(Browser* browser) OVERRIDE { ADD_FAILURE(); } virtual bool HasBubbleView() OVERRIDE { return false; } - virtual void ShowBubbleView(Browser* browser) OVERRIDE { ADD_FAILURE(); } virtual int GetBubbleViewIconResourceID() OVERRIDE { ADD_FAILURE(); return 0; @@ -62,9 +61,15 @@ class BaseError : public GlobalError { ADD_FAILURE(); return string16(); } - virtual void BubbleViewDidClose() OVERRIDE { ADD_FAILURE(); } - virtual void BubbleViewAcceptButtonPressed() OVERRIDE { ADD_FAILURE(); } - virtual void BubbleViewCancelButtonPressed() OVERRIDE { ADD_FAILURE(); } + virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE { + ADD_FAILURE(); + } + virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE { + ADD_FAILURE(); + } + virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE { + ADD_FAILURE(); + } private: // This tracks the number BaseError objects that are currently instantiated. diff --git a/chrome/browser/ui/gtk/global_error_bubble.cc b/chrome/browser/ui/gtk/global_error_bubble.cc index 2e64fa0..2294437 100644 --- a/chrome/browser/ui/gtk/global_error_bubble.cc +++ b/chrome/browser/ui/gtk/global_error_bubble.cc @@ -16,8 +16,6 @@ #include "chrome/browser/ui/gtk/browser_window_gtk.h" #include "chrome/browser/ui/gtk/gtk_theme_service.h" #include "chrome/browser/ui/gtk/gtk_util.h" -#include "chrome/common/chrome_notification_types.h" -#include "content/public/browser/notification_service.h" #include "ui/base/gtk/gtk_hig_constants.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/gtk_util.h" @@ -42,16 +40,20 @@ const int kMessageLabelWidth = 250; } // namespace -GlobalErrorBubble::GlobalErrorBubble(Profile* profile, - GlobalError* error, +GlobalErrorBubble::GlobalErrorBubble(Browser* browser, + const base::WeakPtr<GlobalError>& error, GtkWidget* anchor) - : bubble_(NULL), + : browser_(browser), + bubble_(NULL), error_(error) { + DCHECK(browser_); + DCHECK(error_); GtkWidget* content = gtk_vbox_new(FALSE, kInterLineSpacing); gtk_container_set_border_width(GTK_CONTAINER(content), kContentBorder); g_signal_connect(content, "destroy", G_CALLBACK(OnDestroyThunk), this); - GtkThemeService* theme_service = GtkThemeService::GetFrom(profile); + GtkThemeService* theme_service = + GtkThemeService::GetFrom(browser_->profile()); int resource_id = error_->GetBubbleViewIconResourceID(); ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); @@ -104,9 +106,6 @@ GlobalErrorBubble::GlobalErrorBubble(Profile* profile, G_CALLBACK(OnCancelButtonThunk), this); } - registrar_.Add(this, chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED, - content::Source<Profile>(profile)); - BubbleGtk::ArrowLocationGtk arrow_location = base::i18n::IsRTL() ? BubbleGtk::ARROW_LOCATION_TOP_LEFT : @@ -126,12 +125,8 @@ GlobalErrorBubble::~GlobalErrorBubble() { void GlobalErrorBubble::BubbleClosing(BubbleGtk* bubble, bool closed_by_escape) { - // We unsubscribe from removal notifications here and below because any of - // GlobalError callbacks may remove it from the profile. Here it is needed - // also because |this| will be deleted later asynchronously in OnDestroy. - registrar_.RemoveAll(); if (error_) - error_->BubbleViewDidClose(); + error_->BubbleViewDidClose(browser_); } void GlobalErrorBubble::OnDestroy(GtkWidget* sender) { @@ -139,44 +134,29 @@ void GlobalErrorBubble::OnDestroy(GtkWidget* sender) { } void GlobalErrorBubble::OnAcceptButton(GtkWidget* sender) { - registrar_.RemoveAll(); - error_->BubbleViewAcceptButtonPressed(); + if (error_) + error_->BubbleViewAcceptButtonPressed(browser_); bubble_->Close(); } void GlobalErrorBubble::OnCancelButton(GtkWidget* sender) { - registrar_.RemoveAll(); - error_->BubbleViewCancelButtonPressed(); + if (error_) + error_->BubbleViewCancelButtonPressed(browser_); bubble_->Close(); } -void GlobalErrorBubble::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK(type == chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED); - DCHECK(error_); - if (content::Details<GlobalError>(details).ptr() == error_) { - Profile* profile = content::Source<Profile>(source).ptr(); - const std::vector<GlobalError*>& errors = - GlobalErrorServiceFactory::GetForProfile(profile)->errors(); - // This handles the case when a GlobalError instance is removed from profile - // not as a part of normal flow (i.e., after the bubble has been closed) - // but while the bubble is still showing. |error_| is no longer guaranteed - // to exist so we set it to |NULL| and dismiss the bubble. - if (std::find(errors.begin(), errors.end(), error_) == errors.end()) { - error_ = NULL; - registrar_.RemoveAll(); - bubble_->Close(); - } - } +void GlobalErrorBubble::CloseBubbleView() { + bubble_->Close(); } -void GlobalError::ShowBubbleView(Browser* browser, GlobalError* error) { +GlobalErrorBubbleViewBase* GlobalErrorBubbleViewBase::ShowBubbleView( + Browser* browser, + const base::WeakPtr<GlobalError>& error) { BrowserWindowGtk* browser_window = BrowserWindowGtk::GetBrowserWindowForNativeWindow( browser->window()->GetNativeHandle()); GtkWidget* anchor = browser_window->GetToolbar()->GetAppMenuButton(); // The bubble will be automatically deleted when it's closed. - new GlobalErrorBubble(browser->profile(), error, anchor); + return new GlobalErrorBubble(browser, error, anchor); } diff --git a/chrome/browser/ui/gtk/global_error_bubble.h b/chrome/browser/ui/gtk/global_error_bubble.h index 424dbc4..c306e9a9 100644 --- a/chrome/browser/ui/gtk/global_error_bubble.h +++ b/chrome/browser/ui/gtk/global_error_bubble.h @@ -8,9 +8,9 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/global_error_bubble_view_base.h" #include "chrome/browser/ui/gtk/bubble/bubble_gtk.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" #include "ui/base/gtk/gtk_signal.h" typedef struct _GtkWidget GtkWidget; @@ -19,9 +19,11 @@ class GlobalError; class Profile; class GlobalErrorBubble : public BubbleDelegateGtk, - public content::NotificationObserver { + public GlobalErrorBubbleViewBase { public: - GlobalErrorBubble(Profile* profile, GlobalError* error, GtkWidget* anchor); + GlobalErrorBubble(Browser* browser, + const base::WeakPtr<GlobalError>& error, + GtkWidget* anchor); virtual ~GlobalErrorBubble(); // BubbleDelegateGtk implementation. @@ -32,17 +34,11 @@ class GlobalErrorBubble : public BubbleDelegateGtk, CHROMEGTK_CALLBACK_0(GlobalErrorBubble, void, OnAcceptButton); CHROMEGTK_CALLBACK_0(GlobalErrorBubble, void, OnCancelButton); - // content::NotificationObserver overrides: - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; + virtual void CloseBubbleView() OVERRIDE; + Browser* browser_; BubbleGtk* bubble_; - // Weak reference to the GlobalError instance the bubble is shown for. Is - // reset to |NULL| if instance is removed from GlobalErrorService while - // the bubble is still showing. - GlobalError* error_; - content::NotificationRegistrar registrar_; + base::WeakPtr<GlobalError> error_; DISALLOW_COPY_AND_ASSIGN(GlobalErrorBubble); }; diff --git a/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc b/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc index e6047e46..56a7df8 100644 --- a/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc +++ b/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -39,7 +39,6 @@ class MenuError : public GlobalError { virtual void ExecuteMenuItem(Browser* browser) OVERRIDE { execute_count_++; } virtual bool HasBubbleView() OVERRIDE { return false; } - virtual void ShowBubbleView(Browser* browser) OVERRIDE { ADD_FAILURE(); } virtual int GetBubbleViewIconResourceID() OVERRIDE { ADD_FAILURE(); return 0; @@ -60,9 +59,15 @@ class MenuError : public GlobalError { ADD_FAILURE(); return string16(); } - virtual void BubbleViewDidClose() OVERRIDE { ADD_FAILURE(); } - virtual void BubbleViewAcceptButtonPressed() OVERRIDE { ADD_FAILURE(); } - virtual void BubbleViewCancelButtonPressed() OVERRIDE { ADD_FAILURE(); } + virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE { + ADD_FAILURE(); + } + virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE { + ADD_FAILURE(); + } + virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE { + ADD_FAILURE(); + } private: int command_id_; diff --git a/chrome/browser/ui/views/global_error_bubble_view.cc b/chrome/browser/ui/views/global_error_bubble_view.cc index 9c368da..a801b0f 100644 --- a/chrome/browser/ui/views/global_error_bubble_view.cc +++ b/chrome/browser/ui/views/global_error_bubble_view.cc @@ -11,8 +11,6 @@ #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/toolbar_view.h" #include "chrome/browser/ui/views/window.h" -#include "chrome/common/chrome_notification_types.h" -#include "content/public/browser/notification_service.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/image/image.h" #include "ui/views/controls/button/text_button.h" @@ -40,14 +38,35 @@ const int kLayoutBottomPadding = 2; } // namespace +// GlobalErrorBubbleViewBase --------------------------------------------------- + +// static +GlobalErrorBubbleViewBase* GlobalErrorBubbleViewBase::ShowBubbleView( + Browser* browser, + const base::WeakPtr<GlobalError>& error) { + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); + views::View* wrench_button = browser_view->toolbar()->app_menu(); + GlobalErrorBubbleView* bubble_view = + new GlobalErrorBubbleView(wrench_button, + views::BubbleBorder::TOP_RIGHT, + browser, + error); + browser::CreateViewsBubble(bubble_view); + bubble_view->StartFade(true); + return bubble_view; +} + +// GlobalErrorBubbleView ------------------------------------------------------- + GlobalErrorBubbleView::GlobalErrorBubbleView( views::View* anchor_view, views::BubbleBorder::ArrowLocation location, Browser* browser, - GlobalError* error) + const base::WeakPtr<GlobalError>& error) : BubbleDelegateView(anchor_view, location), browser_(browser), error_(error) { + DCHECK(error_); ResourceBundle& rb = ResourceBundle::GetSharedInstance(); int resource_id = error_->GetBubbleViewIconResourceID(); scoped_ptr<views::ImageView> image_view(new views::ImageView()); @@ -122,9 +141,6 @@ GlobalErrorBubbleView::GlobalErrorBubbleView( // Adjust the message label size in case buttons are too long. message_label->SizeToFit(layout->GetPreferredSize(this).width()); - - registrar_.Add(this, chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED, - content::Source<Profile>(browser->profile())); } GlobalErrorBubbleView::~GlobalErrorBubbleView() { @@ -138,54 +154,22 @@ gfx::Rect GlobalErrorBubbleView::GetAnchorRect() { void GlobalErrorBubbleView::ButtonPressed(views::Button* sender, const views::Event& event) { - // We unsubscribe from removal notifications here and below because any of - // GlobalError callbacks may remove it from the profile. - registrar_.RemoveAll(); - if (sender->tag() == TAG_ACCEPT_BUTTON) - error_->BubbleViewAcceptButtonPressed(); - else if (sender->tag() == TAG_CANCEL_BUTTON) - error_->BubbleViewCancelButtonPressed(); - else - NOTREACHED(); + if (error_) { + if (sender->tag() == TAG_ACCEPT_BUTTON) + error_->BubbleViewAcceptButtonPressed(browser_); + else if (sender->tag() == TAG_CANCEL_BUTTON) + error_->BubbleViewCancelButtonPressed(browser_); + else + NOTREACHED(); + } GetWidget()->Close(); } void GlobalErrorBubbleView::WindowClosing() { - registrar_.RemoveAll(); if (error_) - error_->BubbleViewDidClose(); -} - -void GlobalErrorBubbleView::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK(type == chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED); - DCHECK(error_); - if (content::Details<GlobalError>(details).ptr() == error_) { - Profile* profile = content::Source<Profile>(source).ptr(); - const std::vector<GlobalError*>& errors = - GlobalErrorServiceFactory::GetForProfile(profile)->errors(); - // This handles the case when a GlobalError instance is removed from profile - // not as a part of normal flow (i.e., after the bubble has been closed) - // but while the bubble is still showing. |error_| is no longer guaranteed - // to exist so we set it to |NULL| and dismiss the bubble. - if (std::find(errors.begin(), errors.end(), error_) == errors.end()) { - error_ = NULL; - registrar_.RemoveAll(); - GetWidget()->Close(); - } - } + error_->BubbleViewDidClose(browser_); } -void GlobalError::ShowBubbleView(Browser* browser, GlobalError* error) { - BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); - views::View* wrench_button = browser_view->toolbar()->app_menu(); - GlobalErrorBubbleView* bubble_view = - new GlobalErrorBubbleView(wrench_button, - views::BubbleBorder::TOP_RIGHT, - browser, - error); - browser::CreateViewsBubble(bubble_view); - bubble_view->StartFade(true); +void GlobalErrorBubbleView::CloseBubbleView() { + GetWidget()->Close(); } diff --git a/chrome/browser/ui/views/global_error_bubble_view.h b/chrome/browser/ui/views/global_error_bubble_view.h index 666cd67..116e5be 100644 --- a/chrome/browser/ui/views/global_error_bubble_view.h +++ b/chrome/browser/ui/views/global_error_bubble_view.h @@ -6,8 +6,8 @@ #define CHROME_BROWSER_UI_VIEWS_GLOBAL_ERROR_BUBBLE_VIEW_H_ #pragma once -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/global_error_bubble_view_base.h" #include "ui/views/bubble/bubble_delegate.h" #include "ui/views/controls/button/button.h" @@ -16,12 +16,12 @@ class GlobalError; class GlobalErrorBubbleView : public views::ButtonListener, public views::BubbleDelegateView, - public content::NotificationObserver { + public GlobalErrorBubbleViewBase { public: GlobalErrorBubbleView(views::View* anchor_view, views::BubbleBorder::ArrowLocation location, Browser* browser, - GlobalError* error); + const base::WeakPtr<GlobalError>& error); virtual ~GlobalErrorBubbleView(); // views::BubbleDelegateView implementation. @@ -34,18 +34,12 @@ class GlobalErrorBubbleView : public views::ButtonListener, // views::WidgetDelegate implementation. virtual void WindowClosing() OVERRIDE; - // content::NotificationObserver overrides: - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; + // GlobalErrorBubbleViewBase implementation. + virtual void CloseBubbleView() OVERRIDE; private: Browser* browser_; - // Weak reference to the GlobalError instance the bubble is shown for. Is - // reset to |NULL| if instance is removed from GlobalErrorService while - // the bubble is still showing. - GlobalError* error_; - content::NotificationRegistrar registrar_; + base::WeakPtr<GlobalError> error_; DISALLOW_COPY_AND_ASSIGN(GlobalErrorBubbleView); }; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 26b155f..c7e58f6 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2983,6 +2983,7 @@ 'browser/ui/fullscreen_exit_bubble_type.h', 'browser/ui/global_error.cc', 'browser/ui/global_error.h', + 'browser/ui/global_error_bubble_view_base.h', 'browser/ui/global_error_service.cc', 'browser/ui/global_error_service.h', 'browser/ui/global_error_service_factory.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index e2ca1975..bdb4146 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -3055,8 +3055,6 @@ '../content/renderer/external_popup_menu_browsertest.cc', ], 'sources!': [ - # TODO(ivankr): enable this once http://crbug.com/109728 is fixed. - 'browser/protector/protector_service_browsertest.cc', # TODO(hbono): This test depends on hunspell and we cannot run it on # Mac, which does not use hunspell by default. 'browser/spellchecker/spellcheck_host_browsertest.cc', |