diff options
Diffstat (limited to 'chrome')
23 files changed, 1543 insertions, 12 deletions
diff --git a/chrome/app/nibs/BookmarkBubble.xib b/chrome/app/nibs/BookmarkBubble.xib new file mode 100644 index 0000000..58d3215 --- /dev/null +++ b/chrome/app/nibs/BookmarkBubble.xib @@ -0,0 +1,730 @@ +<?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">9J61</string> + <string key="IBDocument.InterfaceBuilderVersion">677</string> + <string key="IBDocument.AppKitVersion">949.46</string> + <string key="IBDocument.HIToolboxVersion">353.00</string> + <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> + <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="1"/> + </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">BookmarkBubbleController</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="NSCustomView" id="1005"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">268</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSTextField" id="559397096"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{17, 113}, {244, 19}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="368795405"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">272630784</int> + <string key="NSContents">^IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK</string> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.600000e+01</double> + <int key="NSfFlags">16</int> + </object> + <reference key="NSControlView" ref="559397096"/> + <object class="NSColor" key="NSBackgroundColor" id="152587692"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlColor</string> + <object class="NSColor" key="NSColor" id="748407352"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC42NjY2NjY2OQA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor" id="1000275559"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlTextColor</string> + <object class="NSColor" key="NSColor" id="947148753"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MAA</bytes> + </object> + </object> + </object> + </object> + <object class="NSTextField" id="303910295"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{17, 87}, {65, 17}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="628112279"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">272630784</int> + <string key="NSContents">^IDS_BOOMARK_BUBBLE_TITLE_TEXT</string> + <object class="NSFont" key="NSSupport" id="714614853"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.300000e+01</double> + <int key="NSfFlags">1044</int> + </object> + <reference key="NSControlView" ref="303910295"/> + <reference key="NSBackgroundColor" ref="152587692"/> + <reference key="NSTextColor" ref="1000275559"/> + </object> + </object> + <object class="NSTextField" id="228609717"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{17, 62}, {65, 17}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="295393049"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">272630784</int> + <string key="NSContents">^IDS_BOOMARK_BUBBLE_FOLDER_TEXT</string> + <reference key="NSSupport" ref="714614853"/> + <reference key="NSControlView" ref="228609717"/> + <reference key="NSBackgroundColor" ref="152587692"/> + <reference key="NSTextColor" ref="1000275559"/> + </object> + </object> + <object class="NSTextField" id="39428350"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{87, 85}, {267, 22}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="905670292"> + <int key="NSCellFlags">-1804468671</int> + <int key="NSCellFlags2">272630784</int> + <string key="NSContents"/> + <reference key="NSSupport" ref="714614853"/> + <reference key="NSControlView" ref="39428350"/> + <bool key="NSDrawsBackground">YES</bool> + <object class="NSColor" key="NSBackgroundColor" id="1033293763"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">textBackgroundColor</string> + <object class="NSColor" key="NSColor" id="660986653"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MQA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">textColor</string> + <reference key="NSColor" ref="947148753"/> + </object> + </object> + </object> + <object class="NSComboBox" id="977232728"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{87, 56}, {270, 26}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSComboBoxCell" key="NSCell" id="1003570867"> + <int key="NSCellFlags">74579521</int> + <int key="NSCellFlags2">272630784</int> + <string key="NSContents"/> + <reference key="NSSupport" ref="714614853"/> + <reference key="NSControlView" ref="977232728"/> + <bool key="NSDrawsBackground">YES</bool> + <reference key="NSBackgroundColor" ref="1033293763"/> + <reference key="NSTextColor" ref="1000275559"/> + <int key="NSVisibleItemCount">5</int> + <bool key="NSHasVerticalScroller">YES</bool> + <reference key="NSDelegate" ref="977232728"/> + <object class="NSComboTableView" key="NSTableView" id="1071628594"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">274</int> + <string key="NSFrameSize">{15, 0}</string> + <reference key="NSSuperview"/> + <reference key="NSWindow"/> + <bool key="NSEnabled">YES</bool> + <object class="NSMutableArray" key="NSTableColumns"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSTableColumn"> + <integer value="0" key="NSIdentifier"/> + <double key="NSWidth">1.200000e+01</double> + <double key="NSMinWidth">1.000000e+01</double> + <double key="NSMaxWidth">1.000000e+03</double> + <object class="NSTableHeaderCell" key="NSHeaderCell"> + <int key="NSCellFlags">75628032</int> + <int key="NSCellFlags2">0</int> + <string key="NSContents"/> + <object class="NSFont" key="NSSupport" id="930683210"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.200000e+01</double> + <int key="NSfFlags">16</int> + </object> + <object class="NSColor" key="NSBackgroundColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes> + </object> + <reference key="NSTextColor" ref="660986653"/> + </object> + <object class="NSTextFieldCell" key="NSDataCell"> + <int key="NSCellFlags">338820672</int> + <int key="NSCellFlags2">1024</int> + <reference key="NSSupport" ref="714614853"/> + <reference key="NSControlView" ref="1071628594"/> + <bool key="NSDrawsBackground">YES</bool> + <object class="NSColor" key="NSBackgroundColor" id="744868739"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlBackgroundColor</string> + <reference key="NSColor" ref="748407352"/> + </object> + <reference key="NSTextColor" ref="1000275559"/> + </object> + <int key="NSResizingMask">3</int> + <bool key="NSIsResizeable">YES</bool> + <reference key="NSTableView" ref="1071628594"/> + </object> + </object> + <double key="NSIntercellSpacingWidth">3.000000e+00</double> + <double key="NSIntercellSpacingHeight">2.000000e+00</double> + <reference key="NSBackgroundColor" ref="744868739"/> + <object class="NSColor" key="NSGridColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">gridColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC41AA</bytes> + </object> + </object> + <double key="NSRowHeight">1.900000e+01</double> + <string key="NSAction">tableViewAction:</string> + <int key="NSTvFlags">-767524864</int> + <reference key="NSDelegate" ref="1003570867"/> + <reference key="NSDataSource" ref="1003570867"/> + <reference key="NSTarget" ref="1003570867"/> + <int key="NSColumnAutoresizingStyle">1</int> + <int key="NSDraggingSourceMaskForLocal">15</int> + <int key="NSDraggingSourceMaskForNonLocal">0</int> + <bool key="NSAllowsTypeSelect">YES</bool> + </object> + </object> + </object> + <object class="NSButton" id="430629007"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{168, 12}, {96, 32}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="562929863"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents">^IDS_BOOMARK_BUBBLE_OPTIONS</string> + <reference key="NSSupport" ref="714614853"/> + <reference key="NSControlView" ref="430629007"/> + <int key="NSButtonFlags">-2038284033</int> + <int key="NSButtonFlags2">129</int> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> + </object> + <object class="NSButton" id="82356437"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{264, 12}, {96, 32}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="307931553"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents">^IDS_CLOSE</string> + <reference key="NSSupport" ref="714614853"/> + <reference key="NSControlView" ref="82356437"/> + <int key="NSButtonFlags">-2038284033</int> + <int key="NSButtonFlags2">129</int> + <string key="NSAlternateContents"/> + <string type="base64-UTF8" key="NSKeyEquivalent">DQ</string> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> + </object> + <object class="NSButton" id="177936093"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{270, 113}, {84, 19}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="1066753170"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents">^IDS_BOOMARK_BUBBLE_REMOVE_BOOKMARK</string> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.200000e+01</double> + <int key="NSfFlags">4883</int> + </object> + <reference key="NSControlView" ref="177936093"/> + <int key="NSButtonFlags">-2038021889</int> + <int key="NSButtonFlags2">164</int> + <reference key="NSAlternateImage" ref="930683210"/> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">400</int> + <int key="NSPeriodicInterval">75</int> + </object> + </object> + </object> + <string key="NSFrameSize">{374, 152}</string> + <reference key="NSSuperview"/> + <string key="NSClassName">BookmarkBubbleView</string> + </object> + <object class="NSCustomObject" id="704223344"> + <string key="NSClassName">ChromeUILocalizer</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">delegate</string> + <reference key="source" ref="977232728"/> + <reference key="destination" ref="1001"/> + </object> + <int key="connectionID">23</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">remove:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="177936093"/> + </object> + <int key="connectionID">24</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">edit:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="430629007"/> + </object> + <int key="connectionID">25</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">close:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="82356437"/> + </object> + <int key="connectionID">26</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">bigTitle_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="559397096"/> + </object> + <int key="connectionID">28</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">nameTextField_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="39428350"/> + </object> + <int key="connectionID">29</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">view</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="1005"/> + </object> + <int key="connectionID">30</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">owner_</string> + <reference key="source" ref="704223344"/> + <reference key="destination" ref="1001"/> + </object> + <int key="connectionID">32</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">folderComboBox_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="977232728"/> + </object> + <int key="connectionID">33</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="228609717"/> + <reference ref="39428350"/> + <reference ref="977232728"/> + <reference ref="82356437"/> + <reference ref="303910295"/> + <reference ref="559397096"/> + <reference ref="430629007"/> + <reference ref="177936093"/> + </object> + <reference key="parent" ref="1002"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">2</int> + <reference key="object" ref="559397096"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="368795405"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">3</int> + <reference key="object" ref="368795405"/> + <reference key="parent" ref="559397096"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">8</int> + <reference key="object" ref="303910295"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="628112279"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">9</int> + <reference key="object" ref="628112279"/> + <reference key="parent" ref="303910295"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">10</int> + <reference key="object" ref="228609717"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="295393049"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">11</int> + <reference key="object" ref="295393049"/> + <reference key="parent" ref="228609717"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">12</int> + <reference key="object" ref="39428350"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="905670292"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">13</int> + <reference key="object" ref="905670292"/> + <reference key="parent" ref="39428350"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">14</int> + <reference key="object" ref="977232728"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1003570867"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">15</int> + <reference key="object" ref="1003570867"/> + <reference key="parent" ref="977232728"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">16</int> + <reference key="object" ref="430629007"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="562929863"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">17</int> + <reference key="object" ref="562929863"/> + <reference key="parent" ref="430629007"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">18</int> + <reference key="object" ref="82356437"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="307931553"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">19</int> + <reference key="object" ref="307931553"/> + <reference key="parent" ref="82356437"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">20</int> + <reference key="object" ref="177936093"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1066753170"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">21</int> + <reference key="object" ref="1066753170"/> + <reference key="parent" ref="177936093"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">31</int> + <reference key="object" ref="704223344"/> + <reference key="parent" ref="1002"/> + </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.WindowOrigin</string> + <string>1.editorWindowContentRectSynchronizationRect</string> + <string>10.IBPluginDependency</string> + <string>11.IBPluginDependency</string> + <string>12.IBPluginDependency</string> + <string>13.IBPluginDependency</string> + <string>14.IBPluginDependency</string> + <string>15.IBPluginDependency</string> + <string>16.IBPluginDependency</string> + <string>17.IBPluginDependency</string> + <string>18.IBPluginDependency</string> + <string>19.IBPluginDependency</string> + <string>2.IBPluginDependency</string> + <string>20.IBPluginDependency</string> + <string>21.IBPluginDependency</string> + <string>3.IBPluginDependency</string> + <string>31.IBPluginDependency</string> + <string>8.IBPluginDependency</string> + <string>9.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>{{553, 1288}, {374, 152}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{628, 654}</string> + <string>{{357, 416}, {480, 272}}</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> + <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> + <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">33</int> + </object> + <object class="IBClassDescriber" key="IBDocument.Classes"> + <object class="NSMutableArray" key="referencedPartialClassDescriptions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBPartialClassDescription"> + <string key="className">BookmarkBubbleController</string> + <string key="superclassName">NSViewController</string> + <object class="NSMutableDictionary" key="actions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>close:</string> + <string>edit:</string> + <string>remove:</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="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>bigTitle_</string> + <string>delegate_</string> + <string>folderComboBox_</string> + <string>nameTextField_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>NSTextField</string> + <string>id</string> + <string>NSComboBox</string> + <string>NSTextField</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/bookmark_bubble_controller.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">BookmarkBubbleView</string> + <string key="superclassName">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/bookmark_bubble_view.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">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">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> + </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/bookmark_bar_controller.mm b/chrome/browser/cocoa/bookmark_bar_controller.mm index 1f64cf4..75e3441 100644 --- a/chrome/browser/cocoa/bookmark_bar_controller.mm +++ b/chrome/browser/cocoa/bookmark_bar_controller.mm @@ -411,9 +411,9 @@ const CGFloat kBookmarkHorizontalPadding = 1.0; initWithParentWindow:[[self view] window] profile:profile_ node:node]; - [controller runModal]; + [controller runAsModalSheet]; - // runModal will run the window as a sheet. The + // runAsModalSheet will run the window as a sheet. The // BookmarkNameFolderController will release itself when the sheet // ends. } diff --git a/chrome/browser/cocoa/bookmark_bubble_controller.h b/chrome/browser/cocoa/bookmark_bubble_controller.h new file mode 100644 index 0000000..0760fa0 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_bubble_controller.h @@ -0,0 +1,98 @@ +// 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 <Cocoa/Cocoa.h> +#include "base/scoped_nsobject.h" + +class BookmarkModel; +class BookmarkNode; +@class BookmarkBubbleController; + +// Protocol for a BookmarkBubbleController's (BBC's) delegate. +@protocol BookmarkBubbleControllerDelegate + +// The bubble asks the delegate to perform an edit when needed. +- (void)editBookmarkNode:(const BookmarkNode*)node; + +// The bubble tells its delegate when it's done and can be deallocated. +- (void)doneWithBubbleController:(BookmarkBubbleController*)controller; + +@end + +// Controller for the bookmark bubble. The bookmark bubble is a +// bubble that pops up when clicking on the STAR next to the URL to +// add or remove it as a bookmark. This bubble allows for editing of +// the bookmark in various ways (name, folder, etc.) +// +// The bubble is stored in a nib as a view, not as a window, so we can +// make it an actual bubble. There is no nib-rific way to encode a +// NSBorderlessWindowMask NSWindow, and the style of an NSWindow can't +// be set other than init time. To deal, we create the NSWindow +// programatically, but encode the view in a nib. Thus, +// BookmarkBubbleController is an NSViewController, not an +// NSWindowController. +@interface BookmarkBubbleController : NSViewController { + @private + // Unexpected for this controller, perhaps, but our window does NOT + // come from a nib. + scoped_nsobject<NSWindow> window_; + + id<BookmarkBubbleControllerDelegate> delegate_; // weak like other delegates + NSWindow* parentWindow_; // weak + NSPoint topLeftForBubble_; + + // Both weak; owned by the current browser's profile + BookmarkModel* model_; + const BookmarkNode* node_; + + // A mapping from titles to nodes so we only have to walk this once. + scoped_nsobject<NSMutableArray> titleMapping_; + + BOOL alreadyBookmarked_; + scoped_nsobject<NSString> chooseAnotherFolder_; + + IBOutlet NSTextField* bigTitle_; // "Bookmark" or "Bookmark Added!" + IBOutlet NSTextField* nameTextField_; + IBOutlet NSComboBox* folderComboBox_; +} + +// |node| is the bookmark node we edit in this bubble. +// |alreadyBookmarked| tells us if the node was bookmarked before the +// user clicked on the star. (if NO, this is a brand new bookmark). +// The owner of this object is responsible for showing the bubble if +// it desires it to be visible on the screen. It is not shown by the +// init routine. Closing of the window happens implicitly on dealloc. +- (id)initWithDelegate:(id<BookmarkBubbleControllerDelegate>)delegate + parentWindow:(NSWindow*)parentWindow + topLeftForBubble:(NSPoint)topLeftForBubble + model:(BookmarkModel*)model + node:(const BookmarkNode*)node + alreadyBookmarked:(BOOL)alreadyBookmarked; + +- (void)showWindow; + +// Actions for buttons in the dialog. +- (IBAction)edit:(id)sender; +- (IBAction)close:(id)sender; +- (IBAction)remove:(id)sender; + +@end + + +// Exposed only for unit testing. +@interface BookmarkBubbleController(ExposedForUnitTesting) +- (NSWindow*)createBubbleWindow; +- (void)fillInFolderList; +- (BOOL)windowHasBeenClosed; +- (void)addFolderNodes:(const BookmarkNode*)parent toComboBox:(NSComboBox*)box; +- (void)updateBookmarkNode; +- (void)setTitle:(NSString *)title parentFolder:(NSString*)folder; +- (NSString*)chooseAnotherFolderString; +@end + +// Also private but I need to declare them specially for @synthesize to work. +@interface BookmarkBubbleController () +@property (readonly) id delegate; +@property (readonly) NSComboBox* folderComboBox; +@end diff --git a/chrome/browser/cocoa/bookmark_bubble_controller.mm b/chrome/browser/cocoa/bookmark_bubble_controller.mm new file mode 100644 index 0000000..7e9b1e2 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_bubble_controller.mm @@ -0,0 +1,215 @@ +// 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 "app/l10n_util_mac.h" +#include "base/mac_util.h" +#include "base/sys_string_conversions.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#import "chrome/browser/cocoa/bookmark_bubble_controller.h" +#import "chrome/browser/cocoa/bookmark_bubble_window.h" +#include "grit/generated_resources.h" + + +@interface BookmarkBubbleController(PrivateAPI) +- (void)closeWindow; +@end + +@implementation BookmarkBubbleController + +@synthesize delegate = delegate_; +@synthesize folderComboBox = folderComboBox_; + +- (id)initWithDelegate:(id<BookmarkBubbleControllerDelegate>)delegate + parentWindow:(NSWindow*)parentWindow + topLeftForBubble:(NSPoint)topLeftForBubble + model:(BookmarkModel*)model + node:(const BookmarkNode*)node + alreadyBookmarked:(BOOL)alreadyBookmarked { + if ((self = [super initWithNibName:@"BookmarkBubble" + bundle:mac_util::MainAppBundle()])) { + // all these are weak... + delegate_ = delegate; + parentWindow_ = parentWindow; + topLeftForBubble_ = topLeftForBubble; + model_ = model; + node_ = node; + alreadyBookmarked_ = alreadyBookmarked; + // But this is strong. + titleMapping_.reset([[NSMutableDictionary alloc] init]); + } + return self; +} + +- (void)dealloc { + [self closeWindow]; + [super dealloc]; +} + +- (void)showWindow { + [self view]; // force nib load and window_ allocation + [window_ makeKeyAndOrderFront:self]; +} + +// Actually close the window. Do nothing else. +- (void)closeWindow { + [parentWindow_ removeChildWindow:window_]; + [window_ close]; +} + +- (void)awakeFromNib { + window_.reset([self createBubbleWindow]); + [parentWindow_ addChildWindow:window_ ordered:NSWindowAbove]; + + // Fill in inital values for text, controls, ... + + // Default is IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK; "Bookmark". + // If adding for the 1st time the string becomes "Bookmark Added!" + if (!alreadyBookmarked_) { + NSString* title = + l10n_util::GetNSString(IDS_BOOMARK_BUBBLE_PAGE_BOOKMARKED); + [bigTitle_ setStringValue:title]; + } + + [self fillInFolderList]; +} + +- (IBAction)edit:(id)sender { + [self updateBookmarkNode]; + [self closeWindow]; + [delegate_ editBookmarkNode:node_]; + [delegate_ doneWithBubbleController:self]; +} + +- (IBAction)close:(id)sender { + if (node_) { + // no node_ if the bookmark was just removed + [self updateBookmarkNode]; + } + [self closeWindow]; + [delegate_ doneWithBubbleController:self]; +} + +// By implementing this, ESC causes the window to go away. +- (IBAction)cancel:(id)sender { + [self close:sender]; +} + +- (IBAction)remove:(id)sender { + model_->SetURLStarred(node_->GetURL(), node_->GetTitle(), false); + node_ = NULL; // no longer valid + [self close:self]; +} + +// We are the delegate of the combo box so we can tell when "choose +// another folder" was picked. +- (void)comboBoxSelectionDidChange:(NSNotification*)notification { + NSString* selected = [folderComboBox_ objectValueOfSelectedItem]; + if ([selected isEqual:chooseAnotherFolder_.get()]) { + [self edit:self]; + } +} + +// We are the delegate of our own window so we know when we lose key. +// When we lose key status we close, mirroring Windows behaivor. +- (void)windowDidResignKey:(NSNotification*)notification { + if ([window_ isVisible]) + [self close:self]; +} + +@end // BookmarkBubbleController + + +@implementation BookmarkBubbleController(ExposedForUnitTesting) + +// Create and return a retained NSWindow for this bubble. +- (NSWindow*)createBubbleWindow { + NSRect contentRect = [[self view] frame]; + NSPoint origin = topLeftForBubble_; + origin.y -= contentRect.size.height; // since it'll be our bottom-left + contentRect.origin = origin; + // Now convert to global coordinates since it'll be used for a window. + contentRect.origin = [parentWindow_ convertBaseToScreen:contentRect.origin]; + NSWindow* window = [[BookmarkBubbleWindow alloc] + initWithContentRect:contentRect]; + [window setDelegate:self]; + [window setContentView:[self view]]; + return window; +} + +// Fill in all information related to the folder combo box. +// +// TODO(jrg): make sure nested folders that have the same name are +// handled properly. +// http://crbug.com/19408 +- (void)fillInFolderList { + [nameTextField_ setStringValue:base::SysWideToNSString(node_->GetTitle())]; + [self addFolderNodes:model_->root_node() toComboBox:folderComboBox_]; + + // Add "Choose another folder...". Remember it for later to compare against. + chooseAnotherFolder_.reset( + [l10n_util::GetNSString(IDS_BOOMARK_BUBBLE_CHOOSER_ANOTHER_FOLDER) + retain]); + [folderComboBox_ addItemWithObjectValue:chooseAnotherFolder_.get()]; + + // Finally, select the current parent. + NSString* parentTitle = base::SysWideToNSString( + node_->GetParent()->GetTitle()); + [folderComboBox_ selectItemWithObjectValue:parentTitle]; +} + +- (BOOL)windowHasBeenClosed { + return ![window_ isVisible]; +} + +// For the given folder node, walk the tree and add folder names to +// the given combo box. +// +// TODO(jrg): no distinction is made among folders with the same name. +- (void)addFolderNodes:(const BookmarkNode*)parent toComboBox:(NSComboBox*)box { + NSString* title = base::SysWideToNSString(parent->GetTitle()); + if ([title length]) { // no title if root + [box addItemWithObjectValue:title]; + [titleMapping_ setValue:[NSValue valueWithPointer:parent] forKey:title]; + } + for (int i = 0; i < parent->GetChildCount(); i++) { + const BookmarkNode* child = parent->GetChild(i); + if (child->is_folder()) + [self addFolderNodes:child toComboBox:box]; + } +} + +// Look at the dialog; if the user has changed anything, update the +// bookmark node to reflect this. +- (void)updateBookmarkNode { + // First the title... + NSString* oldTitle = base::SysWideToNSString(node_->GetTitle()); + NSString* newTitle = [nameTextField_ stringValue]; + if (![oldTitle isEqual:newTitle]) { + model_->SetTitle(node_, base::SysNSStringToWide(newTitle)); + } + // Then the parent folder. + NSString* oldParentTitle = base::SysWideToNSString( + node_->GetParent()->GetTitle()); + NSString* newParentTitle = [folderComboBox_ objectValueOfSelectedItem]; + if (![oldParentTitle isEqual:newParentTitle]) { + const BookmarkNode* newParent = static_cast<const BookmarkNode*>( + [[titleMapping_ objectForKey:newParentTitle] pointerValue]); + if (newParent) { + // newParent should only ever possibly be NULL in a unit test. + int index = newParent->GetChildCount(); + model_->Move(node_, newParent, index); + } + } +} + +- (void)setTitle:(NSString*)title parentFolder:(NSString*)folder { + [nameTextField_ setStringValue:title]; + [folderComboBox_ selectItemWithObjectValue:folder]; +} + +- (NSString*)chooseAnotherFolderString { + return chooseAnotherFolder_.get(); +} + +@end // implementation BookmarkBubbleController(ExposedForUnitTesting) diff --git a/chrome/browser/cocoa/bookmark_bubble_controller_unittest.mm b/chrome/browser/cocoa/bookmark_bubble_controller_unittest.mm new file mode 100644 index 0000000..2e741c0 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_bubble_controller_unittest.mm @@ -0,0 +1,213 @@ +// 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 <Cocoa/Cocoa.h> + +#include "base/basictypes.h" +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/bookmark_bubble_controller.h" +#include "chrome/browser/cocoa/browser_test_helper.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +@interface BBDelegate : NSObject<BookmarkBubbleControllerDelegate> { + NSWindow* window_; // weak + int edits_; + int dones_; +} +@property (readonly) int edits; +@property (readonly) int dones; +@property (readonly) NSWindow* window; +@end + +@implementation BBDelegate + +@synthesize edits = edits_; +@synthesize window = window_; +@synthesize dones = dones_; + +- (NSPoint)topLeftForBubble { + return NSMakePoint(10, 300); +} + +- (void)editBookmarkNode:(const BookmarkNode*)node { + edits_++; +} + +- (void)doneWithBubbleController:(BookmarkBubbleController*)controller { + dones_++; +} + +- (void)clear { + edits_ = 0; + dones_ = 0; +} + +@end + +namespace { + +class BookmarkBubbleControllerTest : public PlatformTest { + public: + CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc... + BrowserTestHelper helper_; + scoped_nsobject<BBDelegate> delegate_; + scoped_nsobject<BookmarkBubbleController> controller_; + + BookmarkBubbleControllerTest() { + delegate_.reset([[BBDelegate alloc] init]); + } + + // Returns a controller but ownership not transferred. + // Only one of these will be valid at a time. + BookmarkBubbleController* ControllerForNode(const BookmarkNode* node) { + controller_.reset([[BookmarkBubbleController alloc] + initWithDelegate:delegate_.get() + parentWindow:cocoa_helper_.window() + topLeftForBubble:[delegate_ topLeftForBubble] + model:helper_.profile()->GetBookmarkModel() + node:node + alreadyBookmarked:YES]); + [controller_ view]; // force nib load + return controller_.get(); + } + + BookmarkModel* GetBookmarkModel() { + return helper_.profile()->GetBookmarkModel(); + } +}; + +// Confirm basics about the bubble window (e.g. that it is inside the +// parent window) +TEST_F(BookmarkBubbleControllerTest, TestBubbleWindow) { + BookmarkModel* model = GetBookmarkModel(); + const BookmarkNode* node = model->AddURL(model->GetBookmarkBarNode(), + 0, + L"Bookie markie title", + GURL("http://www.google.com")); + BookmarkBubbleController* controller = ControllerForNode(node); + EXPECT_TRUE(controller); + NSWindow* window = [controller createBubbleWindow]; + EXPECT_TRUE(window); + EXPECT_TRUE(NSContainsRect([cocoa_helper_.window() frame], + [window frame])); +} + +// Confirm population of folder list +TEST_F(BookmarkBubbleControllerTest, TestFillInFolder) { + // Create some folders, including a nested folder + BookmarkModel* model = GetBookmarkModel(); + const BookmarkNode* node1 = model->AddGroup(model->GetBookmarkBarNode(), + 0, L"one"); + const BookmarkNode* node2 = model->AddGroup(model->GetBookmarkBarNode(), + 1, L"two"); + const BookmarkNode* node3 = model->AddGroup(model->GetBookmarkBarNode(), + 2, L"three"); + const BookmarkNode* node4 = model->AddGroup(node2, + 0, L"sub"); + model->AddURL(node1, 0, L"title1", GURL("http://www.google.com")); + model->AddURL(node3, 0, L"title2", GURL("http://www.google.com")); + model->AddURL(node4, 0, L"title3", GURL("http://www.google.com/reader")); + + BookmarkBubbleController* controller = ControllerForNode(node4); + EXPECT_TRUE(controller); + + NSArray* items = [[controller folderComboBox] objectValues]; + EXPECT_TRUE([items containsObject:@"one"]); + EXPECT_TRUE([items containsObject:@"two"]); + EXPECT_TRUE([items containsObject:@"three"]); + EXPECT_TRUE([items containsObject:@"sub"]); + EXPECT_FALSE([items containsObject:@"title1"]); + EXPECT_FALSE([items containsObject:@"title2"]); +} + +// Click on edit; bubble gets closed. +TEST_F(BookmarkBubbleControllerTest, TestSimpleActions) { + BookmarkModel* model = GetBookmarkModel(); + const BookmarkNode* node = model->AddURL(model->GetBookmarkBarNode(), + 0, + L"Bookie markie title", + GURL("http://www.google.com")); + BookmarkBubbleController* controller = ControllerForNode(node); + EXPECT_TRUE(controller); + + EXPECT_EQ([delegate_ edits], 0); + EXPECT_EQ([delegate_ dones], 0); + EXPECT_FALSE([controller windowHasBeenClosed]); + [controller edit:controller]; + EXPECT_EQ([delegate_ edits], 1); + EXPECT_EQ([delegate_ dones], 1); + EXPECT_TRUE([controller windowHasBeenClosed]); + + [delegate_ clear]; + EXPECT_EQ([delegate_ edits], 0); + EXPECT_EQ([delegate_ dones], 0); + + controller = ControllerForNode(node); + EXPECT_TRUE(controller); + EXPECT_FALSE([controller windowHasBeenClosed]); + [controller close:controller]; + EXPECT_EQ([delegate_ edits], 0); + EXPECT_EQ([delegate_ dones], 1); + EXPECT_TRUE([controller windowHasBeenClosed]); +} + +// User changes title and parent folder in the UI +TEST_F(BookmarkBubbleControllerTest, TestUserEdit) { + BookmarkModel* model = GetBookmarkModel(); + const BookmarkNode* node = model->AddURL(model->GetBookmarkBarNode(), + 0, + L"short-title", + GURL("http://www.google.com")); + model->AddGroup(model->GetBookmarkBarNode(), 0, L"grandma"); + model->AddGroup(model->GetBookmarkBarNode(), 0, L"grandpa"); + BookmarkBubbleController* controller = ControllerForNode(node); + EXPECT_TRUE(controller); + + // simulate a user edit + [controller setTitle:@"oops" parentFolder:@"grandma"]; + [controller edit:controller]; + + // Make sure bookmark has changed + EXPECT_EQ(node->GetTitle(), L"oops"); + EXPECT_EQ(node->GetParent()->GetTitle(), L"grandma"); +} + +// Click the "remove" button +TEST_F(BookmarkBubbleControllerTest, TestRemove) { + BookmarkModel* model = GetBookmarkModel(); + GURL gurl("http://www.google.com"); + const BookmarkNode* node = model->AddURL(model->GetBookmarkBarNode(), + 0, + L"Bookie markie title", + gurl); + BookmarkBubbleController* controller = ControllerForNode(node); + EXPECT_TRUE(controller); + EXPECT_TRUE(model->IsBookmarked(gurl)); + + [controller remove:controller]; + EXPECT_FALSE(model->IsBookmarked(gurl)); + EXPECT_TRUE([controller windowHasBeenClosed]); + EXPECT_EQ([delegate_ dones], 1); +} + +// Confirm picking "choose another folder" caused edit: to be called. +TEST_F(BookmarkBubbleControllerTest, ComboSelectionChanged) { + BookmarkModel* model = GetBookmarkModel(); + GURL gurl("http://www.google.com"); + const BookmarkNode* node = model->AddURL(model->GetBookmarkBarNode(), + 0, L"super-title", + gurl); + BookmarkBubbleController* controller = ControllerForNode(node); + EXPECT_TRUE(controller); + + NSString* chooseAnotherFolder = [controller chooseAnotherFolderString]; + EXPECT_EQ([delegate_ edits], 0); + [controller setTitle:@"DOH!" parentFolder:chooseAnotherFolder]; + EXPECT_EQ([delegate_ edits], 1); +} + + +} // namespace diff --git a/chrome/browser/cocoa/bookmark_bubble_view.h b/chrome/browser/cocoa/bookmark_bubble_view.h new file mode 100644 index 0000000..1e811a8 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_bubble_view.h @@ -0,0 +1,11 @@ +// 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 <Cocoa/Cocoa.h> + +// Content view for a Bookmark Bubble opened by clicking on the star +// toolbar button. This is where nonrectangular drawing happens. +@interface BookmarkBubbleView : NSView +@end + diff --git a/chrome/browser/cocoa/bookmark_bubble_view.mm b/chrome/browser/cocoa/bookmark_bubble_view.mm new file mode 100644 index 0000000..b4c5c7e56 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_bubble_view.mm @@ -0,0 +1,58 @@ +// 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/bookmark_bubble_view.h" +#import "third_party/GTM/AppKit/GTMTheme.h" + +namespace { +// TODO(jrg): confirm constants with UI dudes +const CGFloat kBubbleCornerRadius = 8.0; +const CGFloat kBubbleArrowXOffset = 10.0; +const CGFloat kBubbleArrowWidth = 15.0; +const CGFloat kBubbleArrowHeight = 8.0; +const CGFloat kBubbleBorderLineWidth = 1.0; +} + +@implementation BookmarkBubbleView + +- (void)drawRect:(NSRect)rect { + // Make room for the border to be seen. + NSRect bounds = [self bounds]; + bounds.size.height -= kBubbleArrowHeight; + bounds = NSInsetRect(bounds, + kBubbleBorderLineWidth/2.0, + kBubbleBorderLineWidth/2.0); + + NSBezierPath* bezier = [NSBezierPath bezierPath]; + rect.size.height -= kBubbleArrowHeight; + + // Start with a rounded rectangle. + [bezier appendBezierPathWithRoundedRect:bounds + xRadius:kBubbleCornerRadius + yRadius:kBubbleCornerRadius]; + + // Add the bubble arrow (pointed at the star). + NSPoint arrowStart = NSMakePoint(NSMinX(bounds), NSMaxY(bounds)); + arrowStart.x += kBubbleArrowXOffset; + [bezier moveToPoint:NSMakePoint(arrowStart.x, arrowStart.y)]; + [bezier lineToPoint:NSMakePoint(arrowStart.x + kBubbleArrowWidth/2.0, + arrowStart.y + kBubbleArrowHeight)]; + [bezier lineToPoint:NSMakePoint(arrowStart.x + kBubbleArrowWidth, + arrowStart.y)]; + [bezier closePath]; + + // Draw the outline... + [[NSColor blackColor] set]; + [bezier setLineWidth:kBubbleBorderLineWidth]; + [bezier stroke]; + + // Then fill the inside. + GTMTheme *theme = [GTMTheme defaultTheme]; + NSGradient *gradient = [theme gradientForStyle:GTMThemeStyleToolBar + state:NO]; + [gradient drawInBezierPath:bezier angle:0.0]; +} + +@end + diff --git a/chrome/browser/cocoa/bookmark_bubble_view_unittest.mm b/chrome/browser/cocoa/bookmark_bubble_view_unittest.mm new file mode 100644 index 0000000..9744397 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_bubble_view_unittest.mm @@ -0,0 +1,36 @@ +// 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 <Cocoa/Cocoa.h> + +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/bookmark_bubble_view.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace { + +class BookmarkBubbleViewTest : public PlatformTest { + public: + BookmarkBubbleViewTest() { + NSRect frame = NSMakeRect(0, 0, 100, 30); + view_.reset([[BookmarkBubbleView alloc] initWithFrame:frame]); + [cocoa_helper_.contentView() addSubview:view_.get()]; + } + + CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc... + scoped_nsobject<BookmarkBubbleView> view_; +}; + +// Test drawing and an add/remove from the view hierarchy to ensure +// nothing leaks or crashes. +TEST_F(BookmarkBubbleViewTest, AddRemoveDisplay) { + [view_ display]; + EXPECT_EQ(cocoa_helper_.contentView(), [view_ superview]); + [view_.get() removeFromSuperview]; + EXPECT_FALSE([view_ superview]); +} + +} // namespace diff --git a/chrome/browser/cocoa/bookmark_bubble_window.h b/chrome/browser/cocoa/bookmark_bubble_window.h new file mode 100644 index 0000000..45e2f3b --- /dev/null +++ b/chrome/browser/cocoa/bookmark_bubble_window.h @@ -0,0 +1,11 @@ +// 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 <Cocoa/Cocoa.h> + +// Window for the bookmark bubble that comes up when you click on "STAR". +@interface BookmarkBubbleWindow : NSWindow +- (id)initWithContentRect:(NSRect)contentRect; +@end + diff --git a/chrome/browser/cocoa/bookmark_bubble_window.mm b/chrome/browser/cocoa/bookmark_bubble_window.mm new file mode 100644 index 0000000..126b30e --- /dev/null +++ b/chrome/browser/cocoa/bookmark_bubble_window.mm @@ -0,0 +1,33 @@ +// 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/bookmark_bubble_window.h" + +@implementation BookmarkBubbleWindow + +- (id)initWithContentRect:(NSRect)contentRect { + if ((self = [super initWithContentRect:contentRect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:YES])) { + [self setReleasedWhenClosed:NO]; + [self setBackgroundColor:[NSColor clearColor]]; + [self setExcludedFromWindowsMenu:YES]; + [self setAlphaValue:1.0]; + [self setOpaque:NO]; + } + return self; +} + +// According to +// http://www.cocoabuilder.com/archive/message/cocoa/2006/6/19/165953, +// NSBorderlessWindowMask windows cannot become key or main. In our +// case, however, we don't want all of that behavior. (As an example, +// our bubble has buttons!) + +- (BOOL)canBecomeKeyWindow { + return YES; +} + +@end diff --git a/chrome/browser/cocoa/bookmark_bubble_window_unittest.mm b/chrome/browser/cocoa/bookmark_bubble_window_unittest.mm new file mode 100644 index 0000000..08baec4 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_bubble_window_unittest.mm @@ -0,0 +1,27 @@ +// 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_ptr.h" +#include "chrome/browser/cocoa/cocoa_test_helper.h" +#include "chrome/browser/cocoa/bookmark_bubble_window.h" +#include "testing/gtest/include/gtest/gtest.h" + +class BookmarkBubbleWindowTest : public testing::Test { + public: + CocoaTestHelper cocoa_helper_; +}; + +TEST_F(BookmarkBubbleWindowTest, Basics) { + scoped_nsobject<BookmarkBubbleWindow> window_; + window_.reset([[BookmarkBubbleWindow alloc] + initWithContentRect:NSMakeRect(0,0,10,10)]); + + EXPECT_TRUE([window_ canBecomeKeyWindow]); + EXPECT_FALSE([window_ canBecomeMainWindow]); + + EXPECT_TRUE([window_ isExcludedFromWindowsMenu]); + EXPECT_FALSE([window_ isReleasedWhenClosed]); +} + + diff --git a/chrome/browser/cocoa/bookmark_editor_controller.h b/chrome/browser/cocoa/bookmark_editor_controller.h index 742fbd1..4c80161 100644 --- a/chrome/browser/cocoa/bookmark_editor_controller.h +++ b/chrome/browser/cocoa/bookmark_editor_controller.h @@ -39,6 +39,9 @@ configuration:(BookmarkEditor::Configuration)configuration handler:(BookmarkEditor::Handler*)handler; +// Run the bookmark editor as a modal sheet. Does not block. +- (void)runAsModalSheet; + // Actions for the buttons at the bottom of the window. - (IBAction)newFolder:(id)sender; - (IBAction)cancel:(id)sender; diff --git a/chrome/browser/cocoa/bookmark_editor_controller.mm b/chrome/browser/cocoa/bookmark_editor_controller.mm index 4ba0ab39..79cd1dc 100644 --- a/chrome/browser/cocoa/bookmark_editor_controller.mm +++ b/chrome/browser/cocoa/bookmark_editor_controller.mm @@ -10,11 +10,6 @@ #include "chrome/browser/profile.h" #import "chrome/browser/cocoa/bookmark_editor_controller.h" -@interface BookmarkEditorController(Private) -// Run the bookmark editor as a modal sheet. Does not block. -- (void)runModal; -@end - // static; implemented for each platform. void BookmarkEditor::Show(gfx::NativeView parent_hwnd, Profile* profile, @@ -30,7 +25,7 @@ void BookmarkEditor::Show(gfx::NativeView parent_hwnd, node:node configuration:configuration handler:handler]; - [controller runModal]; + [controller runAsModalSheet]; } @@ -107,7 +102,7 @@ void BookmarkEditor::Show(gfx::NativeView parent_hwnd, */ // TODO(jrg): consider NSModalSession. -- (void)runModal { +- (void)runAsModalSheet { [NSApp beginSheet:[self window] modalForWindow:parentWindow_ modalDelegate:self diff --git a/chrome/browser/cocoa/bookmark_name_folder_controller.h b/chrome/browser/cocoa/bookmark_name_folder_controller.h index 64c3183..764a04a 100644 --- a/chrome/browser/cocoa/bookmark_name_folder_controller.h +++ b/chrome/browser/cocoa/bookmark_name_folder_controller.h @@ -26,7 +26,7 @@ - (id)initWithParentWindow:(NSWindow*)window profile:(Profile*)profile node:(const BookmarkNode*)node; -- (void)runModal; +- (void)runAsModalSheet; - (IBAction)cancel:(id)sender; - (IBAction)ok:(id)sender; @end diff --git a/chrome/browser/cocoa/bookmark_name_folder_controller.mm b/chrome/browser/cocoa/bookmark_name_folder_controller.mm index fa24ac5..859e8e7 100644 --- a/chrome/browser/cocoa/bookmark_name_folder_controller.mm +++ b/chrome/browser/cocoa/bookmark_name_folder_controller.mm @@ -39,7 +39,7 @@ } // TODO(jrg): consider NSModalSession. -- (void)runModal { +- (void)runAsModalSheet { [NSApp beginSheet:[self window] modalForWindow:parentWindow_ modalDelegate:self diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm index 91c6a0f..ff1d813 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/cocoa/browser_window_cocoa.mm @@ -202,7 +202,8 @@ void BrowserWindowCocoa::ShowBookmarkManager() { void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url, bool already_bookmarked) { - NOTIMPLEMENTED(); + [controller_ showBookmarkBubbleForURL:url + alreadyBookmarked:(already_bookmarked ? YES : NO)]; } bool BrowserWindowCocoa::IsDownloadShelfVisible() const { diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h index 6713044..eb34d94 100644 --- a/chrome/browser/cocoa/browser_window_controller.h +++ b/chrome/browser/cocoa/browser_window_controller.h @@ -16,6 +16,7 @@ #include "base/scoped_ptr.h" #import "chrome/browser/cocoa/tab_window_controller.h" #import "chrome/browser/cocoa/bookmark_bar_controller.h" +#import "chrome/browser/cocoa/bookmark_bubble_controller.h" #import "chrome/browser/cocoa/view_resizer.h" #import "third_party/GTM/AppKit/GTMTheme.h" @@ -40,6 +41,7 @@ class TabStripModelObserverBridge; @interface BrowserWindowController : TabWindowController<NSUserInterfaceValidations, BookmarkURLOpener, + BookmarkBubbleControllerDelegate, ViewResizer, GTMThemeDelegate> { @private @@ -63,6 +65,7 @@ class TabStripModelObserverBridge; scoped_nsobject<InfoBarContainerController> infoBarContainerController_; scoped_ptr<StatusBubble> statusBubble_; scoped_nsobject<DownloadShelfController> downloadShelfController_; + scoped_nsobject<BookmarkBubbleController> bookmarkBubbleController_; scoped_nsobject<GTMTheme> theme_; BOOL ownsBrowser_; // Only ever NO when testing BOOL fullscreen_; @@ -139,6 +142,10 @@ class TabStripModelObserverBridge; // Delegate method for the status bubble to query about its vertical offset. - (float)verticalOffsetForStatusBubble; +// Show the bookmark bubble (e.g. user just clicked on the STAR) +- (void)showBookmarkBubbleForURL:(const GURL&)url + alreadyBookmarked:(BOOL)alreadyBookmarked; + // Returns the (lazily created) window sheet controller of this window. Used // for the per-tab sheets. - (GTMWindowSheetController*)sheetController; @@ -165,6 +172,9 @@ class TabStripModelObserverBridge; // Return an autoreleased NSWindow suitable for fullscreen use. - (NSWindow*)fullscreenWindow; +// Return a point suitable for the topLeft for a bookmark bubble. +- (NSPoint)topLeftForBubble; + @end // BrowserWindowController(TestingAPI) #endif // CHROME_BROWSER_COCOA_BROWSER_WINDOW_CONTROLLER_H_ diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index 5918cc4..01cd173 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -9,6 +9,7 @@ #import "base/scoped_nsobject.h" #include "base/sys_string_conversions.h" #include "chrome/app/chrome_dll_resource.h" // IDC_* +#include "chrome/browser/bookmarks/bookmark_editor.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" @@ -20,6 +21,7 @@ #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/tabs/tab_strip_model.h" #import "chrome/browser/cocoa/bookmark_bar_controller.h" +#import "chrome/browser/cocoa/bookmark_editor_controller.h" #import "chrome/browser/cocoa/browser_window_cocoa.h" #import "chrome/browser/cocoa/browser_window_controller.h" #import "chrome/browser/cocoa/download_shelf_controller.h" @@ -933,6 +935,53 @@ willPositionSheet:(NSWindow*)sheet return theme_ ? theme_ : [GTMTheme defaultTheme]; } +- (NSPoint)topLeftForBubble { + NSRect rect = [toolbarController_ starButtonInWindowCoordinates]; + NSPoint p = NSMakePoint(NSMinX(rect), NSMinY(rect)); // bottom left + return p; +} + +// Show the bookmark bubble (e.g. user just clicked on the STAR). +- (void)showBookmarkBubbleForURL:(const GURL&)url + alreadyBookmarked:(BOOL)alreadyBookmarked { + BookmarkModel* model = browser_->profile()->GetBookmarkModel(); + const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url); + + // Bring up the bubble. But clicking on STAR while the bubble is + // open should make it go away. + if (bookmarkBubbleController_.get()) { + [self doneWithBubbleController:bookmarkBubbleController_.get()]; + } else { + bookmarkBubbleController_.reset([[BookmarkBubbleController alloc] + initWithDelegate:self + parentWindow:[self window] + topLeftForBubble:[self topLeftForBubble] + model:model + node:node + alreadyBookmarked:alreadyBookmarked]); + [bookmarkBubbleController_ showWindow]; + } +} + +// Implement BookmarkBubbleControllerDelegate +- (void)editBookmarkNode:(const BookmarkNode*)node { + // A BookmarkEditorController is a sheet that owns itself, and + // deallocates itself when closed. + [[[BookmarkEditorController alloc] + initWithParentWindow:[self window] + profile:browser_->profile() + parent:node->GetParent() + node:node + configuration:BookmarkEditor::SHOW_TREE + handler:NULL] + runAsModalSheet]; +} + +// Implement BookmarkBubbleControllerDelegate +- (void)doneWithBubbleController:(BookmarkBubbleController*)controller { + bookmarkBubbleController_.reset(nil); +} + @end @implementation BrowserWindowController (Private) diff --git a/chrome/browser/cocoa/browser_window_controller_unittest.mm b/chrome/browser/cocoa/browser_window_controller_unittest.mm index 4b40a67..743c90c 100644 --- a/chrome/browser/cocoa/browser_window_controller_unittest.mm +++ b/chrome/browser/cocoa/browser_window_controller_unittest.mm @@ -257,4 +257,15 @@ TEST_F(BrowserWindowControllerTest, TestResizeViews) { EXPECT_TRUE(NSEqualRects([toolbar frame], NSMakeRect(0, 561, 800, 39))); } +TEST_F(BrowserWindowControllerTest, TestTopLeftForBubble) { + NSPoint p = [controller_ topLeftForBubble]; + NSRect all = [[controller_ window] frame]; + + // As a sanity check make sure the point is vaguely in the top left + // of the window. + EXPECT_GT(p.y, all.origin.y + (all.size.height/2)); + EXPECT_LT(p.x, all.origin.x + (all.size.width/2)); +} + + /* TODO(???): test other methods of BrowserWindowController */ diff --git a/chrome/browser/cocoa/toolbar_controller.h b/chrome/browser/cocoa/toolbar_controller.h index c5135d3..31aafc4 100644 --- a/chrome/browser/cocoa/toolbar_controller.h +++ b/chrome/browser/cocoa/toolbar_controller.h @@ -128,6 +128,10 @@ class ToolbarView; - (IBAction)showPageMenu:(id)sender; - (IBAction)showWrenchMenu:(id)sender; +// The bookmark bubble (when you click the star) needs to know where to go. +// Somewhere near the star button seems like a good start. +- (NSRect)starButtonInWindowCoordinates; + @end // A set of private methods used by tests, in the absence of "friends" in ObjC. diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm index 04c7e5e0..1bcf8a4 100644 --- a/chrome/browser/cocoa/toolbar_controller.mm +++ b/chrome/browser/cocoa/toolbar_controller.mm @@ -373,4 +373,10 @@ class PrefObserverBridge : public NotificationObserver { forView:wrenchButton_]; } +- (NSRect)starButtonInWindowCoordinates { + return [[[starButton_ window] contentView] convertRect:[starButton_ bounds] + fromView:starButton_]; +} + + @end diff --git a/chrome/browser/cocoa/toolbar_controller_unittest.mm b/chrome/browser/cocoa/toolbar_controller_unittest.mm index aa0257193..091bddc 100644 --- a/chrome/browser/cocoa/toolbar_controller_unittest.mm +++ b/chrome/browser/cocoa/toolbar_controller_unittest.mm @@ -248,4 +248,13 @@ TEST_F(ToolbarControllerTest, BookmarkBarIsFullWidth) { EXPECT_TRUE([bookmarkBarView isDescendantOf:[bar_ view]]); } +TEST_F(ToolbarControllerTest, StarButtonInWindowCoordinates) { + NSRect star = [bar_ starButtonInWindowCoordinates]; + NSRect all = [[[bar_ view] window] frame]; + + // Make sure the star is completely inside the window rect + EXPECT_TRUE(NSContainsRect(all, star)); +} + + } // namespace diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index e68faae..2432058 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -816,6 +816,12 @@ 'browser/cocoa/bookmark_bar_controller.mm', 'browser/cocoa/bookmark_bar_view.h', 'browser/cocoa/bookmark_bar_view.mm', + 'browser/cocoa/bookmark_bubble_controller.h', + 'browser/cocoa/bookmark_bubble_controller.mm', + 'browser/cocoa/bookmark_bubble_view.h', + 'browser/cocoa/bookmark_bubble_view.mm', + 'browser/cocoa/bookmark_bubble_window.h', + 'browser/cocoa/bookmark_bubble_window.mm', 'browser/cocoa/bookmark_button_cell.h', 'browser/cocoa/bookmark_button_cell.mm', 'browser/cocoa/bookmark_editor_controller.h', @@ -2173,6 +2179,7 @@ 'xib_files_to_scan': [ # The xib that need localization 'app/nibs/BookmarkBar.xib', + 'app/nibs/BookmarkBubble.xib', 'app/nibs/BookmarkEditor.xib', 'app/nibs/BookmarkNameFolder.xib', 'app/nibs/MainMenu.xib', @@ -2879,6 +2886,7 @@ # them. 'app/nibs/About.xib', 'app/nibs/BookmarkBar.xib', + 'app/nibs/BookmarkBubble.xib', 'app/nibs/BookmarkEditor.xib', 'app/nibs/BookmarkNameFolder.xib', 'app/nibs/BrowserWindow.xib', @@ -3816,6 +3824,9 @@ 'browser/cocoa/bookmark_bar_bridge_unittest.mm', 'browser/cocoa/bookmark_bar_controller_unittest.mm', 'browser/cocoa/bookmark_bar_view_unittest.mm', + 'browser/cocoa/bookmark_bubble_controller_unittest.mm', + 'browser/cocoa/bookmark_bubble_view_unittest.mm', + 'browser/cocoa/bookmark_bubble_window_unittest.mm', 'browser/cocoa/bookmark_button_cell_unittest.mm', 'browser/cocoa/bookmark_editor_controller_unittest.mm', 'browser/cocoa/bookmark_menu_bridge_unittest.mm', |