Index: chrome/browser/ui/cocoa/share_menu/share_menu_controller.mm |
diff --git a/chrome/browser/ui/cocoa/share_menu/share_menu_controller.mm b/chrome/browser/ui/cocoa/share_menu/share_menu_controller.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f2e1cad0088412d99dd7f3cac0f084451521c7da |
--- /dev/null |
+++ b/chrome/browser/ui/cocoa/share_menu/share_menu_controller.mm |
@@ -0,0 +1,314 @@ |
+// Copyright 2015 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/ui/cocoa/share_menu/share_menu_controller.h" |
+ |
+#include "base/strings/sys_string_conversions.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "chrome/app/chrome_command_ids.h" |
+#import "chrome/browser/app_controller_mac.h" |
+#include "chrome/browser/ui/browser_commands.h" |
+#include "chrome/browser/ui/browser_finder.h" |
+#include "chrome/browser/ui/browser_list.h" |
+#include "chrome/browser/ui/browser_list_observer.h" |
+#include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h" |
+#include "chrome/browser/ui/cocoa/share_menu/share_menu_manager.h" |
+#include "chrome/browser/ui/tabs/tab_strip_model.h" |
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h" |
+#include "chrome/grit/generated_resources.h" |
+#include "skia/ext/image_operations.h" |
+#include "ui/base/l10n/l10n_util.h" |
+#include "ui/base/l10n/l10n_util_mac.h" |
+#include "ui/gfx/geometry/size_conversions.h" |
+#include "ui/gfx/geometry/vector2d_conversions.h" |
+#include "ui/gfx/skbitmap_operations.h" |
+#include "ui/snapshot/snapshot.h" |
+#include "net/base/escape.h" |
+ |
+@interface ShareMenuController() <NSSharingServiceDelegate, NSMenuDelegate> |
+- (void)buildShareItemsFor:(Browser* )browser; |
+- (NSMenuItem*)createItemWithTitle:(NSString*)title action:(SEL)sel; |
+- (void)enableShareMenuItemsFor:(Browser*)browser; |
+// Retrieve the list of possible sharing options and create menu item for each. |
+- (NSArray*)shareMenuItemsFor:(NSArray*)items; |
+- (void)setPageScreenShotFor:(content::WebContents*)contents; |
+- (void)setPageUrlFor:(content::WebContents*)contents; |
+@end |
+ |
+namespace ShareMenuControllerInternal { |
+ |
+class Observer : public chrome::BrowserListObserver,TabStripModelObserver { |
+ public: |
+ Observer(ShareMenuController* controller) : controller_(controller) { |
+ BrowserList::AddObserver(this); |
+ } |
+ |
+ ~Observer() override { |
+ BrowserList::RemoveObserver(this); |
+ } |
+ |
+ void OnBrowserAdded(Browser* browser) override { |
+ tab_strip_ = browser->tab_strip_model(); |
+ tab_strip_->AddObserver(this); |
+ } |
+ |
+ void OnBrowserRemoved(Browser* browser) override { |
+ tab_strip_->RemoveObserver(this); |
+ } |
+ |
+ // Wait for a browser tab to become active before building the share menu. |
+ void OnBrowserSetLastActive(Browser* browser) override { |
+ [controller_ setActiveBrowser:browser]; |
+ if (browser && ![controller_ menuItemsLoaded]) { |
+ [controller_ initShareMenuItem]; |
+ [controller_ buildShareItemsFor:browser]; |
+ } |
+ LOG(ERROR) << "page refreshed"; |
+ [controller_ enableShareMenuItemsFor:browser]; |
+ [controller_ setPageContents:tab_strip_->GetActiveWebContents()]; |
+ } |
+ // When a detached tab / or a NTP is added to the tabstrip update webcontents. |
+ void TabInsertedAt(content::WebContents* contents, |
+ int index, |
+ bool foreground) override { |
+ [controller_ setPageUrlFor:contents]; |
+ [controller_ setPageContents:contents]; |
+ } |
+ |
+ // When tabs are switched update webcontents. |
+ void TabSelectionChanged(TabStripModel* tab_strip_model, |
+ const ui::ListSelectionModel& old_model) override { |
+ [controller_ setPageContents:tab_strip_->GetActiveWebContents()]; |
+ Browser* browser = chrome::GetLastActiveBrowser(); |
+ [controller_ enableShareMenuItemsFor:browser]; |
+ LOG(ERROR) << "Tabs switched"; |
+ } |
+ |
+ void TabChangedAt(content::WebContents* contents, |
+ int index, |
+ TabChangeType change_type) override { |
+ LOG(ERROR) << "Tab contents changed"; |
+ [controller_ setPageContents:contents]; |
+ } |
+ |
+ private: |
+ ShareMenuController* controller_; // Weak; owns this. |
+ TabStripModel* tab_strip_; |
+ }; |
+ |
+} // namespace ShareMenuControllerInternal |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+ |
+@implementation ShareMenuController |
+ |
+- (id)initWithMainMenu:(NSMenu*)menu { |
+ if (self = [super init]) { |
+ mainMenu_ = menu; |
+ shareItems_.reset([[NSMutableArray alloc] init]); |
+ pageInfo_.reset([[NSMutableDictionary alloc] init]); |
+ menuItemsLoaded_ = NO; |
+ observer_.reset(new ShareMenuControllerInternal::Observer(self)); |
+ } |
+ return self; |
+} |
+ |
+- (BOOL) menuItemsLoaded { |
+ return menuItemsLoaded_; |
+} |
+ |
+- (void)setPageContents:(content::WebContents*)contents { |
+ pageContents_ = contents; |
+} |
+ |
+- (void)setActiveBrowser:(Browser*)browser { |
+ lastActiveBrowser_ = browser; |
+} |
+ |
+- (void)rebuildShareMenu { |
+ //[shareSubMenu_ removeAllItems]; |
+ //[self buildShareItemsFor:lastActiveBrowser_]; |
+} |
+ |
+// Create a submenu for displaying various system wide sharing options. |
+- (void)initShareMenuItem { |
+ shareSubMenu_.reset([[NSMenu alloc] initWithTitle:@"ShareSubMenu"]); |
+ fileMenuItem_ = [mainMenu_ itemWithTag:IDC_FILE_MENU]; |
+ NSString* shareMenuName = |
+ l10n_util::GetNSStringWithFixup(IDS_SHARE_MENU_MAC); |
+ shareMenuItem_ = [self createItemWithTitle:shareMenuName action:nil]; |
+ [shareMenuItem_ setTag:IDC_SHARE_MENU]; |
+} |
+ |
+- (NSMenu*)shareSubMenu { |
+ return shareSubMenu_; |
+} |
+ |
+- (NSMenuItem*)shareSubMenuItem { |
+ return shareMenuItem_; |
+} |
+ |
+- (void)buildShareItemsFor:(Browser*)browser { |
+ if (!shareSubMenu_) |
+ return; |
+ |
+ [shareItems_ addObject:pageUrlForCurrentTab_]; |
+ NSArray* menuItems = [self shareMenuItemsFor:shareItems_]; |
+ for (NSMenuItem* item in menuItems) { |
+ [shareSubMenu_ addItem:item]; |
+ } |
+ |
+ // Add the Share Menu Item. |
+ NSMenuItem* savePageItem = [[fileMenuItem_ submenu] |
+ itemWithTag:IDC_SAVE_PAGE]; |
+ NSInteger idxSavePage = [[fileMenuItem_ submenu] indexOfItem:savePageItem]; |
+ [[fileMenuItem_ submenu] insertItem:shareMenuItem_ atIndex:idxSavePage + 2]; |
+ |
+ // Remove the Email Page location Menu Item. |
+ NSMenuItem* emailPageItem = [[fileMenuItem_ submenu] |
+ itemWithTag:IDC_EMAIL_PAGE_LOCATION]; |
+ [[fileMenuItem_ submenu] removeItem:emailPageItem]; |
+ |
+ [[fileMenuItem_ submenu] setSubmenu:shareSubMenu_ forItem:shareMenuItem_]; |
+ menuItemsLoaded_ = YES; |
+} |
+ |
+- (NSMenuItem*)createItemWithTitle:(NSString*)title action:(SEL)sel { |
+ NSMenuItem* item = [[[NSMenuItem alloc] initWithTitle:title action:sel |
+ keyEquivalent:@""] |
+ autorelease]; |
+ [item setTarget:self]; |
+ return item; |
+} |
+ |
+- (void)enableShareMenuItemsFor:(Browser*)browser { |
+ [shareSubMenu_ setAutoenablesItems:NO]; |
+ for (NSMenuItem* item in [shareSubMenu_ itemArray]) { |
+ BOOL enabled = chrome::CanEmailPageLocation(browser) ? |
+ [self validateMenuItem:item] : NO; |
+ [item setEnabled:enabled]; |
+ } |
+} |
+ |
+- (NSArray*)shareMenuItemsFor:(NSArray*)items { |
+ base::scoped_nsobject<NSMutableArray> |
+ menuItems([[NSMutableArray alloc] init]); |
+ NSArray *sharingServices = [NSSharingService sharingServicesForItems:items]; |
+ //originalSharableItems_.reset([[NSArray alloc] initWithArray:sharingServices]); |
+ for (NSSharingService* currentService in sharingServices) { |
+ NSString* titleText = nil; |
+ if ([currentService isEqualTo:[NSSharingService sharingServiceNamed |
+ : NSSharingServiceNameComposeEmail]]) { |
+ titleText = l10n_util::GetNSString(IDS_EMAIL_PAGE_LOCATION_MAC); |
+ } else { |
+ titleText = currentService.title; |
+ } |
+ NSMenuItem* item = [self createItemWithTitle:titleText |
+ action:@selector( |
+ systemShareService:)]; |
+ item.image = currentService.image; |
+ item.representedObject = currentService; |
+ [item setTarget:self]; |
+ currentService.delegate = self; |
+ [menuItems addObject:item]; |
+ } |
+ |
+ // Add the AirDrop menu item. |
+ NSMenuItem* item = nil; |
+ NSSharingService* customService = nil; |
+ customService = [NSSharingService sharingServiceNamed |
+ :NSSharingServiceNameSendViaAirDrop]; |
+ item = [self createItemWithTitle:customService.title |
+ action:@selector( |
+ systemShareService:)]; |
+ item.image = customService.image; |
+ item.representedObject = customService; |
+ [item setTarget:self]; |
+ customService.delegate = self; |
+ [menuItems addObject:item]; |
+ |
+ // Add a menu item to open up system share panel. |
+ customService = [[NSSharingService alloc] initWithTitle:@"More" |
+ image:nil |
+ alternateImage:nil |
+ handler:nil]; |
+ item = [self createItemWithTitle:customService.title |
+ action:@selector( |
+ systemShareService:)]; |
+ item.representedObject = customService; |
+ [item setTarget:self]; |
+ customService.delegate = self; |
+ [menuItems addObject:item]; |
+ |
+ return [NSArray arrayWithArray:menuItems]; |
+} |
+ |
+- (void)setPageScreenShotFor:(content::WebContents*)contents { |
+ scoped_ptr<std::vector<unsigned char> > png_representation( |
+ new std::vector<unsigned char>); |
+ NSView* webView = contents->GetNativeView(); |
+ NSRect frame = [webView frame]; |
+ gfx::Rect bounds(frame.origin.x, frame.origin.y, frame.size.width, |
+ frame.size.height); |
+ if (ui::GrabViewSnapshot( |
+ contents->GetNativeView(), png_representation.get(), bounds)) { |
+ base::scoped_nsobject<NSData> image_data( |
+ [[NSData alloc] initWithBytes:&(*png_representation)[0] |
+ length:png_representation->size()]); |
+ contentSnapShot_.reset([[NSImage alloc] initWithData:image_data]); |
+ NSURL* pageUrl = [NSURL URLWithString:pageUrlForCurrentTab_]; |
+ base::scoped_nsobject<NSData> pageData([[NSData alloc] |
+ initWithContentsOfURL:pageUrl]); |
+ NSLog(@"page url %@", pageUrlForCurrentTab_); |
+ page_.reset([[NSString alloc] initWithData:pageData |
+ encoding:NSUTF8StringEncoding]); |
+ pageHtml_.reset([[NSMutableAttributedString alloc] |
+ initWithData:pageData.get() documentAttributes:nil]); |
+ //NSLog(@"page html size %ld", [pageHtml_ length]); |
+ } |
+} |
+ |
+- (void)setPageUrlFor:(content::WebContents*)contents { |
+ std::string pageUrl = contents->GetVisibleURL().spec(); |
+ pageUrlForCurrentTab_ = base::SysUTF8ToNSString(pageUrl); |
+} |
+ |
+- (BOOL)validateMenuItem:(NSMenuItem *)menuItem { |
+ return ([menuItem action] == @selector(systemShareService:)); |
+} |
+ |
+- (void)systemShareService:(id)sender { |
+ NSMenuItem* currentMenuItem = (NSMenuItem*)sender; |
+ [self setPageUrlFor:pageContents_]; |
+ [self setPageScreenShotFor:pageContents_]; |
+ pageInfo_.reset([[NSDictionary alloc] |
+ initWithObjectsAndKeys:pageUrlForCurrentTab_, kPageUrl, |
+ contentSnapShot_.get(), kPageScreenShot, |
+ pageHtml_.get(), kPageHtml,nil]); |
+ |
+ [ShareMenuManager dispatchSharingServiceEventsFor: |
+ currentMenuItem.representedObject AndPageInfo:pageInfo_]; |
+} |
+ |
+// Sharing Service delegate methods. |
+- (NSRect)sharingService:(NSSharingService*)sharingService |
+ sourceFrameOnScreenForShareItem:(id<NSPasteboardWriting>)item { |
+ if (![item isKindOfClass:[NSImage class]]) |
+ return NSZeroRect; |
+ |
+ NSView* webView = pageContents_->GetNativeView(); |
+ NSRect frame = [webView frame]; |
+ return frame; |
+} |
+ |
+- (NSImage *)sharingService:(NSSharingService*)sharingService |
+ transitionImageForShareItem:(id<NSPasteboardWriting>)item |
+ contentRect:(NSRect *)contentRect { |
+ if (![item isKindOfClass:[NSImage class]]) |
+ return nil; |
+ |
+ return contentSnapShot_.get(); |
+} |
+ |
+@end |