| 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
|
|
|