diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/nibs/SadTab.xib | 539 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.mm | 17 | ||||
-rw-r--r-- | chrome/browser/cocoa/sad_tab_controller.h | 32 | ||||
-rw-r--r-- | chrome/browser/cocoa/sad_tab_controller.mm | 48 | ||||
-rw-r--r-- | chrome/browser/cocoa/sad_tab_controller_unittest.mm | 101 | ||||
-rw-r--r-- | chrome/browser/cocoa/sad_tab_view.h | 15 | ||||
-rw-r--r-- | chrome/browser/cocoa/sad_tab_view.mm | 168 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents_view_mac.h | 4 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents_view_mac.mm | 22 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 1 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 3 | ||||
-rwxr-xr-x | chrome/chrome_tests.gypi | 1 |
12 files changed, 874 insertions, 77 deletions
diff --git a/chrome/app/nibs/SadTab.xib b/chrome/app/nibs/SadTab.xib new file mode 100644 index 0000000..6d7e0de --- /dev/null +++ b/chrome/app/nibs/SadTab.xib @@ -0,0 +1,539 @@ +<?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">9J3050</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.InterfaceBuilderKit</string> + <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">SadTabController</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">274</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSImageView" id="48169842"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">301</int> + <object class="NSMutableSet" key="NSDragTypes"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="set.sortedObjects"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>Apple PDF pasteboard type</string> + <string>Apple PICT pasteboard type</string> + <string>Apple PNG pasteboard type</string> + <string>NSFilenamesPboardType</string> + <string>NeXT Encapsulated PostScript v1.2 pasteboard type</string> + <string>NeXT TIFF v4.0 pasteboard type</string> + </object> + </object> + <string key="NSFrame">{{16, 74}, {66, 66}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSImageCell" key="NSCell" id="517261740"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">33554432</int> + <object class="NSFont" key="NSSupport" id="958586153"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.300000e+01</double> + <int key="NSfFlags">1044</int> + </object> + <int key="NSAlign">0</int> + <int key="NSScale">0</int> + <int key="NSStyle">0</int> + <bool key="NSAnimates">NO</bool> + </object> + <bool key="NSEditable">YES</bool> + </object> + <object class="NSTextField" id="261676766"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">301</int> + <string key="NSFrame">{{11, 54}, {74, 17}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="268214702"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">272630784</int> + <string key="NSContents">^IDS_SAD_TAB_TITLE</string> + <reference key="NSSupport" ref="958586153"/> + <reference key="NSControlView" ref="261676766"/> + <object class="NSColor" key="NSBackgroundColor" id="78971029"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC42NjY2NjY2OQA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor" id="7040190"> + <int key="NSColorSpace">1</int> + <bytes key="NSRGB">MSAxIDEAA</bytes> + </object> + </object> + </object> + <object class="NSTextField" id="685519067"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">301</int> + <string key="NSFrame">{{14, 29}, {68, 17}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="865139789"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">138412032</int> + <string key="NSContents">^IDS_SAD_TAB_MESSAGE</string> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.300000e+01</double> + <int key="NSfFlags">16</int> + </object> + <reference key="NSControlView" ref="685519067"/> + <reference key="NSBackgroundColor" ref="78971029"/> + <reference key="NSTextColor" ref="7040190"/> + </object> + </object> + <object class="NSButton" id="437803890"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">301</int> + <string key="NSFrame">{{27, 0}, {42, 32}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="968909108"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents">^IDS_LEARN_MORE</string> + <reference key="NSSupport" ref="958586153"/> + <reference key="NSControlView" ref="437803890"/> + <int key="NSButtonFlags">-2046672641</int> + <int key="NSButtonFlags2">134</int> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> + </object> + </object> + <string key="NSFrameSize">{97, 95}</string> + <reference key="NSSuperview"/> + <string key="NSClassName">SadTabView</string> + </object> + <object class="NSCustomObject" id="125577469"> + <string key="NSClassName">ChromeUILocalizer</string> + </object> + <object class="NSCustomObject" id="773582804"> + <string key="NSClassName">GTMUILocalizerAndLayoutTweaker</string> + </object> + </object> + <object class="IBObjectContainer" key="IBDocument.Objects"> + <object class="NSMutableArray" key="connectionRecords"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">view</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="1005"/> + </object> + <int key="connectionID">18</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">localizer_</string> + <reference key="source" ref="773582804"/> + <reference key="destination" ref="125577469"/> + </object> + <int key="connectionID">21</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">uiObject_</string> + <reference key="source" ref="773582804"/> + <reference key="destination" ref="1005"/> + </object> + <int key="connectionID">22</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">openLearnMoreAboutCrashLink:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="437803890"/> + </object> + <int key="connectionID">37</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">image_</string> + <reference key="source" ref="1005"/> + <reference key="destination" ref="48169842"/> + </object> + <int key="connectionID">40</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">linkButton_</string> + <reference key="source" ref="1005"/> + <reference key="destination" ref="437803890"/> + </object> + <int key="connectionID">41</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">linkCell_</string> + <reference key="source" ref="1005"/> + <reference key="destination" ref="968909108"/> + </object> + <int key="connectionID">42</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">message_</string> + <reference key="source" ref="1005"/> + <reference key="destination" ref="685519067"/> + </object> + <int key="connectionID">43</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">title_</string> + <reference key="source" ref="1005"/> + <reference key="destination" ref="261676766"/> + </object> + <int key="connectionID">44</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="685519067"/> + <reference ref="261676766"/> + <reference ref="437803890"/> + <reference ref="48169842"/> + </object> + <reference key="parent" ref="1002"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">19</int> + <reference key="object" ref="125577469"/> + <reference key="parent" ref="1002"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">20</int> + <reference key="object" ref="773582804"/> + <reference key="parent" ref="1002"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">26</int> + <reference key="object" ref="48169842"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="517261740"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">29</int> + <reference key="object" ref="517261740"/> + <reference key="parent" ref="48169842"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">25</int> + <reference key="object" ref="261676766"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="268214702"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">30</int> + <reference key="object" ref="268214702"/> + <reference key="parent" ref="261676766"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">24</int> + <reference key="object" ref="685519067"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="865139789"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">31</int> + <reference key="object" ref="865139789"/> + <reference key="parent" ref="685519067"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">27</int> + <reference key="object" ref="437803890"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="968909108"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">28</int> + <reference key="object" ref="968909108"/> + <reference key="parent" ref="437803890"/> + </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>19.IBPluginDependency</string> + <string>20.IBPluginDependency</string> + <string>24.IBPluginDependency</string> + <string>25.IBPluginDependency</string> + <string>26.IBPluginDependency</string> + <string>27.IBPluginDependency</string> + <string>28.CustomClassName</string> + <string>28.IBPluginDependency</string> + <string>29.IBPluginDependency</string> + <string>30.IBPluginDependency</string> + <string>31.IBPluginDependency</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilderKit</string> + <string>com.apple.InterfaceBuilderKit</string> + <string>{{71, 671}, {97, 95}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{628, 654}</string> + <string>{{217, 442}, {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>HyperlinkButtonCell</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">44</int> + </object> + <object class="IBClassDescriber" key="IBDocument.Classes"> + <object class="NSMutableArray" key="referencedPartialClassDescriptions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBPartialClassDescription"> + <string key="className">BaseView</string> + <string key="superclassName">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/base_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">GTMUILocalizerAndLayoutTweaker</string> + <string key="superclassName">NSObject</string> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>localizerOwner_</string> + <string>localizer_</string> + <string>uiObject_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>id</string> + <string>GTMUILocalizer</string> + <string>id</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">../third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">HyperlinkButtonCell</string> + <string key="superclassName">NSButtonCell</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/hyperlink_button_cell.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/status_bubble_mac.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/tab_strip_model_observer_bridge.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">SadTabController</string> + <string key="superclassName">NSViewController</string> + <object class="NSMutableDictionary" key="actions"> + <string key="NS.key.0">openLearnMoreAboutCrashLink:</string> + <string key="NS.object.0">id</string> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/sad_tab_controller.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">SadTabView</string> + <string key="superclassName">BaseView</string> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>image_</string> + <string>linkButton_</string> + <string>linkCell_</string> + <string>message_</string> + <string>title_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>NSImageView</string> + <string>NSButton</string> + <string>HyperlinkButtonCell</string> + <string>NSTextField</string> + <string>NSTextField</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/sad_tab_view.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/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index 43416bd..3af0816 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -36,6 +36,7 @@ #include "chrome/browser/cocoa/find_bar_bridge.h" #import "chrome/browser/cocoa/fullscreen_window.h" #import "chrome/browser/cocoa/infobar_container_controller.h" +#import "chrome/browser/cocoa/sad_tab_controller.h" #import "chrome/browser/cocoa/status_bubble_mac.h" #import "chrome/browser/cocoa/tab_strip_model_observer_bridge.h" #import "chrome/browser/cocoa/tab_strip_view.h" @@ -48,6 +49,7 @@ #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" #include "grit/generated_resources.h" +#include "grit/locale_settings.h" #include "grit/theme_resources.h" #import "third_party/GTM/AppKit/GTMTheme.h" @@ -1337,6 +1339,21 @@ willPositionSheet:(NSWindow*)sheet } } +// Handle the openLearnMoreAboutCrashLink: action from SadTabController when +// "Learn more" link in "Aw snap" page (i.e. crash page or sad tab) is +// clicked. Decoupling the action from its target makes unitestting possible. +- (void)openLearnMoreAboutCrashLink:(id)sender { + if ([sender isKindOfClass:[SadTabController class]]) { + SadTabController* sad_tab = static_cast<SadTabController*>(sender); + TabContents* tab_contents = [sad_tab tabContents]; + if (tab_contents) { + std::string linkUrl = l10n_util::GetStringUTF8(IDS_CRASH_REASON_URL); + tab_contents->OpenURL(GURL(linkUrl), GURL(), CURRENT_TAB, + PageTransition::LINK); + } + } +} + // Delegate method called when window did move. (See below for why we don't use // |-windowWillMove:|, which is called less frequently than |-windowDidMove| // instead.) diff --git a/chrome/browser/cocoa/sad_tab_controller.h b/chrome/browser/cocoa/sad_tab_controller.h new file mode 100644 index 0000000..148729a --- /dev/null +++ b/chrome/browser/cocoa/sad_tab_controller.h @@ -0,0 +1,32 @@ +// 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_SAD_TAB_CONTROLLER_H_ +#define CHROME_BROWSER_COCOA_SAD_TAB_CONTROLLER_H_ + +#import <Cocoa/Cocoa.h> + +class TabContents; + +// A controller class that manages the SadTabView (aka "Aw Snap" or crash page). +@interface SadTabController : NSViewController { + @private + TabContents* tabContents_; // Weak reference. +} + +// Designated initializer is initWithTabContents. +- (id)initWithTabContents:(TabContents*)someTabContents + superview:(NSView*)superview; + +// This action just calls the NSApp sendAction to get it into the standard +// Cocoa action processing. +- (IBAction)openLearnMoreAboutCrashLink:(id)sender; + +// Returns a weak reference to the TabContents whose TabContentsView created +// this SadTabController. +- (TabContents*)tabContents; + +@end + +#endif // CHROME_BROWSER_COCOA_SAD_TAB_CONTROLLER_H_ diff --git a/chrome/browser/cocoa/sad_tab_controller.mm b/chrome/browser/cocoa/sad_tab_controller.mm new file mode 100644 index 0000000..c0c832a --- /dev/null +++ b/chrome/browser/cocoa/sad_tab_controller.mm @@ -0,0 +1,48 @@ +// 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 "chrome/browser/cocoa/sad_tab_controller.h" + +#include "base/mac_util.h" +#import "chrome/browser/cocoa/sad_tab_view.h" + +@implementation SadTabController + +- (id)initWithTabContents:(TabContents*)someTabContents + superview:(NSView*)superview { + if ((self = [super initWithNibName:@"SadTab" + bundle:mac_util::MainAppBundle()])) { + tabContents_ = someTabContents; + + NSView* view = [self view]; + [superview addSubview:view]; + [view setFrame:[superview bounds]]; + } + + return self; +} + +- (void)awakeFromNib { + // If tab_contents_ is nil, ask view to remove link. + if (!tabContents_) { + SadTabView* sad_view = static_cast<SadTabView*>([self view]); + [sad_view removeLinkButton]; + } +} + +- (void)dealloc { + [[self view] removeFromSuperview]; + [super dealloc]; +} + +- (TabContents*)tabContents { + return tabContents_; +} + +- (void)openLearnMoreAboutCrashLink:(id)sender { + // Send the action up through the responder chain. + [NSApp sendAction:@selector(openLearnMoreAboutCrashLink:) to:nil from:self]; +} + +@end diff --git a/chrome/browser/cocoa/sad_tab_controller_unittest.mm b/chrome/browser/cocoa/sad_tab_controller_unittest.mm new file mode 100644 index 0000000..9395cbb --- /dev/null +++ b/chrome/browser/cocoa/sad_tab_controller_unittest.mm @@ -0,0 +1,101 @@ +// 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/cocoa_test_helper.h" +#import "chrome/browser/cocoa/sad_tab_controller.h" +#import "chrome/browser/cocoa/sad_tab_view.h" +#include "chrome/browser/renderer_host/site_instance.h" +#include "chrome/browser/tab_contents/tab_contents.h" + +@interface SadTabView (ExposedForTesting) +// Implementation is below. +- (NSButton*)linkButton; +@end + +@implementation SadTabView (ExposedForTesting) +- (NSButton*)linkButton { + return linkButton_; +} +@end + +namespace { + +class SadTabControllerTest : public CocoaTest { + public: + SadTabControllerTest() { + link_clicked_ = false; + } + + TabContents* CreateTabContents() { + SiteInstance* instance = + SiteInstance::CreateSiteInstance(browser_helper_.profile()); + TabContents* tab_contents = new TabContents(browser_helper_.profile(), + instance, MSG_ROUTING_NONE, NULL); + return tab_contents; + } + + // Creates the controller and adds its view to contents, caller has ownership. + SadTabController* CreateController(TabContents* tab_contents) { + NSView* contentView = [test_window() contentView]; + SadTabController* controller = + [[SadTabController alloc] initWithTabContents:tab_contents + superview:contentView]; + EXPECT_TRUE(controller); + NSView* view = [controller view]; + EXPECT_TRUE(view); + + return controller; + } + + NSButton* GetLinkButton(SadTabController* controller) { + SadTabView* view = static_cast<SadTabView*>([controller view]); + return ([view linkButton]); + } + + BrowserTestHelper browser_helper_; + static bool link_clicked_; +}; + +TEST_F(SadTabControllerTest, TestWithTabContents) { + scoped_ptr<TabContents> tab_contents(CreateTabContents()); + scoped_nsobject<SadTabController> + controller(CreateController(tab_contents.get())); + EXPECT_TRUE(controller); + NSButton* link = GetLinkButton(controller); + EXPECT_TRUE(link); +} + +TEST_F(SadTabControllerTest, TestWithoutTabContents) { + scoped_nsobject<SadTabController> controller(CreateController(NULL)); + EXPECT_TRUE(controller); + NSButton* link = GetLinkButton(controller); + EXPECT_FALSE(link); +} + +TEST_F(SadTabControllerTest, TestClickOnLink) { + scoped_ptr<TabContents> tab_contents(CreateTabContents()); + scoped_nsobject<SadTabController> + controller(CreateController(tab_contents.get())); + NSButton* link = GetLinkButton(controller); + EXPECT_TRUE(link); + EXPECT_FALSE(link_clicked_); + [link performClick:link]; + EXPECT_TRUE(link_clicked_); +} + +} // namespace + +@implementation NSApplication (SadTabControllerUnitTest) +// Add handler for the openLearnMoreAboutCrashLink: action to NSApp for testing +// purposes. Normally this would be sent up the responder tree correctly, but +// since tests run in the background, key window and main window are never set +// on NSApplication. Adding it to NSApplication directly removes the need for +// worrying about what the current window with focus is. +- (void)openLearnMoreAboutCrashLink:(id)sender { + SadTabControllerTest::link_clicked_ = true; +} + +@end diff --git a/chrome/browser/cocoa/sad_tab_view.h b/chrome/browser/cocoa/sad_tab_view.h index d003536..f89e679 100644 --- a/chrome/browser/cocoa/sad_tab_view.h +++ b/chrome/browser/cocoa/sad_tab_view.h @@ -5,18 +5,31 @@ #ifndef CHROME_BROWSER_COCOA_SAD_TAB_VIEW_H_ #define CHROME_BROWSER_COCOA_SAD_TAB_VIEW_H_ +#include "base/scoped_nsobject.h" #include "chrome/browser/cocoa/base_view.h" #import <Cocoa/Cocoa.h> -// A view that displays the "sad tab". +@class HyperlinkButtonCell; +// A view that displays the "sad tab" (aka crash page). @interface SadTabView : BaseView { @private + IBOutlet NSImageView* image_; + IBOutlet NSTextField* title_; + IBOutlet NSTextField* message_; + IBOutlet NSButton* linkButton_; + IBOutlet HyperlinkButtonCell* linkCell_; + + scoped_nsobject<NSColor> backgroundColor_; + NSSize messageSize_; } // Designated initializer is -initWithFrame: . +// Called by SadTabController to remove link button. +- (void)removeLinkButton; + @end #endif // CHROME_BROWSER_COCOA_SAD_TAB_VIEW_H_ diff --git a/chrome/browser/cocoa/sad_tab_view.mm b/chrome/browser/cocoa/sad_tab_view.mm index 1143025..ae018f5 100644 --- a/chrome/browser/cocoa/sad_tab_view.mm +++ b/chrome/browser/cocoa/sad_tab_view.mm @@ -4,78 +4,122 @@ #include "chrome/browser/cocoa/sad_tab_view.h" -#include "app/l10n_util_mac.h" #include "app/resource_bundle.h" -#include "base/sys_string_conversions.h" -#include "grit/generated_resources.h" +#include "base/logging.h" +#import "chrome/browser/cocoa/hyperlink_button_cell.h" #include "grit/theme_resources.h" - -static const int kSadTabOffset = -64; -static const int kIconTitleSpacing = 20; -static const int kTitleMessageSpacing = 15; +#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" + +// Offset above vertical middle of page where contents of page start. +static const CGFloat kSadTabOffset = -64; +// Padding between icon and title. +static const CGFloat kIconTitleSpacing = 20; +// Padding between title and message. +static const CGFloat kTitleMessageSpacing = 15; +// Padding between message and link. +static const CGFloat kMessageLinkSpacing = 15; +// Paddings on left and right of page. +static const CGFloat kTabHorzMargin = 13; @implementation SadTabView -- (void)drawRect:(NSRect)dirtyRect { +- (void)awakeFromNib { + // Load resource for image and set it. ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - NSImage* sadTabImage = rb.GetNSImageNamed(IDR_SAD_TAB); - DCHECK(sadTabImage); - NSString* title = l10n_util::GetNSStringWithFixup(IDS_SAD_TAB_TITLE); - NSString* message = l10n_util::GetNSStringWithFixup(IDS_SAD_TAB_MESSAGE); - - NSColor* textColor = [NSColor whiteColor]; - NSColor* backgroundColor = [NSColor colorWithCalibratedRed:(35.0f/255.0f) - green:(48.0f/255.0f) - blue:(64.0f/255.0f) - alpha:1.0]; - - // Layout + NSImage* image = rb.GetNSImageNamed(IDR_SAD_TAB); + DCHECK(image); + [image_ setImage:image]; + + // Set font for title. NSFont* titleFont = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]]; + [title_ setFont:titleFont]; + + // Set font for message. NSFont* messageFont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; + [message_ setFont:messageFont]; + + // If necessary, set font and color for link. + if (linkButton_) { + [linkButton_ setFont:messageFont]; + [linkCell_ setTextColor:[NSColor whiteColor]]; + } + + // Initialize background color. + NSColor* backgroundColor = [[NSColor colorWithCalibratedRed:(35.0f/255.0f) + green:(48.0f/255.0f) + blue:(64.0f/255.0f) + alpha:1.0] retain]; + backgroundColor_.reset(backgroundColor); +} - NSDictionary* titleAttrs = [NSDictionary dictionaryWithObjectsAndKeys: - titleFont, NSFontAttributeName, - textColor, NSForegroundColorAttributeName, - nil]; - NSDictionary* messageAttrs = [NSDictionary dictionaryWithObjectsAndKeys: - messageFont, NSFontAttributeName, - textColor, NSForegroundColorAttributeName, - nil]; - - NSAttributedString* titleString = - [[[NSAttributedString alloc] initWithString:title - attributes:titleAttrs] autorelease]; - NSAttributedString* messageString = - [[[NSAttributedString alloc] initWithString:message - attributes:messageAttrs] autorelease]; - - NSRect viewBounds = [self bounds]; - - NSSize sadTabImageSize = [sadTabImage size]; - CGFloat iconWidth = sadTabImageSize.width; - CGFloat iconHeight = sadTabImageSize.height; - CGFloat iconX = (viewBounds.size.width - iconWidth) / 2; +- (void)drawRect:(NSRect)dirtyRect { + // Paint background. + [backgroundColor_ set]; + NSRectFill(dirtyRect); +} + +- (void)resizeSubviewsWithOldSize:(NSSize)oldSize { + NSRect newBounds = [self bounds]; + CGFloat maxWidth = NSWidth(newBounds) - (kTabHorzMargin * 2); + BOOL callSizeToFit = (messageSize_.width == 0); + + // Set new frame origin for image. + NSRect iconFrame = [image_ frame]; + CGFloat iconX = (maxWidth - NSWidth(iconFrame)) / 2; CGFloat iconY = - ((viewBounds.size.height - iconHeight) / 2) - kSadTabOffset; - - NSSize titleSize = [titleString size]; - CGFloat titleX = (viewBounds.size.width - titleSize.width) / 2; - CGFloat titleY = iconY - kIconTitleSpacing - titleSize.height; - - NSSize messageSize = [messageString size]; - CGFloat messageX = (viewBounds.size.width - messageSize.width) / 2; - CGFloat messageY = titleY - kTitleMessageSpacing - messageSize.height; - - // Paint - [backgroundColor set]; - NSRectFill(viewBounds); - - [sadTabImage drawAtPoint:NSMakePoint(iconX, iconY) - fromRect:NSZeroRect - operation:NSCompositeSourceOver - fraction:1.0f]; - [titleString drawAtPoint:NSMakePoint(titleX, titleY)]; - [messageString drawAtPoint:NSMakePoint(messageX, messageY)]; + MIN(((NSHeight(newBounds) - NSHeight(iconFrame)) / 2) - kSadTabOffset, + NSHeight(newBounds) - NSHeight(iconFrame)); + [image_ setFrameOrigin:NSMakePoint(iconX, iconY)]; + + // Set new frame origin for title. + if (callSizeToFit) + [title_ sizeToFit]; + NSRect titleFrame = [title_ frame]; + CGFloat titleX = (maxWidth - NSWidth(titleFrame)) / 2; + CGFloat titleY = iconY - kIconTitleSpacing - NSHeight(titleFrame); + [title_ setFrameOrigin:NSMakePoint(titleX, titleY)]; + + // Set new frame for message, wrapping or unwrapping the text if necessary. + if (callSizeToFit) { + [message_ sizeToFit]; + messageSize_ = [message_ frame].size; + } + NSRect messageFrame = [message_ frame]; + if (messageSize_.width > maxWidth) { // Need to wrap message. + [message_ setFrameSize:NSMakeSize(maxWidth, messageSize_.height)]; + CGFloat heightChange = + [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_]; + messageFrame.size.width = maxWidth; + messageFrame.size.height = messageSize_.height + heightChange; + messageFrame.origin.x = kTabHorzMargin; + } else { + if (!callSizeToFit) { + [message_ sizeToFit]; + messageFrame = [message_ frame]; + } + messageFrame.origin.x = (maxWidth - NSWidth(messageFrame)) / 2; + } + messageFrame.origin.y = + titleY - kTitleMessageSpacing - NSHeight(messageFrame); + [message_ setFrame:messageFrame]; + + if (linkButton_) { + if (callSizeToFit) + [linkButton_ sizeToFit]; + // Set new frame origin for link. + NSRect linkFrame = [linkButton_ frame]; + CGFloat linkX = (maxWidth - NSWidth(linkFrame)) / 2; + CGFloat linkY = + NSMinY(messageFrame) - kMessageLinkSpacing - NSHeight(linkFrame); + [linkButton_ setFrameOrigin:NSMakePoint(linkX, linkY)]; + } +} + +- (void)removeLinkButton { + if (linkButton_) { + [linkButton_ removeFromSuperview]; + linkButton_ = nil; + } } @end diff --git a/chrome/browser/tab_contents/tab_contents_view_mac.h b/chrome/browser/tab_contents/tab_contents_view_mac.h index c3801a7..1e8e174b 100644 --- a/chrome/browser/tab_contents/tab_contents_view_mac.h +++ b/chrome/browser/tab_contents/tab_contents_view_mac.h @@ -19,7 +19,7 @@ class FilePath; class FindBarMac; @class FocusTracker; -@class SadTabView; +@class SadTabController; class TabContentsViewMac; @class WebDragSource; @class WebDropTarget; @@ -101,7 +101,7 @@ class TabContentsViewMac : public TabContentsView, // Used to render the sad tab. This will be non-NULL only when the sad tab is // visible. - scoped_nsobject<SadTabView> sad_tab_; + scoped_nsobject<SadTabController> sad_tab_; // The page content's intrinsic width. int preferred_width_; diff --git a/chrome/browser/tab_contents/tab_contents_view_mac.mm b/chrome/browser/tab_contents/tab_contents_view_mac.mm index 14b16c6..8c1f3d6 100644 --- a/chrome/browser/tab_contents/tab_contents_view_mac.mm +++ b/chrome/browser/tab_contents/tab_contents_view_mac.mm @@ -14,7 +14,7 @@ #import "chrome/browser/cocoa/chrome_browser_window.h" #import "chrome/browser/cocoa/browser_window_controller.h" #include "chrome/browser/global_keyboard_shortcuts_mac.h" -#include "chrome/browser/cocoa/sad_tab_view.h" +#include "chrome/browser/cocoa/sad_tab_controller.h" #import "chrome/browser/cocoa/web_drag_source.h" #import "chrome/browser/cocoa/web_drop_target.h" #include "chrome/browser/renderer_host/render_view_host_factory.h" @@ -158,13 +158,14 @@ void TabContentsViewMac::SetPageTitle(const std::wstring& title) { void TabContentsViewMac::OnTabCrashed() { if (!sad_tab_.get()) { - SadTabView* view = [[SadTabView alloc] initWithFrame:NSZeroRect]; - sad_tab_.reset(view); - - // Set as the dominant child. - [cocoa_view_.get() addSubview:view]; - [view setFrame:[cocoa_view_.get() bounds]]; - [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + TabContents* contents = tab_contents(); + DCHECK(contents); + if (contents) { + SadTabController* sad_tab = + [[SadTabController alloc] initWithTabContents:contents + superview:cocoa_view_]; + sad_tab_.reset(sad_tab); + } } } @@ -295,10 +296,7 @@ void TabContentsViewMac::Observe(NotificationType type, const NotificationDetails& details) { switch (type.value) { case NotificationType::TAB_CONTENTS_CONNECTED: { - if (sad_tab_.get()) { - [sad_tab_.get() removeFromSuperview]; - sad_tab_.reset(); - } + sad_tab_.reset(); break; } default: diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 031020e..76229cac 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1848,6 +1848,7 @@ 'app/nibs/Preferences.xib', 'app/nibs/ReportBug.xib', 'app/nibs/SaveAccessoryView.xib', + 'app/nibs/SadTab.xib', 'app/nibs/TabContents.xib', 'app/nibs/TabView.xib', 'app/nibs/TaskManager.xib', diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 6f7b8e9..957880c 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -498,6 +498,8 @@ 'browser/cocoa/repost_form_warning_mac.mm', 'browser/cocoa/restart_browser.h', 'browser/cocoa/restart_browser.mm', + 'browser/cocoa/sad_tab_controller.h', + 'browser/cocoa/sad_tab_controller.mm', 'browser/cocoa/sad_tab_view.h', 'browser/cocoa/sad_tab_view.mm', 'browser/cocoa/scoped_authorizationref.h', @@ -2001,6 +2003,7 @@ 'app/nibs/PageInfo.xib', 'app/nibs/Preferences.xib', 'app/nibs/ReportBug.xib', + 'app/nibs/SadTab.xib', 'app/nibs/SaveAccessoryView.xib', 'app/nibs/TabView.xib', 'app/nibs/TaskManager.xib', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index feb4fbf..acf6410 100755 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -626,6 +626,7 @@ 'browser/cocoa/page_info_window_controller_unittest.mm', 'browser/cocoa/preferences_window_controller_unittest.mm', 'browser/cocoa/rwhvm_editcommand_helper_unittest.mm', + 'browser/cocoa/sad_tab_controller_unittest.mm', 'browser/cocoa/sad_tab_view_unittest.mm', 'browser/cocoa/search_engine_list_model_unittest.mm', 'browser/cocoa/status_bubble_mac_unittest.mm', |