diff options
-rw-r--r-- | chrome/app/nibs/DownloadItem.xib | 295 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_item_controller.h | 26 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_item_controller.mm | 92 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_item_mac.h | 3 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_item_mac.mm | 16 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_shelf_controller.h | 3 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_shelf_controller.mm | 61 | ||||
-rw-r--r-- | chrome/browser/download/download_exe.cc | 5 | ||||
-rw-r--r-- | chrome/browser/download/download_manager.cc | 15 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 |
10 files changed, 459 insertions, 59 deletions
diff --git a/chrome/app/nibs/DownloadItem.xib b/chrome/app/nibs/DownloadItem.xib index 6f030e5..11abe7a 100644 --- a/chrome/app/nibs/DownloadItem.xib +++ b/chrome/app/nibs/DownloadItem.xib @@ -8,9 +8,9 @@ <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="1"/> - <integer value="24"/> <integer value="17"/> + <integer value="66"/> + <integer value="24"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -41,6 +41,162 @@ <int key="NSvFlags">292</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSBox" id="55478397"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">-2147483612</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSView" id="325658281"> + <reference key="NSNextResponder" ref="55478397"/> + <int key="NSvFlags">256</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSButton" id="185082033"> + <reference key="NSNextResponder" ref="325658281"/> + <int key="NSvFlags">289</int> + <string key="NSFrame">{{300, 1}, {67, 28}}</string> + <reference key="NSSuperview" ref="325658281"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="136006556"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134348800</int> + <string key="NSContents">Save</string> + <object class="NSFont" key="NSSupport" id="26"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.100000e+01</double> + <int key="NSfFlags">3100</int> + </object> + <reference key="NSControlView" ref="185082033"/> + <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="979385092"> + <reference key="NSNextResponder" ref="325658281"/> + <int key="NSvFlags">289</int> + <string key="NSFrame">{{365, 1}, {67, 28}}</string> + <reference key="NSSuperview" ref="325658281"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="93953286"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134348800</int> + <string key="NSContents">Discard</string> + <reference key="NSSupport" ref="26"/> + <reference key="NSControlView" ref="979385092"/> + <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="NSTextField" id="146169749"> + <reference key="NSNextResponder" ref="325658281"/> + <int key="NSvFlags">290</int> + <string key="NSFrame">{{36, 5}, {264, 22}}</string> + <reference key="NSSuperview" ref="325658281"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="622024590"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">272891904</int> + <string key="NSContents">DO NOT TRANSLATE some placeholder text to make layout easier in Interface Builder</string> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">9.000000e+00</double> + <int key="NSfFlags">3614</int> + </object> + <reference key="NSControlView" ref="146169749"/> + <object class="NSColor" key="NSBackgroundColor"> + <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"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlTextColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MAA</bytes> + </object> + </object> + </object> + </object> + <object class="NSImageView" id="263710528"> + <reference key="NSNextResponder" ref="325658281"/> + <int key="NSvFlags">292</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">{{7, 4}, {24, 24}}</string> + <reference key="NSSuperview" ref="325658281"/> + <bool key="NSEnabled">YES</bool> + <object class="NSImageCell" key="NSCell" id="925428167"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">33685504</int> + <object class="NSCustomResource" key="NSContents"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">alert_small</string> + </object> + <reference key="NSSupport" ref="26"/> + <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> + <string key="NSFrame">{{1, 1}, {438, 32}}</string> + <reference key="NSSuperview" ref="55478397"/> + </object> + </object> + <string key="NSFrameSize">{440, 34}</string> + <reference key="NSSuperview" ref="1005"/> + <string key="NSOffsets">{0, 0}</string> + <object class="NSTextFieldCell" key="NSTitleCell"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">0</int> + <string key="NSContents">Insecure Download</string> + <reference key="NSSupport" ref="26"/> + <object class="NSColor" key="NSBackgroundColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">textBackgroundColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MQA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MCAwLjgwMDAwMDAxAA</bytes> + </object> + </object> + <reference key="NSContentView" ref="325658281"/> + <int key="NSBorderType">1</int> + <int key="NSBoxType">0</int> + <int key="NSTitlePosition">0</int> + <bool key="NSTransparent">NO</bool> + </object> <object class="NSButton" id="575090266"> <reference key="NSNextResponder" ref="1005"/> <int key="NSvFlags">292</int> @@ -66,7 +222,7 @@ </object> </object> </object> - <string key="NSFrameSize">{200, 34}</string> + <string key="NSFrameSize">{440, 34}</string> <reference key="NSSuperview"/> <string key="NSClassName">NSView</string> </object> @@ -360,6 +516,38 @@ </object> <int key="connectionID">65</int> </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">saveDownload:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="185082033"/> + </object> + <int key="connectionID">76</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">discardDownload:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="979385092"/> + </object> + <int key="connectionID">77</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">dangerousDownloadView_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="55478397"/> + </object> + <int key="connectionID">78</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">dangerousDownloadLabel_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="146169749"/> + </object> + <int key="connectionID">79</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -396,6 +584,7 @@ <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="575090266"/> + <reference ref="55478397"/> </object> <reference key="parent" ref="1002"/> </object> @@ -513,6 +702,74 @@ <reference key="object" ref="426590582"/> <reference key="parent" ref="571207526"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">66</int> + <reference key="object" ref="55478397"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="263710528"/> + <reference ref="146169749"/> + <reference ref="185082033"/> + <reference ref="979385092"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">73</int> + <reference key="object" ref="263710528"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="925428167"/> + </object> + <reference key="parent" ref="55478397"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">71</int> + <reference key="object" ref="146169749"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="622024590"/> + </object> + <reference key="parent" ref="55478397"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">67</int> + <reference key="object" ref="185082033"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="136006556"/> + </object> + <reference key="parent" ref="55478397"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">69</int> + <reference key="object" ref="979385092"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="93953286"/> + </object> + <reference key="parent" ref="55478397"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">70</int> + <reference key="object" ref="93953286"/> + <reference key="parent" ref="979385092"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">68</int> + <reference key="object" ref="136006556"/> + <reference key="parent" ref="185082033"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">72</int> + <reference key="object" ref="622024590"/> + <reference key="parent" ref="146169749"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">74</int> + <reference key="object" ref="925428167"/> + <reference key="parent" ref="263710528"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -547,13 +804,23 @@ <string>59.IBPluginDependency</string> <string>60.CustomClassName</string> <string>60.IBPluginDependency</string> + <string>66.IBEditorWindowLastContentRect</string> + <string>66.IBPluginDependency</string> + <string>67.IBPluginDependency</string> + <string>68.IBPluginDependency</string> + <string>69.IBPluginDependency</string> + <string>70.IBPluginDependency</string> + <string>71.IBPluginDependency</string> + <string>72.IBPluginDependency</string> + <string>73.IBPluginDependency</string> + <string>74.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>{{348, 713}, {200, 34}}</string> + <string>{{276, 710}, {440, 34}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{628, 654}</string> <string>{{357, 416}, {480, 272}}</string> @@ -578,6 +845,16 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>DownloadItemCell</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{275, 354}, {440, 34}}</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"> @@ -600,7 +877,7 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">65</int> + <int key="maxID">79</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -620,12 +897,14 @@ <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> + <string>discardDownload:</string> <string>handleAlwaysOpen:</string> <string>handleButtonClick:</string> <string>handleCancel:</string> <string>handleOpen:</string> <string>handleRemove:</string> <string>handleReveal:</string> + <string>saveDownload:</string> <string>updateVisibility:</string> </object> <object class="NSMutableArray" key="dict.values"> @@ -637,6 +916,8 @@ <string>id</string> <string>id</string> <string>id</string> + <string>id</string> + <string>id</string> </object> </object> <object class="NSMutableDictionary" key="outlets"> @@ -646,6 +927,8 @@ <string>activeDownloadMenu_</string> <string>cell_</string> <string>completeDownloadMenu_</string> + <string>dangerousDownloadLabel_</string> + <string>dangerousDownloadView_</string> <string>progressView_</string> </object> <object class="NSMutableArray" key="dict.values"> @@ -653,6 +936,8 @@ <string>NSMenu</string> <string>DownloadItemCell</string> <string>NSMenu</string> + <string>NSTextField</string> + <string>NSView</string> <string>NSButton</string> </object> </object> diff --git a/chrome/browser/cocoa/download_item_controller.h b/chrome/browser/cocoa/download_item_controller.h index 04b28d5..dd8d4e2c 100644 --- a/chrome/browser/cocoa/download_item_controller.h +++ b/chrome/browser/cocoa/download_item_controller.h @@ -5,6 +5,7 @@ #import <Cocoa/Cocoa.h> #include "base/scoped_ptr.h" +#include "base/time.h" class BaseDownloadItemModel; @class DownloadItemCell; @@ -24,16 +25,28 @@ class DownloadShelfContextMenuMac; NSMenu* currentMenu_; // points to one of the two menus above + // This is shown instead of progressView_ for dangerous downloads. + IBOutlet NSView* dangerousDownloadView_; + IBOutlet NSTextField* dangerousDownloadLabel_; + scoped_ptr<DownloadItemMac> bridge_; scoped_ptr<DownloadShelfContextMenuMac> menuBridge_; // Weak pointer to the shelf that owns us. DownloadShelfController* shelf_; + + // The time at which this view was created. + base::Time creationTime_; + + // The state of this item. + enum DownoadItemState { + kNormal, + kDangerous + } state_; }; // Takes ownership of |downloadModel|. -- (id)initWithFrame:(NSRect)frameRect - model:(BaseDownloadItemModel*)downloadModel +- (id)initWithModel:(BaseDownloadItemModel*)downloadModel shelf:(DownloadShelfController*)shelf; // Updates the UI and menu state from |downloadModel|. @@ -52,6 +65,15 @@ class DownloadShelfContextMenuMac; // Download item button clicked - (IBAction)handleButtonClick:(id)sender; +// Returns the size this item wants to have. +- (NSSize)preferredSize; + +// Handling of dangerous downloads +- (void)clearDangerousMode; +- (BOOL)isDangerousMode; +- (IBAction)saveDownload:(id)sender; +- (IBAction)discardDownload:(id)sender; + // Context menu handlers. - (IBAction)handleOpen:(id)sender; - (IBAction)handleAlwaysOpen:(id)sender; diff --git a/chrome/browser/cocoa/download_item_controller.mm b/chrome/browser/cocoa/download_item_controller.mm index fdbdd48..4e2ab11 100644 --- a/chrome/browser/cocoa/download_item_controller.mm +++ b/chrome/browser/cocoa/download_item_controller.mm @@ -4,13 +4,19 @@ #import "chrome/browser/cocoa/download_item_controller.h" +#include "app/gfx/text_elider.h" +#include "app/l10n_util_mac.h" #include "base/mac_util.h" +#include "base/sys_string_conversions.h" #import "chrome/browser/cocoa/download_item_cell.h" #include "chrome/browser/cocoa/download_item_mac.h" +#import "chrome/browser/cocoa/download_shelf_controller.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_shelf.h" #include "chrome/browser/download/download_util.h" +#include "grit/generated_resources.h" +static const int kTextWidth = 140; // Pixels // A class for the chromium-side part of the download shelf context menu. @@ -30,13 +36,15 @@ class DownloadShelfContextMenuMac : public DownloadShelfContextMenu { using DownloadShelfContextMenu::REMOVE_ITEM; }; +@interface DownloadItemController (Private) +- (void)setState:(DownoadItemState)state; +@end // Implementation of DownloadItemController @implementation DownloadItemController -- (id)initWithFrame:(NSRect)frameRect - model:(BaseDownloadItemModel*)downloadModel +- (id)initWithModel:(BaseDownloadItemModel*)downloadModel shelf:(DownloadShelfController*)shelf { if ((self = [super initWithNibName:@"DownloadItem" bundle:mac_util::MainAppBundle()])) { @@ -45,8 +53,8 @@ class DownloadShelfContextMenuMac : public DownloadShelfContextMenu { menuBridge_.reset(new DownloadShelfContextMenuMac(downloadModel)); shelf_ = shelf; - - [[self view] setFrame:frameRect]; + state_ = kNormal; + creationTime_ = base::Time::Now(); } return self; } @@ -57,7 +65,24 @@ class DownloadShelfContextMenuMac : public DownloadShelfContextMenu { } - (void)setStateFromDownload:(BaseDownloadItemModel*)downloadModel { - // TODO(thakis): handling of dangerous downloads -- crbug.com/14667 + DCHECK_EQ(bridge_->download_model(), downloadModel); + + // Handle dangerous downloads. + if (downloadModel->download()->safety_state() == DownloadItem::DANGEROUS) { + [self setState:kDangerous]; + + // Set label. + NSFont* font = [dangerousDownloadLabel_ font]; + gfx::Font fontChr = gfx::Font::CreateFont( + base::SysNSStringToWide([font fontName]), [font pointSize]); + string16 elidedFilename = WideToUTF16(ElideFilename( + downloadModel->download()->original_name(), fontChr, kTextWidth)); + NSString* dangerousWarning = + l10n_util::GetNSStringFWithFixup(IDS_PROMPT_DANGEROUS_DOWNLOAD, + elidedFilename); + [dangerousDownloadLabel_ setStringValue:dangerousWarning]; + return; + } // Set the correct popup menu. if (downloadModel->download()->state() == DownloadItem::COMPLETE) @@ -89,19 +114,68 @@ class DownloadShelfContextMenuMac : public DownloadShelfContextMenu { - (IBAction)handleButtonClick:(id)sender { if ([cell_ isButtonPartPressed]) { DownloadItem* download = bridge_->download_model()->download(); - if (download->state() == DownloadItem::IN_PROGRESS) { + if (download->state() == DownloadItem::IN_PROGRESS) download->set_open_when_complete(!download->open_when_complete()); - } else if (download->state() == DownloadItem::COMPLETE) { + else if (download->state() == DownloadItem::COMPLETE) download_util::OpenDownload(download); - } } else { - // TODO(thakis): Align menu nicely with left view edge [NSMenu popUpContextMenu:currentMenu_ withEvent:[NSApp currentEvent] forView:progressView_]; } } +- (NSSize)preferredSize { + if (state_ == kNormal) + return [progressView_ frame].size; + DCHECK_EQ(kDangerous, state_); + return [dangerousDownloadView_ frame].size; +} + +- (void)clearDangerousMode { + [self setState:kNormal]; +} + +- (BOOL)isDangerousMode { + return state_ == kDangerous; +} + +- (void)setState:(DownoadItemState)state { + if (state_ == state) + return; + state_ = state; + if (state_ == kNormal) { + [progressView_ setHidden:NO]; + [dangerousDownloadView_ setHidden:YES]; + } else { + DCHECK_EQ(kDangerous, state_); + [progressView_ setHidden:YES]; + [dangerousDownloadView_ setHidden:NO]; + } + [shelf_ layoutItems]; +} + +- (IBAction)saveDownload:(id)sender { + // The user has confirmed a dangerous download. We record how quickly the + // user did this to detect whether we're being clickjacked. + UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download", + base::Time::Now() - creationTime_); + // This will change the state and notify us. + bridge_->download_model()->download()->manager()->DangerousDownloadValidated( + bridge_->download_model()->download()); +} + +- (IBAction)discardDownload:(id)sender { + UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", + base::Time::Now() - creationTime_); + if (bridge_->download_model()->download()->state() == + DownloadItem::IN_PROGRESS) + bridge_->download_model()->download()->Cancel(true); + bridge_->download_model()->download()->Remove(true); + // WARNING: we are deleted at this point. Don't access 'this'. +} + + // Sets the enabled and checked state of a particular menu item for this // download. We translate the NSMenuItem selection to menu selections understood // by the non platform specific download context menu. diff --git a/chrome/browser/cocoa/download_item_mac.h b/chrome/browser/cocoa/download_item_mac.h index f992e21..a7f41a8 100644 --- a/chrome/browser/cocoa/download_item_mac.h +++ b/chrome/browser/cocoa/download_item_mac.h @@ -51,6 +51,9 @@ class DownloadItemMac : DownloadItem::Observer { // For canceling an in progress icon request. CancelableRequestConsumerT<int, 0> icon_consumer_; + // Stores the last known name where the file will be saved. + FilePath lastFilePath_; + DISALLOW_COPY_AND_ASSIGN(DownloadItemMac); }; diff --git a/chrome/browser/cocoa/download_item_mac.mm b/chrome/browser/cocoa/download_item_mac.mm index 357c902..453e52c 100644 --- a/chrome/browser/cocoa/download_item_mac.mm +++ b/chrome/browser/cocoa/download_item_mac.mm @@ -25,6 +25,20 @@ DownloadItemMac::~DownloadItemMac() { void DownloadItemMac::OnDownloadUpdated(DownloadItem* download) { DCHECK_EQ(download, download_model_->download()); + if ([item_controller_ isDangerousMode] && + download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) { + // We have been approved. + [item_controller_ clearDangerousMode]; + } + + if (download->full_path() != lastFilePath_) { + // Turns out the file path is "unconfirmed %d.download" for dangerous + // downloads. When the download is confirmed, the file is renamed on + // another thread, so reload the icon if the download filename changes. + LoadIcon(); + lastFilePath_ = download->full_path(); + } + switch (download_model_->download()->state()) { case DownloadItem::REMOVING: [item_controller_ remove]; // We're deleted now! @@ -35,7 +49,7 @@ void DownloadItemMac::OnDownloadUpdated(DownloadItem* download) { [item_controller_ setStateFromDownload:download_model_.get()]; break; default: - NOTREACHED(); + NOTREACHED(); } } diff --git a/chrome/browser/cocoa/download_shelf_controller.h b/chrome/browser/cocoa/download_shelf_controller.h index 9ace0d3..11092b9 100644 --- a/chrome/browser/cocoa/download_shelf_controller.h +++ b/chrome/browser/cocoa/download_shelf_controller.h @@ -76,4 +76,7 @@ class DownloadShelf; // Return the height of the download shelf. - (float)height; +// Re-layouts all download items based on their current state. +- (void)layoutItems; + @end diff --git a/chrome/browser/cocoa/download_shelf_controller.mm b/chrome/browser/cocoa/download_shelf_controller.mm index 8a63da9..c449c98 100644 --- a/chrome/browser/cocoa/download_shelf_controller.mm +++ b/chrome/browser/cocoa/download_shelf_controller.mm @@ -24,12 +24,6 @@ const size_t kMaxDownloadItemCount = 16; // Border padding of a download item. const int kDownloadItemBorderPadding = 3; -// Width of a download item, must match width in DownloadItem.xib. -const int kDownloadItemWidth = 200; - -// Height of a download item, must match height in DownloadItem.xib. -const int kDownloadItemHeight = 34; - // Horizontal padding between two download items. const int kDownloadItemPadding = 10; @@ -42,6 +36,7 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; - (void)applyContentAreaOffset:(BOOL)apply; - (void)showDownloadShelf:(BOOL)enable; - (void)resizeDownloadLinkToFit; +- (void)layoutItems:(BOOL)skipFirst; @end @@ -71,7 +66,6 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( [[NSParagraphStyle defaultParagraphStyle] mutableCopy]); - // TODO(thakis): left-align for RTL languages? [paragraphStyle.get() setAlignment:NSRightTextAlignment]; NSDictionary* linkAttributes = [NSDictionary dictionaryWithObjectsAndKeys: @@ -102,7 +96,7 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; // Get width required by localized download link text. // http://developer.apple.com/documentation/Cocoa/Conceptual/TextLayout/Tasks/StringHeight.html [[showAllDownloadsLink_ textContainer] setLineFragmentPadding:0.0]; - (void)[[showAllDownloadsLink_ layoutManager]glyphRangeForTextContainer: + (void)[[showAllDownloadsLink_ layoutManager] glyphRangeForTextContainer: [showAllDownloadsLink_ textContainer]]; NSRect textRect = [[showAllDownloadsLink_ layoutManager] usedRectForTextContainer:[showAllDownloadsLink_ textContainer]]; @@ -145,8 +139,7 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; [[download view] removeFromSuperview]; [downloadItemControllers_ removeObject:download]; - // TODO(thakis): Need to relayout the remaining item views here ( - // crbug.com/17831 ). + [self layoutItems]; // Check to see if we have any downloads remaining and if not, hide the shelf. if (![downloadItemControllers_ count]) @@ -196,26 +189,32 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; return shelfHeight_; } -- (void)addDownloadItem:(BaseDownloadItemModel*)model { - // TODO(thakis): RTL support? - // (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) - // Shift all existing items to the right +// If |skipFirst| is true, the frame of the leftmost item is not set. +- (void)layoutItems:(BOOL)skipFirst { + CGFloat currentX = 0; for (DownloadItemController* itemController in downloadItemControllers_.get()) { NSRect frame = [[itemController view] frame]; - frame.origin.x += kDownloadItemWidth + kDownloadItemPadding; - [[[itemController view] animator] setFrame:frame]; + frame.origin.x = currentX; + frame.size.width = [itemController preferredSize].width; + if (!skipFirst) + [[[itemController view] animator] setFrame:frame]; + currentX += frame.size.width + kDownloadItemPadding; + skipFirst = NO; } +} +- (void)layoutItems { + [self layoutItems:NO]; +} + +- (void)addDownloadItem:(BaseDownloadItemModel*)model { // Insert new item at the left. - // Start at width 0... - NSRect position = NSMakeRect(0, kDownloadItemBorderPadding, - 0, kDownloadItemHeight); scoped_nsobject<DownloadItemController> controller( - [[DownloadItemController alloc] initWithFrame:position - model:model - shelf:self]); - [downloadItemControllers_ addObject:controller.get()]; + [[DownloadItemController alloc] initWithModel:model shelf:self]); + + // Adding at index 0 in NSMutableArrays is O(1). + [downloadItemControllers_ insertObject:controller.get() atIndex:0]; [itemContainerView_ addSubview:[controller.get() view]]; @@ -230,10 +229,13 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; name:NSViewFrameDidChangeNotification object:itemContainerView_]; - // ...then animate in - NSRect frame = [[controller.get() view] frame]; - frame.size.width = kDownloadItemWidth; + // Start at width 0... + NSSize size = [controller.get() preferredSize]; + NSRect frame = NSMakeRect(0, kDownloadItemBorderPadding, 0, size.height); + [[controller.get() view] setFrame:frame]; + // ...then animate in + frame.size.width = size.width; [NSAnimationContext beginGrouping]; [[NSAnimationContext currentContext] setDuration:kDownloadItemOpenDuration]; [[[controller.get() view] animator] setFrame:frame]; @@ -246,8 +248,13 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; // Since no user will ever see the item being removed (needs a horizontal // screen resolution greater than 3200 at 16 items at 200 pixels each), // there's no point in animating the removal. - [self remove:[downloadItemControllers_ objectAtIndex:0]]; + [self remove:[downloadItemControllers_ lastObject]]; } + + // Finally, move the remaining items to the right. Skip the first item when + // laying out the items, so that the longer animation duration we set up above + // is not overwritten. + [self layoutItems:YES]; } @end diff --git a/chrome/browser/download/download_exe.cc b/chrome/browser/download/download_exe.cc index 2663b54..39a14f7 100644 --- a/chrome/browser/download/download_exe.cc +++ b/chrome/browser/download/download_exe.cc @@ -145,7 +145,10 @@ static const char* const g_executables[] = { "py", "rb", "sh", -#endif // defined(OS_LINUX) +#elif defined(OS_MACOSX) + // TODO(thakis): Figure out what makes sense here -- crbug.com/19096 + "dmg", +#endif }; void InitializeExeTypes(std::set<std::string>* exe_extensions) { diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index 9c1cb11..a00c115 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -19,6 +19,7 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/download/download_file.h" +#include "chrome/browser/download/download_util.h" #include "chrome/browser/extensions/extension_install_ui.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/profile.h" @@ -46,11 +47,6 @@ #include "base/win_util.h" #endif -#if !defined(OS_MACOSX) -// Used for initializing the list of dangerous extensions. We don't support it -// yet on mac. -#include "chrome/browser/download/download_util.h" -#endif #if defined(OS_LINUX) #include <gtk/gtk.h> @@ -528,10 +524,8 @@ bool DownloadManager::Init(Profile* profile) { file_loop_->PostTask(FROM_HERE, NewRunnableFunction( CreateDirectoryPtr, download_path())); -#if defined(OS_WIN) || defined(OS_LINUX) // We use this to determine possibly dangerous downloads. download_util::InitializeExeTypes(&exe_types_); -#endif // We store any file extension that should be opened automatically at // download completion in this pref. @@ -1335,21 +1329,16 @@ bool DownloadManager::IsExecutableMimeType(const std::string& mime_type) { } bool DownloadManager::IsExecutable(const FilePath::StringType& extension) { -#if defined(OS_MACOSX) - // We don't have dangerous download support on mac yet. - return false; -#else if (!IsStringASCII(extension)) return false; #if defined(OS_WIN) std::string ascii_extension = WideToASCII(extension); -#elif defined(OS_LINUX) +#elif defined(OS_POSIX) std::string ascii_extension = extension; #endif StringToLowerASCII(&ascii_extension); return exe_types_.find(ascii_extension) != exe_types_.end(); -#endif // !defined(OS_MACOSX) } void DownloadManager::ResetAutoOpenFiles() { diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 26ada33..1f175c4 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -2058,7 +2058,6 @@ 'browser/bookmarks/bookmark_context_menu.cc', 'browser/bookmarks/bookmark_drop_info.cc', 'browser/dock_info.cc', - 'browser/download/download_exe.cc', 'browser/download/download_request_dialog_delegate_win.cc', 'browser/jankometer.cc', 'browser/login_prompt.cc', @@ -2846,6 +2845,7 @@ 'app/nibs/TabContents.xib', 'app/nibs/TabView.xib', 'app/nibs/Toolbar.xib', + 'app/theme/alert_small.png', 'app/theme/back_Template.pdf', 'app/theme/bookmark_bar_folder.png', 'app/theme/chevron.png', # TODO(jrg): get (and use) a pdf version |