AP4R で Parallels の壁を越える

Mac にようやく慣れてきたこのごろ、ストレスの非常に少い環境で、いままでとの快適さの違いを実感中。
そこで、ストレスが減ってきたために、ひとつ気になる点が目立ちはじめた。メーラーOutlook を使う都合上、Parallels DesktopWindows を動かしてる。そこで、メールの中にある URL をポチッと押したときに、Windows 上の Firefox でページが開くのがとても気になる。そこで Mac 側の Firefox が開いてほしいんよね。というわけで、なんとかして http(s) を MacFirefox でひらくようにしてみる。

たぶん、それなりに簡単に出来るんじゃ、、、というのは無視して、AP4R を使ってやる。あくまでも最小構成は目指しません。というわけで、使うものは、以下。

MozRepl の練習

一番わからないところから入る。MozLab という拡張。はっきりいってこれが一番大事で、あとはどうでもよかったりする。
参考はここ、Ruby スクリプトも参考にさせていただきました。

最速インターフェース研究会 :: Firefoxの拡張MozLabの中に含まれるMozReplがヤバすぎる件について

http://la.ma.la/blog/diary_200609280045.htm

開始するには、[ツール]-[MozLab]-[Start Repl] で、ローカルホストで listen する telnet サーバが起動。あとはコマンドラインででもなんでも繋ぐだけ。ポートは 4242。日本では微妙か?

コマンドラインでひとしきり試し打ちしたあと、Ruby スクリプトを書いてみる。のだけど、ここはワザワザ Rails アプリにする。これも牛刀だなぁ。

require 'net/telnet'

class FirefoxController < ApplicationController
  def open
    if request.post?
      telnet = nil
      begin
        prompt = /^repl> /
        telnet = Net::Telnet.new("Host" => "localhost", "Port" => 4242,
                                 "Timeout" => 10, "Prompt" => prompt)
        telnet.waitfor(prompt)
        telnet.cmd <<-JS_SCRIPT do |c|
          (function(){
            window.top.getBrowser().selectedTab
               =  window.top.getBrowser().addTab(\"#{params[:url]}\");
            return true;
          })();
        JS_SCRIPT
          logger.info("Opened URL in Firefox: #{params[:url]}")
        end
      ensure
        telnet.close if telnet
      end
    end
  end
end

ビュー

<% form_tag :action => "open" do -%>
  <%= hidden_field_tag 'for_ap4r', "true" %>
  <%= text_field_tag 'url', params[:url] || "http://ap4r.rubyforge.org/wiki/wiki.pl", :size => 40  %>
  <%= submit_tag 'open' %>
<% end -%>

これで、 http://localhost:3000/firefox/open をひらいて、URL いれて open とやると別タブで開くところまで OK。hidden は、AP4R のレスポンスに(今のところ)必要なちょっといけてない仕様。見えなければ、スタイルででも良い。見えても気にしないならテキストでも良い。

AP4R 設定、起動

AP4R をインストールしてあれば、ap4r_setup でワークスペースを生成。今回は、設定ファイルと起動スクリプトとをそれぞれ一つしか要らないので、RAILS_ROOT/config/queues_disk.cfg, RAILS_ROOT/script/mongrel_ap4r にコピー、生成したワークスペースは削除。ローカルホストの外側からアクセスしたいので、reliable-msg にちょっと変更。修正箇所は、id:kiwamu さんとこに書いてあるとおり。

kiwamu日記 - ap4r-0.3.0 リリース
reliable-msg へのパッチをあてる
http://d.hatena.ne.jp/kiwamu/20070406/1175859018

加えて、queue-manager.rb については、修正した行の、localhost を、#{drb['host']||'localhost'} にしておく。

queues_disk.cfg で、drb: の設定を少々変更。

  • listen する NIC を設定。ぼくは単純に全部で。セキュリティに気をつかう環境では絞ったほうがよいかもね。(Rails も注意、ローカルホストだけで良い)
  • ACL をいじって、Windows 側の IP を ALLOW に入れておく

修正後

drb:
  host: 0.0.0.0
  port: 6438
  acl: allow 127.0.0.1 allow ::1 allow [ここに Windows の IP]

起動は、ふつうに。

% mongrel_ap4r start -d -A config/queues_disk.cfg

動作確認を IRB で。キューの名前は、queue. で始まれば(ここでは)何でも良い。

>> require 'reliable-msg'
=> ["ReliableMsg"]
>> q = ReliableMsg::Queue.new 'queue.firefox.open'
=> #<ReliableMsg::Queue:0x264b980 @queue="queue.firefox.open">
>> q.put 'url=http://www.google.co.jp', {:dispatch_mode => :HTTP, :target_url => "http://localhost:3000/firefox/open"}

FirefoxGoogle のトップかなにかが開くはず。

Windows の HTTP を処理するスクリプトを書いて設定

URL を貰ったら、それをパラメータとしてメッセージを一つ、キューにいれるスクリプト post_url.rb。Windows 側に、RubyGems とか reliable-msg を入れるのが面倒だったら、DRb のみでもいける。そのときは、reliable-msg の ReliableMsg::Queue とか、ReliableMsg::QueueManager を見て、パラメータの渡し方を見れば OK。

url = ARGV[0]

require 'rubygems'
require 'reliable-msg'

q = ReliableMsg::Queue.new "queue.firefox.open", :drb_uri => "druby://[ここには Mac の IP を入れる]:6438"
q.put "url=#{url}", {:dispatch_mode => :HTTP, :target_url => "http://localhost:3000/firefox/open"}

同じフォルダに、post_url.cmd 作成。

ruby %~dp0post_url.rb %*

あとは、このファイルを、HTTP プロトコルで呼ばれるプログラムに関連付ける。HKCU\Software\Classes\HTTP 以下に値を書き込む。Microsoft のサポート情報はこのへん http://support.microsoft.com/default.aspx/kb/256986/ja 。あとは、HKEY_CURRENT_USER\Software\Classes\HTTP でググッたらいくらか出てくるので。http://www.codingforums.com/showthread.php?t=36323 は丁寧に書いてある。
ここまで出来たら、Outlook を開いて、なんか URL をクリックすると、MacFirefox が新しいタブで開いてくれました。プロセス経由しすぎ。

自分への補足

  • レジストリを、HKCR 以下でいじっていた気がする。一人で使っているから良いか
  • https はまだ設定してない。.html は、ちょっと無理か、Parallels 3 なら?
  • AP4R にローカルコマンドを実行する consumer を実装したい。そしたら Rails プロセス要らない
  • リンクをクリックすると、.cmd の実行のためにコマンドプロンプトが開くのがウザい
  • いくつか、windows 側で開きたいサイトもあるので、post_url.rb にフィルタ書く