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

Unified Diff: chrome/browser/ui/cocoa/preferences_window_controller.mm

Issue 6339002: [Mac] Consolidate all files relating to preferences in a subdir of c/b/ui/coc... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 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/ui/cocoa/preferences_window_controller.mm
===================================================================
--- chrome/browser/ui/cocoa/preferences_window_controller.mm (revision 71447)
+++ chrome/browser/ui/cocoa/preferences_window_controller.mm (working copy)
@@ -1,2171 +0,0 @@
-// Copyright (c) 2011 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.
-
-#import "chrome/browser/ui/cocoa/preferences_window_controller.h"
-
-#include <algorithm>
-
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_aedesc.h"
-#include "base/string16.h"
-#include "base/string_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/autofill/autofill_dialog.h"
-#include "chrome/browser/autofill/autofill_type.h"
-#include "chrome/browser/autofill/personal_data_manager.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/download/download_manager.h"
-#include "chrome/browser/download/download_prefs.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/instant/instant_confirm_dialog.h"
-#include "chrome/browser/instant/instant_controller.h"
-#include "chrome/browser/metrics/metrics_service.h"
-#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/browser/policy/managed_prefs_banner_base.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/prefs/session_startup_pref.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
-#include "chrome/browser/safe_browsing/safe_browsing_service.h"
-#include "chrome/browser/shell_integration.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/sync_ui_util.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
-#import "chrome/browser/ui/cocoa/clear_browsing_data_controller.h"
-#import "chrome/browser/ui/cocoa/content_settings_dialog_controller.h"
-#import "chrome/browser/ui/cocoa/custom_home_pages_model.h"
-#import "chrome/browser/ui/cocoa/font_language_settings_controller.h"
-#import "chrome/browser/ui/cocoa/import_settings_dialog.h"
-#import "chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.h"
-#import "chrome/browser/ui/cocoa/l10n_util.h"
-#import "chrome/browser/ui/cocoa/search_engine_list_model.h"
-#import "chrome/browser/ui/cocoa/vertical_gradient_view.h"
-#import "chrome/browser/ui/cocoa/window_size_autosaver.h"
-#include "chrome/browser/ui/options/options_util.h"
-#include "chrome/browser/ui/options/options_window.h"
-#include "chrome/browser/ui/options/show_options_url.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/installer/util/google_update_settings.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/theme_resources.h"
-#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
-#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-
-namespace {
-
-// Colors for the managed preferences warning banner.
-static const double kBannerGradientColorTop[3] =
- {255.0 / 255.0, 242.0 / 255.0, 183.0 / 255.0};
-static const double kBannerGradientColorBottom[3] =
- {250.0 / 255.0, 230.0 / 255.0, 145.0 / 255.0};
-static const double kBannerStrokeColor = 135.0 / 255.0;
-
-// Tag id for retrieval via viewWithTag in NSView (from IB).
-static const uint32 kBasicsStartupPageTableTag = 1000;
-
-bool IsNewTabUIURLString(const GURL& url) {
- return url == GURL(chrome::kChromeUINewTabURL);
-}
-
-// Helper that sizes two buttons to fit in a row keeping their spacing, returns
-// the total horizontal size change.
-CGFloat SizeToFitButtonPair(NSButton* leftButton, NSButton* rightButton) {
- CGFloat widthShift = 0.0;
-
- NSSize delta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:leftButton];
- DCHECK_EQ(delta.height, 0.0) << "Height changes unsupported";
- widthShift += delta.width;
-
- if (widthShift != 0.0) {
- NSPoint origin = [rightButton frame].origin;
- origin.x += widthShift;
- [rightButton setFrameOrigin:origin];
- }
- delta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:rightButton];
- DCHECK_EQ(delta.height, 0.0) << "Height changes unsupported";
- widthShift += delta.width;
-
- return widthShift;
-}
-
-// The different behaviors for the "pref group" auto sizing.
-enum AutoSizeGroupBehavior {
- kAutoSizeGroupBehaviorVerticalToFit,
- kAutoSizeGroupBehaviorVerticalFirstToFit,
- kAutoSizeGroupBehaviorHorizontalToFit,
- kAutoSizeGroupBehaviorHorizontalFirstGrows,
- kAutoSizeGroupBehaviorFirstTwoAsRowVerticalToFit
-};
-
-// Helper to tweak the layout of the "pref groups" and also ripple any height
-// changes from one group to the next groups' origins.
-// |views| is an ordered list of views with first being the label for the
-// group and the rest being top down or left to right ordering of the views.
-// The label is assumed to already be the same height as all the views it is
-// next too.
-CGFloat AutoSizeGroup(NSArray* views, AutoSizeGroupBehavior behavior,
- CGFloat verticalShift) {
- DCHECK_GE([views count], 2U) << "Should be at least a label and a control";
- NSTextField* label = [views objectAtIndex:0];
- DCHECK([label isKindOfClass:[NSTextField class]])
- << "First view should be the label for the group";
-
- // Auto size the label to see if we need more vertical space for its localized
- // string.
- CGFloat labelHeightChange =
- [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:label];
-
- CGFloat localVerticalShift = 0.0;
- switch (behavior) {
- case kAutoSizeGroupBehaviorVerticalToFit: {
- // Walk bottom up doing the sizing and moves.
- for (NSUInteger index = [views count] - 1; index > 0; --index) {
- NSView* view = [views objectAtIndex:index];
- NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
- DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
- if (localVerticalShift) {
- NSPoint origin = [view frame].origin;
- origin.y += localVerticalShift;
- [view setFrameOrigin:origin];
- }
- localVerticalShift += delta.height;
- }
- break;
- }
- case kAutoSizeGroupBehaviorVerticalFirstToFit: {
- // Just size the top one.
- NSView* view = [views objectAtIndex:1];
- NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
- DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
- localVerticalShift += delta.height;
- break;
- }
- case kAutoSizeGroupBehaviorHorizontalToFit: {
- // Walk left to right doing the sizing and moves.
- // NOTE: Don't worry about vertical, assume it always fits.
- CGFloat horizontalShift = 0.0;
- NSUInteger count = [views count];
- for (NSUInteger index = 1; index < count; ++index) {
- NSView* view = [views objectAtIndex:index];
- NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
- DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
- if (horizontalShift) {
- NSPoint origin = [view frame].origin;
- origin.x += horizontalShift;
- [view setFrameOrigin:origin];
- }
- horizontalShift += delta.width;
- }
- break;
- }
- case kAutoSizeGroupBehaviorHorizontalFirstGrows: {
- // Walk right to left doing the sizing and moves, then apply the space
- // collected into the first.
- // NOTE: Don't worry about vertical, assume it always all fits.
- CGFloat horizontalShift = 0.0;
- for (NSUInteger index = [views count] - 1; index > 1; --index) {
- NSView* view = [views objectAtIndex:index];
- NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
- DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
- horizontalShift -= delta.width;
- NSPoint origin = [view frame].origin;
- origin.x += horizontalShift;
- [view setFrameOrigin:origin];
- }
- if (horizontalShift) {
- NSView* view = [views objectAtIndex:1];
- NSSize delta = NSMakeSize(horizontalShift, 0.0);
- [GTMUILocalizerAndLayoutTweaker
- resizeViewWithoutAutoResizingSubViews:view
- delta:delta];
- }
- break;
- }
- case kAutoSizeGroupBehaviorFirstTwoAsRowVerticalToFit: {
- // Start out like kAutoSizeGroupBehaviorVerticalToFit but don't do
- // the first two. Then handle the two as a row, but apply any
- // vertical shift.
- // All but the first two (in the row); walk bottom up.
- for (NSUInteger index = [views count] - 1; index > 2; --index) {
- NSView* view = [views objectAtIndex:index];
- NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
- DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
- if (localVerticalShift) {
- NSPoint origin = [view frame].origin;
- origin.y += localVerticalShift;
- [view setFrameOrigin:origin];
- }
- localVerticalShift += delta.height;
- }
- // Deal with the two for the horizontal row. Size the second one.
- CGFloat horizontalShift = 0.0;
- NSView* view = [views objectAtIndex:2];
- NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
- DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
- horizontalShift -= delta.width;
- NSPoint origin = [view frame].origin;
- origin.x += horizontalShift;
- if (localVerticalShift) {
- origin.y += localVerticalShift;
- }
- [view setFrameOrigin:origin];
- // Now expand the first item in the row to consume the space opened up.
- view = [views objectAtIndex:1];
- if (horizontalShift) {
- NSSize delta = NSMakeSize(horizontalShift, 0.0);
- [GTMUILocalizerAndLayoutTweaker
- resizeViewWithoutAutoResizingSubViews:view
- delta:delta];
- }
- // And move it up by any amount needed from the previous items.
- if (localVerticalShift) {
- NSPoint origin = [view frame].origin;
- origin.y += localVerticalShift;
- [view setFrameOrigin:origin];
- }
- break;
- }
- default:
- NOTREACHED();
- break;
- }
-
- // If the label grew more then the views, the other views get an extra shift.
- // Otherwise, move the label to its top is aligned with the other views.
- CGFloat nonLabelShift = 0.0;
- if (labelHeightChange > localVerticalShift) {
- // Since the lable is taller, centering the other views looks best, just
- // shift the views by 1/2 of the size difference.
- nonLabelShift = (labelHeightChange - localVerticalShift) / 2.0;
- } else {
- NSPoint origin = [label frame].origin;
- origin.y += localVerticalShift - labelHeightChange;
- [label setFrameOrigin:origin];
- }
-
- // Apply the input shift requested along with any the shift from label being
- // taller then the rest of the group.
- for (NSView* view in views) {
- NSPoint origin = [view frame].origin;
- origin.y += verticalShift;
- if (view != label) {
- origin.y += nonLabelShift;
- }
- [view setFrameOrigin:origin];
- }
-
- // Return how much the group grew.
- return localVerticalShift + nonLabelShift;
-}
-
-// Helper to remove a view and move everything above it down to take over the
-// space.
-void RemoveViewFromView(NSView* view, NSView* toRemove) {
- // Sort bottom up so we can spin over what is above it.
- NSArray* views =
- [[view subviews] sortedArrayUsingFunction:cocoa_l10n_util::CompareFrameY
- context:NULL];
-
- // Find where |toRemove| was.
- NSUInteger index = [views indexOfObject:toRemove];
- DCHECK_NE(index, NSNotFound);
- NSUInteger count = [views count];
- CGFloat shrinkHeight = 0;
- if (index < (count - 1)) {
- // If we're not the topmost control, the amount to shift is the bottom of
- // |toRemove| to the bottom of the view above it.
- CGFloat shiftDown =
- NSMinY([[views objectAtIndex:index + 1] frame]) -
- NSMinY([toRemove frame]);
-
- // Now cycle over the views above it moving them down.
- for (++index; index < count; ++index) {
- NSView* view = [views objectAtIndex:index];
- NSPoint origin = [view frame].origin;
- origin.y -= shiftDown;
- [view setFrameOrigin:origin];
- }
-
- shrinkHeight = shiftDown;
- } else if (index > 0) {
- // If we're the topmost control, there's nothing to shift but we want to
- // shrink until the top edge of the second-topmost control, unless it is
- // actually higher than the topmost control (since we're sorting by the
- // bottom edge).
- shrinkHeight = std::max(0.f,
- NSMaxY([toRemove frame]) -
- NSMaxY([[views objectAtIndex:index - 1] frame]));
- }
- // If we only have one control, don't do any resizing (for now).
-
- // Remove |toRemove|.
- [toRemove removeFromSuperview];
-
- [GTMUILocalizerAndLayoutTweaker
- resizeViewWithoutAutoResizingSubViews:view
- delta:NSMakeSize(0, -shrinkHeight)];
-}
-
-// Simply removes all the views in |toRemove|.
-void RemoveGroupFromView(NSView* view, NSArray* toRemove) {
- for (NSView* viewToRemove in toRemove) {
- RemoveViewFromView(view, viewToRemove);
- }
-}
-
-// Helper to tweak the layout of the "Under the Hood" content by autosizing all
-// the views and moving things up vertically. Special case the two controls for
-// download location as they are horizontal, and should fill the row. Special
-// case "Content Settings" and "Clear browsing data" as they are horizontal as
-// well.
-CGFloat AutoSizeUnderTheHoodContent(NSView* view,
- NSPathControl* downloadLocationControl,
- NSButton* downloadLocationButton) {
- CGFloat verticalShift = 0.0;
-
- // Loop bottom up through the views sizing and shifting.
- NSArray* views =
- [[view subviews] sortedArrayUsingFunction:cocoa_l10n_util::CompareFrameY
- context:NULL];
- for (NSView* view in views) {
- NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
- DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
- if (verticalShift) {
- NSPoint origin = [view frame].origin;
- origin.y += verticalShift;
- [view setFrameOrigin:origin];
- }
- verticalShift += delta.height;
-
- // The Download Location controls go in a row with the button aligned to the
- // right edge and the path control using all the rest of the space.
- if (view == downloadLocationButton) {
- NSPoint origin = [downloadLocationButton frame].origin;
- origin.x -= delta.width;
- [downloadLocationButton setFrameOrigin:origin];
- NSSize controlSize = [downloadLocationControl frame].size;
- controlSize.width -= delta.width;
- [downloadLocationControl setFrameSize:controlSize];
- }
- }
-
- return verticalShift;
-}
-
-} // namespace
-
-//-------------------------------------------------------------------------
-
-@interface PreferencesWindowController(Private)
-// Callback when preferences are changed. |prefName| is the name of the
-// pref that has changed.
-- (void)prefChanged:(std::string*)prefName;
-// Callback when sync state has changed. syncService_ needs to be
-// queried to find out what happened.
-- (void)syncStateChanged;
-// Record the user performed a certain action and save the preferences.
-- (void)recordUserAction:(const UserMetricsAction&) action;
-- (void)registerPrefObservers;
-- (void)configureInstant;
-
-// KVC setter methods.
-- (void)setNewTabPageIsHomePageIndex:(NSInteger)val;
-- (void)setHomepageURL:(NSString*)urlString;
-- (void)setRestoreOnStartupIndex:(NSInteger)type;
-- (void)setShowHomeButton:(BOOL)value;
-- (void)setPasswordManagerEnabledIndex:(NSInteger)value;
-- (void)setIsUsingDefaultTheme:(BOOL)value;
-- (void)setShowAlternateErrorPages:(BOOL)value;
-- (void)setUseSuggest:(BOOL)value;
-- (void)setDnsPrefetch:(BOOL)value;
-- (void)setSafeBrowsing:(BOOL)value;
-- (void)setMetricsReporting:(BOOL)value;
-- (void)setAskForSaveLocation:(BOOL)value;
-- (void)setFileHandlerUIEnabled:(BOOL)value;
-- (void)setTranslateEnabled:(BOOL)value;
-- (void)setTabsToLinks:(BOOL)value;
-- (void)displayPreferenceViewForPage:(OptionsPage)page
- animate:(BOOL)animate;
-- (void)resetSubViews;
-- (void)initBannerStateForPage:(OptionsPage)page;
-
-// KVC getter methods.
-- (BOOL)fileHandlerUIEnabled;
-@end
-
-namespace PreferencesWindowControllerInternal {
-
-// A C++ class registered for changes in preferences. Bridges the
-// notification back to the PWC.
-class PrefObserverBridge : public NotificationObserver,
- public ProfileSyncServiceObserver {
- public:
- PrefObserverBridge(PreferencesWindowController* controller)
- : controller_(controller) {}
-
- virtual ~PrefObserverBridge() {}
-
- // Overridden from NotificationObserver:
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- if (type == NotificationType::PREF_CHANGED)
- [controller_ prefChanged:Details<std::string>(details).ptr()];
- }
-
- // Overridden from ProfileSyncServiceObserver.
- virtual void OnStateChanged() {
- [controller_ syncStateChanged];
- }
-
- private:
- PreferencesWindowController* controller_; // weak, owns us
-};
-
-// Tracks state for a managed prefs banner and triggers UI updates through the
-// PreferencesWindowController as appropriate.
-class ManagedPrefsBannerState : public policy::ManagedPrefsBannerBase {
- public:
- virtual ~ManagedPrefsBannerState() { }
-
- explicit ManagedPrefsBannerState(PreferencesWindowController* controller,
- OptionsPage page,
- PrefService* local_state,
- PrefService* prefs)
- : policy::ManagedPrefsBannerBase(local_state, prefs, page),
- controller_(controller),
- page_(page) { }
-
- BOOL IsVisible() {
- return DetermineVisibility();
- }
-
- protected:
- // Overridden from ManagedPrefsBannerBase.
- virtual void OnUpdateVisibility() {
- [controller_ switchToPage:page_ animate:YES];
- }
-
- private:
- PreferencesWindowController* controller_; // weak, owns us
- OptionsPage page_; // current options page
-};
-
-} // namespace PreferencesWindowControllerInternal
-
-@implementation PreferencesWindowController
-
-@synthesize restoreButtonsEnabled = restoreButtonsEnabled_;
-@synthesize restoreURLsEnabled = restoreURLsEnabled_;
-@synthesize showHomeButtonEnabled = showHomeButtonEnabled_;
-@synthesize defaultSearchEngineEnabled = defaultSearchEngineEnabled_;
-@synthesize passwordManagerChoiceEnabled = passwordManagerChoiceEnabled_;
-@synthesize passwordManagerButtonEnabled = passwordManagerButtonEnabled_;
-@synthesize autoFillSettingsButtonEnabled = autoFillSettingsButtonEnabled_;
-@synthesize showAlternateErrorPagesEnabled = showAlternateErrorPagesEnabled_;
-@synthesize useSuggestEnabled = useSuggestEnabled_;
-@synthesize dnsPrefetchEnabled = dnsPrefetchEnabled_;
-@synthesize safeBrowsingEnabled = safeBrowsingEnabled_;
-@synthesize metricsReportingEnabled = metricsReportingEnabled_;
-@synthesize proxiesConfigureButtonEnabled = proxiesConfigureButtonEnabled_;
-
-- (id)initWithProfile:(Profile*)profile initialPage:(OptionsPage)initialPage {
- DCHECK(profile);
- // Use initWithWindowNibPath:: instead of initWithWindowNibName: so we
- // can override it in a unit test.
- NSString* nibPath = [base::mac::MainAppBundle()
- pathForResource:@"Preferences"
- ofType:@"nib"];
- if ((self = [super initWithWindowNibPath:nibPath owner:self])) {
- profile_ = profile->GetOriginalProfile();
- initialPage_ = initialPage;
- prefs_ = profile->GetPrefs();
- DCHECK(prefs_);
- observer_.reset(
- new PreferencesWindowControllerInternal::PrefObserverBridge(self));
-
- // Set up the model for the custom home page table. The KVO observation
- // tells us when the number of items in the array changes. The normal
- // observation tells us when one of the URLs of an item changes.
- customPagesSource_.reset([[CustomHomePagesModel alloc]
- initWithProfile:profile_]);
- const SessionStartupPref startupPref =
- SessionStartupPref::GetStartupPref(prefs_);
- [customPagesSource_ setURLs:startupPref.urls];
-
- // Set up the model for the default search popup. Register for notifications
- // about when the model changes so we can update the selection in the view.
- searchEngineModel_.reset(
- [[SearchEngineListModel alloc]
- initWithModel:profile->GetTemplateURLModel()]);
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(searchEngineModelChanged:)
- name:kSearchEngineListModelChangedNotification
- object:searchEngineModel_.get()];
-
- // This needs to be done before awakeFromNib: because the bindings set up
- // in the nib rely on it.
- [self registerPrefObservers];
-
- // Use one animation so we can stop it if the user clicks quickly, and
- // start the new animation.
- animation_.reset([[NSViewAnimation alloc] init]);
- // Make this the delegate so it can remove the old view at the end of the
- // animation (once it is faded out).
- [animation_ setDelegate:self];
- [animation_ setAnimationBlockingMode:NSAnimationNonblocking];
-
- // TODO(akalin): handle incognito profiles? The windows version of this
- // (in chrome/browser/ui/views/options/content_page_view.cc) just does what
- // we do below.
- syncService_ = profile_->GetProfileSyncService();
-
- // TODO(akalin): This color is taken from kSyncLabelErrorBgColor in
- // content_page_view.cc. Either decomp that color out into a
- // function/variable that is referenced by both this file and
- // content_page_view.cc, or maybe pick a more suitable color.
- syncErrorBackgroundColor_.reset(
- [[NSColor colorWithDeviceRed:0xff/255.0
- green:0x9a/255.0
- blue:0x9a/255.0
- alpha:1.0] retain]);
-
- // Disable the |autoFillSettingsButton_| if we have no
- // |personalDataManager|.
- PersonalDataManager* personalDataManager =
- profile_->GetPersonalDataManager();
- [autoFillSettingsButton_ setHidden:(personalDataManager == NULL)];
- bool autofill_disabled_by_policy =
- autoFillEnabled_.IsManaged() && !autoFillEnabled_.GetValue();
- [self setAutoFillSettingsButtonEnabled:!autofill_disabled_by_policy];
- [self setPasswordManagerChoiceEnabled:!askSavePasswords_.IsManaged()];
- [self setPasswordManagerButtonEnabled:
- !askSavePasswords_.IsManaged() || askSavePasswords_.GetValue()];
-
- // Initialize the enabled state of the elements on the general tab.
- [self setShowHomeButtonEnabled:!showHomeButton_.IsManaged()];
- [self setEnabledStateOfRestoreOnStartup];
- [self setDefaultSearchEngineEnabled:![searchEngineModel_ isDefaultManaged]];
-
- // Initialize UI state for the advanced page.
- [self setShowAlternateErrorPagesEnabled:!alternateErrorPages_.IsManaged()];
- [self setUseSuggestEnabled:!useSuggest_.IsManaged()];
- [self setDnsPrefetchEnabled:!dnsPrefetch_.IsManaged()];
- [self setSafeBrowsingEnabled:!safeBrowsing_.IsManaged()];
- [self setMetricsReportingEnabled:!metricsReporting_.IsManaged()];
- proxyPrefs_.reset(
- PrefSetObserver::CreateProxyPrefSetObserver(prefs_, observer_.get()));
- [self setProxiesConfigureButtonEnabled:!proxyPrefs_->IsManaged()];
- }
- return self;
-}
-
-- (void)awakeFromNib {
-
- // Validate some assumptions in debug builds.
-
- // "Basics", "Personal Stuff", and "Under the Hood" views should be the same
- // width. They should be the same width so they are laid out to look as good
- // as possible at that width with controls just having to wrap if their text
- // is too long.
- DCHECK_EQ(NSWidth([basicsView_ frame]), NSWidth([personalStuffView_ frame]))
- << "Basics and Personal Stuff should be the same widths";
- DCHECK_EQ(NSWidth([basicsView_ frame]), NSWidth([underTheHoodView_ frame]))
- << "Basics and Under the Hood should be the same widths";
- // "Under the Hood" content should always be skinnier than the scroller it
- // goes into (we resize it).
- DCHECK_LE(NSWidth([underTheHoodContentView_ frame]),
- [underTheHoodScroller_ contentSize].width)
- << "The Under the Hood content should be narrower than the content "
- "of the scroller it goes into";
-
-#if !defined(GOOGLE_CHROME_BUILD)
- // "Enable logging" (breakpad and stats) is only in Google Chrome builds,
- // remove the checkbox and slide everything above it down.
- RemoveViewFromView(underTheHoodContentView_, enableLoggingCheckbox_);
-#endif // !defined(GOOGLE_CHROME_BUILD)
-
- // There are four problem children within the groups:
- // Basics - Default Browser
- // Personal Stuff - Sync
- // Personal Stuff - Themes
- // Personal Stuff - Browser Data
- // These four have buttons that with some localizations are wider then the
- // view. So the four get manually laid out before doing the general work so
- // the views/window can be made wide enough to fit them. The layout in the
- // general pass is a noop for these buttons (since they are already sized).
-
- // Size the default browser button.
- const NSUInteger kDefaultBrowserGroupCount = 3;
- const NSUInteger kDefaultBrowserButtonIndex = 1;
- DCHECK_EQ([basicsGroupDefaultBrowser_ count], kDefaultBrowserGroupCount)
- << "Expected only two items in Default Browser group";
- NSButton* defaultBrowserButton =
- [basicsGroupDefaultBrowser_ objectAtIndex:kDefaultBrowserButtonIndex];
- NSSize defaultBrowserChange =
- [GTMUILocalizerAndLayoutTweaker sizeToFitView:defaultBrowserButton];
- DCHECK_EQ(defaultBrowserChange.height, 0.0)
- << "Button should have been right height in nib";
-
- [self configureInstant];
-
- // Size the sync row.
- CGFloat syncRowChange = SizeToFitButtonPair(syncButton_,
- syncCustomizeButton_);
-
- // Size the themes row.
- const NSUInteger kThemeGroupCount = 3;
- const NSUInteger kThemeResetButtonIndex = 1;
- const NSUInteger kThemeThemesButtonIndex = 2;
- DCHECK_EQ([personalStuffGroupThemes_ count], kThemeGroupCount)
- << "Expected only two items in Themes group";
- CGFloat themeRowChange = SizeToFitButtonPair(
- [personalStuffGroupThemes_ objectAtIndex:kThemeResetButtonIndex],
- [personalStuffGroupThemes_ objectAtIndex:kThemeThemesButtonIndex]);
-
- // Size the Privacy and Clear buttons that make a row in Under the Hood.
- CGFloat privacyRowChange = SizeToFitButtonPair(contentSettingsButton_,
- clearDataButton_);
- // Under the Hood view is narrower (then the other panes) in the nib, subtract
- // out the amount it was already going to grow to match the other panes when
- // calculating how much the row needs things to grow.
- privacyRowChange -=
- ([underTheHoodScroller_ contentSize].width -
- NSWidth([underTheHoodContentView_ frame]));
-
- // Find the most any row changed in size.
- CGFloat maxWidthChange = std::max(defaultBrowserChange.width, syncRowChange);
- maxWidthChange = std::max(maxWidthChange, themeRowChange);
- maxWidthChange = std::max(maxWidthChange, privacyRowChange);
-
- // If any grew wider, make the views wider. If they all shrank, they fit the
- // existing view widths, so no change is needed//.
- if (maxWidthChange > 0.0) {
- NSSize viewSize = [basicsView_ frame].size;
- viewSize.width += maxWidthChange;
- [basicsView_ setFrameSize:viewSize];
- viewSize = [personalStuffView_ frame].size;
- viewSize.width += maxWidthChange;
- [personalStuffView_ setFrameSize:viewSize];
- }
-
- // Now that we have the width needed for Basics and Personal Stuff, lay out
- // those pages bottom up making sure the strings fit and moving things up as
- // needed.
-
- CGFloat newWidth = NSWidth([basicsView_ frame]);
- CGFloat verticalShift = 0.0;
- verticalShift += AutoSizeGroup(basicsGroupDefaultBrowser_,
- kAutoSizeGroupBehaviorVerticalFirstToFit,
- verticalShift);
- verticalShift += AutoSizeGroup(
- basicsGroupSearchEngine_,
- kAutoSizeGroupBehaviorFirstTwoAsRowVerticalToFit,
- verticalShift);
- verticalShift += AutoSizeGroup(basicsGroupToolbar_,
- kAutoSizeGroupBehaviorVerticalToFit,
- verticalShift);
- verticalShift += AutoSizeGroup(basicsGroupHomePage_,
- kAutoSizeGroupBehaviorVerticalToFit,
- verticalShift);
- verticalShift += AutoSizeGroup(basicsGroupStartup_,
- kAutoSizeGroupBehaviorVerticalFirstToFit,
- verticalShift);
- [GTMUILocalizerAndLayoutTweaker
- resizeViewWithoutAutoResizingSubViews:basicsView_
- delta:NSMakeSize(0.0, verticalShift)];
-
- verticalShift = 0.0;
- verticalShift += AutoSizeGroup(personalStuffGroupThemes_,
- kAutoSizeGroupBehaviorHorizontalToFit,
- verticalShift);
- verticalShift += AutoSizeGroup(personalStuffGroupBrowserData_,
- kAutoSizeGroupBehaviorVerticalToFit,
- verticalShift);
- verticalShift += AutoSizeGroup(personalStuffGroupAutofill_,
- kAutoSizeGroupBehaviorVerticalToFit,
- verticalShift);
- verticalShift += AutoSizeGroup(personalStuffGroupPasswords_,
- kAutoSizeGroupBehaviorVerticalToFit,
- verticalShift);
- // TODO(akalin): Here we rely on the initial contents of the sync
- // group's text field/link field to be large enough to hold all
- // possible messages so that we don't have to re-layout when sync
- // state changes. This isn't perfect, since e.g. some sync messages
- // use the user's e-mail address (which may be really long), and the
- // link field is usually not shown (leaving a big empty space).
- // Rethink sync preferences UI for Mac.
- verticalShift += AutoSizeGroup(personalStuffGroupSync_,
- kAutoSizeGroupBehaviorVerticalToFit,
- verticalShift);
- [GTMUILocalizerAndLayoutTweaker
- resizeViewWithoutAutoResizingSubViews:personalStuffView_
- delta:NSMakeSize(0.0, verticalShift)];
-
- if (syncService_) {
- syncService_->AddObserver(observer_.get());
- // Update the controls according to the initial state.
- [self syncStateChanged];
- } else {
- // If sync is disabled we don't want to show the sync controls at all.
- RemoveGroupFromView(personalStuffView_, personalStuffGroupSync_);
- }
-
- // Make the window as wide as the views.
- NSWindow* prefsWindow = [self window];
- NSView* prefsContentView = [prefsWindow contentView];
- NSRect frame = [prefsContentView convertRect:[prefsWindow frame]
- fromView:nil];
- frame.size.width = newWidth;
- frame = [prefsContentView convertRect:frame toView:nil];
- [prefsWindow setFrame:frame display:NO];
-
- // The Under the Hood prefs is a scroller, it shouldn't get any border, so it
- // gets resized to be as wide as the window ended up.
- NSSize underTheHoodSize = [underTheHoodView_ frame].size;
- underTheHoodSize.width = newWidth;
- [underTheHoodView_ setFrameSize:underTheHoodSize];
-
- // Widen the Under the Hood content so things can rewrap to the full width.
- NSSize underTheHoodContentSize = [underTheHoodContentView_ frame].size;
- underTheHoodContentSize.width = [underTheHoodScroller_ contentSize].width;
- [underTheHoodContentView_ setFrameSize:underTheHoodContentSize];
-
- // Now that Under the Hood is the right width, auto-size to the new width to
- // get the final height.
- verticalShift = AutoSizeUnderTheHoodContent(underTheHoodContentView_,
- downloadLocationControl_,
- downloadLocationButton_);
- [GTMUILocalizerAndLayoutTweaker
- resizeViewWithoutAutoResizingSubViews:underTheHoodContentView_
- delta:NSMakeSize(0.0, verticalShift)];
- underTheHoodContentSize = [underTheHoodContentView_ frame].size;
-
- // Put the Under the Hood content view into the scroller and scroll it to the
- // top.
- [underTheHoodScroller_ setDocumentView:underTheHoodContentView_];
- [underTheHoodContentView_ scrollPoint:
- NSMakePoint(0, underTheHoodContentSize.height)];
-
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- NSImage* alertIcon = rb.GetNativeImageNamed(IDR_WARNING);
- DCHECK(alertIcon);
- [managedPrefsBannerWarningImage_ setImage:alertIcon];
-
- [self initBannerStateForPage:initialPage_];
- [self switchToPage:initialPage_ animate:NO];
-
- // Save/restore position based on prefs.
- if (g_browser_process && g_browser_process->local_state()) {
- sizeSaver_.reset([[WindowSizeAutosaver alloc]
- initWithWindow:[self window]
- prefService:g_browser_process->local_state()
- path:prefs::kPreferencesWindowPlacement]);
- }
-
- // Initialize the banner gradient and stroke color.
- NSColor* bannerStartingColor =
- [NSColor colorWithCalibratedRed:kBannerGradientColorTop[0]
- green:kBannerGradientColorTop[1]
- blue:kBannerGradientColorTop[2]
- alpha:1.0];
- NSColor* bannerEndingColor =
- [NSColor colorWithCalibratedRed:kBannerGradientColorBottom[0]
- green:kBannerGradientColorBottom[1]
- blue:kBannerGradientColorBottom[2]
- alpha:1.0];
- scoped_nsobject<NSGradient> bannerGradient(
- [[NSGradient alloc] initWithStartingColor:bannerStartingColor
- endingColor:bannerEndingColor]);
- [managedPrefsBannerView_ setGradient:bannerGradient];
-
- NSColor* bannerStrokeColor =
- [NSColor colorWithCalibratedWhite:kBannerStrokeColor
- alpha:1.0];
- [managedPrefsBannerView_ setStrokeColor:bannerStrokeColor];
-
- // Set accessibility related attributes.
- NSTableView* tableView = [basicsView_ viewWithTag:kBasicsStartupPageTableTag];
- NSString* description =
- l10n_util::GetNSStringWithFixup(IDS_OPTIONS_STARTUP_SHOW_PAGES);
- [tableView accessibilitySetOverrideValue:description
- forAttribute:NSAccessibilityDescriptionAttribute];
-}
-
-- (void)dealloc {
- if (syncService_) {
- syncService_->RemoveObserver(observer_.get());
- }
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [animation_ setDelegate:nil];
- [animation_ stopAnimation];
- [super dealloc];
-}
-
-// Xcode 3.1.x version of Interface Builder doesn't do a lot for editing
-// toolbars in XIB. So the toolbar's delegate is set to the controller so it
-// can tell the toolbar what items are selectable.
-- (NSArray*)toolbarSelectableItemIdentifiers:(NSToolbar*)toolbar {
- DCHECK(toolbar == toolbar_);
- return [[toolbar_ items] valueForKey:@"itemIdentifier"];
-}
-
-// Register our interest in the preferences we're displaying so if anything
-// else in the UI changes them we will be updated.
-- (void)registerPrefObservers {
- if (!prefs_) return;
-
- // Basics panel
- registrar_.Init(prefs_);
- registrar_.Add(prefs::kURLsToRestoreOnStartup, observer_.get());
- restoreOnStartup_.Init(prefs::kRestoreOnStartup, prefs_, observer_.get());
- newTabPageIsHomePage_.Init(prefs::kHomePageIsNewTabPage,
- prefs_, observer_.get());
- homepage_.Init(prefs::kHomePage, prefs_, observer_.get());
- showHomeButton_.Init(prefs::kShowHomeButton, prefs_, observer_.get());
- instantEnabled_.Init(prefs::kInstantEnabled, prefs_, observer_.get());
-
- // Personal Stuff panel
- askSavePasswords_.Init(prefs::kPasswordManagerEnabled,
- prefs_, observer_.get());
- autoFillEnabled_.Init(prefs::kAutoFillEnabled, prefs_, observer_.get());
- currentTheme_.Init(prefs::kCurrentThemeID, prefs_, observer_.get());
-
- // Under the hood panel
- alternateErrorPages_.Init(prefs::kAlternateErrorPagesEnabled,
- prefs_, observer_.get());
- useSuggest_.Init(prefs::kSearchSuggestEnabled, prefs_, observer_.get());
- dnsPrefetch_.Init(prefs::kDnsPrefetchingEnabled, prefs_, observer_.get());
- safeBrowsing_.Init(prefs::kSafeBrowsingEnabled, prefs_, observer_.get());
- autoOpenFiles_.Init(
- prefs::kDownloadExtensionsToOpen, prefs_, observer_.get());
- translateEnabled_.Init(prefs::kEnableTranslate, prefs_, observer_.get());
- tabsToLinks_.Init(prefs::kWebkitTabsToLinks, prefs_, observer_.get());
-
- // During unit tests, there is no local state object, so we fall back to
- // the prefs object (where we've explicitly registered this pref so we
- // know it's there).
- PrefService* local = g_browser_process->local_state();
- if (!local)
- local = prefs_;
- metricsReporting_.Init(prefs::kMetricsReportingEnabled,
- local, observer_.get());
- defaultDownloadLocation_.Init(prefs::kDownloadDefaultDirectory, prefs_,
- observer_.get());
- askForSaveLocation_.Init(prefs::kPromptForDownload, prefs_, observer_.get());
-
- // We don't need to observe changes in this value.
- lastSelectedPage_.Init(prefs::kOptionsWindowLastTabIndex, local, NULL);
-}
-
-// Called when the window wants to be closed.
-- (BOOL)windowShouldClose:(id)sender {
- // Stop any animation and clear the delegate to avoid stale pointers.
- [animation_ setDelegate:nil];
- [animation_ stopAnimation];
-
- return YES;
-}
-
-// Called when the user hits the escape key. Closes the window.
-- (void)cancel:(id)sender {
- [[self window] performClose:self];
-}
-
-// Record the user performed a certain action and save the preferences.
-- (void)recordUserAction:(const UserMetricsAction &)action {
- UserMetrics::RecordAction(action, profile_);
- if (prefs_)
- prefs_->ScheduleSavePersistentPrefs();
-}
-
-// Returns the set of keys that |key| depends on for its value so it can be
-// re-computed when any of those change as well.
-+ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key {
- NSSet* paths = [super keyPathsForValuesAffectingValueForKey:key];
- if ([key isEqualToString:@"isHomepageURLEnabled"]) {
- paths = [paths setByAddingObject:@"newTabPageIsHomePageIndex"];
- paths = [paths setByAddingObject:@"homepageURL"];
- } else if ([key isEqualToString:@"restoreURLsEnabled"]) {
- paths = [paths setByAddingObject:@"restoreOnStartupIndex"];
- } else if ([key isEqualToString:@"isHomepageChoiceEnabled"]) {
- paths = [paths setByAddingObject:@"newTabPageIsHomePageIndex"];
- paths = [paths setByAddingObject:@"homepageURL"];
- } else if ([key isEqualToString:@"newTabPageIsHomePageIndex"]) {
- paths = [paths setByAddingObject:@"homepageURL"];
- } else if ([key isEqualToString:@"hompageURL"]) {
- paths = [paths setByAddingObject:@"newTabPageIsHomePageIndex"];
- } else if ([key isEqualToString:@"isDefaultBrowser"]) {
- paths = [paths setByAddingObject:@"defaultBrowser"];
- } else if ([key isEqualToString:@"defaultBrowserTextColor"]) {
- paths = [paths setByAddingObject:@"defaultBrowser"];
- } else if ([key isEqualToString:@"defaultBrowserText"]) {
- paths = [paths setByAddingObject:@"defaultBrowser"];
- }
- return paths;
-}
-
-// Launch the Keychain Access app.
-- (void)launchKeychainAccess {
- NSString* const kKeychainBundleId = @"com.apple.keychainaccess";
- [[NSWorkspace sharedWorkspace]
- launchAppWithBundleIdentifier:kKeychainBundleId
- options:0L
- additionalEventParamDescriptor:nil
- launchIdentifier:nil];
-}
-
-//-------------------------------------------------------------------------
-// Basics panel
-
-// Sets the home page preferences for kNewTabPageIsHomePage and kHomePage. If a
-// blank or null-host URL is passed in we revert to using NewTab page
-// as the Home page. Note: using SetValue() causes the observers not to fire,
-// which is actually a good thing as we could end up in a state where setting
-// the homepage to an empty url would automatically reset the prefs back to
-// using the NTP, so we'd be never be able to change it.
-- (void)setHomepage:(const GURL&)homepage {
- if (IsNewTabUIURLString(homepage)) {
- newTabPageIsHomePage_.SetValueIfNotManaged(true);
- homepage_.SetValueIfNotManaged(std::string());
- } else if (!homepage.is_valid()) {
- newTabPageIsHomePage_.SetValueIfNotManaged(true);
- if (!homepage.has_host())
- homepage_.SetValueIfNotManaged(std::string());
- } else {
- homepage_.SetValueIfNotManaged(homepage.spec());
- }
-}
-
-// Callback when preferences are changed by someone modifying the prefs backend
-// externally. |prefName| is the name of the pref that has changed. Unlike on
-// Windows, we don't need to use this method for initializing, that's handled by
-// Cocoa Bindings.
-// Handles prefs for the "Basics" panel.
-- (void)basicsPrefChanged:(std::string*)prefName {
- if (*prefName == prefs::kRestoreOnStartup) {
- const SessionStartupPref startupPref =
- SessionStartupPref::GetStartupPref(prefs_);
- [self setRestoreOnStartupIndex:startupPref.type];
- [self setEnabledStateOfRestoreOnStartup];
- } else if (*prefName == prefs::kURLsToRestoreOnStartup) {
- [customPagesSource_ reloadURLs];
- [self setEnabledStateOfRestoreOnStartup];
- } else if (*prefName == prefs::kHomePageIsNewTabPage) {
- NSInteger useNewTabPage = newTabPageIsHomePage_.GetValue() ? 0 : 1;
- [self setNewTabPageIsHomePageIndex:useNewTabPage];
- } else if (*prefName == prefs::kHomePage) {
- NSString* value = base::SysUTF8ToNSString(homepage_.GetValue());
- [self setHomepageURL:value];
- } else if (*prefName == prefs::kShowHomeButton) {
- [self setShowHomeButton:showHomeButton_.GetValue() ? YES : NO];
- [self setShowHomeButtonEnabled:!showHomeButton_.IsManaged()];
- } else if (*prefName == prefs::kInstantEnabled) {
- [self configureInstant];
- }
-}
-
-// Returns the index of the selected cell in the "on startup" matrix based
-// on the "restore on startup" pref. The ordering of the cells is in the
-// same order as the pref.
-- (NSInteger)restoreOnStartupIndex {
- const SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs_);
- return pref.type;
-}
-
-// A helper function that takes the startup session type, grabs the URLs to
-// restore, and saves it all in prefs.
-- (void)saveSessionStartupWithType:(SessionStartupPref::Type)type {
- SessionStartupPref pref;
- pref.type = type;
- pref.urls = [customPagesSource_.get() URLs];
- SessionStartupPref::SetStartupPref(prefs_, pref);
-}
-
-// Sets the pref based on the index of the selected cell in the matrix and
-// marks the appropriate user metric.
-- (void)setRestoreOnStartupIndex:(NSInteger)type {
- SessionStartupPref::Type startupType =
- static_cast<SessionStartupPref::Type>(type);
- switch (startupType) {
- case SessionStartupPref::DEFAULT:
- [self recordUserAction:UserMetricsAction("Options_Startup_Homepage")];
- break;
- case SessionStartupPref::LAST:
- [self recordUserAction:UserMetricsAction("Options_Startup_LastSession")];
- break;
- case SessionStartupPref::URLS:
- [self recordUserAction:UserMetricsAction("Options_Startup_Custom")];
- break;
- default:
- NOTREACHED();
- }
- [self saveSessionStartupWithType:startupType];
-}
-
-// Enables or disables the restoreOnStartup elements
-- (void) setEnabledStateOfRestoreOnStartup {
- const SessionStartupPref startupPref =
- SessionStartupPref::GetStartupPref(prefs_);
- [self setRestoreButtonsEnabled:!SessionStartupPref::TypeIsManaged(prefs_)];
- [self setRestoreURLsEnabled:!SessionStartupPref::URLsAreManaged(prefs_) &&
- [self restoreOnStartupIndex] == SessionStartupPref::URLS];
-}
-
-// Getter for the |customPagesSource| property for bindings.
-- (CustomHomePagesModel*)customPagesSource {
- return customPagesSource_.get();
-}
-
-// Called when the selection in the table changes. If a flag is set indicating
-// that we're waiting for a special select message, edit the cell. Otherwise
-// just ignore it, we don't normally care.
-- (void)tableViewSelectionDidChange:(NSNotification*)aNotification {
- if (pendingSelectForEdit_) {
- NSTableView* table = [aNotification object];
- NSUInteger selectedRow = [table selectedRow];
- [table editColumn:0 row:selectedRow withEvent:nil select:YES];
- pendingSelectForEdit_ = NO;
- }
-}
-
-// Called when the user hits the (+) button for adding a new homepage to the
-// list. This will also attempt to make the new item editable so the user can
-// just start typing.
-- (IBAction)addHomepage:(id)sender {
- [customPagesArrayController_ add:sender];
-
- // When the new item is added to the model, the array controller will select
- // it. We'll watch for that notification (because we are the table view's
- // delegate) and then make the cell editable. Note that this can't be
- // accomplished simply by subclassing the array controller's add method (I
- // did try). The update of the table is asynchronous with the controller
- // updating the model.
- pendingSelectForEdit_ = YES;
-}
-
-// Called when the user hits the (-) button for removing the selected items in
-// the homepage table. The controller does all the work.
-- (IBAction)removeSelectedHomepages:(id)sender {
- [customPagesArrayController_ remove:sender];
-}
-
-// Add all entries for all open browsers with our profile.
-- (IBAction)useCurrentPagesAsHomepage:(id)sender {
- std::vector<GURL> urls;
- for (BrowserList::const_iterator browserIter = BrowserList::begin();
- browserIter != BrowserList::end(); ++browserIter) {
- Browser* browser = *browserIter;
- if (browser->profile() != profile_)
- continue; // Only want entries for open profile.
-
- for (int tabIndex = 0; tabIndex < browser->tab_count(); ++tabIndex) {
- TabContents* tab = browser->GetTabContentsAt(tabIndex);
- if (tab->ShouldDisplayURL()) {
- const GURL url = browser->GetTabContentsAt(tabIndex)->GetURL();
- if (!url.is_empty())
- urls.push_back(url);
- }
- }
- }
- [customPagesSource_ setURLs:urls];
-}
-
-enum { kHomepageNewTabPage, kHomepageURL };
-
-// Here's a table describing the desired characteristics of the homepage choice
-// radio value, it's enabled state and the URL field enabled state. They depend
-// on the values of the managed bits for homepage (m_hp) and
-// homepageIsNewTabPage (m_ntp) preferences, as well as the value of the
-// homepageIsNewTabPage preference (ntp) and whether the homepage preference
-// is equal to the new tab page URL (hpisntp).
-//
-// m_hp m_ntp ntp hpisntp | choice value | choice enabled | URL field enabled
-// --------------------------------------------------------------------------
-// 0 0 0 0 | homepage | 1 | 1
-// 0 0 0 1 | new tab page | 1 | 0
-// 0 0 1 0 | new tab page | 1 | 0
-// 0 0 1 1 | new tab page | 1 | 0
-// 0 1 0 0 | homepage | 0 | 1
-// 0 1 0 1 | homepage | 0 | 1
-// 0 1 1 0 | new tab page | 0 | 0
-// 0 1 1 1 | new tab page | 0 | 0
-// 1 0 0 0 | homepage | 1 | 0
-// 1 0 0 1 | new tab page | 0 | 0
-// 1 0 1 0 | new tab page | 1 | 0
-// 1 0 1 1 | new tab page | 0 | 0
-// 1 1 0 0 | homepage | 0 | 0
-// 1 1 0 1 | new tab page | 0 | 0
-// 1 1 1 0 | new tab page | 0 | 0
-// 1 1 1 1 | new tab page | 0 | 0
-//
-// thus, we have:
-//
-// choice value is new tab page === ntp || (hpisntp && (m_hp || !m_ntp))
-// choice enabled === !m_ntp && !(m_hp && hpisntp)
-// URL field enabled === !ntp && !mhp && !(hpisntp && !m_ntp)
-//
-// which also make sense if you think about them.
-
-// Checks whether the homepage URL refers to the new tab page.
-- (BOOL)isHomepageNewTabUIURL {
- return IsNewTabUIURLString(GURL(homepage_.GetValue().c_str()));
-}
-
-// Returns the index of the selected cell in the "home page" marix based on
-// the "new tab is home page" pref. Sadly, the ordering is reversed from the
-// pref value.
-- (NSInteger)newTabPageIsHomePageIndex {
- return newTabPageIsHomePage_.GetValue() ||
- ([self isHomepageNewTabUIURL] &&
- (homepage_.IsManaged() || !newTabPageIsHomePage_.IsManaged())) ?
- kHomepageNewTabPage : kHomepageURL;
-}
-
-// Sets the pref based on the given index into the matrix and marks the
-// appropriate user metric.
-- (void)setNewTabPageIsHomePageIndex:(NSInteger)index {
- bool useNewTabPage = index == kHomepageNewTabPage ? true : false;
- if (useNewTabPage) {
- [self recordUserAction:UserMetricsAction("Options_Homepage_UseNewTab")];
- } else {
- [self recordUserAction:UserMetricsAction("Options_Homepage_UseURL")];
- if ([self isHomepageNewTabUIURL])
- homepage_.SetValueIfNotManaged(std::string());
- }
- newTabPageIsHomePage_.SetValueIfNotManaged(useNewTabPage);
-}
-
-// Check whether the new tab and URL homepage radios should be enabled, i.e. if
-// the corresponding preference is not managed through configuration policy.
-- (BOOL)isHomepageChoiceEnabled {
- return !newTabPageIsHomePage_.IsManaged() &&
- !(homepage_.IsManaged() && [self isHomepageNewTabUIURL]);
-}
-
-// Returns whether or not the homepage URL text field should be enabled
-// based on if the new tab page is the home page.
-- (BOOL)isHomepageURLEnabled {
- return !newTabPageIsHomePage_.GetValue() && !homepage_.IsManaged() &&
- !([self isHomepageNewTabUIURL] && !newTabPageIsHomePage_.IsManaged());
-}
-
-// Returns the homepage URL.
-- (NSString*)homepageURL {
- NSString* value = base::SysUTF8ToNSString(homepage_.GetValue());
- return [self isHomepageNewTabUIURL] ? nil : value;
-}
-
-// Sets the homepage URL to |urlString| with some fixing up.
-- (void)setHomepageURL:(NSString*)urlString {
- // If the text field contains a valid URL, sync it to prefs. We run it
- // through the fixer upper to allow input like "google.com" to be converted
- // to something valid ("http://google.com").
- std::string unfixedURL = urlString ? base::SysNSStringToUTF8(urlString) :
- chrome::kChromeUINewTabURL;
- [self setHomepage:URLFixerUpper::FixupURL(unfixedURL, std::string())];
-}
-
-// Returns whether the home button should be checked based on the preference.
-- (BOOL)showHomeButton {
- return showHomeButton_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the home button should be displayed
-// based on |value|.
-- (void)setShowHomeButton:(BOOL)value {
- if (value)
- [self recordUserAction:UserMetricsAction(
- "Options_Homepage_ShowHomeButton")];
- else
- [self recordUserAction:UserMetricsAction(
- "Options_Homepage_HideHomeButton")];
- showHomeButton_.SetValueIfNotManaged(value ? true : false);
-}
-
-// Getter for the |searchEngineModel| property for bindings.
-- (id)searchEngineModel {
- return searchEngineModel_.get();
-}
-
-// Bindings for the search engine popup. We not binding directly to the model
-// in order to siphon off the setter so we can record the metric. If we're
-// doing it with one, might as well do it with both.
-- (NSUInteger)searchEngineSelectedIndex {
- return [searchEngineModel_ defaultIndex];
-}
-
-- (void)setSearchEngineSelectedIndex:(NSUInteger)index {
- [self recordUserAction:UserMetricsAction("Options_SearchEngineChanged")];
- [searchEngineModel_ setDefaultIndex:index];
-}
-
-// Called when the search engine model changes. Update the selection in the
-// popup by tickling the bindings with the new value.
-- (void)searchEngineModelChanged:(NSNotification*)notify {
- [self setSearchEngineSelectedIndex:[self searchEngineSelectedIndex]];
- [self setDefaultSearchEngineEnabled:![searchEngineModel_ isDefaultManaged]];
-
-}
-
-- (IBAction)manageSearchEngines:(id)sender {
- [KeywordEditorCocoaController showKeywordEditor:profile_];
-}
-
-- (IBAction)toggleInstant:(id)sender {
- if (instantEnabled_.GetValue()) {
- InstantController::Disable(profile_);
- } else {
- [instantCheckbox_ setState:NSOffState];
- browser::ShowInstantConfirmDialogIfNecessary([self window], profile_);
- }
-}
-
-// Sets the state of the Instant checkbox and adds the type information to the
-// label.
-- (void)configureInstant {
- bool enabled = instantEnabled_.GetValue();
- NSInteger state = enabled ? NSOnState : NSOffState;
- [instantCheckbox_ setState:state];
-}
-
-- (IBAction)learnMoreAboutInstant:(id)sender {
- browser::ShowOptionsURL(profile_, browser::InstantLearnMoreURL());
-}
-
-// Called when the user clicks the button to make Chromium the default
-// browser. Registers http and https.
-- (IBAction)makeDefaultBrowser:(id)sender {
- [self willChangeValueForKey:@"defaultBrowser"];
-
- ShellIntegration::SetAsDefaultBrowser();
- [self recordUserAction:UserMetricsAction("Options_SetAsDefaultBrowser")];
- // If the user made Chrome the default browser, then he/she arguably wants
- // to be notified when that changes.
- prefs_->SetBoolean(prefs::kCheckDefaultBrowser, true);
-
- // Tickle KVO so that the UI updates.
- [self didChangeValueForKey:@"defaultBrowser"];
-}
-
-// Returns the Chromium default browser state.
-- (ShellIntegration::DefaultBrowserState)isDefaultBrowser {
- return ShellIntegration::IsDefaultBrowser();
-}
-
-// Returns the text color of the "chromium is your default browser" text (green
-// for yes, red for no).
-- (NSColor*)defaultBrowserTextColor {
- ShellIntegration::DefaultBrowserState state = [self isDefaultBrowser];
- return (state == ShellIntegration::IS_DEFAULT_BROWSER) ?
- [NSColor colorWithCalibratedRed:0.0 green:135.0/255.0 blue:0 alpha:1.0] :
- [NSColor colorWithCalibratedRed:135.0/255.0 green:0 blue:0 alpha:1.0];
-}
-
-// Returns the text for the "chromium is your default browser" string dependent
-// on if Chromium actually is or not.
-- (NSString*)defaultBrowserText {
- ShellIntegration::DefaultBrowserState state = [self isDefaultBrowser];
- int stringId;
- if (state == ShellIntegration::IS_DEFAULT_BROWSER)
- stringId = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
- else if (state == ShellIntegration::NOT_DEFAULT_BROWSER)
- stringId = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
- else
- stringId = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
- string16 text =
- l10n_util::GetStringFUTF16(stringId,
- l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
- return base::SysUTF16ToNSString(text);
-}
-
-//-------------------------------------------------------------------------
-// User Data panel
-
-// Since passwords and forms are radio groups, 'enabled' is index 0 and
-// 'disabled' is index 1. Yay.
-const int kEnabledIndex = 0;
-const int kDisabledIndex = 1;
-
-// Callback when preferences are changed. |prefName| is the name of the pref
-// that has changed. Unlike on Windows, we don't need to use this method for
-// initializing, that's handled by Cocoa Bindings.
-// Handles prefs for the "Personal Stuff" panel.
-- (void)userDataPrefChanged:(std::string*)prefName {
- if (*prefName == prefs::kPasswordManagerEnabled) {
- [self setPasswordManagerEnabledIndex:askSavePasswords_.GetValue() ?
- kEnabledIndex : kDisabledIndex];
- [self setPasswordManagerChoiceEnabled:!askSavePasswords_.IsManaged()];
- [self setPasswordManagerButtonEnabled:
- !askSavePasswords_.IsManaged() || askSavePasswords_.GetValue()];
- }
- if (*prefName == prefs::kAutoFillEnabled) {
- bool autofill_disabled_by_policy =
- autoFillEnabled_.IsManaged() && !autoFillEnabled_.GetValue();
- [self setAutoFillSettingsButtonEnabled:!autofill_disabled_by_policy];
- }
- if (*prefName == prefs::kCurrentThemeID) {
- [self setIsUsingDefaultTheme:currentTheme_.GetValue().length() == 0];
- }
-}
-
-// Called to launch the Keychain Access app to show the user's stored
-// passwords.
-- (IBAction)showSavedPasswords:(id)sender {
- [self recordUserAction:UserMetricsAction("Options_ShowPasswordsExceptions")];
- [self launchKeychainAccess];
-}
-
-// Called to show the Auto Fill Settings dialog.
-- (IBAction)showAutoFillSettings:(id)sender {
- [self recordUserAction:UserMetricsAction("Options_ShowAutoFillSettings")];
-
- PersonalDataManager* personalDataManager = profile_->GetPersonalDataManager();
- if (!personalDataManager) {
- // Should not reach here because button is disabled when
- // |personalDataManager| is NULL.
- NOTREACHED();
- return;
- }
-
- ShowAutoFillDialog(NULL, personalDataManager, profile_);
-}
-
-// Called to import data from other browsers (Safari, Firefox, etc).
-- (IBAction)importData:(id)sender {
- UserMetrics::RecordAction(UserMetricsAction("Import_ShowDlg"), profile_);
- [ImportSettingsDialogController showImportSettingsDialogForProfile:profile_];
-}
-
-- (IBAction)resetThemeToDefault:(id)sender {
- [self recordUserAction:UserMetricsAction("Options_ThemesReset")];
- profile_->ClearTheme();
-}
-
-- (IBAction)themesGallery:(id)sender {
- [self recordUserAction:UserMetricsAction("Options_ThemesGallery")];
- Browser* browser = BrowserList::GetLastActive();
-
- if (!browser || !browser->GetSelectedTabContents())
- browser = Browser::Create(profile_);
- browser->OpenThemeGalleryTabAndActivate();
-}
-
-// Called when the "stop syncing" confirmation dialog started by
-// doSyncAction is finished. Stop syncing only If the user clicked
-// OK.
-- (void)stopSyncAlertDidEnd:(NSAlert*)alert
- returnCode:(int)returnCode
- contextInfo:(void*)contextInfo {
- DCHECK(syncService_ && !syncService_->IsManaged());
- if (returnCode == NSAlertFirstButtonReturn) {
- syncService_->DisableForUser();
- ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS);
- }
-}
-
-// Called when the user clicks the multi-purpose sync button in the
-// "Personal Stuff" pane.
-- (IBAction)doSyncAction:(id)sender {
- DCHECK(syncService_ && !syncService_->IsManaged());
- if (syncService_->HasSyncSetupCompleted()) {
- // If sync setup has completed that means the sync button was a
- // "stop syncing" button. Bring up a confirmation dialog before
- // actually stopping syncing (see stopSyncAlertDidEnd).
- scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
- [alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
- IDS_SYNC_STOP_SYNCING_CONFIRM_BUTTON_LABEL)];
- [alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
- IDS_CANCEL)];
- [alert setMessageText:l10n_util::GetNSStringWithFixup(
- IDS_SYNC_STOP_SYNCING_DIALOG_TITLE)];
- [alert setInformativeText:l10n_util::GetNSStringFWithFixup(
- IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL,
- l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))];
- [alert setAlertStyle:NSWarningAlertStyle];
- const SEL kEndSelector =
- @selector(stopSyncAlertDidEnd:returnCode:contextInfo:);
- [alert beginSheetModalForWindow:[self window]
- modalDelegate:self
- didEndSelector:kEndSelector
- contextInfo:NULL];
- } else {
- // Otherwise, the sync button was a "sync my bookmarks" button.
- // Kick off the sync setup process.
- syncService_->ShowLoginDialog(NULL);
- ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
- }
-}
-
-// Called when the user clicks on the link to the privacy dashboard.
-- (IBAction)showPrivacyDashboard:(id)sender {
- Browser* browser = BrowserList::GetLastActive();
-
- if (!browser || !browser->GetSelectedTabContents())
- browser = Browser::Create(profile_);
- browser->OpenPrivacyDashboardTabAndActivate();
-}
-
-// Called when the user clicks the "Customize Sync" button in the
-// "Personal Stuff" pane. Spawns a dialog-modal sheet that cleans
-// itself up on close.
-- (IBAction)doSyncCustomize:(id)sender {
- syncService_->ShowConfigure(NULL);
-}
-
-- (IBAction)doSyncReauthentication:(id)sender {
- DCHECK(syncService_ && !syncService_->IsManaged());
- syncService_->ShowLoginDialog(NULL);
-}
-
-- (void)setPasswordManagerEnabledIndex:(NSInteger)value {
- if (value == kEnabledIndex)
- [self recordUserAction:UserMetricsAction(
- "Options_PasswordManager_Enable")];
- else
- [self recordUserAction:UserMetricsAction(
- "Options_PasswordManager_Disable")];
- askSavePasswords_.SetValueIfNotManaged(value == kEnabledIndex ? true : false);
-}
-
-- (NSInteger)passwordManagerEnabledIndex {
- return askSavePasswords_.GetValue() ? kEnabledIndex : kDisabledIndex;
-}
-
-- (void)setIsUsingDefaultTheme:(BOOL)value {
- if (value)
- [self recordUserAction:UserMetricsAction(
- "Options_IsUsingDefaultTheme_Enable")];
- else
- [self recordUserAction:UserMetricsAction(
- "Options_IsUsingDefaultTheme_Disable")];
-}
-
-- (BOOL)isUsingDefaultTheme {
- return currentTheme_.GetValue().length() == 0;
-}
-
-//-------------------------------------------------------------------------
-// Under the hood panel
-
-// Callback when preferences are changed. |prefName| is the name of the pref
-// that has changed. Unlike on Windows, we don't need to use this method for
-// initializing, that's handled by Cocoa Bindings.
-// Handles prefs for the "Under the hood" panel.
-- (void)underHoodPrefChanged:(std::string*)prefName {
- if (*prefName == prefs::kAlternateErrorPagesEnabled) {
- [self setShowAlternateErrorPages:
- alternateErrorPages_.GetValue() ? YES : NO];
- [self setShowAlternateErrorPagesEnabled:!alternateErrorPages_.IsManaged()];
- }
- else if (*prefName == prefs::kSearchSuggestEnabled) {
- [self setUseSuggest:useSuggest_.GetValue() ? YES : NO];
- [self setUseSuggestEnabled:!useSuggest_.IsManaged()];
- }
- else if (*prefName == prefs::kDnsPrefetchingEnabled) {
- [self setDnsPrefetch:dnsPrefetch_.GetValue() ? YES : NO];
- [self setDnsPrefetchEnabled:!dnsPrefetch_.IsManaged()];
- }
- else if (*prefName == prefs::kSafeBrowsingEnabled) {
- [self setSafeBrowsing:safeBrowsing_.GetValue() ? YES : NO];
- [self setSafeBrowsingEnabled:!safeBrowsing_.IsManaged()];
- }
- else if (*prefName == prefs::kMetricsReportingEnabled) {
- [self setMetricsReporting:metricsReporting_.GetValue() ? YES : NO];
- [self setMetricsReportingEnabled:!metricsReporting_.IsManaged()];
- }
- else if (*prefName == prefs::kDownloadDefaultDirectory) {
- // Poke KVO.
- [self willChangeValueForKey:@"defaultDownloadLocation"];
- [self didChangeValueForKey:@"defaultDownloadLocation"];
- }
- else if (*prefName == prefs::kPromptForDownload) {
- [self setAskForSaveLocation:askForSaveLocation_.GetValue() ? YES : NO];
- }
- else if (*prefName == prefs::kEnableTranslate) {
- [self setTranslateEnabled:translateEnabled_.GetValue() ? YES : NO];
- }
- else if (*prefName == prefs::kWebkitTabsToLinks) {
- [self setTabsToLinks:tabsToLinks_.GetValue() ? YES : NO];
- }
- else if (*prefName == prefs::kDownloadExtensionsToOpen) {
- // Poke KVC.
- [self setFileHandlerUIEnabled:[self fileHandlerUIEnabled]];
- }
- else if (proxyPrefs_->IsObserved(*prefName)) {
- [self setProxiesConfigureButtonEnabled:!proxyPrefs_->IsManaged()];
- }
-}
-
-// Set the new download path and notify the UI via KVO.
-- (void)downloadPathPanelDidEnd:(NSOpenPanel*)panel
- code:(NSInteger)returnCode
- context:(void*)context {
- if (returnCode == NSOKButton) {
- [self recordUserAction:UserMetricsAction("Options_SetDownloadDirectory")];
- NSURL* path = [[panel URLs] lastObject]; // We only allow 1 item.
- [self willChangeValueForKey:@"defaultDownloadLocation"];
- defaultDownloadLocation_.SetValue(base::SysNSStringToUTF8([path path]));
- [self didChangeValueForKey:@"defaultDownloadLocation"];
- }
-}
-
-// Bring up an open panel to allow the user to set a new downloads location.
-- (void)browseDownloadLocation:(id)sender {
- NSOpenPanel* panel = [NSOpenPanel openPanel];
- [panel setAllowsMultipleSelection:NO];
- [panel setCanChooseFiles:NO];
- [panel setCanChooseDirectories:YES];
- NSString* path = base::SysUTF8ToNSString(defaultDownloadLocation_.GetValue());
- [panel beginSheetForDirectory:path
- file:nil
- types:nil
- modalForWindow:[self window]
- modalDelegate:self
- didEndSelector:@selector(downloadPathPanelDidEnd:code:context:)
- contextInfo:NULL];
-}
-
-// Called to clear user's browsing data. This puts up an application-modal
-// dialog to guide the user through clearing the data.
-- (IBAction)clearData:(id)sender {
- [ClearBrowsingDataController
- showClearBrowsingDialogForProfile:profile_];
-}
-
-// Opens the "Content Settings" dialog.
-- (IBAction)showContentSettings:(id)sender {
- [ContentSettingsDialogController
- showContentSettingsForType:CONTENT_SETTINGS_TYPE_DEFAULT
- profile:profile_];
-}
-
-- (IBAction)privacyLearnMore:(id)sender {
- GURL url = google_util::AppendGoogleLocaleParam(
- GURL(chrome::kPrivacyLearnMoreURL));
- // We open a new browser window so the Options dialog doesn't get lost
- // behind other windows.
- browser::ShowOptionsURL(profile_, url);
-}
-
-- (IBAction)resetAutoOpenFiles:(id)sender {
- profile_->GetDownloadManager()->download_prefs()->ResetAutoOpen();
- [self recordUserAction:UserMetricsAction("Options_ResetAutoOpenFiles")];
-}
-
-- (IBAction)openProxyPreferences:(id)sender {
- NSArray* itemsToOpen = [NSArray arrayWithObject:[NSURL fileURLWithPath:
- @"/System/Library/PreferencePanes/Network.prefPane"]];
-
- const char* proxyPrefCommand = "Proxies";
- base::mac::ScopedAEDesc<> openParams;
- OSStatus status = AECreateDesc('ptru',
- proxyPrefCommand,
- strlen(proxyPrefCommand),
- openParams.OutPointer());
- LOG_IF(ERROR, status != noErr) << "Failed to create open params: " << status;
-
- LSLaunchURLSpec launchSpec = { 0 };
- launchSpec.itemURLs = (CFArrayRef)itemsToOpen;
- launchSpec.passThruParams = openParams;
- launchSpec.launchFlags = kLSLaunchAsync | kLSLaunchDontAddToRecents;
- LSOpenFromURLSpec(&launchSpec, NULL);
-}
-
-// Returns whether the alternate error page checkbox should be checked based
-// on the preference.
-- (BOOL)showAlternateErrorPages {
- return alternateErrorPages_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the alternate error page checkbox
-// should be displayed based on |value|.
-- (void)setShowAlternateErrorPages:(BOOL)value {
- if (value)
- [self recordUserAction:UserMetricsAction(
- "Options_LinkDoctorCheckbox_Enable")];
- else
- [self recordUserAction:UserMetricsAction(
- "Options_LinkDoctorCheckbox_Disable")];
- alternateErrorPages_.SetValueIfNotManaged(value ? true : false);
-}
-
-// Returns whether the suggest checkbox should be checked based on the
-// preference.
-- (BOOL)useSuggest {
- return useSuggest_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the suggest checkbox should be
-// displayed based on |value|.
-- (void)setUseSuggest:(BOOL)value {
- if (value)
- [self recordUserAction:UserMetricsAction(
- "Options_UseSuggestCheckbox_Enable")];
- else
- [self recordUserAction:UserMetricsAction(
- "Options_UseSuggestCheckbox_Disable")];
- useSuggest_.SetValueIfNotManaged(value ? true : false);
-}
-
-// Returns whether the DNS prefetch checkbox should be checked based on the
-// preference.
-- (BOOL)dnsPrefetch {
- return dnsPrefetch_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the DNS prefetch checkbox should be
-// displayed based on |value|.
-- (void)setDnsPrefetch:(BOOL)value {
- if (value)
- [self recordUserAction:UserMetricsAction(
- "Options_DnsPrefetchCheckbox_Enable")];
- else
- [self recordUserAction:UserMetricsAction(
- "Options_DnsPrefetchCheckbox_Disable")];
- dnsPrefetch_.SetValueIfNotManaged(value ? true : false);
-}
-
-// Returns whether the safe browsing checkbox should be checked based on the
-// preference.
-- (BOOL)safeBrowsing {
- return safeBrowsing_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the safe browsing checkbox should be
-// displayed based on |value|.
-- (void)setSafeBrowsing:(BOOL)value {
- if (value)
- [self recordUserAction:UserMetricsAction(
- "Options_SafeBrowsingCheckbox_Enable")];
- else
- [self recordUserAction:UserMetricsAction(
- "Options_SafeBrowsingCheckbox_Disable")];
- safeBrowsing_.SetValueIfNotManaged(value ? true : false);
- SafeBrowsingService* safeBrowsingService =
- g_browser_process->resource_dispatcher_host()->safe_browsing_service();
- MessageLoop::current()->PostTask(
- FROM_HERE,
- NewRunnableMethod(safeBrowsingService,
- &SafeBrowsingService::OnEnable,
- safeBrowsing_.GetValue()));
-}
-
-// Returns whether the metrics reporting checkbox should be checked based on the
-// preference.
-- (BOOL)metricsReporting {
- return metricsReporting_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the metrics reporting checkbox
-// should be displayed based on |value|.
-- (void)setMetricsReporting:(BOOL)value {
- if (value)
- [self recordUserAction:UserMetricsAction(
- "Options_MetricsReportingCheckbox_Enable")];
- else
- [self recordUserAction:UserMetricsAction(
- "Options_MetricsReportingCheckbox_Disable")];
-
- // TODO(pinkerton): windows shows a dialog here telling the user they need to
- // restart for this to take effect. http://crbug.com/34653
- metricsReporting_.SetValueIfNotManaged(value ? true : false);
-
- bool enabled = metricsReporting_.GetValue();
- GoogleUpdateSettings::SetCollectStatsConsent(enabled);
- bool update_pref = GoogleUpdateSettings::GetCollectStatsConsent();
- if (enabled != update_pref) {
- DVLOG(1) << "GENERAL SECTION: Unable to set crash report status to "
- << enabled;
- }
- // Only change the pref if GoogleUpdateSettings::GetCollectStatsConsent
- // succeeds.
- enabled = update_pref;
-
- MetricsService* metrics = g_browser_process->metrics_service();
- DCHECK(metrics);
- if (metrics) {
- metrics->SetUserPermitsUpload(enabled);
- if (enabled)
- metrics->Start();
- else
- metrics->Stop();
- }
-}
-
-- (NSURL*)defaultDownloadLocation {
- NSString* pathString =
- base::SysUTF8ToNSString(defaultDownloadLocation_.GetValue());
- return [NSURL fileURLWithPath:pathString];
-}
-
-- (BOOL)askForSaveLocation {
- return askForSaveLocation_.GetValue();
-}
-
-- (void)setAskForSaveLocation:(BOOL)value {
- if (value) {
- [self recordUserAction:UserMetricsAction(
- "Options_AskForSaveLocation_Enable")];
- } else {
- [self recordUserAction:UserMetricsAction(
- "Options_AskForSaveLocation_Disable")];
- }
- askForSaveLocation_.SetValue(value);
-}
-
-- (BOOL)fileHandlerUIEnabled {
- if (!profile_->GetDownloadManager()) // Not set in unit tests.
- return NO;
- return profile_->GetDownloadManager()->download_prefs()->IsAutoOpenUsed();
-}
-
-- (void)setFileHandlerUIEnabled:(BOOL)value {
- [resetFileHandlersButton_ setEnabled:value];
-}
-
-- (BOOL)translateEnabled {
- return translateEnabled_.GetValue();
-}
-
-- (void)setTranslateEnabled:(BOOL)value {
- if (value) {
- [self recordUserAction:UserMetricsAction("Options_Translate_Enable")];
- } else {
- [self recordUserAction:UserMetricsAction("Options_Translate_Disable")];
- }
- translateEnabled_.SetValue(value);
-}
-
-- (BOOL)tabsToLinks {
- return tabsToLinks_.GetValue();
-}
-
-- (void)setTabsToLinks:(BOOL)value {
- if (value) {
- [self recordUserAction:UserMetricsAction("Options_TabsToLinks_Enable")];
- } else {
- [self recordUserAction:UserMetricsAction("Options_TabsToLinks_Disable")];
- }
- tabsToLinks_.SetValue(value);
-}
-
-- (void)fontAndLanguageEndSheet:(NSWindow*)sheet
- returnCode:(NSInteger)returnCode
- contextInfo:(void*)context {
- [sheet close];
- [sheet orderOut:self];
- fontLanguageSettings_ = nil;
-}
-
-- (IBAction)changeFontAndLanguageSettings:(id)sender {
- // Intentionally leak the controller as it will clean itself up when the
- // sheet closes.
- fontLanguageSettings_ =
- [[FontLanguageSettingsController alloc] initWithProfile:profile_];
- [NSApp beginSheet:[fontLanguageSettings_ window]
- modalForWindow:[self window]
- modalDelegate:self
- didEndSelector:@selector(fontAndLanguageEndSheet:returnCode:contextInfo:)
- contextInfo:nil];
-}
-
-// Called to launch the Keychain Access app to show the user's stored
-// certificates. Note there's no way to script the app to auto-select the
-// certificates.
-- (IBAction)showCertificates:(id)sender {
- [self recordUserAction:UserMetricsAction("Options_ManagerCerts")];
- [self launchKeychainAccess];
-}
-
-- (IBAction)resetToDefaults:(id)sender {
- // The alert will clean itself up in the did-end selector.
- NSAlert* alert = [[NSAlert alloc] init];
- [alert setMessageText:l10n_util::GetNSString(IDS_OPTIONS_RESET_MESSAGE)];
- NSButton* resetButton = [alert addButtonWithTitle:
- l10n_util::GetNSString(IDS_OPTIONS_RESET_OKLABEL)];
- [resetButton setKeyEquivalent:@""];
- NSButton* cancelButton = [alert addButtonWithTitle:
- l10n_util::GetNSString(IDS_OPTIONS_RESET_CANCELLABEL)];
- [cancelButton setKeyEquivalent:@"\r"];
-
- [alert beginSheetModalForWindow:[self window]
- modalDelegate:self
- didEndSelector:@selector(resetToDefaults:returned:context:)
- contextInfo:nil];
-}
-
-- (void)resetToDefaults:(NSAlert*)alert
- returned:(NSInteger)code
- context:(void*)context {
- if (code == NSAlertFirstButtonReturn) {
- OptionsUtil::ResetToDefaults(profile_);
- }
- [alert autorelease];
-}
-
-//-------------------------------------------------------------------------
-
-// Callback when preferences are changed. |prefName| is the name of the
-// pref that has changed and should not be NULL.
-- (void)prefChanged:(std::string*)prefName {
- DCHECK(prefName);
- if (!prefName) return;
- [self basicsPrefChanged:prefName];
- [self userDataPrefChanged:prefName];
- [self underHoodPrefChanged:prefName];
-}
-
-// Callback when sync service state has changed.
-//
-// TODO(akalin): Decomp this out since a lot of it is copied from the
-// Windows version.
-// TODO(akalin): Change the background of the status label/link on error.
-- (void)syncStateChanged {
- DCHECK(syncService_);
-
- string16 statusLabel, linkLabel;
- sync_ui_util::MessageType status =
- sync_ui_util::GetStatusLabels(syncService_, &statusLabel, &linkLabel);
- bool managed = syncService_->IsManaged();
-
- [syncButton_ setEnabled:!syncService_->WizardIsVisible()];
- NSString* buttonLabel;
- if (syncService_->HasSyncSetupCompleted()) {
- buttonLabel = l10n_util::GetNSStringWithFixup(
- IDS_SYNC_STOP_SYNCING_BUTTON_LABEL);
- [syncCustomizeButton_ setHidden:false];
- } else if (syncService_->SetupInProgress()) {
- buttonLabel = l10n_util::GetNSStringWithFixup(
- IDS_SYNC_NTP_SETUP_IN_PROGRESS);
- [syncCustomizeButton_ setHidden:true];
- } else {
- buttonLabel = l10n_util::GetNSStringWithFixup(
- IDS_SYNC_START_SYNC_BUTTON_LABEL);
- [syncCustomizeButton_ setHidden:true];
- }
- [syncCustomizeButton_ setEnabled:!managed];
- [syncButton_ setTitle:buttonLabel];
- [syncButton_ setEnabled:!managed];
-
- [syncStatus_ setStringValue:base::SysUTF16ToNSString(statusLabel)];
- [syncLink_ setHidden:linkLabel.empty()];
- [syncLink_ setTitle:base::SysUTF16ToNSString(linkLabel)];
- [syncLink_ setEnabled:!managed];
-
- NSButtonCell* syncLinkCell = static_cast<NSButtonCell*>([syncLink_ cell]);
- if (!syncStatusNoErrorBackgroundColor_) {
- DCHECK(!syncLinkNoErrorBackgroundColor_);
- // We assume that the sync controls start off in a non-error
- // state.
- syncStatusNoErrorBackgroundColor_.reset(
- [[syncStatus_ backgroundColor] retain]);
- syncLinkNoErrorBackgroundColor_.reset(
- [[syncLinkCell backgroundColor] retain]);
- }
- if (status == sync_ui_util::SYNC_ERROR) {
- [syncStatus_ setBackgroundColor:syncErrorBackgroundColor_];
- [syncLinkCell setBackgroundColor:syncErrorBackgroundColor_];
- } else {
- [syncStatus_ setBackgroundColor:syncStatusNoErrorBackgroundColor_];
- [syncLinkCell setBackgroundColor:syncLinkNoErrorBackgroundColor_];
- }
-}
-
-// Show the preferences window.
-- (IBAction)showPreferences:(id)sender {
- [self showWindow:sender];
-}
-
-- (IBAction)toolbarButtonSelected:(id)sender {
- DCHECK([sender isKindOfClass:[NSToolbarItem class]]);
- OptionsPage page = [self getPageForToolbarItem:sender];
- [self displayPreferenceViewForPage:page animate:YES];
-}
-
-// Helper to update the window to display a preferences view for a page.
-- (void)displayPreferenceViewForPage:(OptionsPage)page
- animate:(BOOL)animate {
- NSWindow* prefsWindow = [self window];
-
- // Needs to go *after* the call to [self window], which triggers
- // awakeFromNib if necessary.
- NSView* prefsView = [self getPrefsViewForPage:page];
- NSView* contentView = [prefsWindow contentView];
-
- // Make sure we aren't being told to display the same thing again.
- if (currentPrefsView_ == prefsView &&
- managedPrefsBannerVisible_ == bannerState_->IsVisible()) {
- return;
- }
-
- // Remember new options page as current page.
- if (page != OPTIONS_PAGE_DEFAULT)
- lastSelectedPage_.SetValue(page);
-
- // Stop any running animation, and reset the subviews to the new state. We
- // re-add any views we need for animation later.
- [animation_ stopAnimation];
- NSView* oldPrefsView = currentPrefsView_;
- currentPrefsView_ = prefsView;
- [self resetSubViews];
-
- // Update the banner state.
- [self initBannerStateForPage:page];
- BOOL showBanner = bannerState_->IsVisible();
-
- // Update the window title.
- NSToolbarItem* toolbarItem = [self getToolbarItemForPage:page];
- [prefsWindow setTitle:[toolbarItem label]];
-
- // Calculate new frames for the subviews.
- NSRect prefsViewFrame = [prefsView frame];
- NSRect contentViewFrame = [contentView frame];
- NSRect bannerViewFrame = [managedPrefsBannerView_ frame];
-
- // Determine what height the managed prefs banner will use.
- CGFloat bannerViewHeight = showBanner ? NSHeight(bannerViewFrame) : 0.0;
-
- if (animate) {
- // NSViewAnimation doesn't seem to honor subview resizing as it animates the
- // Window's frame. So instead of trying to get the top in the right place,
- // just set the origin where it should be at the end, and let the fade/size
- // slide things into the right spot.
- prefsViewFrame.origin.y = 0.0;
- } else {
- // The prefView is anchored to the top of its parent, so set its origin so
- // that the top is where it should be. When the window's frame is set, the
- // origin will be adjusted to keep it in the right spot.
- prefsViewFrame.origin.y = NSHeight(contentViewFrame) -
- NSHeight(prefsViewFrame) - bannerViewHeight;
- }
- bannerViewFrame.origin.y = NSHeight(prefsViewFrame);
- bannerViewFrame.size.width = NSWidth(contentViewFrame);
- [prefsView setFrame:prefsViewFrame];
-
- // Figure out the size of the window.
- NSRect windowFrame = [contentView convertRect:[prefsWindow frame]
- fromView:nil];
- CGFloat titleToolbarHeight =
- NSHeight(windowFrame) - NSHeight(contentViewFrame);
- windowFrame.size.height =
- NSHeight(prefsViewFrame) + titleToolbarHeight + bannerViewHeight;
- DCHECK_GE(NSWidth(windowFrame), NSWidth(prefsViewFrame))
- << "Initial width set wasn't wide enough.";
- windowFrame = [contentView convertRect:windowFrame toView:nil];
- windowFrame.origin.y = NSMaxY([prefsWindow frame]) - NSHeight(windowFrame);
-
- // Now change the size.
- if (animate) {
- NSMutableArray* animations = [NSMutableArray arrayWithCapacity:4];
- if (oldPrefsView != prefsView) {
- // Fade between prefs views if they change.
- [contentView addSubview:oldPrefsView
- positioned:NSWindowBelow
- relativeTo:nil];
- [animations addObject:
- [NSDictionary dictionaryWithObjectsAndKeys:
- oldPrefsView, NSViewAnimationTargetKey,
- NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey,
- nil]];
- [animations addObject:
- [NSDictionary dictionaryWithObjectsAndKeys:
- prefsView, NSViewAnimationTargetKey,
- NSViewAnimationFadeInEffect, NSViewAnimationEffectKey,
- nil]];
- } else {
- // Make sure the prefs pane ends up in the right position in case we
- // manipulate the banner.
- [animations addObject:
- [NSDictionary dictionaryWithObjectsAndKeys:
- prefsView, NSViewAnimationTargetKey,
- [NSValue valueWithRect:prefsViewFrame],
- NSViewAnimationEndFrameKey,
- nil]];
- }
- if (showBanner != managedPrefsBannerVisible_) {
- // Slide the warning banner in or out of view.
- [animations addObject:
- [NSDictionary dictionaryWithObjectsAndKeys:
- managedPrefsBannerView_, NSViewAnimationTargetKey,
- [NSValue valueWithRect:bannerViewFrame],
- NSViewAnimationEndFrameKey,
- nil]];
- }
- // Window resize animation.
- [animations addObject:
- [NSDictionary dictionaryWithObjectsAndKeys:
- prefsWindow, NSViewAnimationTargetKey,
- [NSValue valueWithRect:windowFrame], NSViewAnimationEndFrameKey,
- nil]];
- [animation_ setViewAnimations:animations];
- // The default duration is 0.5s, which actually feels slow in here, so speed
- // it up a bit.
- [animation_ gtm_setDuration:0.2
- eventMask:NSLeftMouseUpMask];
- [animation_ startAnimation];
- } else {
- // If not animating, odds are we don't want to display either (because it
- // is initial window setup).
- [prefsWindow setFrame:windowFrame display:NO];
- [managedPrefsBannerView_ setFrame:bannerViewFrame];
- }
-
- managedPrefsBannerVisible_ = showBanner;
-}
-
-- (void)resetSubViews {
- // Reset subviews to current prefs view and banner, remove any views that
- // might have been left over from previous state or animation.
- NSArray* subviews = [NSArray arrayWithObjects:
- currentPrefsView_, managedPrefsBannerView_, nil];
- [[[self window] contentView] setSubviews:subviews];
- [[self window] setInitialFirstResponder:currentPrefsView_];
-}
-
-- (void)animationDidEnd:(NSAnimation*)animation {
- DCHECK_EQ(animation_.get(), animation);
- // Animation finished, reset subviews to current prefs view and the banner.
- [self resetSubViews];
-}
-
-// Reinitializes the banner state tracker object to watch for managed bits of
-// preferences relevant to the given options |page|.
-- (void)initBannerStateForPage:(OptionsPage)page {
- page = [self normalizePage:page];
-
- // During unit tests, there is no local state object, so we fall back to
- // the prefs object (where we've explicitly registered this pref so we
- // know it's there).
- PrefService* local = g_browser_process->local_state();
- if (!local)
- local = prefs_;
- bannerState_.reset(
- new PreferencesWindowControllerInternal::ManagedPrefsBannerState(
- self, page, local, prefs_));
-}
-
-- (void)switchToPage:(OptionsPage)page animate:(BOOL)animate {
- [self displayPreferenceViewForPage:page animate:animate];
- NSToolbarItem* toolbarItem = [self getToolbarItemForPage:page];
- [toolbar_ setSelectedItemIdentifier:[toolbarItem itemIdentifier]];
-}
-
-// Called when the window is being closed. Send out a notification that the user
-// is done editing preferences. Make sure there are no pending field editors
-// by clearing the first responder.
-- (void)windowWillClose:(NSNotification*)notification {
- // Setting the first responder to the window ends any in-progress field
- // editor. This will update the model appropriately so there's nothing left
- // to do.
- if (![[self window] makeFirstResponder:[self window]]) {
- // We've hit a recalcitrant field editor, force it to go away.
- [[self window] endEditingFor:nil];
- }
- [self autorelease];
-}
-
-- (void)controlTextDidEndEditing:(NSNotification*)notification {
- [customPagesSource_ validateURLs];
-}
-
-@end
-
-@implementation PreferencesWindowController(Testing)
-
-- (IntegerPrefMember*)lastSelectedPage {
- return &lastSelectedPage_;
-}
-
-- (NSToolbar*)toolbar {
- return toolbar_;
-}
-
-- (NSView*)basicsView {
- return basicsView_;
-}
-
-- (NSView*)personalStuffView {
- return personalStuffView_;
-}
-
-- (NSView*)underTheHoodView {
- return underTheHoodView_;
-}
-
-- (OptionsPage)normalizePage:(OptionsPage)page {
- if (page == OPTIONS_PAGE_DEFAULT) {
- // Get the last visited page from local state.
- page = static_cast<OptionsPage>(lastSelectedPage_.GetValue());
- if (page == OPTIONS_PAGE_DEFAULT) {
- page = OPTIONS_PAGE_GENERAL;
- }
- }
- return page;
-}
-
-- (NSToolbarItem*)getToolbarItemForPage:(OptionsPage)page {
- NSUInteger pageIndex = (NSUInteger)[self normalizePage:page];
- NSArray* items = [toolbar_ items];
- NSUInteger itemCount = [items count];
- DCHECK_GE(pageIndex, 0U);
- if (pageIndex >= itemCount) {
- NOTIMPLEMENTED();
- pageIndex = 0;
- }
- DCHECK_GT(itemCount, 0U);
- return [items objectAtIndex:pageIndex];
-}
-
-- (OptionsPage)getPageForToolbarItem:(NSToolbarItem*)toolbarItem {
- // Tags are set in the nib file.
- switch ([toolbarItem tag]) {
- case 0: // Basics
- return OPTIONS_PAGE_GENERAL;
- case 1: // Personal Stuff
- return OPTIONS_PAGE_CONTENT;
- case 2: // Under the Hood
- return OPTIONS_PAGE_ADVANCED;
- default:
- NOTIMPLEMENTED();
- return OPTIONS_PAGE_GENERAL;
- }
-}
-
-- (NSView*)getPrefsViewForPage:(OptionsPage)page {
- // The views will be NULL if this is mistakenly called before awakeFromNib.
- DCHECK(basicsView_);
- DCHECK(personalStuffView_);
- DCHECK(underTheHoodView_);
- page = [self normalizePage:page];
- switch (page) {
- case OPTIONS_PAGE_GENERAL:
- return basicsView_;
- case OPTIONS_PAGE_CONTENT:
- return personalStuffView_;
- case OPTIONS_PAGE_ADVANCED:
- return underTheHoodView_;
- case OPTIONS_PAGE_DEFAULT:
- case OPTIONS_PAGE_COUNT:
- LOG(DFATAL) << "Invalid page value " << page;
- }
- return basicsView_;
-}
-
-@end

Powered by Google App Engine
This is Rietveld 408576698