Index: ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.mm |
diff --git a/ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.mm b/ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.mm |
index fade9f30af58ed9a648d0c6941780f080649daef..a9e3bc71a7d5bcbafc817f84bd7dab1046806448 100644 |
--- a/ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.mm |
+++ b/ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.mm |
@@ -4,41 +4,190 @@ |
#import "ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.h" |
+#include <objc/runtime.h> |
+ |
+#import "ios/clean/chrome/browser/ui/commands/context_menu_commands.h" |
#import "ios/clean/chrome/browser/ui/context_menu/context_menu_consumer.h" |
+#import "ios/web/public/url_scheme_util.h" |
#import "ios/web/public/web_state/context_menu_params.h" |
#if !defined(__has_feature) || !__has_feature(objc_arc) |
#error "This file requires ARC support." |
#endif |
-@interface ContextMenuMediator () |
-@property(nonatomic, weak) id<ContextMenuConsumer> consumer; |
+@interface ContextMenuMediator () { |
+ // Backing object for |params|. |
+ web::ContextMenuParams _params; |
marq (ping after 24h)
2017/05/04 09:41:28
Why doesn't property autosynthesis take care of th
kkhorimoto
2017/05/05 05:17:54
I'm doing something similar for the new ContextMen
|
+} |
+ |
+// The consumer for context menu functionality mediated by this class. |
+@property(nonatomic, readonly, weak) id<ContextMenuConsumer> consumer; |
+// The ContextMenuParams passed on initialization. |
+@property(nonatomic, readonly) web::ContextMenuParams& params; |
+// Whether this context menu is for an Incognito browser. |
+@property(nonatomic, readonly, getter=isIncognito) BOOL incognito; |
+ |
+// Updates |consumer| using the data from |params|. |
+- (void)updateConsumer; |
+ |
+// Creates an NSInvocation from one of the ContextMenuCommands navigaiton |
+// selectors, using |URL| as the input parameter. |
+- (NSInvocation*)newContextMenuCommandWithSelector:(SEL)selector URL:(GURL&)URL; |
+ |
+// ContextMenuItem factory methods. Each method corresponds to a command in |
+// ContextMenuCommands. The methods will return a ContextMenuItem if its |
+// corresponding command is appropriate for |params|, or nil otherwise. |
+- (ContextMenuItem*)newOpenJavaScriptItem; |
+- (ContextMenuItem*)newOpenInNewTabItem; |
+- (ContextMenuItem*)newOpenInNewIncognitoTabItem; |
+- (ContextMenuItem*)newCopyURLItem; |
+- (ContextMenuItem*)newSaveImageItem; |
+- (ContextMenuItem*)newOpenImageItem; |
+- (ContextMenuItem*)newOpenImageInNewTabItem; |
+ |
@end |
@implementation ContextMenuMediator |
@synthesize consumer = _consumer; |
+@synthesize incognito = _incognito; |
-- (instancetype)initWithConsumer:(id<ContextMenuConsumer>)consumer { |
+- (instancetype)initWithConsumer:(id<ContextMenuConsumer>)consumer |
+ contextMenuParams:(const web::ContextMenuParams&)params |
+ isIncognito:(BOOL)isIncognito { |
if ((self = [super init])) { |
_consumer = consumer; |
+ _params = params; |
+ _incognito = isIncognito; |
[self updateConsumer]; |
} |
return self; |
} |
-// Update the consumer. |
+#pragma mark - Accessors |
+ |
+- (web::ContextMenuParams&)params { |
+ return _params; |
+} |
+ |
+#pragma mark - |
+ |
- (void)updateConsumer { |
- // PLACEHOLDER. Fake title. |
- [self.consumer setContextMenuTitle:@"http://some/link.html"]; |
+ // Use the menu title provided by |params|. |
+ [self.consumer setContextMenuTitle:self.params.menu_title]; |
+ |
+ // Create context menu items. |
NSMutableArray<ContextMenuItem*>* items = |
[[NSMutableArray<ContextMenuItem*> alloc] init]; |
- |
- // PLACEHOLDER. Two non-functional items. |
- [items |
- addObject:[ContextMenuItem itemWithTitle:@"Open in New Tab" command:nil]]; |
- [items |
- addObject:[ContextMenuItem itemWithTitle:@"Copy Link URL" command:nil]]; |
+ ContextMenuItem* item = nil; |
+ if ((item = [self newOpenJavaScriptItem])) |
+ [items addObject:item]; |
+ if ((item = [self newOpenInNewTabItem])) |
+ [items addObject:item]; |
+ if ((item = [self newOpenInNewIncognitoTabItem])) |
+ [items addObject:item]; |
+ if ((item = [self newCopyURLItem])) |
+ [items addObject:item]; |
+ if ((item = [self newSaveImageItem])) |
+ [items addObject:item]; |
+ if ((item = [self newOpenImageItem])) |
+ [items addObject:item]; |
+ if ((item = [self newOpenImageInNewTabItem])) |
+ [items addObject:item]; |
[self.consumer setContextMenuItems:[items copy]]; |
} |
+- (NSInvocation*)newContextMenuCommandWithSelector:(SEL)selector |
+ URL:(GURL&)URL { |
+ struct objc_method_description methodDescription = |
+ protocol_getMethodDescription(@protocol(ContextMenuCommands), selector, |
+ YES /* isRequiredMethod */, |
+ YES /* isInstanceMethod */); |
+ NSMethodSignature* signature = |
+ [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; |
+ NSInvocation* command = |
+ [NSInvocation invocationWithMethodSignature:signature]; |
+ command.selector = selector; |
+ // NSInvocation's |-setArgument:atIndex:| does not work properly for copying |
+ // C++ objects or C++ object references, so the URL is passed by pointer. |
kkhorimoto
2017/05/04 05:38:01
I know that you want to use NSInvocations here to
marq (ping after 24h)
2017/05/04 09:41:28
There are a couple of alternatives.
(1) Don't use
kkhorimoto
2017/05/05 05:17:54
I went with approach (1). Instead of NSInvocation
|
+ GURL* URLPtr = &URL; |
+ [command setArgument:&URLPtr atIndex:2]; |
+ return command; |
+} |
+ |
+- (ContextMenuItem*)newOpenJavaScriptItem { |
+ GURL& URL = self.params.link_url; |
+ if (!URL.is_valid() || !URL.SchemeIs(url::kJavaScriptScheme)) |
+ return nil; |
+ NSString* title = @"Open JavaScript"; |
+ NSInvocation* command = |
+ [self newContextMenuCommandWithSelector:@selector(openJavaScriptURL:) |
+ URL:URL]; |
+ return [ContextMenuItem itemWithTitle:title command:command]; |
+} |
+ |
+- (ContextMenuItem*)newOpenInNewTabItem { |
+ GURL& URL = self.params.link_url; |
+ if (!URL.is_valid() || !web::UrlHasWebScheme(URL)) |
+ return nil; |
+ NSString* title = @"Open In New Tab"; |
+ NSInvocation* command = |
+ [self newContextMenuCommandWithSelector:@selector(openURLInNewTab:) |
+ URL:URL]; |
+ return [ContextMenuItem itemWithTitle:title command:command]; |
+} |
+ |
+- (ContextMenuItem*)newOpenInNewIncognitoTabItem { |
+ GURL& URL = self.params.link_url; |
+ if (!URL.is_valid() || !web::UrlHasWebScheme(URL) || self.incognito) |
+ return nil; |
+ NSString* title = @"Open In New Incognito Tab"; |
+ NSInvocation* command = [self |
+ newContextMenuCommandWithSelector:@selector(openURLInNewIncognitoTab:) |
+ URL:URL]; |
+ return [ContextMenuItem itemWithTitle:title command:command]; |
+} |
+ |
+- (ContextMenuItem*)newCopyURLItem { |
+ GURL& URL = self.params.link_url; |
+ if (!URL.is_valid() || !web::UrlHasWebScheme(URL)) |
+ return nil; |
+ NSString* title = @"Copy Link"; |
+ NSInvocation* command = |
+ [self newContextMenuCommandWithSelector:@selector(copyURL:) URL:URL]; |
+ return [ContextMenuItem itemWithTitle:title command:command]; |
+} |
+ |
+- (ContextMenuItem*)newSaveImageItem { |
+ GURL& imageURL = self.params.src_url; |
+ if (!imageURL.is_valid()) |
+ return nil; |
+ NSString* title = @"Save Image"; |
+ NSInvocation* command = |
+ [self newContextMenuCommandWithSelector:@selector(saveImageAtURL:) |
+ URL:imageURL]; |
+ return [ContextMenuItem itemWithTitle:title command:command]; |
+} |
+ |
+- (ContextMenuItem*)newOpenImageItem { |
+ GURL& imageURL = self.params.src_url; |
+ if (!imageURL.is_valid()) |
+ return nil; |
+ NSString* title = @"Open Image"; |
+ NSInvocation* command = |
+ [self newContextMenuCommandWithSelector:@selector(openImageAtURL:) |
+ URL:imageURL]; |
+ return [ContextMenuItem itemWithTitle:title command:command]; |
+} |
+ |
+- (ContextMenuItem*)newOpenImageInNewTabItem { |
+ GURL& imageURL = self.params.src_url; |
+ if (!imageURL.is_valid()) |
+ return nil; |
+ NSString* title = @"Open Image In New Tab"; |
+ NSInvocation* command = |
+ [self newContextMenuCommandWithSelector:@selector(openImageAtURLInNewTab:) |
+ URL:imageURL]; |
+ return [ContextMenuItem itemWithTitle:title command:command]; |
+} |
+ |
@end |