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>