summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-26 21:45:34 +0000
committerthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-26 21:45:34 +0000
commit96788b0612875c0d12584757b63f02112e9541a7 (patch)
treed7eb82156c83b850d2714110dd7d8bb7aad60c41
parent21ca7bf8f06e3b6e608f26eed8dce30515721b86 (diff)
downloadchromium_src-96788b0612875c0d12584757b63f02112e9541a7.zip
chromium_src-96788b0612875c0d12584757b63f02112e9541a7.tar.gz
chromium_src-96788b0612875c0d12584757b63f02112e9541a7.tar.bz2
Mac: First run bubble.
Add a BaseBubbleController. Move ContentBlockedBubbleController to use it (other bubbles will follow in later CLs), add FIrstRunBubbleController which uses it. Move some l10n stuff to l10n_util and use that, too. Update first run code to actually call the bubble code. Fix a double free while I'm at it (the scoped_ptr<> in DoFirstRun() already does the freeing, no need to do it in FirstRunDone()) BUG=27489,36366 TEST=Firstrun bubble shows up when starting chrome with --first-run, doesn't if starting chrome without that flag. Content blocked bubbles still work. Review URL: http://codereview.chromium.org/2822026 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50940 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/nibs/FirstRunBubble.xib498
-rw-r--r--chrome/browser/cocoa/base_bubble_controller.h53
-rw-r--r--chrome/browser/cocoa/base_bubble_controller.mm123
-rw-r--r--chrome/browser/cocoa/content_blocked_bubble_controller.h8
-rw-r--r--chrome/browser/cocoa/content_blocked_bubble_controller.mm113
-rw-r--r--chrome/browser/cocoa/content_blocked_bubble_controller_unittest.mm2
-rw-r--r--chrome/browser/cocoa/content_settings_dialog_controller.mm37
-rw-r--r--chrome/browser/cocoa/extension_installed_bubble_controller.mm2
-rw-r--r--chrome/browser/cocoa/first_run_bubble_controller.h24
-rw-r--r--chrome/browser/cocoa/first_run_bubble_controller.mm62
-rw-r--r--chrome/browser/cocoa/first_run_bubble_controller_unittest.mm43
-rw-r--r--chrome/browser/cocoa/l10n_util.h13
-rw-r--r--chrome/browser/cocoa/l10n_util.mm29
-rw-r--r--chrome/browser/cocoa/location_bar/location_bar_view_mac.h9
-rw-r--r--chrome/browser/cocoa/location_bar/location_bar_view_mac.mm27
-rw-r--r--chrome/browser/first_run_mac.mm9
-rw-r--r--chrome/browser/gtk/first_run_bubble.cc15
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.h2
-rw-r--r--chrome/browser/search_engines/util.cc25
-rw-r--r--chrome/browser/search_engines/util.h18
-rw-r--r--chrome/browser/views/first_run_bubble.cc26
-rw-r--r--chrome/browser/views/location_bar/location_bar_view.h2
-rw-r--r--chrome/chrome_browser.gypi7
-rw-r--r--chrome/chrome_dll.gypi1
-rw-r--r--chrome/chrome_tests.gypi1
25 files changed, 964 insertions, 185 deletions
diff --git a/chrome/app/nibs/FirstRunBubble.xib b/chrome/app/nibs/FirstRunBubble.xib
new file mode 100644
index 0000000..f2667cc
--- /dev/null
+++ b/chrome/app/nibs/FirstRunBubble.xib
@@ -0,0 +1,498 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+ <data>
+ <int key="IBDocument.SystemTarget">1050</int>
+ <string key="IBDocument.SystemVersion">9L31a</string>
+ <string key="IBDocument.InterfaceBuilderVersion">680</string>
+ <string key="IBDocument.AppKitVersion">949.54</string>
+ <string key="IBDocument.HIToolboxVersion">353.00</string>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="4"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomObject" id="1001">
+ <string key="NSClassName">FirstRunBubbleController</string>
+ </object>
+ <object class="NSCustomObject" id="1003">
+ <string key="NSClassName">FirstResponder</string>
+ </object>
+ <object class="NSCustomObject" id="1004">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSWindowTemplate" id="1005">
+ <int key="NSWindowStyleMask">15</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{196, 426}, {428, 84}}</string>
+ <int key="NSWTFlags">536873984</int>
+ <string key="NSWindowTitle">Window</string>
+ <string key="NSWindowClass">InfoBubbleWindow</string>
+ <nil key="NSViewClass"/>
+ <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+ <object class="NSView" key="NSWindowView" id="1006">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomView" id="301729179">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">274</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSTextField" id="664006571">
+ <reference key="NSNextResponder" ref="301729179"/>
+ <int key="NSvFlags">266</int>
+ <string key="NSFrame">{{17, 17}, {367, 17}}</string>
+ <reference key="NSSuperview" ref="301729179"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="114775885">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">272629760</int>
+ <string key="NSContents">^IDS_FR_BUBBLE_SUBTEXT</string>
+ <object class="NSFont" key="NSSupport">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">1.300000e+01</double>
+ <int key="NSfFlags">1044</int>
+ </object>
+ <reference key="NSControlView" ref="664006571"/>
+ <object class="NSColor" key="NSBackgroundColor" id="8127014">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor" id="573452522">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlTextColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MAA</bytes>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSTextField" id="944552054">
+ <reference key="NSNextResponder" ref="301729179"/>
+ <int key="NSvFlags">266</int>
+ <string key="NSFrame">{{17, 42}, {394, 22}}</string>
+ <reference key="NSSuperview" ref="301729179"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="175463096">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">1346371584</int>
+ <string key="NSContents">^IDS_FR_SE_BUBBLE_TITLE</string>
+ <object class="NSFont" key="NSSupport">
+ <string key="NSName">LucidaGrande-Bold</string>
+ <double key="NSSize">1.800000e+01</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <reference key="NSControlView" ref="944552054"/>
+ <reference key="NSBackgroundColor" ref="8127014"/>
+ <reference key="NSTextColor" ref="573452522"/>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{428, 84}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <string key="NSClassName">InfoBubbleView</string>
+ </object>
+ </object>
+ <string key="NSFrameSize">{428, 84}</string>
+ <reference key="NSSuperview"/>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+ <string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+ </object>
+ <object class="NSCustomObject" id="670916757">
+ <string key="NSClassName">ChromeUILocalizer</string>
+ </object>
+ <object class="NSCustomObject" id="684547419">
+ <string key="NSClassName">GTMUILocalizerAndLayoutTweaker</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">3</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">bubble_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="301729179"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="1005"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">6</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">localizer_</string>
+ <reference key="source" ref="684547419"/>
+ <reference key="destination" ref="670916757"/>
+ </object>
+ <int key="connectionID">22</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">uiObject_</string>
+ <reference key="source" ref="684547419"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">23</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">header_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="944552054"/>
+ </object>
+ <int key="connectionID">51</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <object class="NSArray" key="object" id="1002">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="1001"/>
+ <reference key="parent" ref="1002"/>
+ <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="1003"/>
+ <reference key="parent" ref="1002"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="1004"/>
+ <reference key="parent" ref="1002"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="1005"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1006"/>
+ </object>
+ <reference key="parent" ref="1002"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="1006"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="301729179"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="301729179"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="664006571"/>
+ <reference ref="944552054"/>
+ </object>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">20</int>
+ <reference key="object" ref="670916757"/>
+ <reference key="parent" ref="1002"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">21</int>
+ <reference key="object" ref="684547419"/>
+ <reference key="parent" ref="1002"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">47</int>
+ <reference key="object" ref="664006571"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="114775885"/>
+ </object>
+ <reference key="parent" ref="301729179"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">48</int>
+ <reference key="object" ref="114775885"/>
+ <reference key="parent" ref="664006571"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">49</int>
+ <reference key="object" ref="944552054"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="175463096"/>
+ </object>
+ <reference key="parent" ref="301729179"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">50</int>
+ <reference key="object" ref="175463096"/>
+ <reference key="parent" ref="944552054"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.IBPluginDependency</string>
+ <string>-2.IBPluginDependency</string>
+ <string>-3.IBPluginDependency</string>
+ <string>1.IBEditorWindowLastContentRect</string>
+ <string>1.IBPluginDependency</string>
+ <string>1.IBWindowTemplateEditedContentRect</string>
+ <string>1.NSWindowTemplate.visibleAtLaunch</string>
+ <string>1.WindowOrigin</string>
+ <string>1.editorWindowContentRectSynchronizationRect</string>
+ <string>2.IBPluginDependency</string>
+ <string>20.IBPluginDependency</string>
+ <string>21.IBPluginDependency</string>
+ <string>4.IBPluginDependency</string>
+ <string>47.IBPluginDependency</string>
+ <string>48.IBPluginDependency</string>
+ <string>49.IBPluginDependency</string>
+ <string>50.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{227, 905}, {428, 84}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{227, 905}, {428, 84}}</string>
+ <boolean value="NO"/>
+ <string>{196, 240}</string>
+ <string>{{357, 418}, {480, 270}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">51</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">BaseBubbleController</string>
+ <string key="superclassName">NSWindowController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">bubble_</string>
+ <string key="NS.object.0">InfoBubbleView</string>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/base_bubble_controller.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">ChromeEventProcessingWindow</string>
+ <string key="superclassName">NSWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/chrome_event_processing_window.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">ChromeUILocalizer</string>
+ <string key="superclassName">GTMUILocalizer</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/ui_localizer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">FirstRunBubbleController</string>
+ <string key="superclassName">BaseBubbleController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">header_</string>
+ <string key="NS.object.0">NSTextField</string>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/first_run_bubble_controller.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">GTMUILocalizer</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>otherObjectToLocalize_</string>
+ <string>owner_</string>
+ <string>yetAnotherObjectToLocalize_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>id</string>
+ <string>id</string>
+ <string>id</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../third_party/GTM/AppKit/GTMUILocalizer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">GTMUILocalizerAndLayoutTweaker</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>localizerOwner_</string>
+ <string>localizer_</string>
+ <string>uiObject_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>id</string>
+ <string>GTMUILocalizer</string>
+ <string>id</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">InfoBubbleView</string>
+ <string key="superclassName">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/info_bubble_view.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">InfoBubbleWindow</string>
+ <string key="superclassName">ChromeEventProcessingWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/info_bubble_window.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../third_party/GTM/Foundation/GTMNSObject+KeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/objc_zombie.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/status_bubble_mac.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/tab_strip_model_observer_bridge.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/chrome_browser_window.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/themed_window.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../../chrome.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ </data>
+</archive>
diff --git a/chrome/browser/cocoa/base_bubble_controller.h b/chrome/browser/cocoa/base_bubble_controller.h
new file mode 100644
index 0000000..795f1a1
--- /dev/null
+++ b/chrome/browser/cocoa/base_bubble_controller.h
@@ -0,0 +1,53 @@
+// 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>
+
+#import "base/cocoa_protocols_mac.h"
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+
+@class InfoBubbleView;
+
+// Base class for bubble controllers. Manages a xib that contains an
+// InfoBubbleWindow which contains an InfoBubbleView. Contains code to close
+// the bubble window on clicks outside of the window, and the like.
+// To use this class:
+// 1. Create a new xib that contains a window. Change the window's class to
+// InfoBubbleWindow. Give it a child view that autosizes to the window's full
+// size, give it class InfoBubbleView. Make the controller the window's
+// delegate.
+// 2. Create a subclass of BaseBubbleController.
+// 3. Change the xib's File Owner to your subclass.
+// 4. Hook up the File Owner's |bubble_| to the InfoBubbleView in the xib.
+@interface BaseBubbleController : NSWindowController<NSWindowDelegate> {
+ @private
+ NSWindow* parentWindow_; // weak
+ NSPoint anchor_;
+ IBOutlet InfoBubbleView* bubble_; // to set arrow position
+}
+
+// Creates a bubble. |nibPath| is just the basename, e.g. @"FirstRunBubble".
+// |anchoredAt| is in screen space. You need to call -showWindow: to make the
+// bubble visible. It will autorelease itself when the user dismisses the
+// bubble.
+// This is the designated initializer.
+- (id)initWithWindowNibPath:(NSString*)nibPath
+ parentWindow:(NSWindow*)parentWindow
+ anchoredAt:(NSPoint)anchoredAt;
+
+
+// Creates a bubble. |nibPath| is just the basename, e.g. @"FirstRunBubble".
+// |view| must be in a window. The bubble will point at |offset| relative to
+// |view|'s lower left corner. You need to call -showWindow: to make the
+// bubble visible. It will autorelease itself when the user dismisses the
+// bubble.
+- (id)initWithWindowNibPath:(NSString*)nibPath
+ relativeToView:(NSView*)view
+ offset:(NSPoint)offset;
+
+
+@property (nonatomic, readonly) InfoBubbleView* bubble;
+
+@end
diff --git a/chrome/browser/cocoa/base_bubble_controller.mm b/chrome/browser/cocoa/base_bubble_controller.mm
new file mode 100644
index 0000000..b155a4f
--- /dev/null
+++ b/chrome/browser/cocoa/base_bubble_controller.mm
@@ -0,0 +1,123 @@
+// 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/base_bubble_controller.h"
+
+#include "app/l10n_util.h"
+#include "base/logging.h"
+#include "base/mac_util.h"
+#include "base/string_util.h"
+#import "chrome/browser/cocoa/info_bubble_view.h"
+#include "grit/generated_resources.h"
+
+@implementation BaseBubbleController
+
+@synthesize bubble = bubble_;
+
+- (id)initWithWindowNibPath:(NSString*)nibPath
+ parentWindow:(NSWindow*)parentWindow
+ anchoredAt:(NSPoint)anchoredAt {
+ nibPath = [mac_util::MainAppBundle() pathForResource:nibPath
+ ofType:@"nib"];
+ if ((self = [super initWithWindowNibPath:nibPath owner:self])) {
+ parentWindow_ = parentWindow;
+ anchor_ = anchoredAt;
+
+ // Watch to see if the parent window closes, and if so, close this one.
+ NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+ [center addObserver:self
+ selector:@selector(parentWindowWillClose:)
+ name:NSWindowWillCloseNotification
+ object:parentWindow_];
+ }
+ return self;
+}
+
+- (id)initWithWindowNibPath:(NSString*)nibPath
+ relativeToView:(NSView*)view
+ offset:(NSPoint)offset {
+ DCHECK([view window]);
+ NSWindow* window = [view window];
+ NSRect bounds = [view convertRect:[view bounds] toView:nil];
+ NSPoint anchor = NSMakePoint(NSMinX(bounds) + offset.x,
+ NSMinY(bounds) + offset.y);
+ anchor = [window convertBaseToScreen:anchor];
+ return [self initWithWindowNibPath:nibPath
+ parentWindow:window
+ anchoredAt:anchor];
+}
+
+
+- (void)awakeFromNib {
+ // Check all connections have been made in Interface Builder.
+ DCHECK([self window]);
+ DCHECK(bubble_);
+ DCHECK_EQ(self, [[self window] delegate]);
+
+ [bubble_ setBubbleType:info_bubble::kWhiteInfoBubble];
+ [bubble_ setArrowLocation:info_bubble::kTopRight];
+}
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [super dealloc];
+}
+
+- (void)parentWindowWillClose:(NSNotification*)notification {
+ [self close];
+}
+
+- (void)windowWillClose:(NSNotification*)notification {
+ // We caught a close so we don't need to watch for the parent closing.
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [self autorelease];
+}
+
+// We want this to be a child of a browser window. addChildWindow:
+// (called from this function) will bring the window on-screen;
+// unfortunately, [NSWindowController showWindow:] will also bring it
+// on-screen (but will cause unexpected changes to the window's
+// position). We cannot have an addChildWindow: and a subsequent
+// showWindow:. Thus, we have our own version.
+- (void)showWindow:(id)sender {
+ NSWindow* window = [self window]; // completes nib load
+
+ NSPoint origin = anchor_;
+ NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset +
+ info_bubble::kBubbleArrowWidth / 2.0, 0);
+ offsets = [[parentWindow_ contentView] convertSize:offsets toView:nil];
+ origin.x += offsets.width;
+ if ([bubble_ arrowLocation] == info_bubble::kTopRight)
+ origin.x -= NSWidth([window frame]);
+ origin.y -= NSHeight([window frame]);
+ [window setFrameOrigin:origin];
+ [parentWindow_ addChildWindow:window ordered:NSWindowAbove];
+ [window makeKeyAndOrderFront:self];
+}
+
+- (void)close {
+ [parentWindow_ removeChildWindow:[self window]];
+ [super close];
+}
+
+// The controller is the delegate of the window so it receives did resign key
+// notifications. When key is resigned mirror Windows behavior and close the
+// window.
+- (void)windowDidResignKey:(NSNotification*)notification {
+ NSWindow* window = [self window];
+ DCHECK_EQ([notification object], window);
+ if ([window isVisible]) {
+ // If the window isn't visible, it is already closed, and this notification
+ // has been sent as part of the closing operation, so no need to close.
+ [self close];
+ }
+}
+
+// By implementing this, ESC causes the window to go away.
+- (IBAction)cancel:(id)sender {
+ // This is not a "real" cancel as potential changes to the radio group are not
+ // undone. That's ok.
+ [self close];
+}
+@end // BaseBubbleController
diff --git a/chrome/browser/cocoa/content_blocked_bubble_controller.h b/chrome/browser/cocoa/content_blocked_bubble_controller.h
index 669c437..6bb7c90 100644
--- a/chrome/browser/cocoa/content_blocked_bubble_controller.h
+++ b/chrome/browser/cocoa/content_blocked_bubble_controller.h
@@ -10,6 +10,7 @@
#import "base/cocoa_protocols_mac.h"
#include "base/scoped_nsobject.h"
#include "base/scoped_ptr.h"
+#import "chrome/browser/cocoa/base_bubble_controller.h"
class ContentSettingBubbleModel;
@class InfoBubbleView;
@@ -21,13 +22,8 @@ typedef std::map<NSButton*, int> PopupLinks;
}
// Manages a "content blocked" bubble.
-@interface ContentBlockedBubbleController
- : NSWindowController<NSWindowDelegate> {
+@interface ContentBlockedBubbleController : BaseBubbleController {
@private
- NSWindow* parentWindow_; // weak
- NSPoint anchor_;
- IBOutlet InfoBubbleView* bubble_; // to set arrow position
-
IBOutlet NSTextField* titleLabel_;
IBOutlet NSMatrix* allowBlockRadioGroup_;
diff --git a/chrome/browser/cocoa/content_blocked_bubble_controller.mm b/chrome/browser/cocoa/content_blocked_bubble_controller.mm
index e18370f..a30b336 100644
--- a/chrome/browser/cocoa/content_blocked_bubble_controller.mm
+++ b/chrome/browser/cocoa/content_blocked_bubble_controller.mm
@@ -6,17 +6,14 @@
#include "app/l10n_util.h"
#include "base/logging.h"
-#include "base/mac_util.h"
-#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "chrome/browser/blocked_popup_container.h"
#import "chrome/browser/cocoa/content_settings_dialog_controller.h"
#import "chrome/browser/cocoa/hyperlink_button_cell.h"
#import "chrome/browser/cocoa/info_bubble_view.h"
+#import "chrome/browser/cocoa/l10n_util.h"
#include "chrome/browser/content_setting_bubble_model.h"
#include "chrome/browser/host_content_settings_map.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
#include "grit/generated_resources.h"
#include "skia/ext/skia_utils_mac.h"
#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
@@ -56,17 +53,6 @@ const int kGeoHostPadding = 4;
// Minimal padding between "Manage" and "Done" buttons.
const int kManageDonePadding = 8;
-// Like |ReplaceStringPlaceholders(const string16&, const string16&, size_t*)|,
-// but for a NSString formatString.
-NSString* ReplaceNSStringPlaceholders(NSString* formatString,
- const string16& a,
- size_t* offset) {
- return base::SysUTF16ToNSString(
- ReplaceStringPlaceholders(base::SysNSStringToUTF16(formatString),
- a,
- offset));
-}
-
void SetControlSize(NSControl* control, NSControlSize controlSize) {
CGFloat fontSize = [NSFont systemFontSizeForControlSize:controlSize];
NSCell* cell = [control cell];
@@ -136,20 +122,11 @@ NSTextField* LabelWithFrame(NSString* text, const NSRect& frame) {
nibPaths_requires_an_entry_for_every_setting_type);
const int settingsType = model->content_type();
DCHECK_LT(settingsType, CONTENT_SETTINGS_NUM_TYPES);
- NSString* nibPath =
- [mac_util::MainAppBundle() pathForResource:nibPaths[settingsType]
- ofType:@"nib"];
- if ((self = [super initWithWindowNibPath:nibPath owner:self])) {
- parentWindow_ = parentWindow;
- anchor_ = anchoredAt;
+ if ((self = [super initWithWindowNibPath:nibPaths[settingsType]
+ parentWindow:parentWindow
+ anchoredAt:anchoredAt])) {
contentSettingBubbleModel_.reset(model.release());
-
- // Watch to see if the parent window closes, and if so, close this one.
- NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
- [center addObserver:self
- selector:@selector(parentWindowWillClose:)
- name:NSWindowWillCloseNotification
- object:parentWindow_];
+ [self showWindow:nil];
}
return self;
}
@@ -184,7 +161,7 @@ NSTextField* LabelWithFrame(NSString* text, const NSRect& frame) {
// Copy |host_| into radio group label.
NSCell* radioCell = [allowBlockRadioGroup_ cellWithTag:kAllowTag];
- [radioCell setTitle:ReplaceNSStringPlaceholders(
+ [radioCell setTitle:cocoa_l10n_util::ReplaceNSStringPlaceholders(
[radioCell title], UTF8ToUTF16(radioGroup.url.host()), NULL)];
// Layout radio group labels post-localization.
@@ -218,7 +195,7 @@ NSTextField* LabelWithFrame(NSString* text, const NSRect& frame) {
// If the link text is too long, clamp it.
[button sizeToFit];
- int maxWidth = NSWidth([bubble_ frame]) - 2 * NSMinX(referenceFrame);
+ int maxWidth = NSWidth([[self bubble] frame]) - 2 * NSMinX(referenceFrame);
NSRect buttonFrame = [button frame];
if (NSWidth(buttonFrame) > maxWidth) {
buttonFrame.size.width = maxWidth;
@@ -276,7 +253,7 @@ NSTextField* LabelWithFrame(NSString* text, const NSRect& frame) {
title:base::SysUTF8ToNSString(title)
icon:image
referenceFrame:radioFrame];
- [bubble_ addSubview:button];
+ [[self bubble] addSubview:button];
popupLinks_[button] = row;
}
}
@@ -379,11 +356,8 @@ NSTextField* LabelWithFrame(NSString* text, const NSRect& frame) {
}
- (void)awakeFromNib {
- DCHECK([self window]);
- DCHECK_EQ(self, [[self window] delegate]);
-
- [bubble_ setBubbleType:info_bubble::kWhiteInfoBubble];
- [bubble_ setArrowLocation:info_bubble::kTopRight];
+ [[self bubble] setBubbleType:info_bubble::kWhiteInfoBubble];
+ [[self bubble] setArrowLocation:info_bubble::kTopRight];
// Adapt window size to bottom buttons. Do this before all other layouting.
[self sizeToFitManageDoneButtons];
@@ -400,73 +374,6 @@ NSTextField* LabelWithFrame(NSString* text, const NSRect& frame) {
}
///////////////////////////////////////////////////////////////////////////////
-// Bubble-management related stuff
-
-// TODO(thakis): All that junk below should be in some superclass that all the
-// bubble controllers (bookmark bubble, extension installed bubble, page/browser
-// action bubble, content blocked bubble) derive from -- http://crbug.com/36366
-
-- (void)dealloc {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [super dealloc];
-}
-
-- (void)parentWindowWillClose:(NSNotification*)notification {
- [self close];
-}
-
-- (void)windowWillClose:(NSNotification*)notification {
- // We caught a close so we don't need to watch for the parent closing.
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [self autorelease];
-}
-
-// We want this to be a child of a browser window. addChildWindow:
-// (called from this function) will bring the window on-screen;
-// unfortunately, [NSWindowController showWindow:] will also bring it
-// on-screen (but will cause unexpected changes to the window's
-// position). We cannot have an addChildWindow: and a subsequent
-// showWindow:. Thus, we have our own version.
-- (void)showWindow:(id)sender {
- NSWindow* window = [self window]; // completes nib load
-
- NSPoint origin = anchor_;
- NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset +
- info_bubble::kBubbleArrowWidth / 2.0, 0);
- offsets = [[parentWindow_ contentView] convertSize:offsets toView:nil];
- origin.x -= NSWidth([window frame]) - offsets.width;
- origin.y -= NSHeight([window frame]);
- [window setFrameOrigin:origin];
- [parentWindow_ addChildWindow:window ordered:NSWindowAbove];
- [window makeKeyAndOrderFront:self];
-}
-
-- (void)close {
- [parentWindow_ removeChildWindow:[self window]];
- [super close];
-}
-
-// The controller is the delegate of the window so it receives did resign key
-// notifications. When key is resigned mirror Windows behavior and close the
-// window.
-- (void)windowDidResignKey:(NSNotification*)notification {
- NSWindow* window = [self window];
- DCHECK_EQ([notification object], window);
- if ([window isVisible]) {
- // If the window isn't visible, it is already closed, and this notification
- // has been sent as part of the closing operation, so no need to close.
- [self close];
- }
-}
-
-// By implementing this, ESC causes the window to go away.
-- (IBAction)cancel:(id)sender {
- // This is not a "real" cancel as potential changes to the radio group are not
- // undone. That's ok.
- [self close];
-}
-
-///////////////////////////////////////////////////////////////////////////////
// Actual application logic
- (IBAction)allowBlockToggled:(id)sender {
diff --git a/chrome/browser/cocoa/content_blocked_bubble_controller_unittest.mm b/chrome/browser/cocoa/content_blocked_bubble_controller_unittest.mm
index a7b940e..31b56cf 100644
--- a/chrome/browser/cocoa/content_blocked_bubble_controller_unittest.mm
+++ b/chrome/browser/cocoa/content_blocked_bubble_controller_unittest.mm
@@ -49,7 +49,7 @@ TEST_F(ContentBlockedBubbleControllerTest, Init) {
parentWindow:parent
anchoredAt:NSMakePoint(50, 20)];
EXPECT_TRUE(controller != nil);
- [controller showWindow:nil];
+ EXPECT_TRUE([[controller window] isVisible]);
[parent.get() close];
}
}
diff --git a/chrome/browser/cocoa/content_settings_dialog_controller.mm b/chrome/browser/cocoa/content_settings_dialog_controller.mm
index d909b05..c635a95 100644
--- a/chrome/browser/cocoa/content_settings_dialog_controller.mm
+++ b/chrome/browser/cocoa/content_settings_dialog_controller.mm
@@ -28,32 +28,6 @@ namespace {
// Stores the currently visible content settings dialog, if any.
ContentSettingsDialogController* g_instance = nil;
-// Walks views in top-down order, wraps each to their current width, and moves
-// the latter ones down to prevent overlaps.
-CGFloat VerticallyReflowGroup(NSArray* views) {
- views = [views sortedArrayUsingFunction:cocoa_l10n_util::CompareFrameY
- context:NULL];
- CGFloat localVerticalShift = 0;
- for (NSInteger index = [views count] - 1; index >= 0; --index) {
- NSView* view = [views objectAtIndex:index];
-
- // Since the tab pane is in a horizontal resizer in IB, it's convenient
- // to give all the subviews flexible width so that their sizes are
- // autoupdated in IB. However, in chrome, the subviews shouldn't have
- // flexible widths as this looks weird.
- [view setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
-
- NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
- localVerticalShift += delta.height;
- if (localVerticalShift) {
- NSPoint origin = [view frame].origin;
- origin.y -= localVerticalShift;
- [view setFrameOrigin:origin];
- }
- }
- return localVerticalShift;
-}
-
} // namespace
@@ -196,8 +170,17 @@ class PrefObserverDisabler {
// Adapt views to potentially long localized strings.
CGFloat windowDelta = 0;
for (NSTabViewItem* tab in [tabView_ tabViewItems]) {
+ NSArray* subviews = [[tab view] subviews];
windowDelta = MAX(windowDelta,
- VerticallyReflowGroup([[tab view] subviews]));
+ cocoa_l10n_util::VerticallyReflowGroup(subviews));
+
+ for (NSView* view in subviews) {
+ // Since the tab pane is in a horizontal resizer in IB, it's convenient
+ // to give all the subviews flexible width so that their sizes are
+ // autoupdated in IB. However, in chrome, the subviews shouldn't have
+ // flexible widths as this looks weird.
+ [view setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
+ }
}
NSRect frame = [[self window] frame];
diff --git a/chrome/browser/cocoa/extension_installed_bubble_controller.mm b/chrome/browser/cocoa/extension_installed_bubble_controller.mm
index b255d0e..69046ec 100644
--- a/chrome/browser/cocoa/extension_installed_bubble_controller.mm
+++ b/chrome/browser/cocoa/extension_installed_bubble_controller.mm
@@ -225,7 +225,7 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver {
NSPoint origin =
[parentWindow_ convertBaseToScreen:[self calculateArrowPoint]];
NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset +
- info_bubble::kBubbleArrowWidth / 2.0, 0);
+ info_bubble::kBubbleArrowWidth / 2.0, 0);
offsets = [[window contentView] convertSize:offsets toView:nil];
origin.x -= NSWidth([window frame]) - offsets.width;
origin.y -= NSHeight([window frame]);
diff --git a/chrome/browser/cocoa/first_run_bubble_controller.h b/chrome/browser/cocoa/first_run_bubble_controller.h
new file mode 100644
index 0000000..4e5fac5
--- /dev/null
+++ b/chrome/browser/cocoa/first_run_bubble_controller.h
@@ -0,0 +1,24 @@
+// 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>
+
+#import "chrome/browser/cocoa/base_bubble_controller.h"
+
+class Profile;
+
+// Manages the first run bubble.
+@interface FirstRunBubbleController : BaseBubbleController {
+ @private
+ // Header label.
+ IBOutlet NSTextField* header_;
+
+ Profile* profile_;
+}
+
+// Creates and shows a firstRun bubble.
++ (FirstRunBubbleController*) showForView:(NSView*)view
+ offset:(NSPoint)offset
+ profile:(Profile*)profile;
+@end
diff --git a/chrome/browser/cocoa/first_run_bubble_controller.mm b/chrome/browser/cocoa/first_run_bubble_controller.mm
new file mode 100644
index 0000000..6c4ea32
--- /dev/null
+++ b/chrome/browser/cocoa/first_run_bubble_controller.mm
@@ -0,0 +1,62 @@
+// 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_bubble_controller.h"
+
+#include "app/l10n_util.h"
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#import "chrome/browser/cocoa/l10n_util.h"
+#import "chrome/browser/cocoa/info_bubble_view.h"
+#include "chrome/browser/search_engines/util.h"
+#include "grit/generated_resources.h"
+
+@interface FirstRunBubbleController(Private)
+- (id)initRelativeToView:(NSView*)view
+ offset:(NSPoint)offset
+ profile:(Profile*)profile;
+@end
+
+@implementation FirstRunBubbleController
+
++ (FirstRunBubbleController*) showForView:(NSView*)view
+ offset:(NSPoint)offset
+ profile:(Profile*)profile {
+ // Autoreleases itself on bubble close.
+ return [[FirstRunBubbleController alloc] initRelativeToView:view
+ offset:offset
+ profile:profile];
+}
+
+- (id)initRelativeToView:(NSView*)view
+ offset:(NSPoint)offset
+ profile:(Profile*)profile {
+ if ((self = [super initWithWindowNibPath:@"FirstRunBubble"
+ relativeToView:view
+ offset:offset])) {
+ profile_ = profile;
+ [self showWindow:nil];
+ }
+ return self;
+}
+
+- (void)awakeFromNib {
+ [[self bubble] setBubbleType:info_bubble::kWhiteInfoBubble];
+
+ DCHECK(header_);
+ [header_ setStringValue:cocoa_l10n_util::ReplaceNSStringPlaceholders(
+ [header_ stringValue], GetDefaultSearchEngineName(profile_), NULL)];
+
+ // Adapt window size to bottom buttons. Do this before all other layouting.
+ CGFloat dy = cocoa_l10n_util::VerticallyReflowGroup([[self bubble] subviews]);
+ NSSize ds = NSMakeSize(0, dy);
+ ds = [[self bubble] convertSize:ds toView:nil];
+
+ NSRect frame = [[self window] frame];
+ frame.origin.y -= ds.height;
+ frame.size.height += ds.height;
+ [[self window] setFrame:frame display:YES];
+}
+
+@end // FirstRunBubbleController
diff --git a/chrome/browser/cocoa/first_run_bubble_controller_unittest.mm b/chrome/browser/cocoa/first_run_bubble_controller_unittest.mm
new file mode 100644
index 0000000..a6009a6
--- /dev/null
+++ b/chrome/browser/cocoa/first_run_bubble_controller_unittest.mm
@@ -0,0 +1,43 @@
+// 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_bubble_controller.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/cocoa/browser_test_helper.h"
+#import "chrome/browser/cocoa/cocoa_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class FirstRunBubbleControllerTest : public CocoaTest {
+ public:
+ BrowserTestHelper helper_;
+};
+
+// Check that the bubble doesn't crash or leak.
+TEST_F(FirstRunBubbleControllerTest, Init) {
+ scoped_nsobject<NSWindow> parent([[NSWindow alloc]
+ initWithContentRect:NSMakeRect(0, 0, 800, 600)
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO]);
+ [parent setReleasedWhenClosed:NO];
+ if (DebugUtil::BeingDebugged())
+ [parent.get() orderFront:nil];
+ else
+ [parent.get() orderBack:nil];
+
+ FirstRunBubbleController* controller = [FirstRunBubbleController
+ showForView:[parent.get() contentView]
+ offset:NSMakePoint(300, 300)
+ profile:helper_.profile()];
+ EXPECT_TRUE(controller != nil);
+ EXPECT_TRUE([[controller window] isVisible]);
+ [parent.get() close];
+}
+
+} // namespace
diff --git a/chrome/browser/cocoa/l10n_util.h b/chrome/browser/cocoa/l10n_util.h
index 5e417a1..bb26327 100644
--- a/chrome/browser/cocoa/l10n_util.h
+++ b/chrome/browser/cocoa/l10n_util.h
@@ -4,6 +4,8 @@
#import <Cocoa/Cocoa.h>
+#include "base/string16.h"
+
namespace cocoa_l10n_util {
// Compare function for -[NSArray sortedArrayUsingFunction:context:] that
@@ -16,4 +18,15 @@ NSInteger CompareFrameY(id view1, id view2, void* context);
// anything else: do +[GTMUILocalizerAndLayoutTweaker sizeToFitView:]
NSSize WrapOrSizeToFit(NSView* view);
+// Walks views in top-down order, wraps each to their current width, and moves
+// the latter ones down to prevent overlaps. Returns the vertical delta in view
+// coordinates.
+CGFloat VerticallyReflowGroup(NSArray* views);
+
+// Like |ReplaceStringPlaceholders(const string16&, const string16&, size_t*)|,
+// but for a NSString formatString.
+NSString* ReplaceNSStringPlaceholders(NSString* formatString,
+ const string16& a,
+ size_t* offset);
+
} // namespace cocoa_l10n_util
diff --git a/chrome/browser/cocoa/l10n_util.mm b/chrome/browser/cocoa/l10n_util.mm
index 91691ed..e39bdb3 100644
--- a/chrome/browser/cocoa/l10n_util.mm
+++ b/chrome/browser/cocoa/l10n_util.mm
@@ -4,6 +4,8 @@
#import "chrome/browser/cocoa/l10n_util.h"
+#include "base/string_util.h"
+#include "base/sys_string_conversions.h"
#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
namespace cocoa_l10n_util {
@@ -46,4 +48,31 @@ NSSize WrapOrSizeToFit(NSView* view) {
return [GTMUILocalizerAndLayoutTweaker sizeToFitView:view];
}
+CGFloat VerticallyReflowGroup(NSArray* views) {
+ views = [views sortedArrayUsingFunction:CompareFrameY
+ context:NULL];
+ CGFloat localVerticalShift = 0;
+ for (NSInteger index = [views count] - 1; index >= 0; --index) {
+ NSView* view = [views objectAtIndex:index];
+
+ NSSize delta = WrapOrSizeToFit(view);
+ localVerticalShift += delta.height;
+ if (localVerticalShift) {
+ NSPoint origin = [view frame].origin;
+ origin.y -= localVerticalShift;
+ [view setFrameOrigin:origin];
+ }
+ }
+ return localVerticalShift;
+}
+
+NSString* ReplaceNSStringPlaceholders(NSString* formatString,
+ const string16& a,
+ size_t* offset) {
+ return base::SysUTF16ToNSString(
+ ReplaceStringPlaceholders(base::SysNSStringToUTF16(formatString),
+ a,
+ offset));
+}
+
} // namespace cocoa_l10n_util
diff --git a/chrome/browser/cocoa/location_bar/location_bar_view_mac.h b/chrome/browser/cocoa/location_bar/location_bar_view_mac.h
index f7d77fe..6536a95 100644
--- a/chrome/browser/cocoa/location_bar/location_bar_view_mac.h
+++ b/chrome/browser/cocoa/location_bar/location_bar_view_mac.h
@@ -47,9 +47,7 @@ class LocationBarViewMac : public AutocompleteEditController,
virtual ~LocationBarViewMac();
// Overridden from LocationBar:
- virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type) {
- NOTIMPLEMENTED();
- }
+ virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type);
virtual std::wstring GetInputString() const;
virtual WindowOpenDisposition GetWindowOpenDisposition() const;
virtual PageTransition::Type GetPageTransition() const;
@@ -433,6 +431,8 @@ class LocationBarViewMac : public AutocompleteEditController,
// tab contents state.
void RefreshContentSettingsViews();
+ void ShowFirstRunBubbleInternal(FirstRun::BubbleType bubble_type);
+
scoped_ptr<AutocompleteEditViewMac> edit_view_;
CommandUpdater* command_updater_; // Weak, owned by Browser.
@@ -477,6 +477,9 @@ class LocationBarViewMac : public AutocompleteEditController,
// Used to register for notifications received by NotificationObserver.
NotificationRegistrar registrar_;
+ // Used to schedule a task for the first run info bubble.
+ ScopedRunnableMethodFactory<LocationBarViewMac> first_run_bubble_;
+
DISALLOW_COPY_AND_ASSIGN(LocationBarViewMac);
};
diff --git a/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm
index af31131..146128d 100644
--- a/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm
+++ b/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm
@@ -20,6 +20,7 @@
#include "chrome/browser/cocoa/event_utils.h"
#import "chrome/browser/cocoa/extensions/extension_action_context_menu.h"
#import "chrome/browser/cocoa/extensions/extension_popup_controller.h"
+#import "chrome/browser/cocoa/first_run_bubble_controller.h"
#import "chrome/browser/cocoa/location_bar/autocomplete_text_field.h"
#import "chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.h"
#include "chrome/browser/command_updater.h"
@@ -79,7 +80,8 @@ LocationBarViewMac::LocationBarViewMac(
profile_(profile),
browser_(browser),
toolbar_model_(toolbar_model),
- transition_(PageTransition::TYPED) {
+ transition_(PageTransition::TYPED),
+ first_run_bubble_(this) {
for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
ContentSettingImageView* content_setting_view =
new ContentSettingImageView(static_cast<ContentSettingsType>(i), this,
@@ -109,6 +111,25 @@ LocationBarViewMac::~LocationBarViewMac() {
[cell setStarIconView:NULL];
}
+void LocationBarViewMac::ShowFirstRunBubble(FirstRun::BubbleType bubble_type) {
+ // We need the browser window to be shown before we can show the bubble, but
+ // we get called before that's happened.
+ Task* task = first_run_bubble_.NewRunnableMethod(
+ &LocationBarViewMac::ShowFirstRunBubbleInternal, bubble_type);
+ MessageLoop::current()->PostTask(FROM_HERE, task);
+}
+
+void LocationBarViewMac::ShowFirstRunBubbleInternal(
+ FirstRun::BubbleType bubble_type) {
+ if (!field_ || ![field_ window])
+ return;
+
+ // The bubble needs to be just below the Omnibox and slightly to the right
+ // of the left omnibox icon, so shift x and y co-ordinates.
+ const NSPoint kOffset = NSMakePoint(-18, 4);
+ [FirstRunBubbleController showForView:field_ offset:kOffset profile:profile_];
+}
+
std::wstring LocationBarViewMac::GetInputString() const {
return location_input_;
}
@@ -888,9 +909,9 @@ void LocationBarViewMac::ContentSettingImageView::OnMousePressed(NSRect bounds)
ContentSettingBubbleModel::CreateContentSettingBubbleModel(
tabContents, profile_,
content_setting_image_model_->get_content_settings_type());
- [[ContentBlockedBubbleController showForModel:model
+ [ContentBlockedBubbleController showForModel:model
parentWindow:window
- anchoredAt:anchor] showWindow:nil];
+ anchoredAt:anchor];
}
NSString* LocationBarViewMac::ContentSettingImageView::GetToolTip() {
diff --git a/chrome/browser/first_run_mac.mm b/chrome/browser/first_run_mac.mm
index 4d2d29f..a9c5d21 100644
--- a/chrome/browser/first_run_mac.mm
+++ b/chrome/browser/first_run_mac.mm
@@ -70,10 +70,8 @@ FirstRunController::FirstRunController()
void FirstRunController::FirstRunDone() {
// Set preference to show first run bubble and welcome page.
- // TODO(jeremy): Implement
- // FirstRun::SetShowFirstRunBubblePref(true);
- // FirstRun::SetShowWelcomePagePref();
- delete this;
+ FirstRun::SetShowFirstRunBubblePref(true);
+ FirstRun::SetShowWelcomePagePref();
}
bool FirstRunController::DoFirstRun(Profile* profile,
@@ -151,6 +149,9 @@ bool FirstRunController::DoFirstRun(Profile* profile,
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();
}
return true;
diff --git a/chrome/browser/gtk/first_run_bubble.cc b/chrome/browser/gtk/first_run_bubble.cc
index e86df98..e169aca 100644
--- a/chrome/browser/gtk/first_run_bubble.cc
+++ b/chrome/browser/gtk/first_run_bubble.cc
@@ -12,7 +12,7 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/options_window.h"
-#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/search_engines/util.h"
#include "chrome/common/notification_service.h"
#include "gfx/gtk_util.h"
#include "grit/chromium_strings.h"
@@ -28,19 +28,6 @@ const int kButtonPadding = 4;
// Padding between content and edge of info bubble.
const int kContentBorder = 7;
-
-string16 GetDefaultSearchEngineName(Profile* profile) {
- if (!profile) {
- NOTREACHED();
- return string16();
- }
- const TemplateURL* const default_provider =
- profile->GetTemplateURLModel()->GetDefaultSearchProvider();
- if (!default_provider) {
- return string16();
- }
- return WideToUTF16(default_provider->short_name());
-}
} // namespace
// static
diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h
index 412adf0..da87cdc 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.h
+++ b/chrome/browser/gtk/location_bar_view_gtk.h
@@ -392,7 +392,7 @@ class LocationBarViewGtk : public AutocompleteEditController,
// The transition type to use for the navigation.
PageTransition::Type transition_;
- // Used schedule a task for the first run info bubble.
+ // Used to schedule a task for the first run info bubble.
ScopedRunnableMethodFactory<LocationBarViewGtk> first_run_bubble_;
// When true, the location bar view is read only and also is has a slightly
diff --git a/chrome/browser/search_engines/util.cc b/chrome/browser/search_engines/util.cc
new file mode 100644
index 0000000..28e1c93
--- /dev/null
+++ b/chrome/browser/search_engines/util.cc
@@ -0,0 +1,25 @@
+// 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.
+
+#include "chrome/browser/search_engines/util.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/profile.h"
+
+string16 GetDefaultSearchEngineName(Profile* profile) {
+ if (!profile) {
+ NOTREACHED();
+ return string16();
+ }
+ const TemplateURL* const default_provider =
+ profile->GetTemplateURLModel()->GetDefaultSearchProvider();
+ if (!default_provider) {
+ // TODO(cpu): bug 1187517. It is possible to have no default provider.
+ // returning an empty string is a stopgap measure for the crash
+ // http://code.google.com/p/chromium/issues/detail?id=2573
+ return string16();
+ }
+ return WideToUTF16(default_provider->short_name());
+}
diff --git a/chrome/browser/search_engines/util.h b/chrome/browser/search_engines/util.h
new file mode 100644
index 0000000..07f059c
--- /dev/null
+++ b/chrome/browser/search_engines/util.h
@@ -0,0 +1,18 @@
+// 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.
+
+#ifndef CHROME_BROWSER_SEARCH_ENGINES_UTIL_H_
+#define CHROME_BROWSER_SEARCH_ENGINES_UTIL_H_
+
+// This file contains utility functions for search engine functionality.
+
+#include "base/string16.h"
+
+class Profile;
+
+// Returns the short name of the default search engine, or the empty string if
+// none is set. |profile| may be NULL.
+string16 GetDefaultSearchEngineName(Profile* profile);
+
+#endif // CHROME_BROWSER_SEARCH_ENGINES_UTIL_H_
diff --git a/chrome/browser/views/first_run_bubble.cc b/chrome/browser/views/first_run_bubble.cc
index 2c6bcf9..0ebc0c7 100644
--- a/chrome/browser/views/first_run_bubble.cc
+++ b/chrome/browser/views/first_run_bubble.cc
@@ -8,14 +8,14 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "app/win_util.h"
+#include "base/utf_string_conversions.h"
#include "base/win_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/first_run.h"
#include "chrome/browser/options_window.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/search_engines/util.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
@@ -46,22 +46,6 @@ const int kStringSeparationPadding = 2;
// Margin around close button.
const int kMarginRightOfCloseButton = 7;
-std::wstring GetDefaultSearchEngineName(Profile* profile) {
- if (!profile) {
- NOTREACHED();
- return std::wstring();
- }
- const TemplateURL* const default_provider =
- profile->GetTemplateURLModel()->GetDefaultSearchProvider();
- if (!default_provider) {
- // TODO(cpu): bug 1187517. It is possible to have no default provider.
- // returning an empty string is a stopgap measure for the crash
- // http://code.google.com/p/chromium/issues/detail?id=2573
- return std::wstring();
- }
- return default_provider->short_name();
-}
-
} // namespace
// Base class for implementations of the client view which appears inside the
@@ -133,7 +117,7 @@ FirstRunBubbleView::FirstRunBubbleView(FirstRunBubble* bubble_window,
AddChildView(label2_);
std::wstring question_str = l10n_util::GetStringF(IDS_FR_BUBBLE_QUESTION,
- GetDefaultSearchEngineName(profile));
+ UTF16ToWideHack(GetDefaultSearchEngineName(profile)));
label3_ = new views::Label(question_str);
label3_->SetMultiLine(true);
label3_->SetFont(font);
@@ -142,7 +126,7 @@ FirstRunBubbleView::FirstRunBubbleView(FirstRunBubble* bubble_window,
AddChildView(label3_);
std::wstring keep_str = l10n_util::GetStringF(IDS_FR_BUBBLE_OK,
- GetDefaultSearchEngineName(profile));
+ UTF16ToWideHack(GetDefaultSearchEngineName(profile)));
keep_button_ = new views::NativeButton(this, keep_str);
keep_button_->SetIsDefault(true);
AddChildView(keep_button_);
@@ -421,7 +405,7 @@ FirstRunMinimalBubbleView::FirstRunMinimalBubbleView(
ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont);
label1_ = new views::Label(l10n_util::GetStringF(IDS_FR_SE_BUBBLE_TITLE,
- GetDefaultSearchEngineName(profile_)));
+ UTF16ToWideHack(GetDefaultSearchEngineName(profile_))));
label1_->SetFont(font.DeriveFont(3, gfx::Font::BOLD));
label1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
AddChildView(label1_);
diff --git a/chrome/browser/views/location_bar/location_bar_view.h b/chrome/browser/views/location_bar/location_bar_view.h
index 2419468..538f1ba 100644
--- a/chrome/browser/views/location_bar/location_bar_view.h
+++ b/chrome/browser/views/location_bar/location_bar_view.h
@@ -356,7 +356,7 @@ class LocationBarView : public LocationBar,
// focused. Used when the toolbar is in full keyboard accessibility mode.
bool show_focus_rect_;
- // Used schedule a task for the first run info bubble.
+ // Used to schedule a task for the first run info bubble.
ScopedRunnableMethodFactory<LocationBarView> first_run_bubble_;
DISALLOW_IMPLICIT_CONSTRUCTORS(LocationBarView);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index ec70636..5c5946e 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -586,6 +586,8 @@
'browser/cocoa/background_gradient_view.mm',
'browser/cocoa/background_tile_view.h',
'browser/cocoa/background_tile_view.mm',
+ 'browser/cocoa/base_bubble_controller.h',
+ 'browser/cocoa/base_bubble_controller.mm',
'browser/cocoa/base_view.h',
'browser/cocoa/base_view.mm',
'browser/cocoa/browser_window_factory.mm',
@@ -745,6 +747,8 @@
'browser/cocoa/find_bar_view.mm',
'browser/cocoa/find_pasteboard.h',
'browser/cocoa/find_pasteboard.mm',
+ 'browser/cocoa/first_run_bubble_controller.h',
+ 'browser/cocoa/first_run_bubble_controller.mm',
'browser/cocoa/first_run_dialog.h',
'browser/cocoa/first_run_dialog.mm',
'browser/cocoa/floating_bar_backing_view.h',
@@ -2089,6 +2093,8 @@
'browser/search_engines/template_url_prepopulate_data.h',
'browser/search_engines/template_url_table_model.cc',
'browser/search_engines/template_url_table_model.h',
+ 'browser/search_engines/util.cc',
+ 'browser/search_engines/util.h',
'browser/session_startup_pref.cc',
'browser/session_startup_pref.h',
'browser/sessions/base_session_service.cc',
@@ -2927,6 +2933,7 @@
'app/nibs/ExtensionInstalledBubble.xib',
'app/nibs/ExtensionInstallPrompt.xib',
'app/nibs/ExtensionInstallPromptNoWarnings.xib',
+ 'app/nibs/FirstRunBubble.xib',
'app/nibs/FirstRunDialog.xib',
'app/nibs/FontLanguageSettings.xib',
'app/nibs/GeolocationExceptionsWindow.xib',
diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi
index cb91f9a..b7dfcb6 100644
--- a/chrome/chrome_dll.gypi
+++ b/chrome/chrome_dll.gypi
@@ -222,6 +222,7 @@
'app/nibs/ExtensionInstallPrompt.xib',
'app/nibs/ExtensionInstallPromptNoWarnings.xib',
'app/nibs/FindBar.xib',
+ 'app/nibs/FirstRunBubble.xib',
'app/nibs/FirstRunDialog.xib',
'app/nibs/FontLanguageSettings.xib',
'app/nibs/GeolocationExceptionsWindow.xib',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index bb49425..29c8b466 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -713,6 +713,7 @@
'browser/cocoa/find_bar_text_field_unittest.mm',
'browser/cocoa/find_bar_view_unittest.mm',
'browser/cocoa/find_pasteboard_unittest.mm',
+ 'browser/cocoa/first_run_bubble_controller_unittest.mm',
'browser/cocoa/floating_bar_backing_view_unittest.mm',
'browser/cocoa/focus_tracker_unittest.mm',
'browser/cocoa/font_language_settings_controller_unittest.mm',