JavaScriptからWebKit Plug-Inに値を渡す方法
JavaScriptからWebKit Plug-InのObjective-Cへ値を渡すにはどうすれば良いかやってみた。
Objective-Cのソース
TestPluginView.h
#import <Cocoa/Cocoa.h> #define pluginDebug ( 1 ) #if pluginDebug #define PDEBUG(format,...) NSLog( @"Plug-in: File=%s line=%d proc=%s " format, strrchr("/" __FILE__,'/')+1, __LINE__, __PRETTY_FUNCTION__, ## __VA_ARGS__ ) #else #define PDEBUG(format,...) #endif @interface TestPluginView : NSView <WebPlugInViewFactory> { NSObject * strValue1 ; NSNumber* intValue1 ; } - (void)method1 ; - (void)showVariable ; - (NSString*)strValue1 ; - (void)setStrValue1:(NSObject*)val ; - (NSNumber*)intValue1 ; - (void)setIntValue1:(NSNumber*)val ; @end
TestPluginView.m
#import "TestPluginView.h" @interface TestPluginView (Internal) - (id)_initWithArguments:(NSDictionary *)arguments; @end @implementation TestPluginView // WebPlugInViewFactory protocol // The principal class of the plug-in bundle must implement this protocol. + (NSView *)plugInViewWithArguments:(NSDictionary *)newArguments { return [[[self alloc] _initWithArguments:newArguments] autorelease]; } // WebPlugIn informal protocol - (void)webPlugInInitialize { // This method will be only called once per instance of the plug-in object, and will be called // before any other methods in the WebPlugIn protocol. // You are not required to implement this method. It may safely be removed. } - (void)webPlugInStart { // The plug-in usually begins drawing, playing sounds and/or animation in this method. // You are not required to implement this method. It may safely be removed. } - (void)webPlugInStop { // The plug-in normally stop animations/sounds in this method. // You are not required to implement this method. It may safely be removed. } - (void)webPlugInDestroy { // Perform cleanup and prepare to be deallocated. // You are not required to implement this method. It may safely be removed. } - (void)webPlugInSetIsSelected:(BOOL)isSelected { // This is typically used to allow the plug-in to alter its appearance when selected. // You are not required to implement this method. It may safely be removed. } - (id)objectForWebScript { // Returns the object that exposes the plug-in's interface. The class of this object can implement // methods from the WebScripting informal protocol. // You are not required to implement this method. It may safely be removed. return self; } + (BOOL)isSelectorExcludedFromWebScript:(SEL)selector { if(selector == @selector(method1)) { return NO; } if(selector == @selector(showVariable)) { return NO; } if(selector == @selector(setStrValue1:)) { return NO; } if(selector == @selector(setIntValue1:)) { return NO; } return YES; } + (BOOL)isKeyExcludedFromWebScript:(const char *)property { if (strcmp(property, "strValue1") == 0) { return NO; } if (strcmp(property, "intValue1") == 0) { return NO; } return YES; } - (NSArray *)attributeKeys { return [NSArray arrayWithObjects:@"strValue1",@"intValue1",nil]; } + (NSString *)webScriptNameForSelector:(SEL)aSelector { if ( aSelector == @selector(setStrValue1:) ) { return @"setStrValue1"; } if ( aSelector == @selector(setIntValue1:) ) { return @"setIntValue1"; } else { return nil; } } //================================================================== - (void)method1 { NSLog(@"TestPluginView#method1 ---------- <start>") ; strValue1 = @"BBB" ; NSLog(@"TestPluginView#method1 ---------- <end>") ; } - (void)showVariable { NSLog(@"TestPluginView#showVariable ---------- <start>") ; NSLog(@"TestPluginView#showVariable ---------- strValue1 class name : %@",[strValue1 className]) ; NSLog(@"TestPluginView#showVariable ---------- intValue1 class name : %@",[intValue1 className]) ; NSLog(@"strValue1 : %@",strValue1) ; NSLog(@"intValue1 : %d",[intValue1 intValue]) ; NSLog(@"TestPluginView#showVariable ---------- <end>") ; } - (NSString*)strValue1 { NSLog(@"TestPluginView#strValue1 ---------- <start>") ; return [[strValue1 retain] autorelease]; } - (void)setStrValue1:(NSObject*)val { NSLog(@"TestPluginView#setStrValue1 ---------- <start>") ; NSLog(@"TestPluginView#setStrValue1 class name : %@",[val className]) ; NSLog(@"TestPluginView#setIntValue1 val : %@",val) ; if (strValue1 != val) { [strValue1 release]; strValue1 = [val copy]; } NSLog(@"TestPluginView#setStrValue1 ---------- strValue1 retainCount : %d",[strValue1 retainCount]) ; NSLog(@"TestPluginView#setStrValue1 ---------- strValue1 : %@",strValue1) ; NSLog(@"TestPluginView#setStrValue1 ---------- <end>") ; } - (NSNumber*)intValue1 { return [[intValue1 retain] autorelease]; } - (void)setIntValue1:(NSNumber*)val { NSLog(@"TestPluginView#setIntValue1 ---------- <start>") ; NSLog(@"TestPluginView#setIntValue1 class name : %@",[val className]) ; NSLog(@"TestPluginView#setIntValue1 val : %d",[val intValue]) ; if (intValue1 != val) { [intValue1 release]; intValue1 = [val copy]; } NSLog(@"TestPluginView#setIntValue1 ---------- intValue1 retainCount : %d",[strValue1 retainCount]) ; NSLog(@"TestPluginView#setIntValue1 ---------- strValue1 : %d",[intValue1 intValue]) ; NSLog(@"TestPluginView#setIntValue1 ---------- <end>") ; } @end @implementation TestPluginView (Internal) - (id)_initWithArguments:(NSDictionary *)newArguments { NSLog(@"TestPluginView#_initWithArguments <start>") ; if (!(self = [super initWithFrame:NSZeroRect])) return nil; NSLog(@"newArguments : %@",newArguments) ; NSLog(@"TestPluginView#_initWithArguments <end>") ; return self; } @end
JavaScriptのソース
test.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"> <html> <head> <title>Sample WebKit Safari Plug-In</title> </head> <script LANGUAGE="JavaScript"> // 変数の値を見る function test1_show_variable() { // OK // alert("test1_show_variable--1") ; var plugin = document.embeds["Test1Plugin"]; plugin.showVariable(); // alert("test1_show_variable--2") ; } // method1を実行 function test1_method1() { // OK var plugin = document.embeds["Test1Plugin"]; // TestPluginViewの(void)method1 が呼ばれる plugin.method1(); plugin.showVariable(); } function test1_method2() { // OK var plugin = document.embeds["Test1Plugin"]; // TestPluginViewの(void)setStrValue1:(NSObject*)valが呼ばれる plugin.strValue1 = "AAAA" ; plugin.showVariable(); } function test1_method3() { // OK var plugin = document.embeds["Test1Plugin"]; // TestPluginViewの(void)setIntValue1:(NSNumber*)valが呼ばれる plugin.intValue1 = 2 ; plugin.showVariable(); } // 文字列をメソッドの引数で渡す function test1_set_strval1() { // OK var plugin = document.embeds["Test1Plugin"]; // TestPluginViewの(void)setStrValue1:(NSObject*)valが呼ばれる plugin.setStrValue1("CCCCC"); plugin.showVariable(); } // 数値をメソッドの引数で渡す function test1_set_intval1() { // OK var plugin = document.embeds["Test1Plugin"]; // TestPluginViewの(void)setIntValue1:(NSNumber*)val plugin.setIntValue1(10); plugin.showVariable(); } </script> <body> <embed name="Test1Plugin" width="100" height="80" type="application/x-test1-plugin"></embed> <form action="" method="post"> <input type=button value="変数の値を見る" onClick="test1_show_variable()"> <input type=button value="method1を実行" onClick="test1_method1()"> <input type=button value="method2を実行" onClick="test1_method2()"> <input type=button value="method3を実行" onClick="test1_method3()"> <input type=button value="文字列をメソッドの引数で渡す" onClick="test1_set_strval1()"> <input type=button value="数値をメソッドの引数で渡す" onClick="test1_set_intval1()"> </form> </body> </html>
実行結果
「method1を実行」ボタンの実行結果のコンソール出力
09/09/13 22:33:59 Safari[4768] TestPluginView#method1 ---------- <start> 09/09/13 22:33:59 Safari[4768] TestPluginView#method1 ---------- <end> 09/09/13 22:33:59 Safari[4768] TestPluginView#showVariable ---------- <start> 09/09/13 22:33:59 Safari[4768] TestPluginView#showVariable ---------- strValue1 class name : NSCFString 09/09/13 22:33:59 Safari[4768] TestPluginView#showVariable ---------- intValue1 class name : (null) 09/09/13 22:33:59 Safari[4768] strValue1 : BBB 09/09/13 22:33:59 Safari[4768] intValue1 : 0 09/09/13 22:33:59 Safari[4768] TestPluginView#showVariable ---------- <end>
「method2を実行」ボタンの実行結果のコンソール出力
09/09/13 22:34:44 Safari[4768] TestPluginView#setStrValue1 ---------- <start> 09/09/13 22:34:44 Safari[4768] TestPluginView#setStrValue1 class name : NSCFString 09/09/13 22:34:44 Safari[4768] TestPluginView#setIntValue1 val : AAAA 09/09/13 22:34:44 Safari[4768] TestPluginView#setStrValue1 ---------- strValue1 retainCount : 2 09/09/13 22:34:44 Safari[4768] TestPluginView#setStrValue1 ---------- strValue1 : AAAA 09/09/13 22:34:44 Safari[4768] TestPluginView#setStrValue1 ---------- <end> 09/09/13 22:34:44 Safari[4768] TestPluginView#showVariable ---------- <start> 09/09/13 22:34:44 Safari[4768] TestPluginView#showVariable ---------- strValue1 class name : NSCFString 09/09/13 22:34:44 Safari[4768] TestPluginView#showVariable ---------- intValue1 class name : (null) 09/09/13 22:34:44 Safari[4768] strValue1 : AAAA 09/09/13 22:34:44 Safari[4768] intValue1 : 0 09/09/13 22:34:44 Safari[4768] TestPluginView#showVariable ---------- <end>
「method3を実行」ボタンの実行結果のコンソール出力
09/09/13 22:35:05 Safari[4768] TestPluginView#setIntValue1 ---------- <start> 09/09/13 22:35:05 Safari[4768] TestPluginView#setIntValue1 class name : NSCFNumber 09/09/13 22:35:05 Safari[4768] TestPluginView#setIntValue1 val : 2 09/09/13 22:35:05 Safari[4768] TestPluginView#setIntValue1 ---------- intValue1 retainCount : 1 09/09/13 22:35:05 Safari[4768] TestPluginView#setIntValue1 ---------- strValue1 : 2 09/09/13 22:35:05 Safari[4768] TestPluginView#setIntValue1 ---------- <end> 09/09/13 22:35:05 Safari[4768] TestPluginView#showVariable ---------- <start> 09/09/13 22:35:05 Safari[4768] TestPluginView#showVariable ---------- strValue1 class name : NSCFString 09/09/13 22:35:05 Safari[4768] TestPluginView#showVariable ---------- intValue1 class name : NSCFNumber 09/09/13 22:35:05 Safari[4768] strValue1 : AAAA 09/09/13 22:35:05 Safari[4768] intValue1 : 2 09/09/13 22:35:05 Safari[4768] TestPluginView#showVariable ---------- <end>
「文字列をメソッドの引数で渡す」ボタンの実行結果のコンソール出力
09/09/13 22:35:38 Safari[4768] TestPluginView#setStrValue1 ---------- <start> 09/09/13 22:35:38 Safari[4768] TestPluginView#setStrValue1 class name : NSCFString 09/09/13 22:35:38 Safari[4768] TestPluginView#setIntValue1 val : CCCCC 09/09/13 22:35:38 Safari[4768] TestPluginView#setStrValue1 ---------- strValue1 retainCount : 2 09/09/13 22:35:38 Safari[4768] TestPluginView#setStrValue1 ---------- strValue1 : CCCCC 09/09/13 22:35:38 Safari[4768] TestPluginView#setStrValue1 ---------- <end> 09/09/13 22:35:38 Safari[4768] TestPluginView#showVariable ---------- <start> 09/09/13 22:35:38 Safari[4768] TestPluginView#showVariable ---------- strValue1 class name : NSCFString 09/09/13 22:35:38 Safari[4768] TestPluginView#showVariable ---------- intValue1 class name : NSCFNumber 09/09/13 22:35:38 Safari[4768] strValue1 : CCCCC 09/09/13 22:35:38 Safari[4768] intValue1 : 2 09/09/13 22:35:38 Safari[4768] TestPluginView#showVariable ---------- <end>
「数値をメソッドの引数で渡す」ボタンの実行結果のコンソール出力
09/09/13 22:39:16 Safari[4768] TestPluginView#setIntValue1 ---------- <start> 09/09/13 22:39:16 Safari[4768] TestPluginView#setIntValue1 class name : NSCFNumber 09/09/13 22:39:16 Safari[4768] TestPluginView#setIntValue1 val : 10 09/09/13 22:39:16 Safari[4768] TestPluginView#setIntValue1 ---------- intValue1 retainCount : 1 09/09/13 22:39:16 Safari[4768] TestPluginView#setIntValue1 ---------- strValue1 : 10 09/09/13 22:39:16 Safari[4768] TestPluginView#setIntValue1 ---------- <end> 09/09/13 22:39:16 Safari[4768] TestPluginView#showVariable ---------- <start> 09/09/13 22:39:16 Safari[4768] TestPluginView#showVariable ---------- strValue1 class name : NSCFString 09/09/13 22:39:16 Safari[4768] TestPluginView#showVariable ---------- intValue1 class name : NSCFNumber 09/09/13 22:39:16 Safari[4768] strValue1 : CCCCC 09/09/13 22:39:16 Safari[4768] intValue1 : 10 09/09/13 22:39:16 Safari[4768] TestPluginView#showVariable ---------- <end>