diff options
author | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-18 23:04:52 +0000 |
---|---|---|
committer | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-18 23:04:52 +0000 |
commit | 0d7e8811d119932473dcb7f11632ee4972d19cb6 (patch) | |
tree | dd19e2f189613612a7ed82764bdace2bf5fac374 /chrome/browser | |
parent | 743a1aa270e02d6b5cbf424ba07f1fd77a038f3c (diff) | |
download | chromium_src-0d7e8811d119932473dcb7f11632ee4972d19cb6.zip chromium_src-0d7e8811d119932473dcb7f11632ee4972d19cb6.tar.gz chromium_src-0d7e8811d119932473dcb7f11632ee4972d19cb6.tar.bz2 |
[Mac] If a user clears browsing data with the cookie manager open, update the UI
BUG=32030
TEST=See repro steps in bug report.
Review URL: http://codereview.chromium.org/551058
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36497 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
6 files changed, 147 insertions, 32 deletions
diff --git a/chrome/browser/cocoa/clear_browsing_data_controller.h b/chrome/browser/cocoa/clear_browsing_data_controller.h index 8cded9f..d42f57b 100644 --- a/chrome/browser/cocoa/clear_browsing_data_controller.h +++ b/chrome/browser/cocoa/clear_browsing_data_controller.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2009-2010 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,6 +14,12 @@ class ClearBrowsingObserver; class Profile; @class ThrobberView; +// Name of notification that is called when data is cleared. +extern NSString* const kClearBrowsingDataControllerDidDelete; +// A key in the above notification's userInfo. Contains a NSNumber with the +// logically-ored constants defined in BrowsingDataRemover for the removal. +extern NSString* const kClearBrowsingDataControllerRemoveMask; + // A window controller for managing the "Clear Browsing Data" feature. Modally // presents a dialog offering the user a set of choices of what browsing data // to delete and does so if the user chooses. @@ -74,6 +80,7 @@ class Profile; @property (readonly) int removeMask; - (void)persistToPrefs; - (void)closeDialog; +- (void)dataRemoverDidFinish; @end #endif // CHROME_BROWSER_COCOA_CLEAR_BROWSING_DATA_CONTROLLER_ diff --git a/chrome/browser/cocoa/clear_browsing_data_controller.mm b/chrome/browser/cocoa/clear_browsing_data_controller.mm index 00f2260..4e9e537 100644 --- a/chrome/browser/cocoa/clear_browsing_data_controller.mm +++ b/chrome/browser/cocoa/clear_browsing_data_controller.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2009-2010 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. @@ -12,6 +12,11 @@ #include "chrome/common/pref_service.h" #include "chrome/browser/profile.h" +NSString* const kClearBrowsingDataControllerDidDelete = + @"kClearBrowsingDataControllerDidDelete"; +NSString* const kClearBrowsingDataControllerRemoveMask = + @"kClearBrowsingDataControllerRemoveMask"; + @interface ClearBrowsingDataController(Private) - (void)initFromPrefs; - (void)persistToPrefs; @@ -65,10 +70,12 @@ typedef std::map<Profile*, ClearBrowsingDataController*> ProfileControllerMap; if (it == map->end()) { // Since we don't currently support multiple profiles, this class // has not been tested against this case. - DCHECK_EQ(map->size(), 0U); + if (map->size() != 0) { + return nil; + } ClearBrowsingDataController* controller = - [[self alloc] initWithProfile:profile]; + [[self alloc] initWithProfile:profile]; it = map->insert(std::make_pair(profile, controller)).first; } return it->second; @@ -192,6 +199,15 @@ typedef std::map<Profile*, ClearBrowsingDataController*> ProfileControllerMap; // Called when the data remover object is done with its work. Close the window. // The remover will delete itself. End the modal session at this point. - (void)dataRemoverDidFinish { + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; + int removeMask = [self removeMask]; + NSDictionary* userInfo = + [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:removeMask] + forKey:kClearBrowsingDataControllerRemoveMask]; + [center postNotificationName:kClearBrowsingDataControllerDidDelete + object:self + userInfo:userInfo]; + [self closeDialog]; [[self window] orderOut:self]; [self setIsClearing:NO]; diff --git a/chrome/browser/cocoa/clear_browsing_data_controller_unittest.mm b/chrome/browser/cocoa/clear_browsing_data_controller_unittest.mm index 7c53e19..e4dfd35 100644 --- a/chrome/browser/cocoa/clear_browsing_data_controller_unittest.mm +++ b/chrome/browser/cocoa/clear_browsing_data_controller_unittest.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2009-2010 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,6 +14,7 @@ #include "chrome/common/pref_service.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" namespace { @@ -124,4 +125,31 @@ TEST_F(ClearBrowsingDataControllerTest, SameControllerForProfile) { EXPECT_EQ(controller_, controller); } +TEST_F(ClearBrowsingDataControllerTest, DataRemoverDidFinish) { + id observer = [OCMockObject observerMock]; + // Don't use |controller_| as the object because it will free itself twice + // because both |-dataRemoverDidFinish| and TearDown() call |-closeDialog|. + ClearBrowsingDataController* controller = + [[ClearBrowsingDataController alloc] initWithProfile:helper_.profile()]; + + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; + [center addMockObserver:observer + name:kClearBrowsingDataControllerDidDelete + object:controller]; + + int mask = [controller removeMask]; + NSDictionary* expectedInfo = + [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:mask] + forKey:kClearBrowsingDataControllerRemoveMask]; + [[observer expect] + notificationWithName:kClearBrowsingDataControllerDidDelete + object:controller + userInfo:expectedInfo]; + + // This calls |-closeDialog| and cleans the controller up. + [controller dataRemoverDidFinish]; + + [observer verify]; +} + } // namespace diff --git a/chrome/browser/cocoa/cookies_window_controller.h b/chrome/browser/cocoa/cookies_window_controller.h index c234742..b7ca506 100644 --- a/chrome/browser/cocoa/cookies_window_controller.h +++ b/chrome/browser/cocoa/cookies_window_controller.h @@ -112,6 +112,8 @@ class CookiesTreeModelObserverBridge : public TreeModelObserver { @end @interface CookiesWindowController (UnitTesting) +- (void)clearBrowsingDataNotification:(NSNotification*)notif; - (CookiesTreeModelObserverBridge*)modelObserver; - (NSArray*)icons; +- (void)loadTreeModelFromProfile; @end diff --git a/chrome/browser/cocoa/cookies_window_controller.mm b/chrome/browser/cocoa/cookies_window_controller.mm index 25d4120..8f925fd 100644 --- a/chrome/browser/cocoa/cookies_window_controller.mm +++ b/chrome/browser/cocoa/cookies_window_controller.mm @@ -11,6 +11,8 @@ #import "base/i18n/time_formatting.h" #import "base/mac_util.h" #include "base/sys_string_conversions.h" +#include "chrome/browser/browsing_data_remover.h" +#include "chrome/browser/cocoa/clear_browsing_data_controller.h" #include "chrome/browser/profile.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" @@ -28,9 +30,9 @@ CookiesTreeModelObserverBridge::CookiesTreeModelObserverBridge( // Notification that nodes were added to the specified parent. void CookiesTreeModelObserverBridge::TreeNodesAdded(TreeModel* model, - TreeModelNode* parent, - int start, - int count) { + TreeModelNode* parent, + int start, + int count) { CocoaCookieTreeNode* cocoa_parent = FindCocoaNode(parent, nil); NSMutableArray* cocoa_children = [cocoa_parent children]; @@ -46,9 +48,9 @@ void CookiesTreeModelObserverBridge::TreeNodesAdded(TreeModel* model, // Notification that nodes were removed from the specified parent. void CookiesTreeModelObserverBridge::TreeNodesRemoved(TreeModel* model, - TreeModelNode* parent, - int start, - int count) { + TreeModelNode* parent, + int start, + int count) { CocoaCookieTreeNode* cocoa_parent = FindCocoaNode(parent, nil); [window_controller_ willChangeValueForKey:kCocoaTreeModel]; NSMutableArray* cocoa_children = [cocoa_parent children]; @@ -85,7 +87,7 @@ void CookiesTreeModelObserverBridge::TreeNodeChildrenReordered(TreeModel* model, // Notification that the contents of a node has changed. void CookiesTreeModelObserverBridge::TreeNodeChanged(TreeModel* model, - TreeModelNode* node) { + TreeModelNode* node) { [window_controller_ willChangeValueForKey:kCocoaTreeModel]; CocoaCookieTreeNode* changed_node = FindCocoaNode(node, nil); [changed_node rebuild]; @@ -134,31 +136,28 @@ CocoaCookieTreeNode* CookiesTreeModelObserverBridge::FindCocoaNode( ofType:@"nib"]; if ((self = [super initWithWindowNibPath:nibpath owner:self])) { profile_ = profile; - treeModel_.reset(new CookiesTreeModel(profile_)); - modelObserver_.reset(new CookiesTreeModelObserverBridge(self)); - treeModel_->SetObserver(modelObserver_.get()); - - // Convert the model's icons from Skia to Cocoa. - std::vector<SkBitmap> skiaIcons; - treeModel_->GetIcons(&skiaIcons); - icons_.reset([[NSMutableArray alloc] init]); - for (std::vector<SkBitmap>::iterator it = skiaIcons.begin(); - it != skiaIcons.end(); ++it) { - [icons_ addObject:gfx::SkBitmapToNSImage(*it)]; - } - - // Default icon will be the last item in the array. - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - // TODO(rsesek): Rename this resource now that it's in multiple places. - [icons_ addObject:rb.GetNSImageNamed(IDR_BOOKMARK_BAR_FOLDER)]; - // Create the Cocoa model. - CookieTreeNode* root = static_cast<CookieTreeNode*>(treeModel_->GetRoot()); - cocoaTreeModel_.reset([[CocoaCookieTreeNode alloc] initWithNode:root]); + [self loadTreeModelFromProfile]; + + // Register for Clear Browsing Data controller so we update appropriately. + ClearBrowsingDataController* clearingController = + [ClearBrowsingDataController controllerForProfile:profile_]; + if (clearingController) { + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; + [center addObserver:self + selector:@selector(clearBrowsingDataNotification:) + name:kClearBrowsingDataControllerDidDelete + object:clearingController]; + } } return self; } +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + - (void)awakeFromNib { DCHECK([self window]); DCHECK_EQ(self, [[self window] delegate]); @@ -208,6 +207,14 @@ CocoaCookieTreeNode* CookiesTreeModelObserverBridge::FindCocoaNode( [NSApp endSheet:[self window]]; } +- (void)clearBrowsingDataNotification:(NSNotification*)notif { + NSNumber* removeMask = + [[notif userInfo] objectForKey:kClearBrowsingDataControllerRemoveMask]; + if ([removeMask intValue] & BrowsingDataRemover::REMOVE_COOKIES) { + [self loadTreeModelFromProfile]; + } +} + #pragma mark Getters and Setters - (CocoaCookieTreeNode*)cocoaTreeModel { @@ -265,4 +272,32 @@ CocoaCookieTreeNode* CookiesTreeModelObserverBridge::FindCocoaNode( return icons_.get(); } +// Re-initializes the |treeModel_|, creates a new observer for it, and re- +// builds the |cocoaTreeModel_|. We use this to initialize the controller and +// to rebuild after the user clears browsing data. Because the models get +// clobbered, we rebuild the icon cache for safety (though they do not change). +- (void)loadTreeModelFromProfile { + treeModel_.reset(new CookiesTreeModel(profile_)); + modelObserver_.reset(new CookiesTreeModelObserverBridge(self)); + treeModel_->SetObserver(modelObserver_.get()); + + // Convert the model's icons from Skia to Cocoa. + std::vector<SkBitmap> skiaIcons; + treeModel_->GetIcons(&skiaIcons); + icons_.reset([[NSMutableArray alloc] init]); + for (std::vector<SkBitmap>::iterator it = skiaIcons.begin(); + it != skiaIcons.end(); ++it) { + [icons_ addObject:gfx::SkBitmapToNSImage(*it)]; + } + + // Default icon will be the last item in the array. + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + // TODO(rsesek): Rename this resource now that it's in multiple places. + [icons_ addObject:rb.GetNSImageNamed(IDR_BOOKMARK_BAR_FOLDER)]; + + // Create the Cocoa model. + CookieTreeNode* root = static_cast<CookieTreeNode*>(treeModel_->GetRoot()); + [self setCocoaTreeModel:[[CocoaCookieTreeNode alloc] initWithNode:root]]; +} + @end diff --git a/chrome/browser/cocoa/cookies_window_controller_unittest.mm b/chrome/browser/cocoa/cookies_window_controller_unittest.mm index 0c8cb58..6d41b58 100644 --- a/chrome/browser/cocoa/cookies_window_controller_unittest.mm +++ b/chrome/browser/cocoa/cookies_window_controller_unittest.mm @@ -8,6 +8,8 @@ #import "base/scoped_nsobject.h" #include "base/scoped_ptr.h" #include "chrome/browser/cocoa/browser_test_helper.h" +#include "chrome/browser/browsing_data_remover.h" +#include "chrome/browser/cocoa/clear_browsing_data_controller.h" #import "chrome/browser/cocoa/cookies_window_controller.h" #include "chrome/browser/cocoa/cocoa_test_helper.h" #include "chrome/browser/net/url_request_context_getter.h" @@ -407,4 +409,29 @@ TEST_F(CookiesWindowControllerTest, TestDidExpandItem) { [outlineView verify]; } +TEST_F(CookiesWindowControllerTest, ClearBrowsingData) { + const GURL url = GURL("http://foo.com"); + TestingProfile* profile = browser_helper_.profile(); + net::CookieMonster* cm = profile->GetCookieMonster(); + cm->SetCookie(url, "A=B"); + cm->SetCookie(url, "C=D"); + cm->SetCookie(url, "E=F"); + + id mock = [OCMockObject partialMockForObject:controller_.get()]; + [[mock expect] loadTreeModelFromProfile]; + + NSNumber* mask = + [NSNumber numberWithInt:BrowsingDataRemover::REMOVE_COOKIES]; + NSDictionary* userInfo = + [NSDictionary dictionaryWithObject:mask + forKey:kClearBrowsingDataControllerRemoveMask]; + NSNotification* notif = + [NSNotification notificationWithName:kClearBrowsingDataControllerDidDelete + object:nil + userInfo:userInfo]; + [controller_ clearBrowsingDataNotification:notif]; + + [mock verify]; +} + } // namespace |