summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser_main.cc15
-rw-r--r--chrome/browser/cocoa/first_run_dialog.h15
-rw-r--r--chrome/browser/cocoa/first_run_dialog.mm108
-rw-r--r--chrome/browser/cocoa/search_engine_dialog_controller.h45
-rw-r--r--chrome/browser/cocoa/search_engine_dialog_controller.mm279
-rw-r--r--chrome/browser/first_run/first_run.cc83
-rw-r--r--chrome/browser/first_run/first_run.h27
-rw-r--r--chrome/browser/first_run/first_run_gtk.cc61
-rw-r--r--chrome/browser/first_run/first_run_mac.mm179
9 files changed, 517 insertions, 295 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index 53eeadb..3712a06 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -1203,7 +1203,8 @@ int BrowserMain(const MainFunctionParams& parameters) {
#if !defined(OS_MACOSX)
// Importing other browser settings is done in a browser-like process
// that exits when this task has finished.
- // TODO(port): Port to Mac
+ // TODO(port): Port the Mac's IPC-based implementation to other platforms to
+ // replace this implementation. http://crbug.com/22142
if (parsed_command_line.HasSwitch(switches::kImport) ||
parsed_command_line.HasSwitch(switches::kImportFromFile)) {
return FirstRun::ImportNow(profile, parsed_command_line);
@@ -1248,7 +1249,6 @@ int BrowserMain(const MainFunctionParams& parameters) {
// touches reads preferences.
if (is_first_run) {
if (!first_run_ui_bypass) {
-#if defined(OS_WIN) || defined(OS_LINUX)
FirstRun::AutoImport(profile,
master_prefs.homepage_defined,
master_prefs.do_import_items,
@@ -1257,17 +1257,6 @@ int BrowserMain(const MainFunctionParams& parameters) {
master_prefs.randomize_search_engine_experiment,
master_prefs.make_chrome_default,
&process_singleton);
-#else
- if (!OpenFirstRunDialog(profile,
- master_prefs.homepage_defined,
- master_prefs.do_import_items,
- master_prefs.dont_import_items,
- master_prefs.run_search_engine_experiment,
- master_prefs.randomize_search_engine_experiment,
- &process_singleton)) {
- return ResultCodes::NORMAL_EXIT;
- }
-#endif
#if defined(OS_POSIX)
// On Windows, the download is tagged with enable/disable stats so there
// is no need for this code.
diff --git a/chrome/browser/cocoa/first_run_dialog.h b/chrome/browser/cocoa/first_run_dialog.h
index a96ed17..3e575a3 100644
--- a/chrome/browser/cocoa/first_run_dialog.h
+++ b/chrome/browser/cocoa/first_run_dialog.h
@@ -13,14 +13,8 @@
// us improve Chromium.
@interface FirstRunDialogController : NSWindowController {
@private
- BOOL userDidCancel_;
BOOL statsEnabled_;
- BOOL statsCheckboxHidden_;
BOOL makeDefaultBrowser_;
- BOOL importBookmarks_;
- int browserImportSelectedIndex_;
- NSArray* browserImportList_;
- BOOL browserImportListHidden_;
IBOutlet NSArray* objectsToSize_;
IBOutlet NSButton* statsCheckbox_;
@@ -30,21 +24,12 @@
// Called when the "Start Google Chrome" button is pressed.
- (IBAction)ok:(id)sender;
-// Cancel button calls this.
-- (IBAction)cancel:(id)sender;
-
// Called when the "Learn More" button is pressed.
- (IBAction)learnMore:(id)sender;
// Properties for bindings.
-@property(assign, nonatomic) BOOL userDidCancel;
@property(assign, nonatomic) BOOL statsEnabled;
-@property(assign, nonatomic) BOOL statsCheckboxHidden;
@property(assign, nonatomic) BOOL makeDefaultBrowser;
-@property(assign, nonatomic) BOOL importBookmarks;
-@property(assign, nonatomic) int browserImportSelectedIndex;
-@property(retain, nonatomic) NSArray* browserImportList;
-@property(assign, nonatomic) BOOL browserImportListHidden;
@end
diff --git a/chrome/browser/cocoa/first_run_dialog.mm b/chrome/browser/cocoa/first_run_dialog.mm
index c71750e..123b80b 100644
--- a/chrome/browser/cocoa/first_run_dialog.mm
+++ b/chrome/browser/cocoa/first_run_dialog.mm
@@ -1,19 +1,21 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "chrome/browser/cocoa/first_run_dialog.h"
#include "app/l10n_util_mac.h"
-#include "base/logging.h"
#include "base/mac_util.h"
-#import "base/scoped_nsobject.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/common/pref_names.h"
+#include "base/message_loop.h"
+#include "base/ref_counted.h"
#include "grit/locale_settings.h"
#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+@interface FirstRunDialogController (PrivateMethods)
+// Show the dialog.
+- (void)show;
+@end
+
namespace {
// Compare function for -[NSArray sortedArrayUsingFunction:context:] that
@@ -29,18 +31,30 @@ NSInteger CompareFrameY(id view1, id view2, void* context) {
return NSOrderedSame;
}
+class FirstRunShowBridge : public base::RefCounted<FirstRunShowBridge> {
+ public:
+ FirstRunShowBridge(FirstRunDialogController* controller);
+
+ void ShowDialog();
+ private:
+ FirstRunDialogController* controller_;
+};
+
+FirstRunShowBridge::FirstRunShowBridge(
+ FirstRunDialogController* controller) : controller_(controller) {
+}
+
+void FirstRunShowBridge::ShowDialog() {
+ [controller_ show];
+ MessageLoop::current()->QuitNow();
+}
+
};
@implementation FirstRunDialogController
-@synthesize userDidCancel = userDidCancel_;
@synthesize statsEnabled = statsEnabled_;
-@synthesize statsCheckboxHidden = statsCheckboxHidden_;
@synthesize makeDefaultBrowser = makeDefaultBrowser_;
-@synthesize importBookmarks = importBookmarks_;
-@synthesize browserImportSelectedIndex = browserImportSelectedIndex_;
-@synthesize browserImportList = browserImportList_;
-@synthesize browserImportListHidden = browserImportListHidden_;
- (id)init {
NSString* nibpath =
@@ -50,31 +64,28 @@ NSInteger CompareFrameY(id view1, id view2, void* context) {
if (self != nil) {
// Bound to the dialog checkbox, default to true.
statsEnabled_ = YES;
- importBookmarks_ = YES;
-
-#if defined(GOOGLE_CHROME_BUILD)
- // If the send stats option is controlled by enterprise configuration
- // management, hide the checkbox.
- const PrefService::Preference* metrics_reporting_pref =
- g_browser_process->local_state()->FindPreference(
- prefs::kMetricsReportingEnabled);
- if (metrics_reporting_pref && metrics_reporting_pref->IsManaged())
- statsCheckboxHidden_ = YES;
-#else
- // In Chromium builds all stats reporting is disabled so there's no reason
- // to display the checkbox - the setting is always OFF.
- statsCheckboxHidden_ = YES;
-#endif // !GOOGLE_CHROME_BUILD
}
return self;
}
- (void)dealloc {
- [browserImportList_ release];
[super dealloc];
}
- (IBAction)showWindow:(id)sender {
+ // The main MessageLoop has not yet run, but has been spun. If we call
+ // -[NSApplication runModalForWindow:] we will hang <http://crbug.com/54248>.
+ // Therefore the main MessageLoop is run so things work.
+
+ scoped_refptr<FirstRunShowBridge> bridge = new FirstRunShowBridge(self);
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(bridge.get(),
+ &FirstRunShowBridge::ShowDialog));
+ MessageLoop::current()->Run();
+}
+
+- (void)show {
NSWindow* win = [self window];
// Only support the sizing the window once.
@@ -106,15 +117,13 @@ NSInteger CompareFrameY(id view1, id view2, void* context) {
[win setFrame:windowFrame display:NO];
}
- // The stats checkbox (if visible) gets some really long text, so it gets
- // word wrapped and then sized.
+ // The stats checkbox gets some really long text, so it gets word wrapped
+ // and then sized.
DCHECK(statsCheckbox_);
CGFloat statsCheckboxHeightChange = 0.0;
- if (![self statsCheckboxHidden]) {
- [GTMUILocalizerAndLayoutTweaker wrapButtonTitleForWidth:statsCheckbox_];
- statsCheckboxHeightChange =
- [GTMUILocalizerAndLayoutTweaker sizeToFitView:statsCheckbox_].height;
- }
+ [GTMUILocalizerAndLayoutTweaker wrapButtonTitleForWidth:statsCheckbox_];
+ statsCheckboxHeightChange =
+ [GTMUILocalizerAndLayoutTweaker sizeToFitView:statsCheckbox_].height;
// Walk bottom up shuffling for all the hidden views.
NSArray* subViews =
@@ -172,42 +181,15 @@ NSInteger CompareFrameY(id view1, id view2, void* context) {
[NSApp runModalForWindow:win];
}
-- (void)closeDialog {
+- (IBAction)ok:(id)sender {
[[self window] close];
[NSApp stopModal];
}
-- (IBAction)ok:(id)sender {
- [self closeDialog];
-}
-
-- (IBAction)cancel:(id)sender {
- [self closeDialog];
- [self setUserDidCancel:YES];
-}
-
- (IBAction)learnMore:(id)sender {
NSString* urlStr = l10n_util::GetNSString(IDS_LEARN_MORE_REPORTING_URL);
NSURL* learnMoreUrl = [NSURL URLWithString:urlStr];
[[NSWorkspace sharedWorkspace] openURL:learnMoreUrl];
}
-// Custom property getters
-
-- (BOOL)importBookmarks {
- // If the UI for browser import is hidden, report the choice as off.
- if ([self browserImportListHidden]) {
- return NO;
- }
- return importBookmarks_;
-}
-
-- (BOOL)statsEnabled {
- // If the UI for stats is hidden, report the choice as off.
- if ([self statsCheckboxHidden]) {
- return NO;
- }
- return statsEnabled_;
-}
-
@end
diff --git a/chrome/browser/cocoa/search_engine_dialog_controller.h b/chrome/browser/cocoa/search_engine_dialog_controller.h
new file mode 100644
index 0000000..a410614
--- /dev/null
+++ b/chrome/browser/cocoa/search_engine_dialog_controller.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include <vector>
+
+#import "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+
+class Profile;
+class SearchEngineDialogControllerBridge;
+class TemplateURL;
+class TemplateURLModel;
+
+// Class that acts as a controller for the search engine choice dialog.
+@interface SearchEngineDialogController : NSWindowController {
+ @private
+ // Our current profile.
+ Profile* profile_;
+
+ // If logos are to be displayed in random order. Used for UX testing.
+ bool randomize_;
+
+ // Owned by the profile_.
+ TemplateURLModel* searchEnginesModel_;
+
+ // Bridge to the C++ world.
+ scoped_ptr<SearchEngineDialogControllerBridge> bridge_;
+
+ // Offered search engine choices.
+ std::vector<const TemplateURL*> choices_;
+
+ IBOutlet NSImageView* headerImageView_;
+ IBOutlet NSView* searchEngineView_;
+}
+
+@property(assign, nonatomic) Profile* profile;
+@property(assign, nonatomic) bool randomize;
+
+// Properties for bindings.
+@property(readonly) NSFont* mainLabelFont;
+
+@end
diff --git a/chrome/browser/cocoa/search_engine_dialog_controller.mm b/chrome/browser/cocoa/search_engine_dialog_controller.mm
new file mode 100644
index 0000000..4863c07
--- /dev/null
+++ b/chrome/browser/cocoa/search_engine_dialog_controller.mm
@@ -0,0 +1,279 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/cocoa/search_engine_dialog_controller.h"
+
+#include <algorithm>
+
+#include "app/l10n_util_mac.h"
+#include "app/resource_bundle.h"
+#include "base/mac_util.h"
+#include "base/nsimage_cache_mac.h"
+#include "base/sys_string_conversions.h"
+#include "base/time.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/search_engines/template_url_model_observer.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+
+// Horizontal spacing between search engine choices.
+const int kSearchEngineSpacing = 20;
+
+// Vertical spacing between the search engine logo and the button underneath.
+const int kLogoButtonSpacing = 10;
+
+// Width of a label used in place of a logo.
+const int kLogoLabelWidth = 170;
+
+// Height of a label used in place of a logo.
+const int kLogoLabelHeight = 25;
+
+@interface SearchEngineDialogController (Private)
+- (void)onTemplateURLModelChanged;
+- (void)buildSearchEngineView;
+- (NSView*)viewForSearchEngine:(const TemplateURL*)engine
+ atIndex:(size_t)index;
+- (IBAction)searchEngineSelected:(id)sender;
+@end
+
+class SearchEngineDialogControllerBridge : public TemplateURLModelObserver {
+ public:
+ SearchEngineDialogControllerBridge(SearchEngineDialogController* controller);
+
+ // TemplateURLModelObserver
+ virtual void OnTemplateURLModelChanged();
+
+ private:
+ SearchEngineDialogController* controller_;
+};
+
+SearchEngineDialogControllerBridge::SearchEngineDialogControllerBridge(
+ SearchEngineDialogController* controller) : controller_(controller) {
+}
+
+void SearchEngineDialogControllerBridge::OnTemplateURLModelChanged() {
+ [controller_ onTemplateURLModelChanged];
+ MessageLoop::current()->QuitNow();
+}
+
+@implementation SearchEngineDialogController
+
+@synthesize profile = profile_;
+@synthesize randomize = randomize_;
+
+- (id)init {
+ NSString* nibpath =
+ [mac_util::MainAppBundle() pathForResource:@"SearchEngineDialog"
+ ofType:@"nib"];
+ self = [super initWithWindowNibPath:nibpath owner:self];
+ if (self != nil) {
+ bridge_.reset(new SearchEngineDialogControllerBridge(self));
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+- (IBAction)showWindow:(id)sender {
+ searchEnginesModel_ = profile_->GetTemplateURLModel();
+ searchEnginesModel_->AddObserver(bridge_.get());
+
+ if (searchEnginesModel_->loaded()) {
+ [self onTemplateURLModelChanged];
+ } else {
+ searchEnginesModel_->Load();
+ MessageLoop::current()->Run();
+ }
+}
+
+- (void)onTemplateURLModelChanged {
+ searchEnginesModel_->RemoveObserver(bridge_.get());
+
+ // Add the search engines in the search_engines_model_ to the buttons list.
+ // The first three will always be from prepopulated data.
+ std::vector<const TemplateURL*> templateUrls =
+ searchEnginesModel_->GetTemplateURLs();
+
+ // If we have fewer than two search engines, end the search engine dialog
+ // immediately, leaving the imported default search engine setting intact.
+ if (templateUrls.size() < 2) {
+ return;
+ }
+
+ NSWindow* win = [self window];
+
+ [win setBackgroundColor:[NSColor whiteColor]];
+
+ NSImage* headerImage = ResourceBundle::GetSharedInstance().
+ GetNSImageNamed(IDR_SEARCH_ENGINE_DIALOG_TOP);
+ [headerImageView_ setImage:headerImage];
+
+ // Is the user's default search engine included in the first three
+ // prepopulated set? If not, we need to expand the dialog to include a fourth
+ // engine.
+ const TemplateURL* defaultSearchEngine =
+ searchEnginesModel_->GetDefaultSearchProvider();
+
+ std::vector<const TemplateURL*>::iterator engineIter =
+ templateUrls.begin();
+ for (int i = 0; engineIter != templateUrls.end(); ++i, ++engineIter) {
+ if (i < 3) {
+ choices_.push_back(*engineIter);
+ } else {
+ if (*engineIter == defaultSearchEngine)
+ choices_.push_back(*engineIter);
+ }
+ }
+
+ // Randomize the order of the logos if the option has been set.
+ if (randomize_) {
+ int seed = static_cast<int>(base::Time::Now().ToInternalValue());
+ srand(seed);
+ std::random_shuffle(choices_.begin(), choices_.end());
+ }
+
+ [self buildSearchEngineView];
+
+ // Display the dialog.
+ NSInteger choice = [NSApp runModalForWindow:win];
+ searchEnginesModel_->SetDefaultSearchProvider(choices_.at(choice));
+}
+
+- (void)buildSearchEngineView {
+ scoped_nsobject<NSMutableArray> searchEngineViews
+ ([[NSMutableArray alloc] init]);
+
+ for (size_t i = 0; i < choices_.size(); ++i)
+ [searchEngineViews addObject:[self viewForSearchEngine:choices_.at(i)
+ atIndex:i]];
+
+ NSSize newOverallSize = NSZeroSize;
+ for (NSView* view in searchEngineViews.get()) {
+ NSRect engineFrame = [view frame];
+ engineFrame.origin = NSMakePoint(newOverallSize.width, 0);
+ [searchEngineView_ addSubview:view];
+ [view setFrame:engineFrame];
+ newOverallSize = NSMakeSize(
+ newOverallSize.width + NSWidth(engineFrame) + kSearchEngineSpacing,
+ std::max(newOverallSize.height, NSHeight(engineFrame)));
+ }
+ newOverallSize.width -= kSearchEngineSpacing;
+
+ // Resize the window to fit (and because it's bound on all sides it will
+ // resize the search engine view).
+ NSSize currentOverallSize = [searchEngineView_ bounds].size;
+ NSSize deltaSize = NSMakeSize(
+ newOverallSize.width - currentOverallSize.width,
+ newOverallSize.height - currentOverallSize.height);
+ NSSize windowDeltaSize = [searchEngineView_ convertSize:deltaSize toView:nil];
+ NSRect windowFrame = [[self window] frame];
+ windowFrame.size.width += windowDeltaSize.width;
+ windowFrame.size.height += windowDeltaSize.height;
+ [[self window] setFrame:windowFrame display:NO];
+}
+
+- (NSView*)viewForSearchEngine:(const TemplateURL*)engine
+ atIndex:(size_t)index {
+ bool useImages = false;
+#if defined(GOOGLE_CHROME_BUILD)
+ useImages = true;
+#endif
+
+ // Make the engine identifier.
+ NSView* engineIdentifier = nil; // either the logo or the text label
+
+ int logoId = engine->logo_id();
+ if (useImages && logoId > 0) {
+ NSImage* logoImage =
+ ResourceBundle::GetSharedInstance().GetNSImageNamed(logoId);
+ NSRect logoBounds = NSZeroRect;
+ logoBounds.size = [logoImage size];
+ NSImageView* logoView =
+ [[[NSImageView alloc] initWithFrame:logoBounds] autorelease];
+ [logoView setImage:logoImage];
+ [logoView setEditable:NO];
+
+ // Tooltip text provides accessibility.
+ [logoView setToolTip:base::SysWideToNSString(engine->short_name())];
+ engineIdentifier = logoView;
+ } else {
+ // No logo -- we must show a text label.
+ NSRect labelBounds = NSMakeRect(0, 0, kLogoLabelWidth, kLogoLabelHeight);
+ NSTextField* labelField =
+ [[[NSTextField alloc] initWithFrame:labelBounds] autorelease];
+ [labelField setBezeled:NO];
+ [labelField setEditable:NO];
+ [labelField setSelectable:NO];
+
+ scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
+ [[NSMutableParagraphStyle alloc] init]);
+ [paragraphStyle setAlignment:NSCenterTextAlignment];
+ NSDictionary* attrs = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSFont boldSystemFontOfSize:13], NSFontAttributeName,
+ paragraphStyle.get(), NSParagraphStyleAttributeName,
+ nil];
+
+ NSString* value = base::SysWideToNSString(engine->short_name());
+ scoped_nsobject<NSAttributedString> attrValue(
+ [[NSAttributedString alloc] initWithString:value
+ attributes:attrs]);
+
+ [labelField setAttributedStringValue:attrValue.get()];
+
+ engineIdentifier = labelField;
+ }
+
+ // Make the "Choose" button.
+ scoped_nsobject<NSButton> chooseButton(
+ [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 34)]);
+ [chooseButton setBezelStyle:NSRoundedBezelStyle];
+ [[chooseButton cell] setFont:[NSFont systemFontOfSize:
+ [NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
+ [chooseButton setTitle:l10n_util::GetNSStringWithFixup(IDS_FR_SEARCH_CHOOSE)];
+ [GTMUILocalizerAndLayoutTweaker sizeToFitView:chooseButton.get()];
+ [chooseButton setTag:index];
+ [chooseButton setTarget:self];
+ [chooseButton setAction:@selector(searchEngineSelected:)];
+
+ // Put 'em together.
+ NSRect engineIdentifierFrame = [engineIdentifier frame];
+ NSRect chooseButtonFrame = [chooseButton frame];
+
+ NSRect containingViewFrame = NSZeroRect;
+ containingViewFrame.size.width += engineIdentifierFrame.size.width;
+ containingViewFrame.size.height += engineIdentifierFrame.size.height;
+ containingViewFrame.size.height += kLogoButtonSpacing;
+ containingViewFrame.size.height += chooseButtonFrame.size.height;
+
+ NSView* containingView =
+ [[[NSView alloc] initWithFrame:containingViewFrame] autorelease];
+
+ [containingView addSubview:engineIdentifier];
+ engineIdentifierFrame.origin.y =
+ chooseButtonFrame.size.height + kLogoButtonSpacing;
+ [engineIdentifier setFrame:engineIdentifierFrame];
+
+ [containingView addSubview:chooseButton];
+ chooseButtonFrame.origin.x =
+ int((containingViewFrame.size.width - chooseButtonFrame.size.width) / 2);
+ [chooseButton setFrame:chooseButtonFrame];
+
+ return containingView;
+}
+
+- (NSFont*)mainLabelFont {
+ return [NSFont boldSystemFontOfSize:13];
+}
+
+- (IBAction)searchEngineSelected:(id)sender {
+ [[self window] close];
+ [NSApp stopModalWithCode:[sender tag]];
+}
+
+@end
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc
index b072ef8..6f43ddf 100644
--- a/chrome/browser/first_run/first_run.cc
+++ b/chrome/browser/first_run/first_run.cc
@@ -461,8 +461,6 @@ void FirstRunImportObserver::Finish() {
MessageLoop::current()->Quit();
}
-// TODO(avi): port the relevant pieces and enable this.
-#if !defined(OS_MACOSX)
// static
void FirstRun::AutoImport(
Profile* profile,
@@ -487,7 +485,15 @@ void FirstRun::AutoImport(
bool local_state_file_exists = file_util::PathExists(local_state_path);
scoped_refptr<ImporterHost> importer_host;
- importer_host = new ImporterHost();
+ // TODO(csilv,mirandac): Out-of-process import has only been qualified on
+ // MacOS X, so we will only use it on that platform since it is required.
+ // Remove this conditional logic once oop import is qualified for
+ // Linux/Windows. http://crbug.com/22142
+#if defined(OS_MACOSX)
+ importer_host = new ExternalProcessImporterHost;
+#else
+ importer_host = new ImporterHost;
+#endif
// Do import if there is an available profile for us to import.
if (importer_host->GetAvailableProfileCount() > 0) {
// Don't show the warning dialog if import fails.
@@ -547,4 +553,73 @@ void FirstRun::AutoImport(
process_singleton->Unlock();
FirstRun::CreateSentinel();
}
-#endif // !defined(OS_MACOSX)
+
+#if defined(OS_POSIX)
+namespace {
+
+// This class acts as an observer for the ImporterHost::Observer::ImportEnded
+// callback. When the import process is started, certain errors may cause
+// ImportEnded() to be called synchronously, but the typical case is that
+// ImportEnded() is called asynchronously. Thus we have to handle both cases.
+class ImportEndedObserver : public ImporterHost::Observer {
+ public:
+ ImportEndedObserver() : ended_(false),
+ should_quit_message_loop_(false) {}
+ virtual ~ImportEndedObserver() {}
+
+ virtual void ImportItemStarted(importer::ImportItem item) {}
+ virtual void ImportItemEnded(importer::ImportItem item) {}
+ virtual void ImportStarted() {}
+ virtual void ImportEnded() {
+ ended_ = true;
+ if (should_quit_message_loop_)
+ MessageLoop::current()->Quit();
+ }
+
+ void set_should_quit_message_loop() {
+ should_quit_message_loop_ = true;
+ }
+
+ bool ended() {
+ return ended_;
+ }
+
+ private:
+ // Set if the import has ended.
+ bool ended_;
+
+ // Set by the client (via set_should_quit_message_loop) if, when the import
+ // ends, this class should quit the message loop.
+ bool should_quit_message_loop_;
+};
+
+} // namespace
+
+// static
+bool FirstRun::ImportSettings(Profile* profile,
+ scoped_refptr<ImporterHost> importer_host,
+ int items_to_import) {
+ const ProfileInfo& source_profile = importer_host->GetSourceProfileInfoAt(0);
+
+ // Ensure that importers aren't requested to import items that they do not
+ // support.
+ items_to_import &= source_profile.services_supported;
+
+ scoped_ptr<ImportEndedObserver> observer(new ImportEndedObserver);
+ importer_host->SetObserver(observer.get());
+ importer_host->StartImportSettings(source_profile,
+ profile,
+ items_to_import,
+ new ProfileWriter(profile),
+ true);
+ // If the import process has not errored out, block on it.
+ if (!observer->ended()) {
+ observer->set_should_quit_message_loop();
+ MessageLoop::current()->Run();
+ }
+
+ // Unfortunately there's no success/fail signal in ImporterHost.
+ return true;
+}
+
+#endif // OS_POSIX
diff --git a/chrome/browser/first_run/first_run.h b/chrome/browser/first_run/first_run.h
index 87b2524..ea6489d 100644
--- a/chrome/browser/first_run/first_run.h
+++ b/chrome/browser/first_run/first_run.h
@@ -306,31 +306,4 @@ class FirstRunImportObserver : public ImportObserver {
DISALLOW_COPY_AND_ASSIGN(FirstRunImportObserver);
};
-#if defined(OS_MACOSX)
-// Show the First Run UI to the user, allowing them to create shortcuts for
-// the app, import their bookmarks and other data from another browser into
-// |profile| and perhaps some other tasks.
-// |process_singleton| is used to lock the handling of CopyData messages
-// while the First Run UI is visible.
-// |homepage_defined| true indicates that homepage is defined in master
-// preferences and should not be imported from another browser.
-// |import_items| specifies the items to import, specified in master
-// preferences and will override default behavior of importer.
-// |dont_import_items| specifies the items *not* to import, specified in master
-// preferences and will override default behavior of importer.
-// |search_engine_experiment| indicates whether the experimental search engine
-// window should be shown.
-// |randomize_search_engine_experiment| is true if the logos in the search
-// engine window should be shown in randomized order.
-// Returns true if the user clicked "Start", false if the user pressed "Cancel"
-// or closed the dialog.
-bool OpenFirstRunDialog(Profile* profile,
- bool homepage_defined,
- int import_items,
- int dont_import_items,
- bool search_engine_experiment,
- bool randomize_search_engine_experiment,
- ProcessSingleton* process_singleton);
-#endif // OS_MACOSX
-
#endif // CHROME_BROWSER_FIRST_RUN_FIRST_RUN_H_
diff --git a/chrome/browser/first_run/first_run_gtk.cc b/chrome/browser/first_run/first_run_gtk.cc
index 06febbd..3dd5ffa 100644
--- a/chrome/browser/first_run/first_run_gtk.cc
+++ b/chrome/browser/first_run/first_run_gtk.cc
@@ -22,44 +22,6 @@
#include "chrome/installer/util/google_update_settings.h"
#include "googleurl/src/gurl.h"
-namespace {
-
-// This class acts as an observer for the ImporterHost::Observer::ImportEnded
-// callback. When the import process is started, certain errors may cause
-// ImportEnded() to be called synchronously, but the typical case is that
-// ImportEnded() is called asynchronously. Thus we have to handle both cases.
-class ImportEndedObserver : public ImporterHost::Observer {
- public:
- ImportEndedObserver()
- : ended_(false),
- quit_message_loop_(false) {
- }
- virtual ~ImportEndedObserver() {}
-
- virtual void ImportItemStarted(importer::ImportItem item) {}
- virtual void ImportItemEnded(importer::ImportItem item) {}
- virtual void ImportStarted() {}
- virtual void ImportEnded() {
- ended_ = true;
- if (quit_message_loop_)
- MessageLoop::current()->Quit();
- }
-
- void set_quit_message_loop() {
- quit_message_loop_ = true;
- }
-
- bool ended() {
- return ended_;
- }
-
- private:
- bool ended_;
- bool quit_message_loop_;
-};
-
-} // namespace
-
// TODO(port): This is just a piece of the silent import functionality from
// ImportSettings for Windows. It would be nice to get the rest of it ported.
bool FirstRun::ImportBookmarks(const FilePath& import_bookmarks_path) {
@@ -121,29 +83,6 @@ double Upgrade::GetLastModifiedTimeOfExe() {
}
#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
-// At least for now, we do profile import in-process on Linux.
-// static
-bool FirstRun::ImportSettings(Profile* profile,
- scoped_refptr<ImporterHost> importer_host,
- int items_to_import) {
- // Import data.
- const ProfileInfo& source_profile = importer_host->GetSourceProfileInfoAt(0);
- scoped_ptr<ImportEndedObserver> observer(new ImportEndedObserver);
- importer_host->SetObserver(observer.get());
- importer_host->StartImportSettings(source_profile,
- profile,
- items_to_import,
- new ProfileWriter(profile),
- true);
- // If the import process has not errored out, block on it.
- if (!observer->ended()) {
- observer->set_quit_message_loop();
- MessageLoop::current()->Run();
- }
- // Unfortunately there's no success/fail signal in ImporterHost.
- return true;
-}
-
// static
void FirstRun::ShowFirstRunDialog(Profile* profile,
bool randomize_search_engine_experiment) {
diff --git a/chrome/browser/first_run/first_run_mac.mm b/chrome/browser/first_run/first_run_mac.mm
index 0795bce..3159e9d 100644
--- a/chrome/browser/first_run/first_run_mac.mm
+++ b/chrome/browser/first_run/first_run_mac.mm
@@ -5,110 +5,50 @@
#include "chrome/browser/first_run/first_run.h"
#import "base/scoped_nsobject.h"
-#include "base/sys_string_conversions.h"
#import "chrome/app/breakpad_mac.h"
#import "chrome/browser/cocoa/first_run_dialog.h"
-#import "chrome/browser/cocoa/import_progress_dialog.h"
-#include "chrome/browser/importer/importer.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/metrics/user_metrics.h"
+#import "chrome/browser/cocoa/search_engine_dialog_controller.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/shell_integration.h"
+#include "chrome/common/pref_names.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_update_settings.h"
-// Class that handles conducting the first run operation.
-// FirstRunController deletes itself when the first run operation ends.
-class FirstRunController : public ImportObserver {
- public:
- explicit FirstRunController();
- virtual ~FirstRunController() {}
+namespace {
- // Overridden methods from ImportObserver.
- virtual void ImportCanceled() {
- FirstRunDone();
- }
- virtual void ImportComplete() {
- FirstRunDone();
- }
-
- // Display first run UI, start the import and return when it's all over.
- bool DoFirstRun(Profile* profile, ProcessSingleton* process_singleton);
-
- private:
- // This method closes the first run window and quits the message loop so that
- // the Chrome startup can continue. This should be called when all the
- // first run tasks are done.
- void FirstRunDone();
-
- scoped_refptr<ImporterHost> importer_host_;
-
- DISALLOW_COPY_AND_ASSIGN(FirstRunController);
-};
-
-
-bool OpenFirstRunDialog(Profile* profile,
- bool homepage_defined,
- int import_items,
- int dont_import_items,
- bool search_engine_experiment,
- bool randomize_search_engine_experiment,
- ProcessSingleton* process_singleton) {
- FirstRunController* controller = new FirstRunController;
- return controller->DoFirstRun(profile, process_singleton);
-}
-
-FirstRunController::FirstRunController()
- : importer_host_(new ExternalProcessImporterHost) {
-}
-
-void FirstRunController::FirstRunDone() {
- // Set preference to show first run bubble and welcome page.
- FirstRun::SetShowFirstRunBubblePref(true);
- FirstRun::SetShowWelcomePagePref();
-}
-
-bool FirstRunController::DoFirstRun(Profile* profile,
- ProcessSingleton* process_singleton) {
- // This object is responsible for deleting itself, make sure that happens.
- scoped_ptr<FirstRunController> gc(this);
-
- scoped_nsobject<FirstRunDialogController> dialog(
- [[FirstRunDialogController alloc] init]);
+// Show the search engine selection dialog.
+void ShowSearchEngineSelectionDialog(Profile* profile,
+ bool randomize_search_engine_experiment) {
+ scoped_nsobject<SearchEngineDialogController> dialog(
+ [[SearchEngineDialogController alloc] init]);
+ [dialog.get() setProfile:profile];
+ [dialog.get() setRandomize:randomize_search_engine_experiment];
- // Set list of browsers we know how to import.
- ssize_t profiles_count = importer_host_->GetAvailableProfileCount();
-
- // TODO(jeremy): Test on newly created account.
- // TODO(jeremy): Correctly handle case where no browsers to import from
- // are detected.
- NSMutableArray *browsers = [NSMutableArray arrayWithCapacity:profiles_count];
- for (int i = 0; i < profiles_count; ++i) {
- std::wstring profile = importer_host_->GetSourceProfileNameAt(i);
- [browsers addObject:base::SysWideToNSString(profile)];
- }
- [dialog.get() setBrowserImportList:browsers];
-
- BOOL browser_import_disabled = profiles_count == 0;
- [dialog.get() setBrowserImportListHidden:browser_import_disabled];
-
- // FirstRunDialogController will call exit if "Cancel" is clicked.
[dialog.get() showWindow:nil];
+}
- // If user clicked cancel, bail - browser_main will return if we haven't
- // turned off the first run flag when this function returns.
- if ([dialog.get() userDidCancel]) {
- return false;
- }
-
- FirstRun::CreateSentinel();
-
- // If the dialog asked the user to opt-in for stats and crash reporting,
- // record the decision and enable the crash reporter if appropriate.
- if (![dialog.get() statsCheckboxHidden]) {
+// Show the first run UI.
+void ShowFirstRun(Profile* profile) {
+#if defined(GOOGLE_CHROME_BUILD)
+ // The purpose of the dialog is to ask the user to enable stats and crash
+ // reporting. This setting may be controlled through configuration management
+ // in enterprise scenarios. If that is the case, skip the dialog entirely, as
+ // it's not worth bothering the user for only the default browser question
+ // (which is likely to be forced in enterprise deployments anyway).
+ const PrefService::Preference* metrics_reporting_pref =
+ g_browser_process->local_state()->FindPreference(
+ prefs::kMetricsReportingEnabled);
+ if (!metrics_reporting_pref || !metrics_reporting_pref->IsManaged()) {
+ scoped_nsobject<FirstRunDialogController> dialog(
+ [[FirstRunDialogController alloc] init]);
+
+ [dialog.get() showWindow:nil];
+
+ // If the dialog asked the user to opt-in for stats and crash reporting,
+ // record the decision and enable the crash reporter if appropriate.
bool stats_enabled = [dialog.get() statsEnabled];
GoogleUpdateSettings::SetCollectStatsConsent(stats_enabled);
-#if defined(GOOGLE_CHROME_BUILD)
// Breakpad is normally enabled very early in the startup process. However,
// on the first run it may not have been enabled due to the missing opt-in
// from the user. If the user agreed now, enable breakpad if necessary.
@@ -116,33 +56,48 @@ bool FirstRunController::DoFirstRun(Profile* profile,
InitCrashReporter();
InitCrashProcessInfo();
}
-#endif // GOOGLE_CHROME_BUILD
- }
- // If selected set as default browser.
- BOOL make_default_browser = [dialog.get() makeDefaultBrowser];
- if (make_default_browser) {
- bool success = ShellIntegration::SetAsDefaultBrowser();
- DCHECK(success);
+ // If selected set as default browser.
+ BOOL make_default_browser = [dialog.get() makeDefaultBrowser];
+ if (make_default_browser) {
+ bool success = ShellIntegration::SetAsDefaultBrowser();
+ DCHECK(success);
+ }
}
+#else // GOOGLE_CHROME_BUILD
+ // We don't show the dialog in Chromium.
+#endif // GOOGLE_CHROME_BUILD
- // Import bookmarks.
- if (!browser_import_disabled && [dialog.get() importBookmarks]) {
- const importer::ProfileInfo& source_profile = importer_host_->
- GetSourceProfileInfoAt([dialog.get() browserImportSelectedIndex]);
- int16 items = source_profile.services_supported;
- // TODO(port): Do the actual import in a new process like Windows.
- ignore_result(gc.release());
- StartImportingWithUI(nil, items, importer_host_.get(),
- source_profile, profile, this, true);
- } else {
- // This is called by the importer if it runs.
- FirstRunDone();
- }
+ FirstRun::CreateSentinel();
- return true;
+ // Set preference to show first run bubble and welcome page.
+ FirstRun::SetShowFirstRunBubblePref(true);
+ FirstRun::SetShowWelcomePagePref();
+}
+
+} // namespace
+
+// static
+void FirstRun::ShowFirstRunDialog(Profile* profile,
+ bool randomize_search_engine_experiment) {
+ ShowSearchEngineSelectionDialog(profile,
+ randomize_search_engine_experiment);
+ ShowFirstRun(profile);
}
+
bool FirstRun::ImportBookmarks(const FilePath& import_bookmarks_path) {
// http://crbug.com/48880
return false;
}
+
+// static
+bool FirstRun::IsOrganic() {
+ // We treat all installs as organic.
+ return true;
+}
+
+// static
+void FirstRun::PlatformSetup() {
+ // Things that Windows does here (creating a desktop icon, for example) are
+ // not needed.
+}