<?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>Web scratch &#187; Firefox</title>
	<atom:link href="http://efcl.info/category/firefox/feed/" rel="self" type="application/rss+xml" />
	<link>http://efcl.info</link>
	<description>フリーソフトやFirefoxなどについて、web全般なサイト</description>
	<lastBuildDate>Wed, 08 Sep 2010 05:51:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>またニコニコ動画見てるGreasemonkeyのOAuth対応版</title>
		<link>http://efcl.info/2010/0906/res1930/</link>
		<comments>http://efcl.info/2010/0906/res1930/#comments</comments>
		<pubDate>Mon, 06 Sep 2010 11:50:21 +0000</pubDate>
		<dc:creator>azu</dc:creator>
				<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[ニコニコ動画]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://efcl.info/?p=1930</guid>
		<description><![CDATA[2010.8月末にTwitterのBASIC認証が終わったので、今までのまたニコぐりもんは動かなくなっていると思います。なのでOAuth認証に対応してるまたニコニコ見てるを作ってみました。(作ったのは結構前だけどね)

 [...]]]></description>
			<content:encoded><![CDATA[<p>2010.8月末にTwitterのBASIC認証が終わったので、今までのまたニコぐりもんは動かなくなっていると思います。<br />なのでOAuth認証に対応してるまたニコニコ見てるを作ってみました。(作ったのは結構前だけどね)</p>
<ul>
<li><a href="http://userscripts.org/scripts/show/83795">mataniconicomiteru for Greasemonkey</a></li>
</ul>
<h3>使用方法</h3>
<p>まずはニコニコ動画の動画ページでステータスバーのGreasemonkeyアイコンを右クリック→ユーザースクリプトコマンドからOAuth認証をする必要があります。 <br /><a href="http://efcl.info/wp-content/uploads/2010/09/ss-2010-09-06-11.png"><img class="alignnone size-medium wp-image-1938" title="ss-2010-09-06-1" src="http://efcl.info/wp-content/uploads/2010/09/ss-2010-09-06-11-300x95.png" alt="" width="300" height="95" /></a></p>
<p>コマンドを実行するとOAuth認証のパネルが出てくるので、ボタンからTwitterへ行きOAuth認証してPINコードをコピーしてテキストエリアに入力すると準備完了です。<br /><a href="http://efcl.info/wp-content/uploads/2010/09/large.png"><img class="alignnone size-medium wp-image-1939" title="large" src="http://efcl.info/wp-content/uploads/2010/09/large-300x192.png" alt="" width="300" height="192" /></a></p>
<p>認証済みだったら動画タイトル部分にまたニコのボタンが出るので、それをクリックしてコメントを入力してまたボタンを押せばTwitterへ投稿できます。(nico.msのURLを使って投稿します。<br /><a href="http://efcl.info/wp-content/uploads/2010/09/input_mata.png"><img class="alignnone size-full wp-image-1940" title="input_mata" src="http://efcl.info/wp-content/uploads/2010/09/input_mata.png" alt="" width="482" height="78" /></a></p>
<p>オリジナルの機能としてはコメント入力欄の右側に文字数のカウンターが付いてるぐらいです。</p>
<dl>
<dt><strong>mataniconicomiteru for Greasemonkey</strong></dt>
<dd><a title="mataniconicomiteru for Greasemonkey" href="http://userscripts.org/scripts/show/83795">http://userscripts.org/scripts/show/83795</a></dd>
</dl>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://efcl.info/2010/0906/res1930/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Jetpack SDKで生成したアドオンの名前にスペースなど入れる方法</title>
		<link>http://efcl.info/2010/0905/res1923/</link>
		<comments>http://efcl.info/2010/0905/res1923/#comments</comments>
		<pubDate>Sat, 04 Sep 2010 17:04:19 +0000</pubDate>
		<dc:creator>azu</dc:creator>
				<category><![CDATA[Jetpack]]></category>
		<category><![CDATA[エラー]]></category>

		<guid isPermaLink="false">http://efcl.info/?p=1923</guid>
		<description><![CDATA[

xpiの名前変えたいのだけどよくわからん。パッケージフォルダ名とpackage.jsonを書き換えて同名にしてもcfx xpiでエラーでる。
コード整形とシンタックスハイライトするjetpackを作った &#8211 [...]]]></description>
			<content:encoded><![CDATA[<div class="quote">
<blockquote title="コード整形とシンタックスハイライトするjetpackを作った - Cherenkovの暗中模索にっき" cite="http://d.hatena.ne.jp/Cherenkov/20100904/p2">
<p>xpiの名前変えたいのだけどよくわからん。パッケージフォルダ名とpackage.jsonを書き換えて同名にしてもcfx xpiでエラーでる。</p>
<p><cite><a href="http://d.hatena.ne.jp/Cherenkov/20100904/p2">コード整形とシンタックスハイライトするjetpackを作った &#8211; Cherenkovの暗中模索にっき</a></cite></p>
</blockquote>
</div>
<p>Jetpack SDKでcfx xpiによってxpiファイルを生成して、そのアドオンをインストールするとpackage.jsonのnameに書かれていた名前がアドオンの名前になります。<br />しかし、package.jsonのnameはパッケージの名前なので大文字やマルチバイト文字やスペースなどが使えず自由に名前をつけようとするとエラーになります。<br />名前を自由につけるにはpackage.jsonに<tt>fullName</tt>というキーを追加して、そこにスペースや大文字(マルチバイトをつけるとエラーになった…)を使った名前をつけることで、cfx xpiによって生成されたアドオンの名前に反映されます。</p>
<pre>{
 "id": "jid0-xxxxxxxxx",
 "version": "0.1",
 "description": "test",
 "name": "test-package",
 "fullName" : "THIS is TEST package",
 "author": "azu"
}</pre>
<p>実際の生成の流れとしてはpackage.jsonにfullNameがなかったら、nameの中身がfullNameとして扱われるようになっているみたいです。<br />fullNameに日本語入れる方法はよく分かりませんでした。ユニコードエスケープしてもエラーになる。<br />生成されるxpiファイル自体のファイル名はnameの中身が使われるようです。</p>
<dl>
<dt><strong>Google Web Historyに見たページを自動記録するアドオン(Jetpack SDK) | Web scratch</strong></dt>
<dd><a title="Google Web Historyに見たページを自動記録するアドオン(Jetpack SDK) | Web scratch" href="http://efcl.info/2010/0809/res1872/">http://efcl.info/2010/0809/res1872/</a></dd>
</dl>
<dl>
<dt><strong>Labs/Jetpack/JEP/31 &#8211; MozillaWiki</strong></dt>
<dd><a title="Labs/Jetpack/JEP/31 - MozillaWiki" href="https://wiki.mozilla.org/Labs/Jetpack/JEP/31#Packages">https://wiki.mozilla.org/Labs/Jetpack/JEP/31#Packages</a></dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://efcl.info/2010/0905/res1923/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tomblooのポスト先にはてなダイアリーを追加するパッチ</title>
		<link>http://efcl.info/2010/0825/res1909/</link>
		<comments>http://efcl.info/2010/0825/res1909/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 15:55:59 +0000</pubDate>
		<dc:creator>azu</dc:creator>
				<category><![CDATA[Tombloo]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[はてな]]></category>

		<guid isPermaLink="false">http://efcl.info/?p=1909</guid>
		<description><![CDATA[以前からずっと書いて修正していたパッチですが、Tombloo 0.4.11(自動更新はこないので手動でアップデートしましょう)で、はてなダイアリーのユーザー情報取得方法がスクレイピングからhttp://b.hatena. [...]]]></description>
			<content:encoded><![CDATA[<p>以前からずっと<span style="text-decoration: line-through;">書いて</span>修正していたパッチですが、<a href="http://github.com/to/tombloo/downloads">Tombloo </a>0.4.11(自動更新はこないので手動でアップデートしましょう)で、<br />はてなダイアリーのユーザー情報取得方法がスクレイピングから<a title="http://b.hatena.ne.jp/my.name" href="http://b.hatena.ne.jp/my.name">http://b.hatena.ne.jp/my.name</a>のAPIを利用したものに変わったので、<br />はてなダイアリーへのポストができるように修正しました。</p>
<p><span id="more-1909"></span></p>
<p><script src="http://gist.github.com/547176.js?file=model.HatenaDairy.js"></script></p>
<p>rawのリンク上で右クリック、[Tombloo]-[Tomblooパッチのインストール]で簡単インストールできます。<br /><a href="http://efcl.info/wp-content/uploads/2010/08/ss-2010-08-25-1.png"><img class="alignnone size-medium wp-image-1910" title="ss-2010-08-25-1" src="http://efcl.info/wp-content/uploads/2010/08/ss-2010-08-25-1-300x141.png" alt="" width="300" height="141" /></a><br />インストールすると利用サービスにはてなダイアリーが増えていると思います。<br />はてなブックマークと同じくはてなにログインしてから使用します。</p>
<p>確かその場編集モード を使ってるとポストできないらしいので、ホントはAtomAPIでやった方がよいらしい<br />残骸<a href="http://gist.github.com/354700">gist: 354700 &#8211; GitHub</a></p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 83px; width: 1px; height: 1px; overflow: hidden;">&lt;a href=&#8221;http://gist.github.com/354700&#8243;&gt;gist: 354700 &#8211; GitHub&lt;/a&gt;</div>
]]></content:encoded>
			<wfw:commentRss>http://efcl.info/2010/0825/res1909/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ページ移動時などに音を鳴らすアドオン「KIRISAKE」</title>
		<link>http://efcl.info/2010/0821/res1906/</link>
		<comments>http://efcl.info/2010/0821/res1906/#comments</comments>
		<pubDate>Sat, 21 Aug 2010 05:27:05 +0000</pubDate>
		<dc:creator>azu</dc:creator>
				<category><![CDATA[Jetpack]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[アドオン]]></category>
		<category><![CDATA[拡張機能]]></category>

		<guid isPermaLink="false">http://efcl.info/?p=1906</guid>
		<description><![CDATA[またJetpack SDKで1つアドオンを作成してみました。リンクをクリックしてページ移動などの通信が始まった際に、風を切り裂くような音を出すアドオンです。

KIRISAKE :: Add-ons for Firefo [...]]]></description>
			<content:encoded><![CDATA[<p>またJetpack SDKで1つアドオンを作成してみました。<br />リンクをクリックしてページ移動などの通信が始まった際に、風を切り裂くような音を出すアドオンです。</p>
<ul>
<li><a href="https://addons.mozilla.org/ja/firefox/addon/220208/">KIRISAKE :: Add-ons for Firefox</a> ダウンロード先</li>
<li><a href="http://github.com/azu/JetpackSDK/tree/master/KIRISAKE/">KIRISAKE at master from azu&#8217;s JetpackSDK &#8211; GitHub</a> ソースコード</li>
</ul>
<p>作った理由ですが、<br />移動する際に音を出すと、ちゃんとリンクをクリックできたかなどが聴覚的にも認識できるのと、上記のような音を使う事でブラウザが少し早くなったような感じがします(I shallplease)</p>
<p>という後付けの理由があったりしますが、HTML5のAudioタグを使って見たかったというのが第一の要因です。<br />そういう気分になったのは中国のJetpackerのLT資料を見つけて、pageWorkerでhtmlファイルを読み込んでその中でAudioタグを鳴らすというサンプルが載っていたので実践してみました。<br />見つけたLTの資料はこれ<a href="http://www.slideshare.net/littlebtc/jetpack-sdk-the-new-possibility-of-the-extensions-on-browser">Jetpack SDK: The new possibility of the extensions on browser</a></p>
<p>処理的にはたいしたことはやっていませんが、Jetpack SDKにはページ移動(ページを読み込みじゃなくて、通信が始まった瞬間)に反応するAPIはまだないような感じなので、nsIWebProgressを使った普通のFirefox拡張機能と同じように直に書きました。<br />Components.interfacesとか使う必要性が出てくるわけですが、Jetpack SDK0.6からはCiやCcというエイリアスがデフォルトではなくなったので、以下のようにrequireしてから使う必要があります。<br /><a href="https://dev.mozilla.jp/2010/07/jetpack-sdk-0-6/">Jetpack SDK 0.6 がリリースされました « Mozilla Developer Street (modest)</a></p>
<pre>var {Cc, Ci} = require("chrome");
</pre>
<p>ちなみにこのvar {a,b} = obj;みたいな表記は<a href="https://developer.mozilla.org/ja/New_in_JavaScript_1.7#.e5.88.86.e5.89.b2.e4.bb.a3.e5.85.a5">分割代入</a>というJavaScript 1.7からの機能を使ったもので、</p>
<pre>var Cc = require("chrome").Cc , Ci = require("chrome").Ci;
</pre>
<p>というのと同様の意味になります。一部地域ではよく見かけるので覚えておくと便利です。</p>
<ul>
<li><a href="http://nanto.asablo.jp/blog/2009/12/30/4784624">Kanasan.JS Jetpack ワークショップ: Days on the Moon</a></li>
<li><a href="http://d.hatena.ne.jp/mooz/20100729/p1">JavaScript の分割代入まとめ &#8211; mooz deceives you</a></li>
</ul>
<p>参考サイト</p>
<ul>
<li><a href="http://d.hatena.ne.jp/cou929_la/20100301/1267434283">Progress Listenersでロケーションバーのurl変更されたときに何かする &#8211; フリーフォーム フリークアウト</a></li>
<li><a href="http://piro.sakura.ne.jp/latest/blosxom/mozilla/xul/2007-01-21_splitbrowser-subbrowser.htm">Latest topics &gt; Split Browser開発のよもやま話（6）：分割されたブラウザの作り込み &#8211; outsider reflex</a></li>
</ul>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 108px; width: 1px; height: 1px; overflow: hidden;">Components.interfaces</div>
]]></content:encoded>
			<wfw:commentRss>http://efcl.info/2010/0821/res1906/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Web Historyに見たページを自動記録するアドオン(Jetpack SDK)</title>
		<link>http://efcl.info/2010/0809/res1872/</link>
		<comments>http://efcl.info/2010/0809/res1872/#comments</comments>
		<pubDate>Sun, 08 Aug 2010 17:16:16 +0000</pubDate>
		<dc:creator>azu</dc:creator>
				<category><![CDATA[Jetpack]]></category>
		<category><![CDATA[アドオン]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://efcl.info/?p=1872</guid>
		<description><![CDATA[GoogleにはGoogle &#8211; ウェブ履歴というものがあり、検索してどのページを訪ねたかなどが記録されています。またその記録は検索ページで既読リンクの色にするなどの判定にも使われています。Google検索か [...]]]></description>
			<content:encoded><![CDATA[<p>Googleには<a href="https://www.google.com/history/">Google &#8211; ウェブ履歴</a>というものがあり、検索してどのページを訪ねたかなどが記録されています。<br />またその記録は検索ページで既読リンクの色にするなどの判定にも使われています。<br />Google検索から訪ねたサイト以外のURLもウェブ履歴に登録するFirefox拡張機能を作成してみました。<br />既に</p>
<ul>
<li><a href="http://d.hatena.ne.jp/brazil/20080514/1210767708">Googleウェブ履歴を残すGreasemonkeyスクリプト</a></li>
<li><a href="http://d.hatena.ne.jp/mallowlabs/20080104/1199461216">Opera で Google Web History を使えるようにする UserJS &#8211; mallowlabsの備忘録</a></li>
</ul>
<p>などGreasemonkeyやTomblooパッチなど代わりになる手段は山ほどある気がしますが、<strong>Jetpack SDK</strong>を使いたかったのと、意外にもFirefoxアドオンとして同じ役割するものが見つからなかったので作ってみました。</p>
<p>他のスクリプトとの違いは大して無いと思いますが、できるだけ無駄な送信を控えるようにしています。</p>
<ul>
<li>最近訪れたサイトは重複送信しない(100件ぐらいでクリアされます)</li>
<li><a href="http://outgoing.mozilla.org/v1/62ec45e9d2205ac4d757b771a01ed16cc048d97e/https%3A//">https://はホストのみを送信</a></li>
<li>ローカルやIPアドレスベースのURLの場合は送らない</li>
</ul>
<p>ダウンロードはAMOからできるようにしてあります。<br />Firefoxアドオンのxpiを簡単における場所が無かったので、AMOに登録しておいてあります。</p>
<ul>
<li><a href="https://addons.mozilla.org/ja/firefox/addon/213956/">Google WebHistory Updater :: Add-ons for Firefox</a></li>
</ul>
<p>Jetpack SDKでコンパイル?前のソースコードはこちらに</p>
<ul>
<li><a href="http://github.com/azu/JetpackSDK/tree/master/Google-webhistory-updater/">Google-webhistory-updater at master from azu&#8217;s JetpackSDK &#8211; GitHub</a></li>
</ul>
<h3>Jetpack SDKで何か作るには</h3>
<p>Jetpack SDKで既に<a href="https://addons.mozilla.org/ja/firefox/user/2222641/">3つ</a>ほどアドオンを作成していますが、0.5だとJetpack prototypeとできることはそこまで変わってないです。(prototypeのギャラリー無くなったみたいですね。8個ぐらい作った気がする)<br />Jetpack SDKで作る上で参考にしたのは</p>
<ul>
<li><a href="http://www.xuldev.org/blog/?cat=42">SCRAPBLOG : Jetpack</a> 基礎的なAPIの使い方</li>
<li><a href="http://www.asukaze.net/etc/jetpack/">Jetpack SDK &#8211; あすかぜ・ねっと</a> とても参考になる</li>
<li><a href="https://jetpack.mozillalabs.com/sdk/latest/docs/#guide/getting-started">Jetpack SDK Docs</a></li>
</ul>
<p>最後のJetpack SDK Docsはcfx docsで開いて、jetpack-coreあたりに現在使えるAPIが載っているのでそれを見て使い方を調べるとAPIの使い方は分かる感じ。(Jetpack prototypeの頃よりはドキュメントにサンプルもあってマシになりました)<br />一番ハマるところはcfxとかコマンドでエラーがでるとかその辺だった気がする。<br />環境はWindows Vistaです。<br />cfx testallすら通らない場合は-aとか-bオプションを指定してみるといい。 <a href="http://d.hatena.ne.jp/Cherenkov/20100603/p1">Jetpack SDK 0.4でcfx testallを成功させる方法 (windows) &#8211; Cherenkovの暗中模索にっき</a><br />毎回オプションを付けるのが面倒になったら<a href="http://www.xuldev.org/blog/?p=697">local.json</a>を作りデフォルト値を決めてみましょう。<br />自分はjetpack用のプロファイルを作りそれを指定してます</p>
<pre>{
  "configs": {
    "default": &#91;
      "-a", "firefox",
      "-b", "C:\\Program Files\\Mozilla Firefox\\firefox.exe",
      "-P", "%appdata%\\Mozilla\\Firefox\\Profiles\\h545wqkn.jetpack"
    &#93;,
    "ff37": &#91;
      "-a", "firefox",
      "-b", "C:\\Program Files\\Mozilla Firefox 3.7\\firefox.exe",
      "-P", "C:\\Users\\admin\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\testuser"
    &#93;
  }
}</pre>
<p>package.jsonを作り、libフォルダを作りmain.jsを書いて → さあcfx runで起動しようとしたら、まずはpackage.json内にidが自動生成されます。そしてもう一度cfx runすると下のようなエラーが出てくることがあります。</p>
<pre>Traceback (most recent call last):
  File "D:\jetpack\bin\cfx", line 6, in
    cuddlefish.run()
  File "D:\jetpack\python-lib\cuddlefish\__init__.py", line 475, in run
    include_dep_tests=options.dep_tests
  File "D:\jetpack\python-lib\cuddlefish\packaging.py", line 267, in generate_bu
ild_for_target
    add_dep_to_build(dep)
  File "D:\jetpack\python-lib\cuddlefish\packaging.py", line 254, in add_dep_to_
build
    add_section_to_build(dep_cfg, "lib", is_code=True)
  File "D:\jetpack\python-lib\cuddlefish\packaging.py", line 232, in add_section
_to_build
    validate_resource_hostname(name)
  File "D:\jetpack\python-lib\cuddlefish\packaging.py", line 65, in validate_res
ource_hostname
    raise ValueError('invalid resource hostname: %s' % name)
ValueError: invalid resource hostname: jid0-英数字-フォルダ名-lib</pre>
<p>これはpackage.jsonのnameに<strong>大文字</strong>やマルチバイト文字やスペースなどが含まれていると出てきます。(んなの分かるか)<br />なので小文字英数とハイホンあたりでnameを決めておきましょう。</p>
<p>console.logはコマンドプロンプトの方にでてくるので、それを使って(他に何かあるのかなー)デバッグしながらmain.jsなどを完成させて、xpiをcfx xpiコマンドではき出せば完成です。<br />まだ設定画面やパネルなどのGUIが簡単に使えなかったりしますが、用途が合えば簡単にアドオンを作成できるのでなかなか面白いです。</p>
<dl>
<dt><strong>Google WebHistory Updater :: Add-ons for Firefox</strong></dt>
<dd><a title="Google WebHistory Updater :: Add-ons for Firefox" href="https://addons.mozilla.org/ja/firefox/addon/213956/">https://addons.mozilla.org/ja/firefox/addon/213956/</a></dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://efcl.info/2010/0809/res1872/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>UstreamのFlash動画内広告を消す方法</title>
		<link>http://efcl.info/2010/0723/res1841/</link>
		<comments>http://efcl.info/2010/0723/res1841/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 10:25:28 +0000</pubDate>
		<dc:creator>azu</dc:creator>
				<category><![CDATA[アドオン]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[ust]]></category>
		<category><![CDATA[広告]]></category>

		<guid isPermaLink="false">http://efcl.info/?p=1841</guid>
		<description><![CDATA[USTREAMでは動画内に広告があって一定のタイミングで表示されたりしてとても邪魔になったりします。その広告をAdblockでブロックして出現しないようにする方法。
方法は単純で動画内広告も外部から読み込んだFlashで [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ustream.tv/">USTREAM</a>では動画内に広告があって一定のタイミングで表示されたりしてとても邪魔になったりします。<br />その広告を<a href="http://firefox.geckodev.org/?Adblock">Adblock</a>でブロックして出現しないようにする方法。</p>
<p>方法は単純で動画内広告も外部から読み込んだFlashで動作しているのでそのswfを読み込まないようにするだけです。<br />広告は以下のアドレスのブロックすると読み込まれなくなります。(正規表現でマッチするAdblockだとmedia\.scanscout\.comみたいにエスケープする。)</p>
<pre>media.scanscout.com
</pre>
<p>ブロックされているswfはhttp://media.scanscout.com/ads/ss_ads3.swf Youtubeとか他のサイトでも使われてるとか聞きました。<br />自分は<a href="http://pc12.2ch.net/test/read.cgi/software/1247819523/737">Adblock++</a>を使って正規表現を使わずに単純に広告をブロックしているので、/adsをというキーワードで広告がブロックされていたようです。<br />一応自分の<a href="http://gist.github.com/487255">adblock++.ini</a> (プロファイルの所にadblock++.iniがあるのでそこに上書き)<br />広告を全てなくしたい訳ではなくて、iframeを使って重かったり、大きな画像を使って見づらくしたり、幾度も注視点を奪うだけの広告が嫌いなだけです。</p>
<pre></pre>
]]></content:encoded>
			<wfw:commentRss>http://efcl.info/2010/0723/res1841/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>FirefoxのOOPP(Flashの別プロセス化)を無効にする</title>
		<link>http://efcl.info/2010/0628/res1811/</link>
		<comments>http://efcl.info/2010/0628/res1811/#comments</comments>
		<pubDate>Mon, 28 Jun 2010 05:36:20 +0000</pubDate>
		<dc:creator>azu</dc:creator>
				<category><![CDATA[Firefox]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[ソフトウェア]]></category>
		<category><![CDATA[プラグイン]]></category>
		<category><![CDATA[設定]]></category>

		<guid isPermaLink="false">http://efcl.info/?p=1811</guid>
		<description><![CDATA[公式にFirefox3.6.4がリリースされ、その中の大きな変更としてサードパーティ製プラグインを別プロセス化するOOPPという機能が盛り込まれデフォルトで有効になっています。3.6.4ではサードパーティ製プラグインのク [...]]]></description>
			<content:encoded><![CDATA[<p>公式にFirefox3.6.4がリリースされ、その中の大きな変更としてサードパーティ製プラグインを別プロセス化するOOPPという機能が盛り込まれデフォルトで有効になっています。<br />3.6.4ではサードパーティ製プラグインのクラッシュ判定が応答しなくなって10秒となっていたのが3.6.6では判定時間を 45 秒に延長されています。(判定時間はdom.ipc.plugins.timeoutSecsで設定できます)</p>
<ul>
<li><a href="http://mozilla.jp/firefox/3.6.4/releasenotes/">次世代ブラウザ Firefox – Firefox 3.6.4 リリースノート</a></li>
<li><a href="http://mozilla.jp/firefox/3.6.6/releasenotes/">次世代ブラウザ Firefox – Firefox 3.6.6 リリースノート</a></li>
</ul>
<p>プロセスを分離することで、Flashがクラッシュしてもブラウザ全体を巻き込んで落ちなくなることが期待できますが、プロセスを分離したことで少し問題も発生したりします。<br />OOPPはWindows と Linuxで導入されましたが、環境によっては逆に不安定になったりすることや、今までFirefoxのプロセスをホックして動作していたソフトウェアが正しく動作しなくなることがあります。<br />具体的に言えば、Windowsでの<strong>音量ミキサ</strong>(プロセスごとに音量を設定する)や<strong>myspeed</strong>(ブラウザ上のFlashの再生速度を変更する)などのソフトウェアはプロセスが分離されたことで上手く動かなくなったりします。<br />(音量ミキサの場合は&#8221;Plugin Container for Firefox&#8221;というプロセスの音量を設定することでなんとかなるかも)</p>
<h3>OOPPの無効化</h3>
<p>ロケーションバーに<a href="http://wiki.mozilla.gr.jp/wiki.cgi?page=aboutconfig">about:config</a>と入力して、<em>dom.ipc.plugins.enabled</em>と入力するとOOPPの有効無効の有無を決める設定が出てきます。<br /><a href="http://efcl.info/wp-content/uploads/2010/06/ss-2010-06-28-1.png"><img class="alignnone size-medium wp-image-1812" title="ss-2010-06-28-1" src="http://efcl.info/wp-content/uploads/2010/06/ss-2010-06-28-1-300x119.png" alt="" width="300" height="119" /></a></p>
<p>出てくる項目で、<em>dom.ipc.plugins.enabled</em> はOOPP全体の有無でfalseにすれば無効となります。<br /><em>dom.ipc.plugins.enabled.npswf32.dll</em> はFlashのプロセスを分離するかを決めることができ、入っているプラグインごとにそれぞれ決めることができます。<br />プラグイン同士で<a href="http://forums.mozillazine.jp/viewtopic.php?t=10306&amp;sid=454af6926a56fcd38a4aff7558479b4e">連携</a>していたりすることがあるらしいので、全てをtrue(有効)かfalse(無効)のどちらかにした方がいい気がします。<br />falseにすると今まで同じようにプロセスは一緒になるので(音量ミキサやmyspeedも動作する)、OOPPが安定したりソフトウェアが対応するまでは無効化するのもありかと思います。</p>
<dl>
<dt><strong>MozillaZine.jp :: トピックを表示 &#8211; 【ヒント】Firefox 3.6.4 と OOPP について</strong></dt>
<dd><a title="MozillaZine.jp :: トピックを表示 - 【ヒント】Firefox 3.6.4 と OOPP について" href="http://forums.mozillazine.jp/viewtopic.php?t=10328&amp;sid=4b9e3ceea6409b2f1e02c4db6fef54c6">http://forums.mozillazine.jp/viewtopic.php?t=10328&amp;sid=4b9e3ceea6409b2f1e02c4db6fef54c6</a></dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://efcl.info/2010/0628/res1811/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Greasemonkeyにデバッグ関数を追加するuserChrome.js</title>
		<link>http://efcl.info/2010/0612/res1754/</link>
		<comments>http://efcl.info/2010/0612/res1754/#comments</comments>
		<pubDate>Sat, 12 Jun 2010 04:50:36 +0000</pubDate>
		<dc:creator>azu</dc:creator>
				<category><![CDATA[userChome.js]]></category>
		<category><![CDATA[Firebug]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[userChrome.js]]></category>

		<guid isPermaLink="false">http://efcl.info/?p=1754</guid>
		<description><![CDATA[以前、GreasemonkeyにGrowlのような通知を呼ぶ機能を加える「Dbus Notify」 &#124; Web scratchでGreasemonkeyから使える機能を増やせたら楽しそうと書いたと書きましたが、callo [...]]]></description>
			<content:encoded><![CDATA[<p>以前、<a href="http://efcl.info/2010/0606/res1708/">GreasemonkeyにGrowlのような通知を呼ぶ機能を加える「Dbus Notify」 | Web scratch</a>でGreasemonkeyから使える機能を増やせたら楽しそうと書いたと書きましたが、<a title="lackac's callout at master - GitHub" href="http://github.com/lackac/callout">callout</a>のソースを参考にGreasemonkeyスクリプトから使える関数を追加するuseChrome.jsを書いてみました。</p>
<p><script src="http://gist.github.com/428596.js?file=ore2Greasemonkey.uc.js"></script></p>
<p>このuserChrome.jsを読み込むと、</p>
<pre>fbug
Clipboard.get
Clipboard.set</pre>
<p>などのメソッドがGreasemonkeyスクリプトから使えるようになります。<br />fbugはconsole.logと同じ動作ですが、Firebugのウィンドウを開いていない状態(Firebugがオフ)でもFirebugのウィンドウを開いてからlogを出してくれる関数です。(元ネタは<a href="https://addons.mozilla.org/ja/firefox/addon/159546/">xqjs</a>)<br />Clipboardの方はjetpack prototypeからのコピペなのであんまり確認してません。</p>
<p>当たり前ですがこのuseChrome.jsをインストールしてない人の環境ではfbugなどの関数は使えないため、デバッグ目的か自分用のGreasemonkeyに使用する感じになると思います。<br />以下のようにデバッグ時のみ動く関数でラップしておけば、配布の際にDEBUG = false;とするだけでいいので楽かも知れません。</p>
<pre class="brush:javascript;">var DEBUG = true;

    log("なんとか");
    // DEBUG - http://gist.github.com/428596
    function log() {
        if ( typeof DEBUG != 'undefined' &amp;&amp; DEBUG ) {
            fbug.apply(this, arguments);
        }
    }</pre>
<p>何かもっと便利なデバッグ関数とか作れそうな気がします。<br />多分Greasemonkeyスクリプトからしか動かないようにできているので(あんまり自信ない)、そこまで危険な事は起こらないかと思いますが安全は保証できないので自己責任でというテンプレを入れておく。</p>
<dl>
<dt><strong>gist: 428596 &#8211; Greasemonkeyから使える関数を追加するuserChrome.js- GitHub</strong></dt>
<dd><a title="gist: 428596 - Greasemonkeyから使える関数を追加するuserChrome.js- GitHub" href="http://gist.github.com/428596">http://gist.github.com/428596</a></dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://efcl.info/2010/0612/res1754/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OAuth for Greasemonkeyのラッパーライブラリ</title>
		<link>http://efcl.info/2010/0610/res1721/</link>
		<comments>http://efcl.info/2010/0610/res1721/#comments</comments>
		<pubDate>Thu, 10 Jun 2010 03:33:32 +0000</pubDate>
		<dc:creator>azu</dc:creator>
				<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://efcl.info/?p=1721</guid>
		<description><![CDATA[Post Now browsing to TwitterをOAuth認証に対応しました &#124; Web scratchでGreasemonkeyスクリプトの「Post Now browsing   to Twitter」をO [...]]]></description>
			<content:encoded><![CDATA[<p><strong><a href="http://efcl.info/2010/0609/res1715/">Post Now browsing to TwitterをOAuth認証に対応しました | Web scratch</a></strong>でGreasemonkeyスクリプトの「<a href="http://userscripts.org/scripts/show/46441">Post Now browsing   to Twitter</a>」をOAuth認証に対応したものを作りました。<br />OAuthのJavaScript実装はいくつかあるみたいですがGreasemonkeyで使う感じになってるものは無かったみたいなので、OAuth.jsを使ったtwitterでのOAuth認証を手助けするラッパーみたいなものを書きました。</p>
<p>xAuthを使えば楽な気もしますがブラウザベースのものはxAuthを使わずに<a href="http://help.twitter.com/requests/982242">OAuthを使ってね</a>との事です</p>
<p>大部分は</p>
<ul>
<li><a href="http://blog.tomatomax.net/archives/2696">TwitterクライアントのOAuth対応(Javascript編) | tomatomax.net</a></li>
<li><a href="http://techno-st.net/2009/11/26/twitter-api-oauth-0.html">Twitter API を OAuth で認証するスクリプトを 0 から書いてみた &#8211; trial and error</a></li>
<li><a href="http://sites.google.com/site/elekmole/twitter4jtop/00-preparation/h-oauth-preparation">H.Basic認証/OAuth認証 (陽昇れども地の底に光届かず)</a></li>
</ul>
<p>を参考に書きました。<br />何となく分かるかも知れませんが、今回扱うアプリはApplication Typeがclientタイプのものです。</p>
<p><a href="http://userscripts.org/scripts/show/78102"><span id="more-1721"></span><br /></a>今回書いたラッパーは以下のOAuthライブラリを簡単に扱うためのものになってます。<br /> OAuth.js<br /> SHA-1.js<br /> <a href="http://code.google.com/p/oauth/source/browse/code/javascript/">http://code.google.com/p/oauth/source/browse/code/javascript/</a> あたりにある。<br /> ラッパーと併せて3つのjsからなりますが、3回も@requireするのは面倒だったので一つのファイルにまとめたソースコードを<strong><a href="http://userscripts.org/scripts/show/78102">OAuth for Greasemonkey for Greasemonkey</a></strong>に置いてあります。<br />OAuth.jsはApache license ver2、SHA-1.jsはBSDライセンスになっています。<br />自分が書いたラッパー部分はMITライセンスとしておきます(基本的に自由に使える)<br />しかし、いつ変更するか分からないので自分で別途保存して@requireする方が良いでしょう。<br />追記: <strong>githubに置いたのでこちらを利用した方がいいと思います</strong></p>
<ul>
<li>
<h4><a href="http://github.com/azu/OAuth-for-Greasemonkey">azu&#8217;s OAuth-for-Greasemonkey at master &#8211; GitHub</a></h4>
</li>
</ul>
<p>以下はラッパー部分だけを抜き出したものです。(2010/08/07現在のソースから)<br /><strong>ここに書いてあるのは古いと思うので上のリンクから適当に見て下さい。</strong></p>
<pre class="brush:javascript;">// TwitterOauth for Greasemonkey
function TwitterOauth(){
    this.initialize.apply(this, arguments);
}
TwitterOauth.prototype = {
    initialize: function(con) {
        var accessor = this.getAccessor();
        if(accessor){
            this.accessor = accessor;
        }else{
            this.accessor.consumerKey = con.consumerKey;
            this.accessor.consumerSecret = con.consumerSecret;
            this.accessor.token = "";
            this.accessor.tokenSecret = "";
        }
    },
    accessor : {
        consumerKey : "",
        consumerSecret: "",
        token: "",// response access_token
        tokenSecret: "", // response access_token_secret
    },
    // temp for request
    request : {
        token :"",// response oauth_token
        tokenSecret: ""// response oauth_token_secret
    },
    // トークンが取得済みかの真偽値を返す
    isAuthorize : function(){
        var accessor = this.accessor;
        if(accessor.consumerKey &amp;&amp; accessor.consumerSecret &amp;&amp; accessor.token &amp;&amp; accessor.tokenSecret){
            return true;
        }else{
            return false;
        }
    },
    getAccessor : function(){
        var accessor = GM_getValue("OAuthAccessor", null);
        if(accessor){
            return JSON.parse(accessor);
        }else{
            return false;
        }
    },
    // 取得したトークンを保存
    saveAccessor : function(){
        GM_setValue("OAuthAccessor",JSON.stringify(this.accessor));
    },
    deleteAccessor : function(){
        var clientInfo = {
            consumerKey: this.accessor.consumerKey,
            consumerSecret: this.accessor.consumerSecret,
        }
        GM_deleteValue("OAuthAccessor");
        this.initialize(clientInfo);
    },
    // 認証ページのURLを取得
    getRequestToken : function(callback){
        var message = {
          method: "GET",
          action: "https://twitter.com/oauth/request_token",
          parameters: {
            oauth_signature_method: "HMAC-SHA1",
            oauth_consumer_key: this.accessor.consumerKey
          }
        };
        OAuth.setTimestampAndNonce(message);
        OAuth.SignatureMethod.sign(message, this.accessor);
        var target = OAuth.addToURL(message.action, message.parameters);
        var self = this;
        var options = {
          method: message.method,
          url: target,
          onload: function(d) {
            if(d.status == 200){
                var res = d.responseText;
                var parameter = self.getParameter(res);
                self.request.token = parameter&#91;"oauth_token"&#93;;
                self.request.tokenSecret = parameter&#91;"oauth_token_secret"&#93;;
                // requestURLを引数にcallback
                if(callback){
                    callback("https://twitter.com/oauth/authorize?oauth_token="+self.request.token);
                }
            }else{
                alert(d.statusText);
            }
          },
        };
        GM_xmlhttpRequest(options);

    },
    // pinを元にAccess Tokenを取得して保存、callbackにはaccessorオブジェクトを渡す
    getAccessToken : function(pin ,callback) {
        var message = {
          method: "GET",
          action: "https://twitter.com/oauth/access_token",
          parameters: {
            oauth_signature_method: "HMAC-SHA1",
            oauth_consumer_key: this.accessor.consumerKey,
            oauth_token: this.request.token, // Request Token
            oauth_verifier: pin
          }
        };
        OAuth.setTimestampAndNonce(message);
        OAuth.SignatureMethod.sign(message, this.request);
        var target = OAuth.addToURL(message.action, message.parameters);
        var self = this;
        var options = {
          method: message.method,
          url: target,
          onload: function(d) {
            if(d.status == 200){
                /* 返り値からAccess Token/Access Token Secretを取り出す */
                var res = d.responseText;
                var parameter = self.getParameter(res);
                self.accessor.token = parameter&#91;"oauth_token"&#93;;
                self.accessor.tokenSecret = parameter&#91;"oauth_token_secret"&#93;;
                // Accessorの保存
                self.saveAccessor();
                if(callback){
                    callback(self.accessor);
                }
            }else{
                alert(d.statusText);
            }
          },
        };

        GM_xmlhttpRequest(options); // 送信
    },
    // api+?+query にアクセスした結果をcallbackに渡す
    get : function(api, query, callback) {
        var btquery = (query)? "?"+this.buildQuery(query) : "";
        var message = {
          method: "GET",
          action: api + btquery,
          parameters: {
            oauth_signature_method: "HMAC-SHA1",
            oauth_consumer_key: this.accessor.consumerKey,// queryの構築
            oauth_token: this.accessor.token // Access Token
          }
        };
        OAuth.setTimestampAndNonce(message);
        OAuth.SignatureMethod.sign(message, this.accessor);
        var target = OAuth.addToURL(message.action, message.parameters);
        var options = {
          method: message.method,
          url: target,
          onload: function(d) {
            if(d.status == 200){
                if(callback){
                    callback(d.responseText);
                }
            }else{
                callback(d.statusText);
            }
          },
        };
        GM_xmlhttpRequest(options); // 送信
    },
    post : function(api, content, callback) {
        var message = {
          method: "POST",
          action: api,
          parameters: {
            oauth_signature_method: "HMAC-SHA1",
            oauth_consumer_key: this.accessor.consumerKey,
            oauth_token: this.accessor.token // Access Token
          }
        };
        // 送信するデータをパラメータに追加する
        for ( var key in content ) {
          message.parameters&#91;key&#93; = content&#91;key&#93;;
        }
        OAuth.setTimestampAndNonce(message);
        OAuth.SignatureMethod.sign(message, this.accessor);
        var target = OAuth.addToURL(message.action, message.parameters);
        var options = {
            method: message.method,
            url: target,
            onload: function(d) {
                if (d.status == 200) {
                    if (callback) {
                        callback(d.responseText);
                    }
                } else {
                    // typeof d == object
                    callback(d);
                }
            }
        };
        GM_xmlhttpRequest(options); // 送信
    },
    // GM_xmlhttpRequest風に使う
    xhr : function(opts){
        if(!(opts &amp;&amp; opts.url &amp;&amp; opts.method)){
            GM_log("URLまたはメソッドが指定されていません");
            return;
        }
        var message = {
          method: opts.method,
          action: opts.url,
          parameters: {
            oauth_signature_method: "HMAC-SHA1",
            oauth_consumer_key: this.accessor.consumerKey,
            oauth_token: this.accessor.token // Access Token
          }
        };
        // POST - opts.dataは文字列でもオブジェクトでも可能にする
        if(opts &amp;&amp; opts.method.toLowerCase() == "post" &amp;&amp; opts.data){
            if(typeof(opts.data) === "string"){// 文字列からパラメータオブジェクトを作る
                opts.data = this.getParameter(opts.data);
            }
            var content = opts.data;
            if(typeof(content) === "object"){
                for(var key in content) {
                    message.parameters&#91;key&#93; = content&#91;key&#93;;
                }
            }
        }
        OAuth.setTimestampAndNonce(message);
        OAuth.SignatureMethod.sign(message, this.accessor);
        opts.url = OAuth.addToURL(message.action, message.parameters);// URLを書き換え
        GM_xmlhttpRequest(opts);// 送信
    },
    // utility関数
    // http://kevin.vanzonneveld.net
    urlencode : function (str) {
        str = (str+'').toString();
        return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').
                                                                        replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+');
    },
    // オブジェクトからクエリを生成
    buildQuery : function(formdata, numeric_prefix, arg_separator) {
        // *     example 1: http_build_query({foo: 'bar', php: 'hypertext processor', baz: 'boom', cow: 'milk'}, '', '&amp;amp;');
        // *     returns 1: 'foo=bar&amp;amp;php=hypertext+processor&amp;amp;baz=boom&amp;amp;cow=milk'
        // *     example 2: http_build_query({'php': 'hypertext processor', 0: 'foo', 1: 'bar', 2: 'baz', 3: 'boom', 'cow': 'milk'}, 'myvar_');
        // *     returns 2: 'php=hypertext+processor&amp;myvar_0=foo&amp;myvar_1=bar&amp;myvar_2=baz&amp;myvar_3=boom&amp;cow=milk'
        var value, key, tmp = &#91;&#93;;
        var self = this;
        var _http_build_query_helper = function (key, val, arg_separator) {
            var k, tmp = &#91;&#93;;
            if (val === true) {
                val = "1";
            } else if (val === false) {
                val = "0";
            }
            if (val !== null &amp;&amp; typeof(val) === "object") {
                for (k in val) {
                    if (val&#91;k&#93; !== null) {
                        tmp.push(_http_build_query_helper(key + "&#91;" + k + "&#93;", val&#91;k&#93;, arg_separator));
                    }
                }
                return tmp.join(arg_separator);
            } else if (typeof(val) !== "function") {
                return self.urlencode(key) + "=" + self.urlencode(val);
            } else {
                throw new Error('There was an error processing for http_build_query().');
            }
        };

        if (!arg_separator) {
            arg_separator = "&amp;";
        }
        for (key in formdata) {
            value = formdata&#91;key&#93;;
            if (numeric_prefix &amp;&amp; !isNaN(key)) {
                key = String(numeric_prefix) + key;
            }
            tmp.push(_http_build_query_helper(key, value, arg_separator));
        }

        return tmp.join(arg_separator);
    },
    // Query String から 連想配列を返す
    getParameter: function(str){
      var dec = decodeURIComponent;
      var par = {}, itm;
      if(typeof(str) == 'undefined') return par;
      if(str.indexOf('?', 0) &#62; -1) str = str.split('?')&#91;1&#93;;
      str = str.split('&amp;');
      for(var i = 0; str.length &#62; i; i++){
        itm = str&#91;i&#93;.split("=");
        if(itm&#91;0&#93; != ''){
          par&#91;itm&#91;0&#93;&#93; = typeof(itm&#91;1&#93;) == 'undefined' ? true : dec(itm&#91;1&#93;);
        }
      }
      return par;
   }
};
</pre>
<p>OAuth認証を手助けすることを目的に書いたので、アクセストークンを使って実際にAPIをたたく部分のTwitterOauth.getやTwitterOauth.postは適当です。<br />ラッパーの動作自体はそこまで難しい事はやってないので、<strong>OAuth認証の手順を理解する方が大切</strong>です。<br /><a href="http://dev.twitter.com/apps">Twitter Applications | dev.twitter.com</a> から自分の作成するGreasemonkeyをnew appから登録しておきます。<br />Application TypeはClientならPINコードを使うタイプ、Browserなら認証したときにリダイレクトするURLを決めてそのURLでアクセストークンを受け取れます。今回は<strong>ClientタイプつまりPINコードを使う方法</strong>です。</p>
<div id="attachment_1745" class="wp-caption alignnone" style="width: 310px"><a href="http://efcl.info/wp-content/uploads/2010/06/sshot-2010-06-10-4.png"><img class="size-medium wp-image-1745" title="sshot-2010-06-10-4" src="http://efcl.info/wp-content/uploads/2010/06/sshot-2010-06-10-4-300x284.png" alt="" width="300" height="284" /></a><p class="wp-caption-text">登録でClientを選ぶ</p></div>
<p>ユーザーにPINコードをコピーさせてそれを入力させるという動作が、普通のWebサービスではあまり見ない流れだと思います。このラッパーでやっているOAuth認証の流れを簡単に図にするとこんな流れです。(Browserタイプよりユーザーの負担が大きい)</p>
<p><a href="http://efcl.info/wp-content/uploads/2010/06/4853f6fc7d7316c872b273d972580a55.png"><img class="aligncenter size-medium wp-image-1724" title="シーケンス図0" src="http://efcl.info/wp-content/uploads/2010/06/4853f6fc7d7316c872b273d972580a55-270x300.png" alt="" width="270" height="300" /></a>もっとコアの流れをみるなら<a href="http://d.hatena.ne.jp/furyu-tei/20090929/1254225568">OAuthのやり取りを読み取ってみる &#8211; 風柳メモ</a> とか</p>
<p>実際にGreasemonkeyでやってる動画 <a href="http://www.youtube.com/watch?v=8oXTuZk5xAk">YouTube &#8211; Post Now browsing to Twitter for Greasemonkey</a><br />かなり大雑把な流れなので詳しくは他のサイトを参照して下さい。<br />基本的にはトークンなどを元にしてOAuth.jsのOAuth.SignatureMethod.signでシグネチャを作成して、それを元に新たなトークンを受け取ってまたOAuth.SignatureMethod.signでシグネチャを作るみたいな繰り返しです。<br />最終的にAPIを叩く際に必要なものがアクセストークンとなります。</p>
<ol>
<li>リクエストトークンとリクエストトークンシークレットをもらいに行く。(タイムスタンプとconsumerKeyで一意な情報を元にする)</li>
<li>もらってきたリクエストトークンを使って認証ページのURLを作る。<br />(https://twitter.com/oauth/authorize?oauth_token= + リクエストトークンが認証ページのURL)</li>
<li>ユーザーに認証の動作を行ってもらう。</li>
<li>認証するとPINコードが表示されるので、ユーザーにPINコードをコピーしてアプリに入力してもらう。</li>
<li>入力してもらったPINコードを元にアクセストークンとアクセストークンシークレットをもらいに行く。(アクセストークンがAPIにたたくときに必要となるものです。リクエストトークンは認証時に必要となるだけなので使い捨てです。)</li>
<li>アクセストークンをもらったら保存して完了。</li>
</ol>
<p>実際にラッパーを使った大筋の流れとして、まずラッパーを呼び出して各自のアプリ情報を渡して初期化します。</p>
<pre class="brush:javascript;">// http://dev.twitter.com/apps に書いてある。
var clientInfo = {
    name: 'アプリ名',
    consumerKey: '各自アプリ',
    consumerSecret: '各自アプリ',
}
// TwitterOauthにクライアント情報を渡してnewする(必須)
var tw = new TwitterOauth(clientInfo);
</pre>
<p>そして、tw.isAuthorize() で既にアクセストークンを持っているかを調べられる(持ってたら直ぐにAPIをたたける)ので、持っていなかったらリクエストトークンをもらいに行きます。</p>
<pre class="brush:javascript;">if(tw.isAuthorize()){// まだ認証していない
    tw.getRequestToken(callback);
    // callbackに渡る引数は認証ページのURL
}
</pre>
<p>getRequestTokenのcallback関数には認証ページのURLが渡るので、それを元にユーザーにそのページに行ってもらいアプリのOAuth認証してPINコードをコピーしてきてもらいます。<br />PINコードを入力してもらう必要があるので、適当な入力エリアを作っておく必要もあります。</p>
<pre class="brush:javascript;">// アクセストークンをもらいに行く。
// アクセストークンを取得できたら自動で保存処理を行っています。
// callbackにはaccessor(アクセストークンなどが入ったオブジェクト)を渡しますが、使い道は…
tw.getAccessToken(callback);
// 取得したアクセストークンを捨てたいときは
// tw.deleteAccessor() で破棄できます。
</pre>
<p>アクセストークンを取得して保存できたらOAuth認証は完了です。<br />アクセストークンを持っていればAPIをたたけるので、tw.get、tw.postを使ってAPIを叩きます。</p>
<pre class="brush:javascript;">   // get第二引数はクエリになるオブジェクトを渡す
   // 以下はapi?q=oauth&amp;per_page=5 となる。
    var query = {
        q : "oauth",
        per_page : 5
    }
    // get : function(api, query, callback)
    tw.get("http://api.twitter.com/1/users/search.json" , query ,function(res){
        if(typeof res != "object"){// Twitterのエラー時はリスポンスのオブジェクトをそのまま返すため
            console.log(res); // firebug
        }
    })
</pre>
<pre class="brush:javascript;">    // postはそのまま何も工夫がない。
    var content = {status: "update test", source: clientInfo.name};
    tw.post('http://twitter.com/statuses/update.json', content ,function(){
        console.log(res); // firebug
    });
</pre>
<p><a href="http://apiwiki.twitter.com/Twitter-API-Documentation">Twitter API Wiki / Twitter API Documentation</a> を参考に使う。<br />HTTP MethodがGETならそのクエリになるようにAPIのURLとクエリオブジェクトをtw.getに渡す。<br />HTTP MethodがPOSTなら、APIのURLにcontentとなるオブジェクトを渡す。という感じでかなり適当な作りをしています。<br /><a href="http://code.google.com/p/twigadge/source/browse/trunk/js/twigadge.js">twigadge</a> のようにもう少し機能別に作った方が使いやすくなると思います。</p>
<p>以上で説明のようなそうでないものは終わりですが、以下に簡単なサンプルGreasemonkeyを置いてあります。</p>
<ul>
<li><a href="http://gist.github.com/418274">GreasemonkeyでOAuth認証を手助けするライブラリとそのサンプル</a><br />(猿アイコンのユーザースクリプトから認証とget、postのテストができます。できれば自分のconsumerKeyとか使ってね。)</li>
</ul>
<p><strong>追記</strong></p>
<p>新たにxhrというメソッドを追加しました。(上記ならtw.xhr({})みたいな使い方)<br />xhrメソッドはGM_xmlhttpRequestと同じようにオプションのオブジェクトを引数にとって、APIと通信します。<br />GM_xmlhttpRequestをラップしているので、感覚的にはGM_xmlhttpRequestと同じ感じで使えると思います。<br />一つサンプル</p>
<p><script src="http://gist.github.com/511308.js?file=twitter%20OAuth%20test.user.js"></script></p>
<p>// ↓↓↓↓Your Script↓↓↓↓ の所までがOAuth認証のパネルを作ったりするテンプレート的なものです。<br />OAuth認証が済んでない（tw.isAuthorize()==false)なら途中でreturnされるので、既存コードの上部に<em>// ClientInfomation</em> から <em>// ↓↓↓↓Your Script↓↓↓↓</em>までをコピペして、API周りを修正すれば簡単にOAuth認証に対応できます。(できる限り自分の登録したアプリのclientInfoを使って下さい)<br />当たり前ですが、その時@requireでOAuth.jsの3点セットを読み込んでおいて、インストールし直す必要があります(<strong>@requireが動作するのはインストール時のみ</strong>)<br />APIを叩くときにOAuth認証で得たアクセストークンからシグネチャを作る必要があるので、GM_xmlhttpRequestでそのままAPIを叩いたままでは通りません。そこで今回追加したxhrメソッドの出番です。<br />Getメソッドの場合だとGM_xmlhttpRequestをtw.xhrに変更するだけで既存のコードは通ると思います。<br />POSTメソッドもGM_xmlhttpRequestをxhrメソッドに変えるだけで大体通ると思います。<br />GM_xmlhttpRequestだとdata部分は文字列で書くので、そのまま&#8221;foo=fizz&amp;bar=bazz&#8221;と書く方法と下のようにオブジェクト書く方法が使えます。(オブジェクトの方が効率がいい)</p>
<pre>data : {
    foo:fizz,
    bar:bazz,
}</pre>
<p>サンプルは猿アイコンを右クリックからでるユーザーコマンドで、xhrのそれぞれgetとpostをテストする関数が動作するだけです。</p>
<p>以下リンクまとめ</p>
<p>ライブラリの置き場所。こっちが多分一番新しい。</p>
<dl>
<dt><strong>azu&#8217;s OAuth-for-Greasemonkey at master &#8211; GitHub</strong></dt>
<dd><a title="azu's OAuth-for-Greasemonkey at master - GitHub" href="http://github.com/azu/OAuth-for-Greasemonkey">http://github.com/azu/OAuth-for-Greasemonkey</a></dd>
</dl>
<dl>
<dt>実際にラッパーを使ったGreasemonkey</dt>
<dt><strong>Post Now browsing to Twitter for Greasemonkey</strong></dt>
<dd><a title="Post Now browsing to Twitter for Greasemonkey" href="http://userscripts.org/scripts/show/46441">http://userscripts.org/scripts/show/46441</a></dd>
</dl>
<dl>
<dt>上のGreasemonkeyで使ってるラッパーライブラリとかをまとめたもの</dt>
<dt><strong>OAuth for Greasemonkey for Greasemonkey</strong></dt>
<dd><a title="OAuth for Greasemonkey for Greasemonkey" href="http://userscripts.org/scripts/show/78102">http://userscripts.org/scripts/show/78102</a></dd>
</dl>
<p>&nbsp;</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 6332px; width: 1px; height: 1px;">HTTP MethodがGETならそのクエリになるようにAPIのURLとクエリオブジェクトをtw.getに渡す。</div>
]]></content:encoded>
			<wfw:commentRss>http://efcl.info/2010/0610/res1721/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Post Now browsing to TwitterをOAuth認証に対応しました</title>
		<link>http://efcl.info/2010/0609/res1715/</link>
		<comments>http://efcl.info/2010/0609/res1715/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 10:55:01 +0000</pubDate>
		<dc:creator>azu</dc:creator>
				<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[設定]]></category>

		<guid isPermaLink="false">http://efcl.info/?p=1715</guid>
		<description><![CDATA[Twitterへ今見ているサイトをコメントと共に投稿する「Post Now browsing  to Twitter」がOAuth認証に対応しました。このGreasemonkeyをインストールする前に、以前のバージョン( [...]]]></description>
			<content:encoded><![CDATA[<p>Twitterへ今見ているサイトをコメントと共に投稿する「<a href="http://userscripts.org/scripts/show/46441">Post Now browsing  to Twitter</a>」が<strong>OAuth認証に対応</strong>しました。<br />このGreasemonkeyをインストールする前に、<strong>以前のバージョン(2010年6月より前)のものを入れている場合はそれをアンインストール</strong>してから、改めて「<a href="http://userscripts.org/scripts/show/46441">Post Now browsing to Twitter</a>」をインストールして下さい。(以前と設定の互換が無くなったため設定ごと破棄をお勧めします)<br />ツール→Greasemonkey(もしくはステータスバーの猿アイコン)→ユーザースクリプトの管理→Post Now browsing to  Twitterを選択→✓関連付けられた設定も削除にチェック→アンインストール</p>
<p><span id="more-1715"></span>主な変更点を箇条書きすると以下のような感じです。</p>
<p>変更内容<br />1. OAuth対応<br />BASIC認証が2010年6月末に廃止されるためOAuth認証に対応しました。<br />設定画面から認証できます。<br />BlowsingNow!などの外部サーバを経由するものとは違い、PINコードを使ってGreasemonkeyスクリプト単体でOAuth認証を行います。<br />2. 入力UIがサイトの影響を受けなくなった<br />入力UI自体は以前と同じですが、サイト側CSSの影響を受けることがあったのを改善し、影響を受けないようにしました。<br />3. 設定項目の変更<br />以前と設定項目が変わったため設定の互換性がありません。<br />そのため、<strong>以前のものはアンインストールから</strong>インストールして下さい。</p>
<ol>
<li>短縮URLの選択肢が増えた<br /> 新たにbit.ly(j.mp)、goo.glを追加しました。<br /> bit.ly(j.mp)はAPIの設定も行えます。</li>
<li>Ctrl+Enterでのポスト<br /> デフォルトはEnterで送信ですが、設定のチェックの意味が逆になったという変更。(正直気にすることはない)<br /> 設定でCtrl+Enterでポストするように変更できます。</li>
<li>Twitterアカウントの入力項目廃止<br /> 以前はベーシック認証を使っていたので、Twitterアカウントの入力項目がありましたが、OAuth認証に対応したため廃止しました。</li>
</ol>
<p>OAuth認証は設定の一番下に表示されます。(いつでも認証を解除する事ができます。)<br />4. 短縮URLのリトライ機能<br />短縮URLサービスのサーバにアクセスできないときに(5秒でタイムアウト)、別の短縮URLサービスに切り替えて短縮します。</p>
<p>ぱっとした変化を見ると、OAuthに対応したのと、bit.ly、goo.glなどの短縮URLが使えるようになったぐらいかな。</p>
<h3>OAuth認証の手順</h3>
<p>Greasemonkey 単体でOAuth認証を行うようにしたので手順が少し複雑です。<br />以下の動画を参考にして下さい。</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/8oXTuZk5xAk&amp;hl=ja_JP&amp;fs=1&amp;rel=0&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="385" src="http://www.youtube.com/v/8oXTuZk5xAk&amp;hl=ja_JP&amp;fs=1&amp;rel=0&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>文字で書くと、</p>
<ol>
<li>ステータスバーのGreasemonkeyアイコンを右クリック<br />ユーザースクリプトコマンド→Post Now browsing to Twitter Settingから設定画面へ</li>
<li>OAuth認証をまだしてないなら、&#8221;Sign in with Twitter&#8221;ボタンが表示されるのでクリック</li>
<li>OAuth認証ページが開くので、そこへ行き許可(Allow)する。</li>
<li>PINコードが表示されるのでCtrl+Cなどでコピーする。</li>
<li>再び設定画面に戻り、インプットボックスへPINコードをCtrl+V(ペースト)して、Comfirmボタンを押す。</li>
<li>Success!出たら、ページでショートカットキー(デフォルトはCtrl+Shift+Enter)を押し、入力UIを出す。</li>
<li>適当にコメントとかを書いたらEnter(設定でCtrl+Enterに変えられます)でTwitterへポストする</li>
<li>投稿できたらOK</li>
</ol>
<p>5ぐらいまでがOAuth認証の手順で、6以降は投稿する手順。</p>
<p>以下感想<br />OAuthに対応してるGreasemonkeyが皆無で結局自分で色々書かないといけなかった。<br />OAuth.jsとかライブラリを使ってるので結構サイズが大きくなった。<br />OAuthページとかのアイコンがやっつけ感酷いのでアイコン募集中。</p>
<dl>
<dt>機能説明ページ</dt>
<dt><strong>Post Now browsing to Twitter | Web scratch</strong></dt>
<dd><a title="Post Now browsing to Twitter | Web scratch" href="../post-now-browsing-to-twitter/">http://efcl.info/post-now-browsing-to-twitter/</a></dd>
</dl>
<dl>
<dt>スクリプト配布ページ</dt>
<dt><strong>Post Now browsing to Twitter for Greasemonkey</strong></dt>
<dd><a title="Post Now browsing to Twitter for Greasemonkey" href="http://userscripts.org/scripts/show/46441">http://userscripts.org/scripts/show/46441</a></dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://efcl.info/2010/0609/res1715/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
