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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/cocoa/clear_browsing_data_controller.mm
===================================================================
--- chrome/browser/cocoa/clear_browsing_data_controller.mm (revision 61509)
+++ chrome/browser/cocoa/clear_browsing_data_controller.mm (working copy)
@@ -5,15 +5,20 @@
#import "chrome/browser/cocoa/clear_browsing_data_controller.h"
#include "app/l10n_util.h"
+#include "base/command_line.h"
#include "base/mac_util.h"
#include "base/scoped_nsobject.h"
#include "base/singleton.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/browsing_data_remover.h"
+#include "chrome/browser/platform_util.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
@@ -22,27 +27,43 @@
NSString* const kClearBrowsingDataControllerRemoveMask =
@"kClearBrowsingDataControllerRemoveMask";
+namespace {
+
+// Compare function for -[NSArray sortedArrayUsingFunction:context:] that
+// sorts the views in Y order top down.
+NSInteger CompareFrameY(id view1, id view2, void* context) {
+ CGFloat y1 = NSMinY([view1 frame]);
+ CGFloat y2 = NSMinY([view2 frame]);
+ if (y1 < y2)
+ return NSOrderedDescending;
+ else if (y1 > y2)
+ return NSOrderedAscending;
+ else
+ return NSOrderedSame;
+}
+
+typedef std::map<Profile*, ClearBrowsingDataController*> ProfileControllerMap;
+
+} // namespace
+
@interface ClearBrowsingDataController(Private)
- (void)initFromPrefs;
- (void)persistToPrefs;
- (void)dataRemoverDidFinish;
+- (void)syncStateChanged;
@end
-class ClearBrowsingObserver : public BrowsingDataRemover::Observer {
+class ClearBrowsingObserver : public BrowsingDataRemover::Observer,
+ public ProfileSyncServiceObserver {
public:
ClearBrowsingObserver(ClearBrowsingDataController* controller)
: controller_(controller) { }
void OnBrowsingDataRemoverDone() { [controller_ dataRemoverDidFinish]; }
+ void OnStateChanged() { [controller_ syncStateChanged]; }
private:
ClearBrowsingDataController* controller_;
};
-namespace {
-
-typedef std::map<Profile*, ClearBrowsingDataController*> ProfileControllerMap;
-
-} // namespace
-
@implementation ClearBrowsingDataController
@synthesize clearBrowsingHistory = clearBrowsingHistory_;
@@ -53,14 +74,15 @@
@synthesize clearFormData = clearFormData_;
@synthesize timePeriod = timePeriod_;
@synthesize isClearing = isClearing_;
+@synthesize clearingStatus = clearingStatus_;
+ (void)showClearBrowsingDialogForProfile:(Profile*)profile {
ClearBrowsingDataController* controller =
[ClearBrowsingDataController controllerForProfile:profile];
if (![controller isWindowLoaded]) {
- // This function needs to return instead of blocking, to match the windows
- // api call. It caused problems when launching the dialog from the
- // DomUI history page. See bug and code review for more details.
+ // This function needs to return instead of blocking, to match the Windows
+ // version. It caused problems when launching the dialog from the
+ // DomUI history page. See bug and code review for more details.
// http://crbug.com/37976
[controller performSelector:@selector(runModalDialog)
withObject:nil
@@ -101,6 +123,8 @@
if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
profile_ = profile;
observer_.reset(new ClearBrowsingObserver(self));
+ profile_->GetProfileSyncService()->ResetClearServerDataState();
+ profile_->GetProfileSyncService()->AddObserver(observer_.get());
[self initFromPrefs];
}
return self;
@@ -113,6 +137,8 @@
// while clearing is in progress as the dialog is modal and not closeable).
remover_->RemoveObserver(observer_.get());
}
+ profile_->GetProfileSyncService()->RemoveObserver(observer_.get());
+ [self setClearingStatus:nil];
[super dealloc];
}
@@ -124,28 +150,65 @@
// triggered twice.
DCHECK([NSThread isMainThread]);
if (![self isWindowLoaded]) {
- // The Window size in the nib is a min size, loop over the views collecting
- // the max they grew by, that is how much the window needs to be widened by.
+ // It takes two passes to adjust the window size. The first pass is to
+ // determine the width of all the non-wrappable items. The window is then
+ // resized to that width. Once the width is fixed, the heights of the
+ // variable-height items can then be calculated, the items can be spaced,
+ // and the window resized (again) if necessary.
+
+ NSWindow* window = [self window];
+
+ // Adjust the widths of non-wrappable items.
CGFloat maxWidthGrowth = 0.0;
- NSWindow* window = [self window];
- NSView* contentView = [window contentView];
Class widthBasedTweakerClass = [GTMWidthBasedTweaker class];
- for (id subView in [contentView subviews]) {
- if ([subView isKindOfClass:widthBasedTweakerClass]) {
- GTMWidthBasedTweaker* tweaker = subView;
- CGFloat delta = [tweaker changedWidth];
- maxWidthGrowth = std::max(maxWidthGrowth, delta);
+ for (NSTabViewItem* tabViewItem in [tabView_ tabViewItems])
+ for (NSView* subView in [[tabViewItem view] subviews])
+ if ([subView isKindOfClass:widthBasedTweakerClass]) {
+ GTMWidthBasedTweaker* tweaker = (GTMWidthBasedTweaker*)subView;
+ CGFloat delta = [tweaker changedWidth];
+ maxWidthGrowth = std::max(maxWidthGrowth, delta);
+ }
+
+ // Adjust the width of the window.
+ if (maxWidthGrowth > 0.0) {
+ NSSize adjustSize = NSMakeSize(maxWidthGrowth, 0);
+ adjustSize = [[window contentView] convertSize:adjustSize toView:nil];
+ NSRect windowFrame = [window frame];
+ windowFrame.size.width += adjustSize.width;
+ [window setFrame:windowFrame display:NO];
+ }
+
+ // Adjust the heights and locations of the items on the "Other data" tab.
+ CGFloat cumulativeHeightGrowth = 0.0;
+ NSArray* subViews =
+ [[otherDataTab_ subviews] sortedArrayUsingFunction:CompareFrameY
+ context:NULL];
+ for (NSView* view in subViews) {
+ if ([view isHidden])
+ continue;
+
+ if ([objectsToVerticallySize_ containsObject:view]) {
+ DCHECK([view isKindOfClass:[NSTextField class]]);
+ CGFloat viewHeightGrowth = [GTMUILocalizerAndLayoutTweaker
+ sizeToFitFixedWidthTextField:(NSTextField*)view];
+ if (viewHeightGrowth > 0.0)
+ cumulativeHeightGrowth += viewHeightGrowth;
}
+
+ NSRect viewFrame = [view frame];
+ viewFrame.origin.y -= cumulativeHeightGrowth;
+ [view setFrame:viewFrame];
}
- if (maxWidthGrowth > 0.0) {
- NSRect rect = [contentView convertRect:[window frame] fromView:nil];
- rect.size.width += maxWidthGrowth;
- rect = [contentView convertRect:rect toView:nil];
- [window setFrame:rect display:NO];
- // For some reason the content view is resizing, but some times not
- // adjusting its origin, so correct it manually.
- [contentView setFrameOrigin:NSZeroPoint];
+
+ // Adjust the height of the window.
+ if (cumulativeHeightGrowth > 0.0) {
+ NSSize adjustSize = NSMakeSize(0, cumulativeHeightGrowth);
+ adjustSize = [[window contentView] convertSize:adjustSize toView:nil];
+ NSRect windowFrame = [window frame];
+ windowFrame.size.height += adjustSize.height;
+ [window setFrame:windowFrame display:NO];
}
+
// Now start the modal loop.
[NSApp runModalForWindow:window];
}
@@ -160,9 +223,9 @@
if (emptyCache_)
removeMask |= BrowsingDataRemover::REMOVE_CACHE;
if (deleteCookies_)
- removeMask |= BrowsingDataRemover::REMOVE_COOKIES;
+ removeMask |= BrowsingDataRemover::REMOVE_COOKIES;
if (clearSavedPasswords_)
- removeMask |= BrowsingDataRemover::REMOVE_PASSWORDS;
+ removeMask |= BrowsingDataRemover::REMOVE_PASSWORDS;
if (clearFormData_)
removeMask |= BrowsingDataRemover::REMOVE_FORM_DATA;
return removeMask;
@@ -174,6 +237,7 @@
// While we're working, dim the buttons so the user can't click them.
- (IBAction)clearData:(id)sender {
// Set that we're working so that the buttons disable.
+ [self setClearingStatus:l10n_util::GetNSString(IDS_CLEAR_DATA_DELETING)];
[self setIsClearing:YES];
[self persistToPrefs];
@@ -204,6 +268,17 @@
browser->window()->Show();
}
+- (IBAction)openGoogleDashboard:(id)sender {
+ // The "Clear Data" dialog is app-modal on OS X. Hence, close it before
+ // opening a tab with the dashboard.
+ [self closeDialog];
+
+ Browser* browser = Browser::Create(profile_);
+ browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_PRIVACY_DASHBOARD_URL)),
+ GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
+ browser->window()->Show();
+}
+
- (void)closeDialog {
ProfileControllerMap* map = Singleton<ProfileControllerMap>::get();
ProfileControllerMap::iterator it = map->find(profile_);
@@ -256,9 +331,73 @@
userInfo:userInfo];
[self closeDialog];
- [[self window] orderOut:self];
+ [self setClearingStatus:nil];
[self setIsClearing:NO];
remover_ = NULL;
}
+- (IBAction)stopSyncAndDeleteData:(id)sender {
+ // Protect against the unlikely case where the server received a message, and
+ // the syncer syncs and resets itself before the user tries pressing the Clear
+ // button in this dialog again. TODO(raz) Confirm whether we have an issue
+ // here
+ if (profile_->GetProfileSyncService()->HasSyncSetupCompleted()) {
+ bool clear = platform_util::SimpleYesNoBox(
+ nil,
+ l10n_util::GetStringUTF16(IDS_CONFIRM_CLEAR_TITLE),
+ l10n_util::GetStringUTF16(IDS_CONFIRM_CLEAR_DESCRIPTION));
+ if (clear) {
+ profile_->GetProfileSyncService()->ClearServerData();
+ [self syncStateChanged];
+ }
+ }
+}
+
+- (void)syncStateChanged {
+ bool deleteInProgress = false;
+
+ ProfileSyncService::ClearServerDataState clearState =
+ profile_->GetProfileSyncService()->GetClearServerDataState();
+ profile_->GetProfileSyncService()->ResetClearServerDataState();
+
+ switch (clearState) {
+ case ProfileSyncService::CLEAR_NOT_STARTED:
+ // This can occur on a first start and after a failed clear (which does
+ // not close the tab). Do nothing.
+ break;
+ case ProfileSyncService::CLEAR_CLEARING:
+ // Clearing buttons on all tabs are disabled at this point, throbber is
+ // going.
+ [self setClearingStatus:l10n_util::GetNSString(IDS_CLEAR_DATA_SENDING)];
+ deleteInProgress = true;
+ break;
+ case ProfileSyncService::CLEAR_FAILED:
+ // Show an error and reallow clearing.
+ [self setClearingStatus:l10n_util::GetNSString(IDS_CLEAR_DATA_ERROR)];
+ deleteInProgress = false;
+ break;
+ case ProfileSyncService::CLEAR_SUCCEEDED:
+ // Close the dialog box, success!
+ [self setClearingStatus:nil];
+ deleteInProgress = false;
+ [self closeDialog];
+ break;
+ }
+
+ [self setIsClearing:deleteInProgress];
+}
+
+- (BOOL)isSyncEnabled {
+ BOOL allowClearServerDataUI =
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableClearServerData);
+
+ return allowClearServerDataUI &&
+ profile_->GetProfileSyncService()->HasSyncSetupCompleted();
+}
+
+- (NSFont*)labelFont {
+ return [NSFont boldSystemFontOfSize:13];
+}
+
@end

Powered by Google App Engine
This is Rietveld 408576698