diff options
author | pinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-05 18:19:10 +0000 |
---|---|---|
committer | pinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-05 18:19:10 +0000 |
commit | d2123de693b44900b587ef1955af5e5217d68c42 (patch) | |
tree | 4e970debf26f143250a52d89b5f897362565ab77 /chrome | |
parent | 376883a4ccd8f92817de1355317adea570a730ce (diff) | |
download | chromium_src-d2123de693b44900b587ef1955af5e5217d68c42.zip chromium_src-d2123de693b44900b587ef1955af5e5217d68c42.tar.gz chromium_src-d2123de693b44900b587ef1955af5e5217d68c42.tar.bz2 |
Implement table for custom home pages at startup on Mac.
BUG=13151
TEST=custom home pages table. adding to it, removing. use current. enabling and disabling when applicable.
Review URL: http://codereview.chromium.org/119242
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17740 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/nibs/en.lproj/Preferences.xib | 242 | ||||
-rw-r--r-- | chrome/browser/cocoa/custom_home_pages_model.h | 52 | ||||
-rw-r--r-- | chrome/browser/cocoa/custom_home_pages_model.mm | 119 | ||||
-rw-r--r-- | chrome/browser/cocoa/custom_home_pages_model_unittest.mm | 141 | ||||
-rw-r--r-- | chrome/browser/cocoa/preferences_window_controller.h | 15 | ||||
-rw-r--r-- | chrome/browser/cocoa/preferences_window_controller.mm | 168 | ||||
-rw-r--r-- | chrome/chrome.gyp | 5 |
7 files changed, 660 insertions, 82 deletions
diff --git a/chrome/app/nibs/en.lproj/Preferences.xib b/chrome/app/nibs/en.lproj/Preferences.xib index b70ecfc..91eaaea 100644 --- a/chrome/app/nibs/en.lproj/Preferences.xib +++ b/chrome/app/nibs/en.lproj/Preferences.xib @@ -43,7 +43,7 @@ <nil key="NSViewClass"/> <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string> <object class="NSView" key="NSWindowView" id="408649839"> - <nil key="NSNextResponder"/> + <reference key="NSNextResponder"/> <int key="NSvFlags">256</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -52,12 +52,13 @@ <int key="NSvFlags">36</int> <string key="NSFrame">{{13, 10}, {533, 499}}</string> <reference key="NSSuperview" ref="408649839"/> + <reference key="NSWindow"/> <object class="NSMutableArray" key="NSTabViewItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSTabViewItem" id="1024664267"> <string key="NSIdentifier">1</string> <object class="NSView" key="NSView" id="412364894"> - <nil key="NSNextResponder"/> + <reference key="NSNextResponder" ref="838559838"/> <int key="NSvFlags">256</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -66,6 +67,7 @@ <int key="NSvFlags">268</int> <string key="NSFrame">{{273, 275}, {182, 23}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="788559409"> <int key="NSCellFlags">-2080244224</int> @@ -90,6 +92,7 @@ <int key="NSvFlags">268</int> <string key="NSFrame">{{171, 275}, {52, 23}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="709698869"> <int key="NSCellFlags">-2080244224</int> @@ -114,6 +117,7 @@ <int key="NSvFlags">268</int> <string key="NSFrame">{{222, 275}, {52, 23}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="517413682"> <int key="NSCellFlags">-2080244224</int> @@ -138,6 +142,7 @@ <int key="NSvFlags">268</int> <string key="NSFrame">{{41, 148}, {123, 17}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="519689237"> <int key="NSCellFlags">68288064</int> @@ -174,6 +179,7 @@ <int key="NSvFlags">268</int> <string key="NSFrame">{{169, 147}, {236, 18}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="131780438"> <int key="NSCellFlags">-1543373312</int> @@ -201,6 +207,7 @@ <int key="NSvFlags">268</int> <string key="NSFrame">{{41, 419}, {123, 17}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="542921234"> <int key="NSCellFlags">68288064</int> @@ -217,6 +224,7 @@ <int key="NSvFlags">268</int> <string key="NSFrame">{{171, 368}, {300, 70}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <int key="NSNumRows">3</int> <int key="NSNumCols">1</int> @@ -544,6 +552,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{169, 124}, {311, 18}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="114177510"> <int key="NSCellFlags">-1543373312</int> @@ -566,6 +575,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{41, 223}, {123, 17}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="901046858"> <int key="NSCellFlags">68288064</int> @@ -582,13 +592,14 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{171, 196}, {300, 46}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <int key="NSNumRows">2</int> <int key="NSNumCols">1</int> <object class="NSMutableArray" key="NSCells"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSButtonCell" id="182948450"> - <int key="NSCellFlags">-2080244224</int> + <int key="NSCellFlags">67239424</int> <int key="NSCellFlags2">0</int> <string key="NSContents">Use the New Tab page</string> <reference key="NSSupport" ref="445696277"/> @@ -602,7 +613,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSPeriodicInterval">25</int> </object> <object class="NSButtonCell" id="1001736883"> - <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags">-2080244224</int> <int key="NSCellFlags2">0</int> <string key="NSContents">Open this page:</string> <reference key="NSSupport" ref="445696277"/> @@ -764,7 +775,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSPeriodicDelay">400</int> <int key="NSPeriodicInterval">75</int> </object> - <reference key="NSSelectedCell" ref="182948450"/> + <int key="NSSelectedRow">1</int> + <reference key="NSSelectedCell" ref="1001736883"/> <reference key="NSBackgroundColor" ref="592613688"/> <reference key="NSCellBackgroundColor" ref="571857138"/> <reference key="NSFont" ref="445696277"/> @@ -774,6 +786,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{41, 37}, {123, 17}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="617938891"> <int key="NSCellFlags">68288064</int> @@ -790,6 +803,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{41, 70}, {123, 17}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="952238196"> <int key="NSCellFlags">68288064</int> @@ -806,6 +820,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{171, 65}, {161, 26}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSComboBoxCell" key="NSCell" id="317144895"> <int key="NSCellFlags">879885888</int> @@ -902,6 +917,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{163, 27}, {306, 32}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="523146452"> <int key="NSCellFlags">67239424</int> @@ -922,6 +938,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{295, 196}, {160, 22}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="771835631"> <int key="NSCellFlags">-1804468671</int> @@ -954,6 +971,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">256</int> <string key="NSFrameSize">{282, 63}</string> <reference key="NSSuperview" ref="570210247"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="_NSCornerView" key="NSCornerView"> <nil key="NSNextResponder"/> @@ -1006,7 +1024,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <reference key="NSBackgroundColor" ref="571857138"/> <reference key="NSGridColor" ref="345127196"/> <double key="NSRowHeight">1.700000e+01</double> - <int key="NSTvFlags">-700448768</int> + <int key="NSTvFlags">-901775360</int> <int key="NSColumnAutoresizingStyle">4</int> <int key="NSDraggingSourceMaskForLocal">15</int> <int key="NSDraggingSourceMaskForNonLocal">0</int> @@ -1015,6 +1033,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSFrame">{{1, 1}, {282, 63}}</string> <reference key="NSSuperview" ref="54854923"/> + <reference key="NSWindow"/> <reference key="NSDocView" ref="165250101"/> <reference key="NSBGColor" ref="452188023"/> <int key="NScvFlags">4</int> @@ -1022,8 +1041,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <object class="NSScroller" id="895676258"> <reference key="NSNextResponder" ref="54854923"/> <int key="NSvFlags">-2147483392</int> - <string key="NSFrame">{{268, 1}, {15, 75}}</string> + <string key="NSFrame">{{272, 1}, {11, 63}}</string> <reference key="NSSuperview" ref="54854923"/> + <reference key="NSWindow"/> + <int key="NSsFlags">256</int> <reference key="NSTarget" ref="54854923"/> <string key="NSAction">_doScroller:</string> <double key="NSPercent">9.868421e-01</double> @@ -1033,6 +1054,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">256</int> <string key="NSFrame">{{-100, -100}, {267, 15}}</string> <reference key="NSSuperview" ref="54854923"/> + <reference key="NSWindow"/> <int key="NSsFlags">1</int> <reference key="NSTarget" ref="54854923"/> <string key="NSAction">_doScroller:</string> @@ -1041,6 +1063,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSFrame">{{171, 295}, {284, 65}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <int key="NSsFlags">530</int> <reference key="NSVScroller" ref="895676258"/> <reference key="NSHScroller" ref="757862790"/> @@ -1052,6 +1075,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{337, 61}, {124, 32}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="580118686"> <int key="NSCellFlags">-1543373312</int> @@ -1077,12 +1101,13 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{168, 13}, {306, 14}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="448510798"> <int key="NSCellFlags">68288064</int> <int key="NSCellFlags2">272630784</int> <string key="NSContents">Chromium is not the default browser.</string> - <object class="NSFont" key="NSSupport" id="726730448"> + <object class="NSFont" key="NSSupport" id="783256529"> <string key="NSName">LucidaGrande</string> <double key="NSSize">1.100000e+01</double> <int key="NSfFlags">16</int> @@ -1105,10 +1130,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">256</int> <string key="NSFrameSize">{495, 1}</string> <reference key="NSSuperview" ref="786243832"/> + <reference key="NSWindow"/> </object> </object> <string key="NSFrame">{{9, 258}, {495, 1}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <string key="NSOffsets">{0, 0}</string> <object class="NSTextFieldCell" key="NSTitleCell"> <int key="NSCellFlags">67239424</int> @@ -1145,10 +1172,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">256</int> <string key="NSFrameSize">{495, 1}</string> <reference key="NSSuperview" ref="459939641"/> + <reference key="NSWindow"/> </object> </object> <string key="NSFrame">{{9, 181}, {495, 1}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <string key="NSOffsets">{0, 0}</string> <object class="NSTextFieldCell" key="NSTitleCell"> <int key="NSCellFlags">67239424</int> @@ -1185,10 +1214,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">256</int> <string key="NSFrameSize">{495, 1}</string> <reference key="NSSuperview" ref="291785667"/> + <reference key="NSWindow"/> </object> </object> <string key="NSFrame">{{9, 108}, {495, 1}}</string> <reference key="NSSuperview" ref="412364894"/> + <reference key="NSWindow"/> <string key="NSOffsets">{0, 0}</string> <object class="NSTextFieldCell" key="NSTitleCell"> <int key="NSCellFlags">67239424</int> @@ -1217,6 +1248,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> </object> <string key="NSFrame">{{10, 33}, {513, 453}}</string> + <reference key="NSSuperview" ref="838559838"/> + <reference key="NSWindow"/> </object> <string key="NSLabel">Basics</string> <reference key="NSColor" ref="592613688"/> @@ -1225,7 +1258,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <object class="NSTabViewItem" id="614928174"> <string key="NSIdentifier">2</string> <object class="NSView" key="NSView" id="712581699"> - <reference key="NSNextResponder" ref="838559838"/> + <nil key="NSNextResponder"/> <int key="NSvFlags">256</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -1609,7 +1642,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <object class="NSTextField" id="357234760"> <reference key="NSNextResponder" ref="712581699"/> <int key="NSvFlags">268</int> - <string key="NSFrame">{{168, 207}, {331, 34}}</string> + <string key="NSFrame">{{168, 211}, {331, 30}}</string> <reference key="NSSuperview" ref="712581699"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="1066779324"> @@ -1617,7 +1650,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSCellFlags2">272629760</int> <string type="base64-UTF8" key="NSContents">WW91IGNhbiBpbXBvcnQgeW91ciBib29rbWFya3MgYW5kIHNldHRpbmdzIGZyb20gb3RoZXIgYnJvd3Nl cnMgb24gdGhpcyBjb21wdXRlci4KA</string> - <reference key="NSSupport" ref="726730448"/> + <reference key="NSSupport" ref="783256529"/> <reference key="NSControlView" ref="357234760"/> <reference key="NSBackgroundColor" ref="592613688"/> <reference key="NSTextColor" ref="748094473"/> @@ -1709,7 +1742,7 @@ cnMgb24gdGhpcyBjb21wdXRlci4KA</string> <int key="NSCellFlags">67239424</int> <int key="NSCellFlags2">272629760</int> <string key="NSContents">Be aware that this may adversely affect the content of the New Tab Page.</string> - <reference key="NSSupport" ref="726730448"/> + <reference key="NSSupport" ref="783256529"/> <reference key="NSControlView" ref="732636188"/> <reference key="NSBackgroundColor" ref="592613688"/> <reference key="NSTextColor" ref="748094473"/> @@ -1735,7 +1768,7 @@ cnMgb24gdGhpcyBjb21wdXRlci4KA</string> <int key="NSPeriodicInterval">25</int> </object> </object> - <object class="NSMatrix" id="1046974247"> + <object class="NSMatrix" id="854747859"> <reference key="NSNextResponder" ref="712581699"/> <int key="NSvFlags">268</int> <string key="NSFrame">{{171, 312}, {300, 38}}</string> @@ -1745,13 +1778,13 @@ cnMgb24gdGhpcyBjb21wdXRlci4KA</string> <int key="NSNumCols">1</int> <object class="NSMutableArray" key="NSCells"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSButtonCell" id="758090254"> + <object class="NSButtonCell" id="674682819"> <int key="NSCellFlags">-2080244224</int> <int key="NSCellFlags2">0</int> <string key="NSContents">Automatically fill forms on web pages</string> <reference key="NSSupport" ref="445696277"/> <int key="NSTag">1</int> - <reference key="NSControlView" ref="1046974247"/> + <reference key="NSControlView" ref="854747859"/> <int key="NSButtonFlags">1211912703</int> <int key="NSButtonFlags2">128</int> <reference key="NSAlternateImage" ref="1028460734"/> @@ -1760,12 +1793,12 @@ cnMgb24gdGhpcyBjb21wdXRlci4KA</string> <int key="NSPeriodicDelay">200</int> <int key="NSPeriodicInterval">25</int> </object> - <object class="NSButtonCell" id="828688506"> + <object class="NSButtonCell" id="201008548"> <int key="NSCellFlags">67239424</int> <int key="NSCellFlags2">0</int> <string key="NSContents">Never fill forms.</string> <reference key="NSSupport" ref="445696277"/> - <reference key="NSControlView" ref="1046974247"/> + <reference key="NSControlView" ref="854747859"/> <int key="NSButtonFlags">1211912703</int> <int key="NSButtonFlags2">128</int> <object class="NSImage" key="NSNormalImage"> @@ -1870,7 +1903,7 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA</bytes> <string key="NSIntercellSpacing">{4, 2}</string> <int key="NSMatrixFlags">1151868928</int> <string key="NSCellClass">NSActionCell</string> - <object class="NSButtonCell" key="NSProtoCell" id="184803297"> + <object class="NSButtonCell" key="NSProtoCell" id="726075166"> <int key="NSCellFlags">67239424</int> <int key="NSCellFlags2">0</int> <string key="NSContents">Radio</string> @@ -1922,14 +1955,13 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSPeriodicDelay">400</int> <int key="NSPeriodicInterval">75</int> </object> - <reference key="NSSelectedCell" ref="758090254"/> + <reference key="NSSelectedCell" ref="674682819"/> <reference key="NSBackgroundColor" ref="592613688"/> <reference key="NSCellBackgroundColor" ref="571857138"/> <reference key="NSFont" ref="445696277"/> </object> </object> <string key="NSFrame">{{10, 33}, {513, 453}}</string> - <reference key="NSSuperview" ref="838559838"/> </object> <string key="NSLabel">User Data</string> <reference key="NSColor" ref="592613688"/> @@ -2024,18 +2056,20 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <reference key="NSTabView" ref="838559838"/> </object> </object> - <reference key="NSSelectedTabViewItem" ref="614928174"/> + <reference key="NSSelectedTabViewItem" ref="1024664267"/> <reference key="NSFont" ref="445696277"/> <int key="NSTvFlags">0</int> <bool key="NSAllowTruncatedLabels">YES</bool> <bool key="NSDrawsBackground">YES</bool> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="712581699"/> + <reference ref="412364894"/> </object> </object> </object> <string key="NSFrameSize">{559, 515}</string> + <reference key="NSSuperview"/> + <reference key="NSWindow"/> </object> <string key="NSScreenRect">{{0, 0}, {1440, 878}}</string> <string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string> @@ -2135,7 +2169,7 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <object class="NSButton" id="307133548"> <reference key="NSNextResponder" ref="1016273328"/> <int key="NSvFlags">268</int> - <string key="NSFrame">{{38, 543}, {63, 18}}</string> + <string key="NSFrame">{{38, 543}, {22, 18}}</string> <reference key="NSSuperview" ref="1016273328"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="108251948"> @@ -2157,7 +2191,7 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <object class="NSTextField" id="177474426"> <reference key="NSNextResponder" ref="1016273328"/> <int key="NSvFlags">268</int> - <string key="NSFrame">{{57, 524}, {441, 40}}</string> + <string key="NSFrame">{{63, 530}, {441, 34}}</string> <reference key="NSSuperview" ref="1016273328"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="373591416"> @@ -2173,7 +2207,7 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <object class="NSButton" id="1060684618"> <reference key="NSNextResponder" ref="1016273328"/> <int key="NSvFlags">268</int> - <string key="NSFrame">{{62, 502}, {99, 19}}</string> + <string key="NSFrame">{{66, 497}, {99, 25}}</string> <reference key="NSSuperview" ref="1016273328"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="163141236"> @@ -2740,6 +2774,21 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <object class="NSCustomObject" id="775776152"> <string key="NSClassName">PreferencesLocalizer</string> </object> + <object class="NSArrayController" id="495015235"> + <object class="NSMutableArray" key="NSDeclaredKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>customPagesSource.customHomePages</string> + <string>URL</string> + </object> + <string key="NSObjectClassName">CustomHomePageEntry</string> + <bool key="NSEditable">YES</bool> + <object class="_NSManagedProxy" key="_NSManagedProxy"/> + <bool key="NSAvoidsEmptySelection">YES</bool> + <bool key="NSPreservesSelection">YES</bool> + <bool key="NSSelectsInsertedObjects">YES</bool> + <bool key="NSFilterRestrictsInsertion">YES</bool> + <bool key="NSClearsFilterPredicateOnInsertion">YES</bool> + </object> </object> <object class="IBObjectContainer" key="IBDocument.Objects"> <object class="NSMutableArray" key="connectionRecords"> @@ -2999,10 +3048,10 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <object class="IBConnectionRecord"> <object class="IBBindingConnection" key="connection"> <string key="label">selectedIndex: formAutofillEnabledIndex</string> - <reference key="source" ref="1046974247"/> + <reference key="source" ref="854747859"/> <reference key="destination" ref="1001"/> <object class="NSNibBindingConnector" key="connector"> - <reference key="NSSource" ref="1046974247"/> + <reference key="NSSource" ref="854747859"/> <reference key="NSDestination" ref="1001"/> <string key="NSLabel">selectedIndex: formAutofillEnabledIndex</string> <string key="NSBinding">selectedIndex</string> @@ -3064,6 +3113,94 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> </object> <int key="connectionID">379</int> </object> + <object class="IBConnectionRecord"> + <object class="IBBindingConnection" key="connection"> + <string key="label">contentArray: customPagesSource.customHomePages</string> + <reference key="source" ref="495015235"/> + <reference key="destination" ref="1001"/> + <object class="NSNibBindingConnector" key="connector"> + <reference key="NSSource" ref="495015235"/> + <reference key="NSDestination" ref="1001"/> + <string key="NSLabel">contentArray: customPagesSource.customHomePages</string> + <string key="NSBinding">contentArray</string> + <string key="NSKeyPath">customPagesSource.customHomePages</string> + <int key="NSNibBindingConnectorVersion">2</int> + </object> + </object> + <int key="connectionID">389</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBBindingConnection" key="connection"> + <string key="label">value: arrangedObjects.URL</string> + <reference key="source" ref="1005813658"/> + <reference key="destination" ref="495015235"/> + <object class="NSNibBindingConnector" key="connector"> + <reference key="NSSource" ref="1005813658"/> + <reference key="NSDestination" ref="495015235"/> + <string key="NSLabel">value: arrangedObjects.URL</string> + <string key="NSBinding">value</string> + <string key="NSKeyPath">arrangedObjects.URL</string> + <int key="NSNibBindingConnectorVersion">2</int> + </object> + </object> + <int key="connectionID">395</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBBindingConnection" key="connection"> + <string key="label">enabled: enableRestoreButtons</string> + <reference key="source" ref="165250101"/> + <reference key="destination" ref="1001"/> + <object class="NSNibBindingConnector" key="connector"> + <reference key="NSSource" ref="165250101"/> + <reference key="NSDestination" ref="1001"/> + <string key="NSLabel">enabled: enableRestoreButtons</string> + <string key="NSBinding">enabled</string> + <string key="NSKeyPath">enableRestoreButtons</string> + <int key="NSNibBindingConnectorVersion">2</int> + </object> + </object> + <int key="connectionID">397</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">customPagesArrayController_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="495015235"/> + </object> + <int key="connectionID">400</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">addHomepage:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="909713979"/> + </object> + <int key="connectionID">401</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">removeSelectedHomepages:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="940065158"/> + </object> + <int key="connectionID">402</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">delegate</string> + <reference key="source" ref="165250101"/> + <reference key="destination" ref="1001"/> + </object> + <int key="connectionID">405</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">useCurrentPagesAsHomepage:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="810089388"/> + </object> + <int key="connectionID">407</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -3179,7 +3316,7 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <reference ref="987908490"/> <reference ref="732636188"/> <reference ref="921350969"/> - <reference ref="1046974247"/> + <reference ref="854747859"/> <reference ref="105783425"/> </object> <reference key="parent" ref="614928174"/> @@ -3457,7 +3594,6 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="590725975"/> - <reference ref="1060684618"/> <reference ref="514356928"/> <reference ref="860741341"/> <reference ref="416742488"/> @@ -3475,7 +3611,6 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <reference ref="412658410"/> <reference ref="348105916"/> <reference ref="307133548"/> - <reference ref="177474426"/> <reference ref="480577047"/> <reference ref="808321623"/> <reference ref="1006300402"/> @@ -3487,8 +3622,11 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <reference ref="913832943"/> <reference ref="928184762"/> <reference ref="777041502"/> + <reference ref="177474426"/> + <reference ref="1060684618"/> </object> <reference key="parent" ref="1002"/> + <string key="objectName">Under The Hood</string> </object> <object class="IBObjectRecord"> <int key="objectID">77</int> @@ -4315,29 +4453,35 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> </object> <object class="IBObjectRecord"> <int key="objectID">362</int> - <reference key="object" ref="1046974247"/> + <reference key="object" ref="854747859"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="184803297"/> - <reference ref="828688506"/> - <reference ref="758090254"/> + <reference ref="726075166"/> + <reference ref="201008548"/> + <reference ref="674682819"/> </object> <reference key="parent" ref="712581699"/> </object> <object class="IBObjectRecord"> <int key="objectID">363</int> - <reference key="object" ref="184803297"/> - <reference key="parent" ref="1046974247"/> + <reference key="object" ref="726075166"/> + <reference key="parent" ref="854747859"/> </object> <object class="IBObjectRecord"> <int key="objectID">364</int> - <reference key="object" ref="828688506"/> - <reference key="parent" ref="1046974247"/> + <reference key="object" ref="201008548"/> + <reference key="parent" ref="854747859"/> </object> <object class="IBObjectRecord"> <int key="objectID">365</int> - <reference key="object" ref="758090254"/> - <reference key="parent" ref="1046974247"/> + <reference key="object" ref="674682819"/> + <reference key="parent" ref="854747859"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">380</int> + <reference key="object" ref="495015235"/> + <reference key="parent" ref="1002"/> + <string key="objectName">CustomHomePages Array Controller</string> </object> </object> </object> @@ -4461,6 +4605,7 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <string>365.IBPluginDependency</string> <string>37.IBPluginDependency</string> <string>38.IBPluginDependency</string> + <string>380.IBPluginDependency</string> <string>39.IBPluginDependency</string> <string>4.IBPluginDependency</string> <string>40.IBPluginDependency</string> @@ -4601,8 +4746,8 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{81, 469}, {559, 515}}</string> - <string>{{81, 469}, {559, 515}}</string> + <string>{{91, 590}, {559, 515}}</string> + <string>{{91, 590}, {559, 515}}</string> <reference ref="6"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -4676,7 +4821,8 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{500, 0}, {524, 856}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{671, 173}, {524, 856}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -4722,7 +4868,7 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> </object> </object> <nil key="sourceID"/> - <int key="maxID">379</int> + <int key="maxID">407</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -4772,12 +4918,15 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> + <string>addHomepage:</string> <string>clearData:</string> <string>importData:</string> <string>makeDefaultBrowser:</string> + <string>removeSelectedHomepages:</string> <string>resetTheme:</string> <string>showPreferences:</string> <string>showSavedPasswords:</string> + <string>useCurrentPagesAsHomepage:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -4787,6 +4936,9 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <string>id</string> <string>id</string> <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> </object> </object> <object class="NSMutableDictionary" key="outlets"> @@ -4795,12 +4947,14 @@ ZGVkIGZpbGVzIGRvbid0IG9wZW4gYXV0b21hdGljYWxseS4</string> <bool key="EncodedWithXMLCoder">YES</bool> <string>advancedScroller_</string> <string>advancedView_</string> + <string>customPagesArrayController_</string> <string>tabView_</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>NSScrollView</string> <string>NSView</string> + <string>NSArrayController</string> <string>NSTabView</string> </object> </object> diff --git a/chrome/browser/cocoa/custom_home_pages_model.h b/chrome/browser/cocoa/custom_home_pages_model.h new file mode 100644 index 0000000..ba56e5f --- /dev/null +++ b/chrome/browser/cocoa/custom_home_pages_model.h @@ -0,0 +1,52 @@ +// Copyright (c) 2009 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_COCOA_CUSTOM_HOME_PAGES_MODEL_H_ +#define CHROME_BROWSER_COCOA_CUSTOM_HOME_PAGES_MODEL_H_ + +#import <Cocoa/Cocoa.h> + +#include <vector> +#include "base/scoped_nsobject.h" +#include "googleurl/src/gurl.h" + +class Profile; + +// The model for the "custom home pages" table in preferences. Contains a list +// of CustomHomePageEntry objects. This is intended to be used with Cocoa +// bindings. +// +// The supported binding is |customHomePages|, a to-many relationship which +// can be observed with an array controller. + +@interface CustomHomePagesModel : NSObject { + @private + scoped_nsobject<NSArray> entries_; + Profile* profile_; // weak, used for loading favicons +} + +// Initialize with |profile|, which must not be NULL. The profile is used for +// loading favicons for urls. +- (id)initWithProfile:(Profile*)profile; + +// Get/set the urls the model currently contains as a group. Only one change +// notification will be sent. +- (std::vector<GURL>)URLs; +- (void)setURLs:(const std::vector<GURL>&)urls; + +// For binding |customHomePages| to a mutable array controller. +- (NSUInteger)countOfCustomHomePages; +- (id)objectInCustomHomePagesAtIndex:(NSUInteger)index; +- (void)insertObject:(id)object inCustomHomePagesAtIndex:(NSUInteger)index; +- (void)removeObjectFromCustomHomePagesAtIndex:(NSUInteger)index; +@end + +// A notification that fires when the URL of one of the entries changes. +// Prevents interested parties from having to observe all model objects in order +// to persist changes to a single entry. Changes to the number of items in the +// model can be observed by watching |customHomePages| via KVO so an additional +// notification is not sent. +extern NSString* const kHomepageEntryChangedNotification; + +#endif // CHROME_BROWSER_COCOA_CUSTOM_HOME_PAGES_MODEL_H_ diff --git a/chrome/browser/cocoa/custom_home_pages_model.mm b/chrome/browser/cocoa/custom_home_pages_model.mm new file mode 100644 index 0000000..1204ac6 --- /dev/null +++ b/chrome/browser/cocoa/custom_home_pages_model.mm @@ -0,0 +1,119 @@ +// Copyright (c) 2009 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/custom_home_pages_model.h" + +#include "base/sys_string_conversions.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/net/url_fixer_upper.h" + +NSString* const kHomepageEntryChangedNotification = + @"kHomepageEntryChangedNotification"; + +// An entry representing a single item in the custom home page model. Stores +// a url and a favicon. +@interface CustomHomePageEntry : NSObject { + @private + scoped_nsobject<NSString> url_; + scoped_nsobject<NSImage> icon_; + + // If non-zero, indicates we're loading the favicon for the page. + HistoryService::Handle icon_handle_; +} +@property(nonatomic, copy) NSString* URL; +@property(nonatomic, retain) NSImage* image; +@end + +//---------------------------------------------------------------------------- + + +@implementation CustomHomePagesModel + +- (id)initWithProfile:(Profile*)profile { + if ((self = [super init])) { + profile_ = profile; + entries_.reset([[NSMutableArray alloc] init]); + } + return self; +} + +- (NSUInteger)countOfCustomHomePages { + return [entries_ count]; +} + +- (id)objectInCustomHomePagesAtIndex:(NSUInteger)index { + return [entries_ objectAtIndex:index]; +} + +- (void)insertObject:(id)object inCustomHomePagesAtIndex:(NSUInteger)index { + [entries_ insertObject:object atIndex:index]; +} + +- (void)removeObjectFromCustomHomePagesAtIndex:(NSUInteger)index { + [entries_ removeObjectAtIndex:index]; +} + +// Get/set the urls the model currently contains as a group. These will weed +// out any URLs that are empty and not add them to the model. As a result, +// the next time they're persisted to the prefs backend, they'll disappear. + +- (std::vector<GURL>)URLs { + std::vector<GURL> urls; + for (CustomHomePageEntry* entry in entries_.get()) { + const char* urlString = [[entry URL] UTF8String]; + if (urlString && std::strlen(urlString)) { + urls.push_back(GURL(std::string(urlString))); + } + } + return urls; +} + +- (void)setURLs:(const std::vector<GURL>&)urls { + [self willChangeValueForKey:@"customHomePages"]; + [entries_ removeAllObjects]; + for (size_t i = 0; i < urls.size(); ++i) { + scoped_nsobject<CustomHomePageEntry> entry( + [[CustomHomePageEntry alloc] init]); + const char* urlString = urls[i].spec().c_str(); + if (urlString && std::strlen(urlString)) { + [entry setURL:[NSString stringWithCString:urlString + encoding:NSUTF8StringEncoding]]; + [entries_ addObject:entry]; + } + } + [self didChangeValueForKey:@"customHomePages"]; +} + +@end + +//--------------------------------------------------------------------------- + +@implementation CustomHomePageEntry + +- (void)setURL:(NSString*)url { + // Make sure the url is valid before setting it by fixing it up. + std::string urlToFix(base::SysNSStringToUTF8(url)); + urlToFix = URLFixerUpper::FixupURL(urlToFix, ""); + url_.reset([base::SysUTF8ToNSString(urlToFix) retain]); + + // Broadcast that an individual item has changed. + [[NSNotificationCenter defaultCenter] + postNotificationName:kHomepageEntryChangedNotification object:nil]; + + // TODO(pinkerton): fetch favicon, convert to NSImage +} + +- (NSString*)URL { + return url_.get(); +} + +- (void)setImage:(NSImage*)image { + icon_.reset(image); +} + +- (NSImage*)image { + return icon_.get(); +} + +@end diff --git a/chrome/browser/cocoa/custom_home_pages_model_unittest.mm b/chrome/browser/cocoa/custom_home_pages_model_unittest.mm new file mode 100644 index 0000000..7ca6402 --- /dev/null +++ b/chrome/browser/cocoa/custom_home_pages_model_unittest.mm @@ -0,0 +1,141 @@ +// Copyright (c) 2009 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 "base/scoped_nsobject.h" +#include "chrome/browser/cocoa/browser_test_helper.h" +#import "chrome/browser/cocoa/custom_home_pages_model.h" +#include "testing/gtest/include/gtest/gtest.h" + +// A helper for KVO and NSNotifications. Makes a note that it's been called +// back. +@interface CustomHomePageHelper : NSObject { + @public + BOOL sawNotification_; +} +@end + +@implementation CustomHomePageHelper +- (void)observeValueForKeyPath:(NSString*)keyPath + ofObject:(id)object + change:(NSDictionary*)change + context:(void*)context { + sawNotification_ = YES; +} + +- (void)entryChanged:(NSNotification*)notify { + sawNotification_ = YES; +} +@end + +class CustomHomePagesModelTest : public testing::Test { + public: + CustomHomePagesModelTest() { + model_.reset([[CustomHomePagesModel alloc] + initWithProfile:helper_.profile()]); + } + ~CustomHomePagesModelTest() { } + + BrowserTestHelper helper_; + scoped_nsobject<CustomHomePagesModel> model_; +}; + +TEST_F(CustomHomePagesModelTest, Init) { + scoped_nsobject<CustomHomePagesModel> model( + [[CustomHomePagesModel alloc] initWithProfile:helper_.profile()]); +} + +TEST_F(CustomHomePagesModelTest, GetSetURLs) { + // Basic test. + std::vector<GURL> urls; + urls.push_back(GURL("http://www.google.com")); + [model_ setURLs:urls]; + std::vector<GURL> received_urls = [model_.get() URLs]; + EXPECT_EQ(received_urls.size(), 1U); + EXPECT_TRUE(urls[0] == received_urls[0]); + + // Set an empty list, make sure we get back an empty list. + std::vector<GURL> empty; + [model_ setURLs:empty]; + received_urls = [model_.get() URLs]; + EXPECT_EQ(received_urls.size(), 0U); + + // Give it a list with not well-formed URLs and make sure we get back. + // only the good ones. + std::vector<GURL> poorly_formed; + poorly_formed.push_back(GURL("http://www.google.com")); // good + poorly_formed.push_back(GURL("www.google.com")); // bad + poorly_formed.push_back(GURL("www.yahoo.")); // bad + poorly_formed.push_back(GURL("http://www.yahoo.com")); // good + [model_ setURLs:poorly_formed]; + received_urls = [model_.get() URLs]; + EXPECT_EQ(received_urls.size(), 2U); +} + +// Test that we get a KVO notification when called setURLs. +TEST_F(CustomHomePagesModelTest, KVOObserveWhenListChanges) { + scoped_nsobject<CustomHomePageHelper> kvo_helper( + [[CustomHomePageHelper alloc] init]); + [model_ addObserver:kvo_helper + forKeyPath:@"customHomePages" + options:0L + context:NULL]; + EXPECT_FALSE(kvo_helper.get()->sawNotification_); + + std::vector<GURL> urls; + urls.push_back(GURL("http://www.google.com")); + [model_ setURLs:urls]; // Should send kvo change notification. + EXPECT_TRUE(kvo_helper.get()->sawNotification_); +} + +// Test the KVO "to-many" bindings for |customHomePages| and the KVO +// notifiation when items are added to and removed from the list. +TEST_F(CustomHomePagesModelTest, KVO) { + EXPECT_EQ([model_ countOfCustomHomePages], 0U); + + scoped_nsobject<CustomHomePageHelper> kvo_helper( + [[CustomHomePageHelper alloc] init]); + [model_ addObserver:kvo_helper + forKeyPath:@"customHomePages" + options:0L + context:NULL]; + EXPECT_FALSE(kvo_helper.get()->sawNotification_); + + // Cheat and insert NSString objects into the array. As long as we don't + // call -URLs, we'll be ok. + [model_ insertObject:@"www.google.com" inCustomHomePagesAtIndex:0]; + EXPECT_TRUE(kvo_helper.get()->sawNotification_); + [model_ insertObject:@"www.yahoo.com" inCustomHomePagesAtIndex:1]; + [model_ insertObject:@"dev.chromium.org" inCustomHomePagesAtIndex:2]; + EXPECT_EQ([model_ countOfCustomHomePages], 3U); + + EXPECT_TRUE([[model_ objectInCustomHomePagesAtIndex:1] + isEqualToString:@"www.yahoo.com"]); + + kvo_helper.get()->sawNotification_ = NO; + [model_ removeObjectFromCustomHomePagesAtIndex:1]; + EXPECT_TRUE(kvo_helper.get()->sawNotification_); + EXPECT_EQ([model_ countOfCustomHomePages], 2U); + EXPECT_TRUE([[model_ objectInCustomHomePagesAtIndex:1] + isEqualToString:@"dev.chromium.org"]); + EXPECT_TRUE([[model_ objectInCustomHomePagesAtIndex:0] + isEqualToString:@"www.google.com"]); +} + +// Test that when individual items are changed that they broadcast a message. +TEST_F(CustomHomePagesModelTest, ModelChangedNotification) { + scoped_nsobject<CustomHomePageHelper> kvo_helper( + [[CustomHomePageHelper alloc] init]); + [[NSNotificationCenter defaultCenter] + addObserver:kvo_helper + selector:@selector(entryChanged:) + name:kHomepageEntryChangedNotification + object:nil]; + + std::vector<GURL> urls; + urls.push_back(GURL("http://www.google.com")); + [model_ setURLs:urls]; + id entry = [model_ objectInCustomHomePagesAtIndex:0]; + [entry setURL:@"http://www.foo.bar"]; + EXPECT_TRUE(kvo_helper.get()->sawNotification_); +} diff --git a/chrome/browser/cocoa/preferences_window_controller.h b/chrome/browser/cocoa/preferences_window_controller.h index 57ff985..e7f7734 100644 --- a/chrome/browser/cocoa/preferences_window_controller.h +++ b/chrome/browser/cocoa/preferences_window_controller.h @@ -8,10 +8,10 @@ #include "base/scoped_nsobject.h" #include "chrome/common/pref_member.h" +@class CustomHomePagesModel; class PrefObserverBridge; class PrefService; class Profile; -@class StartupURLDataSource; // A window controller that handles the preferences window. The bulk of the // work is handled via Cocoa Bindings and getter/setter methods that wrap @@ -31,14 +31,17 @@ class Profile; PrefService* prefs_; // weak ref - Obtained from profile_ for convenience. scoped_ptr<PrefObserverBridge> observer_; // Watches for pref changes. IBOutlet NSTabView* tabView_; + IBOutlet NSArrayController* customPagesArrayController_; // Basics panel IntegerPrefMember restoreOnStartup_; - scoped_nsobject<StartupURLDataSource> customPagesSource_; + scoped_nsobject<CustomHomePagesModel> customPagesSource_; BooleanPrefMember newTabPageIsHomePage_; StringPrefMember homepage_; BooleanPrefMember showHomeButton_; BooleanPrefMember showPageOptionButtons_; + // Used when creating a new home page url to make the new cell editable. + BOOL pendingSelectForEdit_; // User Data panel BooleanPrefMember askSavePasswords_; @@ -59,6 +62,9 @@ class Profile; // Basics panel - (IBAction)makeDefaultBrowser:(id)sender; +- (IBAction)addHomepage:(id)sender; +- (IBAction)removeSelectedHomepages:(id)sender; +- (IBAction)useCurrentPagesAsHomepage:(id)sender; // User Data panel - (IBAction)showSavedPasswords:(id)sender; @@ -66,7 +72,10 @@ class Profile; - (IBAction)clearData:(id)sender; - (IBAction)resetTheme:(id)sender; -@end +// Usable from cocoa bindings to hook up the custom home pages table. +@property(readonly) CustomHomePagesModel* customPagesSource; // NSNotification sent when the prefs window is closed. extern NSString* const kUserDoneEditingPrefsNotification; + +@end diff --git a/chrome/browser/cocoa/preferences_window_controller.mm b/chrome/browser/cocoa/preferences_window_controller.mm index ef5c207..cd800cb 100644 --- a/chrome/browser/cocoa/preferences_window_controller.mm +++ b/chrome/browser/cocoa/preferences_window_controller.mm @@ -8,7 +8,10 @@ #include "base/mac_util.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" #import "chrome/browser/cocoa/clear_browsing_data_controller.h" +#import "chrome/browser/cocoa/custom_home_pages_model.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/net/url_fixer_upper.h" #include "chrome/browser/profile.h" @@ -33,24 +36,6 @@ std::wstring GetNewTabUIURLString() { } } // namespace -// A data source object for the "startup urls" table. -// TODO(pinkerton): hook this up to bindings. -@interface StartupURLDataSource : NSObject { - @private - Profile* profile_; // weak, used to load icons -} -- (id)initWithProfile:(Profile*)profile; -@end - -@implementation StartupURLDataSource -- (id)initWithProfile:(Profile*)profile { - if ((self = [super init])) { - profile_ = profile; - } - return self; -} -@end - //------------------------------------------------------------------------- @interface PreferencesWindowController(Private) @@ -62,6 +47,8 @@ std::wstring GetNewTabUIURLString() { - (void)registerPrefObservers; - (void)unregisterPrefObservers; +- (void)customHomePagesChanged; + // KVC setter methods. - (void)setNewTabPageIsHomePageIndex:(NSInteger)val; - (void)setHomepageURL:(NSString*)urlString; @@ -104,8 +91,25 @@ class PrefObserverBridge : public NotificationObserver { prefs_ = profile->GetPrefs(); DCHECK(prefs_); observer_.reset(new PrefObserverBridge(self)); - customPagesSource_.reset([[StartupURLDataSource alloc] + + // Set up the model for the custom home page table. The KVO observation + // tells us when the number of items in the array changes. The normal + // observation tells us when one of the URLs of an item changes. + customPagesSource_.reset([[CustomHomePagesModel alloc] initWithProfile:profile_]); + const SessionStartupPref startupPref = + SessionStartupPref::GetStartupPref(prefs_); + [customPagesSource_ setURLs:startupPref.urls]; + [customPagesSource_ addObserver:self + forKeyPath:@"customHomePages" + options:0L + context:NULL]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(homepageEntryChanged:) + name:kHomepageEntryChangedNotification + object:nil]; + // This needs to be done before awakeFromNib: because the bindings set up // in the nib rely on it. [self registerPrefObservers]; @@ -128,6 +132,8 @@ class PrefObserverBridge : public NotificationObserver { } - (void)dealloc { + [customPagesSource_ removeObserver:self forKeyPath:@"customHomePages"]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; [self unregisterPrefObservers]; [super dealloc]; } @@ -149,7 +155,7 @@ class PrefObserverBridge : public NotificationObserver { // TODO(pinkerton): Register Default search. // UserData panel - askSavePasswords_.Init(prefs::kPasswordManagerEnabled, + askSavePasswords_.Init(prefs::kPasswordManagerEnabled, prefs_, observer_.get()); formAutofill_.Init(prefs::kFormAutofillEnabled, prefs_, observer_.get()); @@ -166,10 +172,25 @@ class PrefObserverBridge : public NotificationObserver { // User Data panel // Nothing to do here. - + // TODO(pinkerton): do other panels... } +// Called when a key we're observing via KVO changes. +- (void)observeValueForKeyPath:(NSString*)keyPath + ofObject:(id)object + change:(NSDictionary*)change + context:(void*)context { + if ([keyPath isEqualToString:@"customHomePages"]) { + [self customHomePagesChanged]; + return; + } + [super observeValueForKeyPath:keyPath + ofObject:object + change:change + context:context]; +} + // Record the user performed a certain action and save the preferences. - (void)recordUserAction:(const wchar_t*)action { UserMetrics::RecordComputedAction(action, profile_); @@ -228,15 +249,14 @@ class PrefObserverBridge : public NotificationObserver { // TODO(beng): Note that the kURLsToRestoreOnStartup pref is a mutable list, // and changes to mutable lists aren't broadcast through the - // observer system, so the second half of this condition will + // observer system, so this condition will // never match. Once support for broadcasting such updates is // added, this will automagically start to work, and this comment // can be removed. if (*prefName == prefs::kURLsToRestoreOnStartup) { const SessionStartupPref startupPref = SessionStartupPref::GetStartupPref(prefs_); - // Set table model. - NOTIMPLEMENTED(); + [customPagesSource_ setURLs:startupPref.urls]; } if (*prefName == prefs::kHomePageIsNewTabPage) { @@ -261,18 +281,39 @@ class PrefObserverBridge : public NotificationObserver { // on the "restore on startup" pref. The ordering of the cells is in the // same order as the pref. - (NSInteger)restoreOnStartupIndex { - const SessionStartupPref startupPref = - SessionStartupPref::GetStartupPref(prefs_); - return startupPref.type; + const SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs_); + return pref.type; +} + +// A helper function that takes the startup session type, grabs the URLs to +// restore, and saves it all in prefs. +- (void)saveSessionStartupWithType:(SessionStartupPref::Type)type { + SessionStartupPref pref; + pref.type = type; + pref.urls = [customPagesSource_.get() URLs]; + SessionStartupPref::SetStartupPref(prefs_, pref); +} + +// Called when the custom home pages array changes. Force a save to prefs, but +// in order to save it, we have to look up what the current radio button +// setting is (since they're set together). What a pain. +- (void)customHomePagesChanged { + const SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs_); + [self saveSessionStartupWithType:pref.type]; +} + +// Called when an entry in the custom home page array changes URLs. Force +// a save to prefs. +- (void)homepageEntryChanged:(NSNotification*)notify { + [self customHomePagesChanged]; } // Sets the pref based on the index of the selected cell in the matrix and // marks the appropriate user metric. - (void)setRestoreOnStartupIndex:(NSInteger)type { - SessionStartupPref pref; - pref.type = static_cast<SessionStartupPref::Type>(type); - // TODO(pinkerton): list of pages in |pref.urls| - switch (pref.type) { + SessionStartupPref::Type startupType = + static_cast<SessionStartupPref::Type>(type); + switch (startupType) { case SessionStartupPref::DEFAULT: [self recordUserAction:L"Options_Startup_Homepage"]; break; @@ -285,7 +326,7 @@ class PrefObserverBridge : public NotificationObserver { default: NOTREACHED(); } - SessionStartupPref::SetStartupPref(prefs_, pref); + [self saveSessionStartupWithType:startupType]; } // Returns whether or not the +/-/Current buttons should be enabled, based on @@ -294,6 +335,65 @@ class PrefObserverBridge : public NotificationObserver { return [self restoreOnStartupIndex] == SessionStartupPref::URLS; } +// Getter for the |customPagesSource| property for bindings. +- (id)customPagesSource { + return customPagesSource_.get(); +} + +// Called when the selection in the table changes. If a flag is set indicating +// that we're waiting for a special select message, edit the cell. Otherwise +// just ignore it, we don't normally care. +- (void)tableViewSelectionDidChange:(NSNotification *)aNotification { + if (pendingSelectForEdit_) { + NSTableView* table = [aNotification object]; + NSUInteger selectedRow = [table selectedRow]; + [table editColumn:0 row:selectedRow withEvent:nil select:YES]; + pendingSelectForEdit_ = NO; + } +} + +// Called when the user hits the (+) button for adding a new homepage to the +// list. This will also attempt to make the new item editable so the user can +// just start typing. +- (IBAction)addHomepage:(id)sender { + [customPagesArrayController_ add:sender]; + + // When the new item is added to the model, the array controller will select + // it. We'll watch for that notification (because we are the table view's + // delegate) and then make the cell editable. Note that this can't be + // accomplished simply by subclassing the array controller's add method (I + // did try). The update of the table is asynchronous with the controller + // updating the model. + pendingSelectForEdit_ = YES; +} + +// Called when the user hits the (-) button for removing the selected items in +// the homepage table. The controller does all the work. +- (IBAction)removeSelectedHomepages:(id)sender { + [customPagesArrayController_ remove:sender]; +} + +// Add all entries for all open browsers with our profile. +- (IBAction)useCurrentPagesAsHomepage:(id)sender { + std::vector<GURL> urls; + for (BrowserList::const_iterator browserIter = BrowserList::begin(); + browserIter != BrowserList::end(); ++browserIter) { + Browser* browser = *browserIter; + if (browser->profile() != profile_) + continue; // Only want entries for open profile. + + for (int tabIndex = 0; tabIndex < browser->tab_count(); ++tabIndex) { + TabContents* tab = browser->GetTabContentsAt(tabIndex); + if (tab->ShouldDisplayURL()) { + const GURL url = browser->GetTabContentsAt(tabIndex)->GetURL(); + if (!url.is_empty()) + urls.push_back(url); + } + } + } + [customPagesSource_ setURLs:urls]; +} + enum { kHomepageNewTabPage, kHomepageURL }; // Returns the index of the selected cell in the "home page" marix based on @@ -441,9 +541,9 @@ const int kDisabledIndex = 1; - (IBAction)showSavedPasswords:(id)sender { NSString* const kKeychainBundleId = @"com.apple.keychainaccess"; [self recordUserAction:L"Options_ShowPasswordsExceptions"]; - [[NSWorkspace sharedWorkspace] + [[NSWorkspace sharedWorkspace] launchAppWithBundleIdentifier:kKeychainBundleId - options:0L + options:0L additionalEventParamDescriptor:nil launchIdentifier:nil]; } diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 9de7a5c..4e8d7a2 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -686,6 +686,8 @@ 'browser/cocoa/cocoa_test_helper.h', 'browser/cocoa/command_observer_bridge.h', 'browser/cocoa/command_observer_bridge.mm', + 'browser/cocoa/custom_home_pages_model.h', + 'browser/cocoa/custom_home_pages_model.mm', 'browser/cocoa/encoding_menu_controller_delegate_mac.h', 'browser/cocoa/encoding_menu_controller_delegate_mac.mm', 'browser/cocoa/find_bar_bridge.h', @@ -3095,7 +3097,7 @@ 'browser/cocoa/browser_window_cocoa_unittest.mm', 'browser/cocoa/browser_window_controller_unittest.mm', 'browser/cocoa/command_observer_bridge_unittest.mm', - 'browser/encoding_menu_controller_unittest.cc', + 'browser/cocoa/custom_home_pages_model_unittest.mm', 'browser/cocoa/find_bar_bridge_unittest.mm', 'browser/cocoa/find_bar_cocoa_controller_unittest.mm', 'browser/cocoa/find_bar_view_unittest.mm', @@ -3121,6 +3123,7 @@ 'browser/download/download_manager_unittest.cc', 'browser/download/download_request_manager_unittest.cc', 'browser/download/save_package_unittest.cc', + 'browser/encoding_menu_controller_unittest.cc', 'browser/extensions/extension_messages_unittest.cc', 'browser/extensions/extension_process_manager_unittest.cc', 'browser/extensions/extension_ui_unittest.cc', |