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

Side by Side Diff: chrome/browser/cocoa/clear_browsing_data_controller.mm

Issue 3590020: [Mac] UI for clearing sync data on the server.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/cocoa/clear_browsing_data_controller.h" 5 #import "chrome/browser/cocoa/clear_browsing_data_controller.h"
6 6
7 #include "app/l10n_util.h" 7 #include "app/l10n_util.h"
8 #include "base/command_line.h"
8 #include "base/mac_util.h" 9 #include "base/mac_util.h"
9 #include "base/scoped_nsobject.h" 10 #include "base/scoped_nsobject.h"
10 #include "base/singleton.h" 11 #include "base/singleton.h"
11 #include "chrome/browser/browser.h" 12 #include "chrome/browser/browser.h"
12 #include "chrome/browser/browser_window.h" 13 #include "chrome/browser/browser_window.h"
13 #include "chrome/browser/browsing_data_remover.h" 14 #include "chrome/browser/browsing_data_remover.h"
15 #include "chrome/browser/platform_util.h"
14 #include "chrome/browser/prefs/pref_service.h" 16 #include "chrome/browser/prefs/pref_service.h"
15 #include "chrome/browser/profile.h" 17 #include "chrome/browser/profile.h"
18 #include "chrome/browser/sync/profile_sync_service.h"
19 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names.h"
21 #include "grit/generated_resources.h"
17 #include "grit/locale_settings.h" 22 #include "grit/locale_settings.h"
18 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" 23 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
19 24
20 NSString* const kClearBrowsingDataControllerDidDelete = 25 NSString* const kClearBrowsingDataControllerDidDelete =
21 @"kClearBrowsingDataControllerDidDelete"; 26 @"kClearBrowsingDataControllerDidDelete";
22 NSString* const kClearBrowsingDataControllerRemoveMask = 27 NSString* const kClearBrowsingDataControllerRemoveMask =
23 @"kClearBrowsingDataControllerRemoveMask"; 28 @"kClearBrowsingDataControllerRemoveMask";
24 29
30 namespace {
31
32 // Compare function for -[NSArray sortedArrayUsingFunction:context:] that
33 // sorts the views in Y order top down.
34 NSInteger CompareFrameY(id view1, id view2, void* context) {
35 CGFloat y1 = NSMinY([view1 frame]);
36 CGFloat y2 = NSMinY([view2 frame]);
37 if (y1 < y2)
38 return NSOrderedDescending;
39 else if (y1 > y2)
40 return NSOrderedAscending;
41 else
42 return NSOrderedSame;
43 }
44
45 typedef std::map<Profile*, ClearBrowsingDataController*> ProfileControllerMap;
46
47 } // namespace
48
25 @interface ClearBrowsingDataController(Private) 49 @interface ClearBrowsingDataController(Private)
26 - (void)initFromPrefs; 50 - (void)initFromPrefs;
27 - (void)persistToPrefs; 51 - (void)persistToPrefs;
28 - (void)dataRemoverDidFinish; 52 - (void)dataRemoverDidFinish;
53 - (void)syncStateChanged;
29 @end 54 @end
30 55
31 class ClearBrowsingObserver : public BrowsingDataRemover::Observer { 56 class ClearBrowsingObserver : public BrowsingDataRemover::Observer,
57 public ProfileSyncServiceObserver {
32 public: 58 public:
33 ClearBrowsingObserver(ClearBrowsingDataController* controller) 59 ClearBrowsingObserver(ClearBrowsingDataController* controller)
34 : controller_(controller) { } 60 : controller_(controller) { }
35 void OnBrowsingDataRemoverDone() { [controller_ dataRemoverDidFinish]; } 61 void OnBrowsingDataRemoverDone() { [controller_ dataRemoverDidFinish]; }
62 void OnStateChanged() { [controller_ syncStateChanged]; }
36 private: 63 private:
37 ClearBrowsingDataController* controller_; 64 ClearBrowsingDataController* controller_;
38 }; 65 };
39 66
40 namespace {
41
42 typedef std::map<Profile*, ClearBrowsingDataController*> ProfileControllerMap;
43
44 } // namespace
45
46 @implementation ClearBrowsingDataController 67 @implementation ClearBrowsingDataController
47 68
48 @synthesize clearBrowsingHistory = clearBrowsingHistory_; 69 @synthesize clearBrowsingHistory = clearBrowsingHistory_;
49 @synthesize clearDownloadHistory = clearDownloadHistory_; 70 @synthesize clearDownloadHistory = clearDownloadHistory_;
50 @synthesize emptyCache = emptyCache_; 71 @synthesize emptyCache = emptyCache_;
51 @synthesize deleteCookies = deleteCookies_; 72 @synthesize deleteCookies = deleteCookies_;
52 @synthesize clearSavedPasswords = clearSavedPasswords_; 73 @synthesize clearSavedPasswords = clearSavedPasswords_;
53 @synthesize clearFormData = clearFormData_; 74 @synthesize clearFormData = clearFormData_;
54 @synthesize timePeriod = timePeriod_; 75 @synthesize timePeriod = timePeriod_;
55 @synthesize isClearing = isClearing_; 76 @synthesize isClearing = isClearing_;
77 @synthesize clearingStatus = clearingStatus_;
56 78
57 + (void)showClearBrowsingDialogForProfile:(Profile*)profile { 79 + (void)showClearBrowsingDialogForProfile:(Profile*)profile {
58 ClearBrowsingDataController* controller = 80 ClearBrowsingDataController* controller =
59 [ClearBrowsingDataController controllerForProfile:profile]; 81 [ClearBrowsingDataController controllerForProfile:profile];
60 if (![controller isWindowLoaded]) { 82 if (![controller isWindowLoaded]) {
61 // This function needs to return instead of blocking, to match the windows 83 // This function needs to return instead of blocking, to match the Windows
62 // api call. It caused problems when launching the dialog from the 84 // version. It caused problems when launching the dialog from the
63 // DomUI history page. See bug and code review for more details. 85 // DomUI history page. See bug and code review for more details.
64 // http://crbug.com/37976 86 // http://crbug.com/37976
65 [controller performSelector:@selector(runModalDialog) 87 [controller performSelector:@selector(runModalDialog)
66 withObject:nil 88 withObject:nil
67 afterDelay:0]; 89 afterDelay:0];
68 } 90 }
69 } 91 }
70 92
71 + (ClearBrowsingDataController *)controllerForProfile:(Profile*)profile { 93 + (ClearBrowsingDataController *)controllerForProfile:(Profile*)profile {
72 // Get the original profile in case we get here from an incognito window 94 // Get the original profile in case we get here from an incognito window
73 // |GetOriginalProfile()| will return the same profile if it is the original 95 // |GetOriginalProfile()| will return the same profile if it is the original
(...skipping 20 matching lines...) Expand all
94 - (id)initWithProfile:(Profile*)profile { 116 - (id)initWithProfile:(Profile*)profile {
95 DCHECK(profile); 117 DCHECK(profile);
96 // Use initWithWindowNibPath:: instead of initWithWindowNibName: so we 118 // Use initWithWindowNibPath:: instead of initWithWindowNibName: so we
97 // can override it in a unit test. 119 // can override it in a unit test.
98 NSString *nibpath = [mac_util::MainAppBundle() 120 NSString *nibpath = [mac_util::MainAppBundle()
99 pathForResource:@"ClearBrowsingData" 121 pathForResource:@"ClearBrowsingData"
100 ofType:@"nib"]; 122 ofType:@"nib"];
101 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { 123 if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
102 profile_ = profile; 124 profile_ = profile;
103 observer_.reset(new ClearBrowsingObserver(self)); 125 observer_.reset(new ClearBrowsingObserver(self));
126 profile_->GetProfileSyncService()->ResetClearServerDataState();
127 profile_->GetProfileSyncService()->AddObserver(observer_.get());
104 [self initFromPrefs]; 128 [self initFromPrefs];
105 } 129 }
106 return self; 130 return self;
107 } 131 }
108 132
109 - (void)dealloc { 133 - (void)dealloc {
110 if (remover_) { 134 if (remover_) {
111 // We were destroyed while clearing history was in progress. This can only 135 // We were destroyed while clearing history was in progress. This can only
112 // occur during automated tests (normally the user can't close the dialog 136 // occur during automated tests (normally the user can't close the dialog
113 // while clearing is in progress as the dialog is modal and not closeable). 137 // while clearing is in progress as the dialog is modal and not closeable).
114 remover_->RemoveObserver(observer_.get()); 138 remover_->RemoveObserver(observer_.get());
115 } 139 }
140 profile_->GetProfileSyncService()->RemoveObserver(observer_.get());
141 [self setClearingStatus:nil];
116 142
117 [super dealloc]; 143 [super dealloc];
118 } 144 }
119 145
120 // Run application modal. 146 // Run application modal.
121 - (void)runModalDialog { 147 - (void)runModalDialog {
122 // Check again to make sure there is only one window. Since we use 148 // Check again to make sure there is only one window. Since we use
123 // |performSelector:afterDelay:| it is possible for this to somehow be 149 // |performSelector:afterDelay:| it is possible for this to somehow be
124 // triggered twice. 150 // triggered twice.
125 DCHECK([NSThread isMainThread]); 151 DCHECK([NSThread isMainThread]);
126 if (![self isWindowLoaded]) { 152 if (![self isWindowLoaded]) {
127 // The Window size in the nib is a min size, loop over the views collecting 153 // It takes two passes to adjust the window size. The first pass is to
128 // the max they grew by, that is how much the window needs to be widened by. 154 // determine the width of all the non-wrappable items. The window is then
155 // resized to that width. Once the width is fixed, the heights of the
156 // variable-height items can then be calculated, the items can be spaced,
157 // and the window resized (again) if necessary.
158
159 NSWindow* window = [self window];
160
161 // Adjust the widths of non-wrappable items.
129 CGFloat maxWidthGrowth = 0.0; 162 CGFloat maxWidthGrowth = 0.0;
130 NSWindow* window = [self window];
131 NSView* contentView = [window contentView];
132 Class widthBasedTweakerClass = [GTMWidthBasedTweaker class]; 163 Class widthBasedTweakerClass = [GTMWidthBasedTweaker class];
133 for (id subView in [contentView subviews]) { 164 for (NSTabViewItem* tabViewItem in [tabView_ tabViewItems])
134 if ([subView isKindOfClass:widthBasedTweakerClass]) { 165 for (NSView* subView in [[tabViewItem view] subviews])
135 GTMWidthBasedTweaker* tweaker = subView; 166 if ([subView isKindOfClass:widthBasedTweakerClass]) {
136 CGFloat delta = [tweaker changedWidth]; 167 GTMWidthBasedTweaker* tweaker = (GTMWidthBasedTweaker*)subView;
137 maxWidthGrowth = std::max(maxWidthGrowth, delta); 168 CGFloat delta = [tweaker changedWidth];
169 maxWidthGrowth = std::max(maxWidthGrowth, delta);
170 }
171
172 // Adjust the width of the window.
173 if (maxWidthGrowth > 0.0) {
174 NSSize adjustSize = NSMakeSize(maxWidthGrowth, 0);
175 adjustSize = [[window contentView] convertSize:adjustSize toView:nil];
176 NSRect windowFrame = [window frame];
177 windowFrame.size.width += adjustSize.width;
178 [window setFrame:windowFrame display:NO];
179 }
180
181 // Adjust the heights and locations of the items on the "Other data" tab.
182 CGFloat cumulativeHeightGrowth = 0.0;
183 NSArray* subViews =
184 [[otherDataTab_ subviews] sortedArrayUsingFunction:CompareFrameY
185 context:NULL];
186 for (NSView* view in subViews) {
187 if ([view isHidden])
188 continue;
189
190 if ([objectsToVerticallySize_ containsObject:view]) {
191 DCHECK([view isKindOfClass:[NSTextField class]]);
192 CGFloat viewHeightGrowth = [GTMUILocalizerAndLayoutTweaker
193 sizeToFitFixedWidthTextField:(NSTextField*)view];
194 if (viewHeightGrowth > 0.0)
195 cumulativeHeightGrowth += viewHeightGrowth;
138 } 196 }
197
198 NSRect viewFrame = [view frame];
199 viewFrame.origin.y -= cumulativeHeightGrowth;
200 [view setFrame:viewFrame];
139 } 201 }
140 if (maxWidthGrowth > 0.0) { 202
141 NSRect rect = [contentView convertRect:[window frame] fromView:nil]; 203 // Adjust the height of the window.
142 rect.size.width += maxWidthGrowth; 204 if (cumulativeHeightGrowth > 0.0) {
143 rect = [contentView convertRect:rect toView:nil]; 205 NSSize adjustSize = NSMakeSize(0, cumulativeHeightGrowth);
144 [window setFrame:rect display:NO]; 206 adjustSize = [[window contentView] convertSize:adjustSize toView:nil];
145 // For some reason the content view is resizing, but some times not 207 NSRect windowFrame = [window frame];
146 // adjusting its origin, so correct it manually. 208 windowFrame.size.height += adjustSize.height;
147 [contentView setFrameOrigin:NSZeroPoint]; 209 [window setFrame:windowFrame display:NO];
148 } 210 }
211
149 // Now start the modal loop. 212 // Now start the modal loop.
150 [NSApp runModalForWindow:window]; 213 [NSApp runModalForWindow:window];
151 } 214 }
152 } 215 }
153 216
154 - (int)removeMask { 217 - (int)removeMask {
155 int removeMask = 0L; 218 int removeMask = 0L;
156 if (clearBrowsingHistory_) 219 if (clearBrowsingHistory_)
157 removeMask |= BrowsingDataRemover::REMOVE_HISTORY; 220 removeMask |= BrowsingDataRemover::REMOVE_HISTORY;
158 if (clearDownloadHistory_) 221 if (clearDownloadHistory_)
159 removeMask |= BrowsingDataRemover::REMOVE_DOWNLOADS; 222 removeMask |= BrowsingDataRemover::REMOVE_DOWNLOADS;
160 if (emptyCache_) 223 if (emptyCache_)
161 removeMask |= BrowsingDataRemover::REMOVE_CACHE; 224 removeMask |= BrowsingDataRemover::REMOVE_CACHE;
162 if (deleteCookies_) 225 if (deleteCookies_)
163 removeMask |= BrowsingDataRemover::REMOVE_COOKIES; 226 removeMask |= BrowsingDataRemover::REMOVE_COOKIES;
164 if (clearSavedPasswords_) 227 if (clearSavedPasswords_)
165 removeMask |= BrowsingDataRemover::REMOVE_PASSWORDS; 228 removeMask |= BrowsingDataRemover::REMOVE_PASSWORDS;
166 if (clearFormData_) 229 if (clearFormData_)
167 removeMask |= BrowsingDataRemover::REMOVE_FORM_DATA; 230 removeMask |= BrowsingDataRemover::REMOVE_FORM_DATA;
168 return removeMask; 231 return removeMask;
169 } 232 }
170 233
171 // Called when the user clicks the "clear" button. Do the work and persist 234 // Called when the user clicks the "clear" button. Do the work and persist
172 // the prefs for next time. We don't stop the modal session until we get 235 // the prefs for next time. We don't stop the modal session until we get
173 // the callback from the BrowsingDataRemover so the window stays on the screen. 236 // the callback from the BrowsingDataRemover so the window stays on the screen.
174 // While we're working, dim the buttons so the user can't click them. 237 // While we're working, dim the buttons so the user can't click them.
175 - (IBAction)clearData:(id)sender { 238 - (IBAction)clearData:(id)sender {
176 // Set that we're working so that the buttons disable. 239 // Set that we're working so that the buttons disable.
240 [self setClearingStatus:l10n_util::GetNSString(IDS_CLEAR_DATA_DELETING)];
177 [self setIsClearing:YES]; 241 [self setIsClearing:YES];
178 242
179 [self persistToPrefs]; 243 [self persistToPrefs];
180 244
181 // BrowsingDataRemover deletes itself when done. 245 // BrowsingDataRemover deletes itself when done.
182 remover_ = new BrowsingDataRemover(profile_, 246 remover_ = new BrowsingDataRemover(profile_,
183 static_cast<BrowsingDataRemover::TimePeriod>(timePeriod_), 247 static_cast<BrowsingDataRemover::TimePeriod>(timePeriod_),
184 base::Time()); 248 base::Time());
185 remover_->AddObserver(observer_.get()); 249 remover_->AddObserver(observer_.get());
186 remover_->Remove([self removeMask]); 250 remover_->Remove([self removeMask]);
(...skipping 10 matching lines...) Expand all
197 // The "Clear Data" dialog is app-modal on OS X. Hence, close it before 261 // The "Clear Data" dialog is app-modal on OS X. Hence, close it before
198 // opening a tab with flash settings. 262 // opening a tab with flash settings.
199 [self closeDialog]; 263 [self closeDialog];
200 264
201 Browser* browser = Browser::Create(profile_); 265 Browser* browser = Browser::Create(profile_);
202 browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_URL)), 266 browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_URL)),
203 GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); 267 GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
204 browser->window()->Show(); 268 browser->window()->Show();
205 } 269 }
206 270
271 - (IBAction)openGoogleDashboard:(id)sender {
272 // The "Clear Data" dialog is app-modal on OS X. Hence, close it before
273 // opening a tab with the dashboard.
274 [self closeDialog];
275
276 Browser* browser = Browser::Create(profile_);
277 browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_PRIVACY_DASHBOARD_URL)),
278 GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
279 browser->window()->Show();
280 }
281
207 - (void)closeDialog { 282 - (void)closeDialog {
208 ProfileControllerMap* map = Singleton<ProfileControllerMap>::get(); 283 ProfileControllerMap* map = Singleton<ProfileControllerMap>::get();
209 ProfileControllerMap::iterator it = map->find(profile_); 284 ProfileControllerMap::iterator it = map->find(profile_);
210 if (it != map->end()) { 285 if (it != map->end()) {
211 map->erase(it); 286 map->erase(it);
212 } 287 }
213 [self autorelease]; 288 [self autorelease];
214 [[self window] orderOut:self]; 289 [[self window] orderOut:self];
215 [NSApp stopModal]; 290 [NSApp stopModal];
216 } 291 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; 324 NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
250 int removeMask = [self removeMask]; 325 int removeMask = [self removeMask];
251 NSDictionary* userInfo = 326 NSDictionary* userInfo =
252 [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:removeMask] 327 [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:removeMask]
253 forKey:kClearBrowsingDataControllerRemoveMask]; 328 forKey:kClearBrowsingDataControllerRemoveMask];
254 [center postNotificationName:kClearBrowsingDataControllerDidDelete 329 [center postNotificationName:kClearBrowsingDataControllerDidDelete
255 object:self 330 object:self
256 userInfo:userInfo]; 331 userInfo:userInfo];
257 332
258 [self closeDialog]; 333 [self closeDialog];
259 [[self window] orderOut:self]; 334 [self setClearingStatus:nil];
260 [self setIsClearing:NO]; 335 [self setIsClearing:NO];
261 remover_ = NULL; 336 remover_ = NULL;
262 } 337 }
263 338
339 - (IBAction)stopSyncAndDeleteData:(id)sender {
340 // Protect against the unlikely case where the server received a message, and
341 // the syncer syncs and resets itself before the user tries pressing the Clear
342 // button in this dialog again. TODO(raz) Confirm whether we have an issue
343 // here
344 if (profile_->GetProfileSyncService()->HasSyncSetupCompleted()) {
345 bool clear = platform_util::SimpleYesNoBox(
346 nil,
347 l10n_util::GetStringUTF16(IDS_CONFIRM_CLEAR_TITLE),
348 l10n_util::GetStringUTF16(IDS_CONFIRM_CLEAR_DESCRIPTION));
349 if (clear) {
350 profile_->GetProfileSyncService()->ClearServerData();
351 [self syncStateChanged];
352 }
353 }
354 }
355
356 - (void)syncStateChanged {
357 bool deleteInProgress = false;
358
359 ProfileSyncService::ClearServerDataState clearState =
360 profile_->GetProfileSyncService()->GetClearServerDataState();
361 profile_->GetProfileSyncService()->ResetClearServerDataState();
362
363 switch (clearState) {
364 case ProfileSyncService::CLEAR_NOT_STARTED:
365 // This can occur on a first start and after a failed clear (which does
366 // not close the tab). Do nothing.
367 break;
368 case ProfileSyncService::CLEAR_CLEARING:
369 // Clearing buttons on all tabs are disabled at this point, throbber is
370 // going.
371 [self setClearingStatus:l10n_util::GetNSString(IDS_CLEAR_DATA_SENDING)];
372 deleteInProgress = true;
373 break;
374 case ProfileSyncService::CLEAR_FAILED:
375 // Show an error and reallow clearing.
376 [self setClearingStatus:l10n_util::GetNSString(IDS_CLEAR_DATA_ERROR)];
377 deleteInProgress = false;
378 break;
379 case ProfileSyncService::CLEAR_SUCCEEDED:
380 // Close the dialog box, success!
381 [self setClearingStatus:nil];
382 deleteInProgress = false;
383 [self closeDialog];
384 break;
385 }
386
387 [self setIsClearing:deleteInProgress];
388 }
389
390 - (BOOL)isSyncEnabled {
391 BOOL allowClearServerDataUI =
392 CommandLine::ForCurrentProcess()->HasSwitch(
393 switches::kEnableClearServerData);
394
395 return allowClearServerDataUI &&
396 profile_->GetProfileSyncService()->HasSyncSetupCompleted();
397 }
398
399 - (NSFont*)labelFont {
400 return [NSFont boldSystemFontOfSize:13];
401 }
402
264 @end 403 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698