<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>へびにっき &#187; Greasemonkey</title>
	<atom:link href="http://wp.serpere.info/archives/tag/greasemonkey/feed" rel="self" type="application/rss+xml" />
	<link>http://wp.serpere.info</link>
	<description>樹上で暮らすヘビのように生きたい</description>
	<lastBuildDate>Mon, 06 Sep 2010 07:43:34 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>XPCNativeWrapperとunsafeWindowの間で同期処理を行う</title>
		<link>http://wp.serpere.info/archives/1110</link>
		<comments>http://wp.serpere.info/archives/1110#comments</comments>
		<pubDate>Sat, 30 Jan 2010 04:06:00 +0000</pubDate>
		<dc:creator>tkyk</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Greasemonkey]]></category>

		<guid isPermaLink="false">http://wp.serpere.info/?p=1110</guid>
		<description><![CDATA[先日使い方を学んだ MessageEvent と、location.href+javascript:ハックとJSDeferred userscript版とを組み合わせ、XPCNativeWrapper と unsafeWindow の間で同期処理を行うコードを書いてみた。 まずは MessageEvent を使って前回 evalInPage 相当の処理を作る。キャンセル処理も入れたかったので UnsafeWrapper というオブジェクトにまとめることにした。前回より長くなったように見えるが、実際には MessageEvent の lastEventId が使えるようになった分、簡潔になっている。 var UnsafeWrapper = new &#40;function&#40;&#41; &#123; var seqId = 0, waiting = &#123;&#125;, self = this, noop = function&#40;&#41;&#123;&#125;; &#160; function dispatch&#40;data, id&#41; &#123; var e = document.createEvent&#40;&#34;MessageEvent&#34;&#41;; e.initMessageEvent&#40;'GM_UnsafeWrapper_returned', true, false, data, location.protocol + &#34;//&#34; + location.host, [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwp.serpere.info%252Farchives%252F1110%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2FcfbBWG%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22XPCNativeWrapper%E3%81%A8unsafeWindow%E3%81%AE%E9%96%93%E3%81%A7%E5%90%8C%E6%9C%9F%E5%87%A6%E7%90%86%E3%82%92%E8%A1%8C%E3%81%86%22%20%7D);"></div>
<p>
<a href="http://wp.serpere.info/archives/1107">先日</a>使い方を学んだ MessageEvent と、location.href+javascript:ハックと<a href="http://github.com/cho45/jsdeferred">JSDeferred</a> userscript版とを組み合わせ、XPCNativeWrapper と unsafeWindow の間で同期処理を行うコードを書いてみた。
</p>
<p>
まずは MessageEvent を使って前回 evalInPage 相当の処理を作る。キャンセル処理も入れたかったので UnsafeWrapper というオブジェクトにまとめることにした。前回より長くなったように見えるが、実際には MessageEvent の lastEventId が使えるようになった分、簡潔になっている。
</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> UnsafeWrapper <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> seqId <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> waiting <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> self <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> noop <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">function</span> dispatch<span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> id<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #003366; font-weight: bold;">var</span> e <span style="color: #339933;">=</span> document.<span style="color: #660066;">createEvent</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;MessageEvent&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    e.<span style="color: #660066;">initMessageEvent</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'GM_UnsafeWrapper_returned'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
			       data<span style="color: #339933;">,</span> location.<span style="color: #660066;">protocol</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;//&quot;</span> <span style="color: #339933;">+</span> location.<span style="color: #660066;">host</span><span style="color: #339933;">,</span>
			       id<span style="color: #339933;">,</span> window<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    document.<span style="color: #660066;">dispatchEvent</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">function</span> listen<span style="color: #009900;">&#40;</span>func<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    document.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'GM_UnsafeWrapper_returned'</span><span style="color: #339933;">,</span> func<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	listen<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>waiting<span style="color: #009900;">&#91;</span>e.<span style="color: #660066;">lastEventId</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		    waiting<span style="color: #009900;">&#91;</span>e.<span style="color: #660066;">lastEventId</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span>self<span style="color: #339933;">,</span> JSON.<span style="color: #660066;">parse</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">data</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		    <span style="color: #000066; font-weight: bold;">delete</span> waiting<span style="color: #009900;">&#91;</span>e.<span style="color: #660066;">lastEventId</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">exec</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>func<span style="color: #339933;">,</span> args<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #003366; font-weight: bold;">var</span> userFunc <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;(&quot;</span><span style="color: #339933;">+</span> func <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;).apply(null,&quot;</span><span style="color: #339933;">+</span> JSON.<span style="color: #660066;">stringify</span><span style="color: #009900;">&#40;</span>args <span style="color: #339933;">||</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #339933;">;</span>
	    waiting<span style="color: #009900;">&#91;</span>seqId<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> callback <span style="color: #339933;">||</span> noop<span style="color: #339933;">;</span>
	    location.<span style="color: #660066;">href</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;javascript:void &quot;</span><span style="color: #339933;">+</span>
	    <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>dispatch<span style="color: #339933;">,</span> ret<span style="color: #339933;">,</span> id<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> dispatch<span style="color: #009900;">&#40;</span>JSON.<span style="color: #660066;">stringify</span><span style="color: #009900;">&#40;</span>ret<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> id<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span>
	    <span style="color: #3366CC;">&quot;(&quot;</span><span style="color: #339933;">+</span> dispatch <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;,&quot;</span><span style="color: #339933;">+</span> userFunc <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;,&quot;</span> <span style="color: #339933;">+</span> JSON.<span style="color: #660066;">stringify</span><span style="color: #009900;">&#40;</span>seqId<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #339933;">;</span>
	    <span style="color: #000066; font-weight: bold;">return</span> seqId<span style="color: #339933;">++;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">cancel</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #000066; font-weight: bold;">delete</span> waiting<span style="color: #009900;">&#91;</span>id<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>



<p>
そして Deferred に対するアダプタを書く。とても簡単。
</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">with</span><span style="color: #009900;">&#40;</span>D<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">function</span> unsafeExec<span style="color: #009900;">&#40;</span>func<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> d <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Deferred<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> id <span style="color: #339933;">=</span> UnsafeWrapper.<span style="color: #660066;">exec</span><span style="color: #009900;">&#40;</span>func<span style="color: #339933;">,</span> args<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ret<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		d.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span>ret<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	d.<span style="color: #660066;">canceller</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> UnsafeWrapper.<span style="color: #660066;">cancel</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">return</span> d<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>



<p>
これで例えば、GM_xmlhttpRequest で外部ドメインからデータを取得して、そのデータを整形して、unsafeWindow 側で表示処理を行って、そしてその結果をuserscript側で受け取って…という処理は次のように書くことができる。
</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">with</span><span style="color: #009900;">&#40;</span>D<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
xhttp.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;http://example.com/&quot;</span><span style="color: #009900;">&#41;</span>
    .<span style="color: #660066;">next</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> data <span style="color: #339933;">=</span> res.<span style="color: #660066;">responseText</span><span style="color: #339933;">;</span>
            <span style="color: #006600; font-style: italic;">//....</span>
&nbsp;
	    <span style="color: #000066; font-weight: bold;">return</span> unsafeExec<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    $.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>k<span style="color: #339933;">,</span>v<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                      <span style="color: #006600; font-style: italic;">//...</span>
                    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #006600; font-style: italic;">//...</span>
		    <span style="color: #000066; font-weight: bold;">return</span> result<span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
		<span style="color: #009900;">&#91;</span>data<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
    .<span style="color: #660066;">next</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>result<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #006600; font-style: italic;">//...</span>
	<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>



<p>
より実用性を高めるのであれば、location.href で実行するコード全体を try {} で囲み、catch したエラーをJSONに変換して _failed イベントを dispatch して、Deferred の fail に転送すれば、unsafeWindow 側で起こったエラーをuserscript側のDeferred chainで捕捉できるようになる。
</p>
<p>参考：</p>
<ul>
<li><a href="http://d.hatena.ne.jp/Constellation/20090326/1238073714">unsafeExec on JSDeferred &#8211; 枕を欹てて聴く</a></li>
<li><a href="http://cho45.stfuawsc.com/jsdeferred/doc/intro.html">JSDeferred 紹介</a></li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://wp.serpere.info/archives/1110/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XPCNativeWrapperとunsafeWindowの間でデータを送受信する</title>
		<link>http://wp.serpere.info/archives/1107</link>
		<comments>http://wp.serpere.info/archives/1107#comments</comments>
		<pubDate>Sat, 23 Jan 2010 13:59:30 +0000</pubDate>
		<dc:creator>tkyk</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Greasemonkey]]></category>

		<guid isPermaLink="false">http://wp.serpere.info/?p=1107</guid>
		<description><![CDATA[XPCNativeWrapperの外側でスクリプトを評価する関数。Firebugも同じことをしている。unsafeWindowを触らないので安全。 function evalInPage&#40;fun&#41; &#123; location.href = &#34;javascript:void (&#34; + fun + &#34;)()&#34;; &#125; SmartLDR更新 &#8211; 素人がプログラミングを勉強するブログ これは面白い！Function.prototype.toString が関数のソースコードを返すことを利用した、巧妙にして簡潔なハック。 次のように引数を渡せるように改良すればさらに強力になる（引数に渡せるのはJSON化可能な値のみ）。 function evalInPage&#40;func, args&#41; &#123; var argStr = JSON.stringify&#40;args &#124;&#124; &#91;&#93;&#41;; location.href = &#34;javascript:void &#34;+ func +&#34;.apply(null,&#34;+ argStr +&#34;)&#34;; &#125; GM_xmlhttpRequest を使って別ドメインから得たデータを、unsafeWindow 上のライブラリを使って表示する、といったコードが安全かつ自然に書けるようになる。 // データの取得は Greasemonkey で行う GM_xmlhttpRequest&#40;&#123; method:&#34;GET&#34;, url: &#34;http://example.com/api&#34;, onload: function&#40;response&#41; &#123; var data = [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwp.serpere.info%252Farchives%252F1107%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2F8lBQsJ%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22XPCNativeWrapper%E3%81%A8unsafeWindow%E3%81%AE%E9%96%93%E3%81%A7%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E9%80%81%E5%8F%97%E4%BF%A1%E3%81%99%E3%82%8B%22%20%7D);"></div>
<blockquote>
<p>
XPCNativeWrapperの外側でスクリプトを評価する関数。Firebugも同じことをしている。unsafeWindowを触らないので安全。
</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> evalInPage<span style="color: #009900;">&#40;</span>fun<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  location.<span style="color: #660066;">href</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;javascript:void (&quot;</span> <span style="color: #339933;">+</span> fun <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;)()&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>



<p><cite><a href="http://d.hatena.ne.jp/javascripter/20090324/1237903880">SmartLDR更新 &#8211; 素人がプログラミングを勉強するブログ</a></cite></p>
</blockquote>
<p>
これは面白い！Function.prototype.toString が関数のソースコードを返すことを利用した、巧妙にして簡潔なハック。
</p>
<p>
次のように引数を渡せるように改良すればさらに強力になる（引数に渡せるのはJSON化可能な値のみ）。
</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> evalInPage<span style="color: #009900;">&#40;</span>func<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> argStr <span style="color: #339933;">=</span> JSON.<span style="color: #660066;">stringify</span><span style="color: #009900;">&#40;</span>args <span style="color: #339933;">||</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    location.<span style="color: #660066;">href</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;javascript:void &quot;</span><span style="color: #339933;">+</span> func <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;.apply(null,&quot;</span><span style="color: #339933;">+</span> argStr <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>



<p>
GM_xmlhttpRequest を使って別ドメインから得たデータを、unsafeWindow 上のライブラリを使って表示する、といったコードが安全かつ自然に書けるようになる。
</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// データの取得は Greasemonkey で行う</span>
GM_xmlhttpRequest<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> method<span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;GET&quot;</span><span style="color: #339933;">,</span>
                    url<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;http://example.com/api&quot;</span><span style="color: #339933;">,</span>
                    <span style="color: #000066;">onload</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                      <span style="color: #003366; font-weight: bold;">var</span> data <span style="color: #339933;">=</span> response.<span style="color: #660066;">responseText</span><span style="color: #339933;">;</span>
                      <span style="color: #006600; font-style: italic;">//...</span>
                      evalInPage<span style="color: #009900;">&#40;</span>render<span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>data<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #009900;">&#125;</span>
                  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// データの表示は unsafeWindow 上で行う</span>
<span style="color: #006600; font-style: italic;">// jQueryなど unsafeWindow 上のライブラリが使える</span>
<span style="color: #003366; font-weight: bold;">function</span> render<span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  $.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>k<span style="color: #339933;">,</span>v<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">//...</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>



<p>
これだけでも十分便利なのだが、「返り値が利用できない」「Firefoxのlocation.hrefは非同期で実行される」といった難点があるらしい。それを回避するために<a href="http://d.hatena.ne.jp/Constellation/20090326/1238073714">unsafeExec on JSDeferred &#8211; 枕を欹てて聴く</a>においてはJSDeferredというライブラリを使う方法が紹介されているのだが、コードを見る限り unsafeWindow に対するアクセスが必要になるようだ。
</p>
<p>
unsafeWindow にアクセスせずにGreasemonkeyに制御を戻すには、DOM Eventを使うのが良いと思う。以下、DOMNodeInserted イベントを使って実装してみた（返り値として利用できるのはJSON化可能な値のみ）。
</p>
<p>
<ins datetime="2010-01-24T02:29:03+00:00"><strong>追記:</strong> <a href="http://wp.serpere.info/archives/1107/comment-page-1#comment-809">Constellationさんからコメントをいただきました</a>。DOMNodeInsertedなどのイベントを使わなくても、直接createEvent/dispatchEventでイベントを生成・データを送受信する方法があるようです。 詳細はこのページの Constellationさんのコメントや、『<a href="http://nanto.asablo.jp/blog/2008/06/26/3596261">Greasemonkey スクリプトとイベントで通信: Days on the Moon</a>』など参照してください。</ins>
</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> getUniqId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">do</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> id <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;_tmp&quot;</span> <span style="color: #339933;">+</span> String<span style="color: #009900;">&#40;</span>Math.<span style="color: #660066;">random</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">slice</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">while</span><span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">return</span> id<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> evalInPage<span style="color: #009900;">&#40;</span>func<span style="color: #339933;">,</span> args<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> argStr <span style="color: #339933;">=</span> JSON.<span style="color: #660066;">stringify</span><span style="color: #009900;">&#40;</span>args <span style="color: #339933;">||</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
        userFunc <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;(&quot;</span><span style="color: #339933;">+</span> func <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;).apply(null,&quot;</span><span style="color: #339933;">+</span> argStr <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        location.<span style="color: #660066;">href</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;javascript:void &quot;</span><span style="color: #339933;">+</span> userFunc<span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> div <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'div'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
        id <span style="color: #339933;">=</span> getUniqId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    div.<span style="color: #660066;">id</span> <span style="color: #339933;">=</span> id<span style="color: #339933;">;</span>
    div.<span style="color: #660066;">style</span>.<span style="color: #660066;">display</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'none'</span><span style="color: #339933;">;</span>
    document.<span style="color: #660066;">body</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>div<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    div.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'DOMNodeInserted'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            callback<span style="color: #009900;">&#40;</span>JSON.<span style="color: #660066;">parse</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">target</span>.<span style="color: #660066;">nodeValue</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            div.<span style="color: #660066;">parentNode</span>.<span style="color: #660066;">removeChild</span><span style="color: #009900;">&#40;</span>div<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    location.<span style="color: #660066;">href</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;javascript:void &quot;</span><span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ret<span style="color: #339933;">,</span> id<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span>
            .<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">createTextNode</span><span style="color: #009900;">&#40;</span>JSON.<span style="color: #660066;">stringify</span><span style="color: #009900;">&#40;</span>ret<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;.call(null,&quot;</span><span style="color: #339933;">+</span> userFunc <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;,&quot;</span> <span style="color: #339933;">+</span> JSON.<span style="color: #660066;">stringify</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>



<p>JSDreferredを使う方法と同じく、戻り値を受け取るコールバック関数を指定する。</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">evalInPage<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>obj<span style="color: #339933;">,</span> num<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">//この中のコードは unsafeWindow で実行される</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#123;</span> answer<span style="color: #339933;">:</span> obj.<span style="color: #660066;">a</span> <span style="color: #339933;">+</span> num <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#123;</span>a<span style="color: #339933;">:</span><span style="color: #CC0000;">99</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ret<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">//この中のコードは Greasemonkey で実行される</span>
	alret<span style="color: #009900;">&#40;</span>ret.<span style="color: #660066;">answer</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>



<p>
多分まじめに作り込めば一種のRPCシステムみたいになると思う。
</p>
]]></content:encoded>
			<wfw:commentRss>http://wp.serpere.info/archives/1107/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ow.ly や oneclip.jp のフレームを外す user script</title>
		<link>http://wp.serpere.info/archives/1104</link>
		<comments>http://wp.serpere.info/archives/1104#comments</comments>
		<pubDate>Tue, 19 Jan 2010 13:52:31 +0000</pubDate>
		<dc:creator>tkyk</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Greasemonkey]]></category>

		<guid isPermaLink="false">http://wp.serpere.info/?p=1104</guid>
		<description><![CDATA[ow.lyやoneclip.jpなど、元コンテンツをiframe内に表示するタイプのURL短縮サービスから、自動的に元URLにリダイレクトするuser scriptを作りました。 Redirect to the iframed URL 同様の機能を持つものとしてiframe redirectorがあり、今まで私も使用していたのですが、対象サービスのURLやHTML構造に依存するコードが含まれているため、対象サービスの構成が変化すると動かなくなってしまいます（少し前に am6.jp の仕様が変わって動かなくなりました。現在は修正されています）。 そのため拙作のスクリプトではURLやHTMLに依存するコードは使わず、「面積比でbodyの4分の1を占めるiframe」を元コンテンツと判断するようにしました。おそらくほとんどのケースで問題なく動作するものと思われます。 デフォルトでは以下のURLで動作します。 http://ow.ly/* http://oneclip.jp/* http://am6.jp/* 今後新たに同種のサイトが登場した場合は（登場してほしくないのですが）、Greasemonkeyの管理ダイアログから「ユーザスクリプトを実行するページ」にURLを追加してください。スクリプトの修正は不要です。 Firefox 3.5.7 + Greasemonkey 0.8.2 および Mac版 Google Chrome 4.0.295.9 で動作確認しています。 参考 URL短縮サービス ow.ly は実URLが表示されずに危険 → グリモン書いた &#8211; まちゅダイアリー(2009-11-05)]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwp.serpere.info%252Farchives%252F1104%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2F7RbHkQ%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22ow.ly%20%E3%82%84%20oneclip.jp%20%E3%81%AE%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%82%92%E5%A4%96%E3%81%99%20user%20script%22%20%7D);"></div>
<p>
<a href="http://ow.ly/">ow.ly</a>や<a href="http://oneclip.jp/">oneclip.jp</a>など、元コンテンツをiframe内に表示するタイプのURL短縮サービスから、自動的に元URLにリダイレクトするuser scriptを作りました。
</p>
<p>
<a href="http://userscripts.org/scripts/show/66765">Redirect to the iframed URL</a>
</p>
<p>
同様の機能を持つものとして<a href="http://userscripts.org/scripts/show/59863">iframe redirector</a>があり、今まで私も使用していたのですが、対象サービスのURLやHTML構造に依存するコードが含まれているため、対象サービスの構成が変化すると動かなくなってしまいます（少し前に am6.jp の仕様が変わって動かなくなりました。現在は修正されています）。
</p>
<p>
そのため拙作のスクリプトではURLやHTMLに依存するコードは使わず、「面積比でbodyの4分の1を占めるiframe」を元コンテンツと判断するようにしました。おそらくほとんどのケースで問題なく動作するものと思われます。
</p>
<p>
デフォルトでは以下のURLで動作します。
</p>
<ul>
<li>http://ow.ly/*</li>
<li>http://oneclip.jp/*</li>
<li>http://am6.jp/*</li>
</ul>
<p>
今後新たに同種のサイトが登場した場合は（登場してほしくないのですが）、Greasemonkeyの管理ダイアログから「ユーザスクリプトを実行するページ」にURLを追加してください。スクリプトの修正は不要です。
</p>
<p>
Firefox 3.5.7 + Greasemonkey 0.8.2 および Mac版 Google Chrome 4.0.295.9 で動作確認しています。
</p>
<h3>参考</h3>
<p><a href="http://www.machu.jp/diary/20091105.html#p01" target="_blank">URL短縮サービス <span class="highlight">ow.ly</span> は実URLが表示されずに危険 → グリモン書いた &#8211; まちゅダイアリー(2009-11-05)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://wp.serpere.info/archives/1104/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
