Home > Latest topics

Latest topics 近況報告

たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。

萌えるふぉくす子さんだば子本制作プロジェクトの動向はもえじら組ブログで。

宣伝1。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

宣伝2。Firefox Hacks Rebooted発売中。本書の1/3を使って、再起動不要なアドオンの作り方のテクニックや非同期処理の効率のいい書き方などを解説しています。既刊のFirefox 3 Hacks拡張機能開発チュートリアルと併せてどうぞ。

Firefox Hacks Rebooted ―Mozillaテクノロジ徹底活用テクニック
浅井 智也 池田 譲治 小山田 昌史 五味渕 大賀 下田 洋志 寺田 真 松澤 太郎
オライリージャパン

Page 31/239: « 27 28 29 30 31 32 33 34 35 »

タブをまとめてリロードする時にちょっとずつリロードを行うようにする「Reload Tabs Progressively」をリリースしたよ - Feb 02, 2010

とりあえずMozilla Add-onsにうぷした

マルチプルタブハンドラについて「複数のタブをリロードする時、全部一気に読み込み始めるんじゃなく、3秒ずつ位間を空けて読み込むような機能を付けて欲しい」という風な要望をもらったんだけど、マルチプルタブハンドラに依存する機能にするよりは単機能で使えるようにしといた方がいいような気がしたので、サクッと作って公開した。

  • BarTapで待機状態になってるタブについては、リロードではなく普通の読み込み開始になります。
  • ナローバンドだったりPCが遅かったりすると効果的かもしれない。
  • 副作用として、いつまでもリロード中になってしまうようなページ(Cometでセッション張りっぱなしでレスポンスを待つようなページ)があると他のタブの再読み込みがいつまで待っても始まらないかもしれません。
  • tabbrowser要素のreloadTab()メソッドとreloadAllTabs()メソッドをゴッソリ入れ替えてるので、この辺を触ってるアドオンがもしあったら衝突するかも。

こういう風にブラウザそのものの挙動を変えてしまうアドオンはChrome(Chromium)では作るのは難しいような気がするけど、実際にチャレンジしたわけではないので、ほんとのところはどうなんだろ。

束縛 - Feb 01, 2010

ひょっとしたら同じような事を既に書いたかもしれないけど。

僕は、あまり束縛はしたくないと考えてる。理由はいくつかある。

  • 相手が嫌がる事をなるべくしたくない。束縛されるのは嫌だと言ってる人の事を束縛するのは、タバコが嫌いだと言ってる人の目の前で喫煙するのと同じような事だと思ってる。
    • それで自分が嫌われるのが怖い。
    • 相手のためを思いやって、というのが全く無いわけではないと思うけど。
  • 束縛しても無駄だと思ってる。同じ家に住んでて、同じ会社で働いてて、という風な条件でも揃ってない限り、完璧な束縛は不可能だと思う。抜け道はいくらでもある、浮気とか二股とかやろうと思えばいくらでもできる、と思う。
    • 「束縛しないと浮気される」のであれば、その関係は既に破綻してるんだと思う。
    • そんな状態なんだったら、束縛しててもそれをかいくぐって浮気する道を探られるんじゃないの?
  • 行動は縛れても、思想は縛れないと思ってるし、縛ろうとしてはいけないと思ってる。
    • 表現の自由は大事ですよ。
  • そもそも束縛するのが面倒というのもある。
    • 相手の一挙手一投足を監視するのって、それだけで大変だろう。自分の気も休まらないだろう。
    • 探偵とか興信所とか、そんなお金ありません!

「不安にならないのか?」と訊かれたけれども、不安がってもしょうがないというか、相手が束縛を嫌がるからという理由でまず「束縛したくても束縛できない」し、束縛されるのを嫌がってるのを無理に束縛するのはただの嫌がらせにしかならないと思うし、束縛したって(腰の退けた束縛の仕方にしかならないから)いくらでも浮気二股やろうと思えばできると思うし。結局、相手の言ってる事を信じるしかないよね。という感じで僕は開き直ってます。

もちろんその信用を裏切られる事はないと思いたいけれども、もし裏切られても、まあいいか、と。もちろん、本当に裏切られたらきっとものすごいショックを受けるだろうけれども、でも「裏切られる事」を恐れて束縛を強めることが結果的に相手を「裏切り」に走らせる事に繋がるのなら、束縛してもしなくても結局同じだと思う。僕は相手の事を信じる事にした、その上で相手が僕の事を裏切る事にしたんだったらそれはもうどうしようもないだろうなあ、と。裏切って欲しくないと僕が思っていて、そう言っていて、それでも裏切らずにはいられなくなったのであれば、そりゃもうしょうがないよね、と。

ところで、束縛というと「相手が自由意志で何かをしようとすることを、無理矢理引き留める」というイメージがあるけど、「相手がやりたくないと思ってる事を、無理矢理やらせる」のも本質的には同じ事だと思う。料理が嫌いな人に手料理を無理矢理作らせたりとか。クリスマスやバレンタインデーといったイベント事に何かする事を強要したりとか。

束縛って、要は相手の事を完全に支配したい、コントロール下に置きたいと願うという事だと思う。相手をコントロールしたいなんておこがましいと僕は思うし、コントロールしきれるとも思ってない。じゃあ、そんな僕が相手を束縛するというのは、コントロールしきれるとも思ってないしコントロールする権利もないと思っている相手の事を、コントロールしようとするという、賽の河原で石を積むような行為だよね。それって意味無いよね。と思ったら、束縛する気が萎えてしまいました。そんな感じ。

コアJetpackミーティング - Jan 26, 2010

23日にMozilla Japanで行われたコアJetpackミーティングに参加してきました。2月にGomitaさんとあかつかさんがMozilla Corporationまで行く時に持って行く意見・アイデア等をまとめるのが趣旨の会合でした。Mozilla信者な視点だけからでは意見が偏るんじゃないかと思ったので、Chrome拡張機能のえらい人のos0xさんにも来てもらいました。

議題は「Jetpackのスクリプトの開発環境について」「Jetpack Galleryについて」「Jetpackが提供するAPIについて」の3つでした。以下、思い出しながらグダグダ書いてみます。

開発環境について

既存のアドオンを冷遇していくとかの話はさておき、これまで普通のアドオンを作ってた人が、Jetpackで事足りるような機能についてはJetpackでやるようになる、という未来を実現するには何が必要か? という話をしました。

結論としては、Bespin要らないんじゃね、ていうか好きなエディタを使わせて下さい、的な所に意見が集中しました。Bespin自体技術デモの性格が強いような物で、IMEがまともに使えない等のどうしようもない問題を沢山抱えていて、はっきり言って「これで(vim|Emacs|秀丸)を捨てられる!」みたいな未来は当分、つうか絶対に来ないと思われるわけで。かといって、eclipseみたいなファットな開発環境をJetpackの中に突っ込むというのも、それはなんか違うんじゃないの? とも思うし。既にデバッグ用にはFirebugを使うのがお勧めみたいな事も言ってる事だし、適材適所でそれぞれ分担すりゃいいじゃないの。頑張ってここ(BespinとJetpackの連携)に色々と機能追加する事にリソースを作よりも別の所で頑張りませんか? というのが、参加者達の総意だった気がします。

「新規のアドオン開発者」として取り込みたいターゲットと思われるWeb制作の現場の人のためには何をすればいいか? という事を次に議論したんですが、参加者の中にWebデベロッパが一人もいないという状況だったので(ひでーな!)想像だけで議論した限りでは、とりあえず、「スクリプトの頭と尻にお約束の構文を書いたら後はwindow等の見慣れたキーワードに普通にアクセスできる」ような状態にしておいた方がいいんじゃないのか、という事を提案しました。Greasemonkeyが受け入れられたのって、Webページの中に埋め込まれるスクリプトと全く同じ感覚で書けたからだと思うんですよね。で、Webのスクリプトを書く時、名前空間の違いとかクロスウィンドウなスクリプトとかそういうのを意識する事ってまず無くて、1つのフレームの中で動くスクリプトを書く感覚が染み着いてるんじゃないのかと。その感覚でスクリプトを書けるかどうかってのが、Webデベロッパに対する第1印象を決定づけるんじゃないのだろうかと。ちなみに、Google Chromeではこの要求に対する回答として、「コンテントスクリプト」という種類の拡張機能であればWebページ内のスクリプトと同じ感覚で書けるという設計になってるようです。

一般ユーザ、つまり今までアドオンを作った事もなければスクリプトを書いた事もないという層の人に対してはどうか。

グラフィカルプログラミングがどうとかそういう話もチラッと出はしたんですが、そこに力を入れるのもやっぱりJetpackの仕事じゃないんじゃないの? と。そういうのは大学の研究室とかで頭のいい人達が散々やってるわけだし。

ポイントは、「簡単にプログラムをかけるかどうか」「知識が無くてもプログラムをかけるかどうか」ではなくて、そもそも「プログラムを書かなくてもカスタマイズできるかどうか」なんじゃないのか、という指摘が出てました。Ubiquityでは複数のコマンドをユーザが組み合わせて使う事を想定している(これはコマンドラインで複数のコマンドをパイプで繋げて使うような感覚)、というのを引き合いに出して、例えるなら「新しい文房具を簡単に作れるようにする」んじゃなくて「ハサミとホッチキスとセロテープ、という道具を手に入れたユーザがそれを好きなように組み合わせて使えるようにする」という風な。そこが大事なんじゃないのか、と。だから例えばAutoPagerizeのSITEINFO on wedataとか、アップローダに勝手改造版スクリプトをアップロードするみたいな、「スクラッチでスクリプトを書ける人以外でも気軽に改良できる、参加できる」ような仕組みがあるといいんじゃないか? という提案が出ました。そういうAPIがJetpackに標準で入ってて、Jetpack GalleryでユーザがSITEINFOをどんどん追加できるようになってて、APIを使っていればそれを簡単に取得できる、みたいな仕組みが用意されていれば、もっと「Webを便利にしてくれる人」の裾野が広がるのではないかなー。と、僕は思ってます。

Jetpack Galleryについて

Jetpack Galleryへの要望・提案としては、まず前述の話にも出た、JetpackのAPIとも連携したwedataのような仕組みがあるといいんじゃないかという話を出しました。

それと、ドキュメント類が不足してる問題への解として、Galleryに登録されてるスクリプト全部をオンラインで検索できるMXRみたいな機能があればいいんじゃないの?という話も出しました。実際、自分がアドオン作る時でも、使い方が分からないAPIはMDCのドキュメントを見るだけでなく、MXRでFirefoxのソースを検索して「ほうほうこうやって使うのか」と調べる場合が非常に多いです(MDCにドキュメントが無ければそれしかないし)。ドキュメントを書け書けと言っても人はめんどくさがって絶対にそんなもん用意せんのだから、じゃあ既にあるコードをスニペットとして全部活用できるようにすりゃあいいじゃないか、という意図での提案です。

現状のGalleryにはレビューの仕組みがないので危険だ、という話も出ました。これは次の話にも関係してるので、そっちで詳しく書く事にします。

APIについて

ここは議論が割れました。あかつかさんはrawのような仕組み、つまりAPIが用意されてない部分にアクセスしてその気になればなんでもできるような余地を残しておいた方がいいんじゃないのか、という立場で、僕とかは、そういう余地は一切残すべきでないという立場で話をしました。

確かに、そういう余地があったからこそ今のFirefoxのアドオンはここまで色々なものが出てきたわけで、そういう自由度をなくしてしまうのは残念だという感覚は、僕もよく分かります。ただ、だからってFrozenじゃない所に全部アクセスできるようにしてしまうというのも乱暴すぎて、それじゃあ結局今のアドオンのように、Firefoxのバージョンが上がったら使えなくなっちゃいました、アドオンのバージョンアップ待ちです、みたいな状況が絶対また出てくる。それって、Jetpackが謳う「安定したAPIでバージョンごとの非互換から解放されます」という話とまるっきり矛盾してしまうわけです。

それに、レビューの問題もある。今はJetpack GalleryにはAMOのような「レビューが通らないと一般公開されない」という風な仕組みはないけど、「最初は無難そうなスクリプトで登録して関係者を欺いて、後からプライバシーぶっこ抜きなコードを追加したものを自動アップデートで一斉配信して、悪意のある開発者がウマー」という事態を防ぐには(今のGalleryではこれが出来てしまう!)、レビューの仕組みは絶対必要になります。

その時に、rawで生のXPCOM等を直接触れてしまう仕組みがあると、レビュワーは結局全部のコードをしっかり精査しないといけないことになる。レビュワーにも知識と経験が求められる。それでは、今のAMOにありがちな「有能なレビュワーのリソースは限られてるので、レビュー完了まで何ヶ月も待たされてしまう。なので、何ヶ月も最新版が公開されないで放置されてしまう。」という風な状態が、Jetpack Galleryにも発生してしまうわけです。

Jetpackが提供するAPIしか使えないのなら、そういう状況に陥る事を防げる。例えば、「Jetpackが提供するAPIでなければファイルにアクセスできないと」いう仕様で、スクリプトの先頭に書く各種の宣言部分で「このパス以下のファイルしか読み込みません」という宣言を書かなければファイルアクセスは一切できない、ファイルアクセスをする時も宣言された範囲のファイルにしかアクセスできない、そういう設計になったとしましょう。すると、レビュワーは冒頭の宣言部分だけ読めば「こいつは危険だな」とか「こいつは安全だ」といった判断ができて、レビューが早く進むようになる。また、スクリプト作者が面倒くさがって「あらゆるファイルにアクセスする可能性があります」みたいな宣言を書くと、レビュワーから疑われていつまでも放置されるから、いつまで経っても公開されないことになる。なのでスクリプト作者は詳細な指定を宣言に嫌でも書かないといけない事になる。そういう風に、みんながみんな自分の利益を最大化する事が結果としてコミュニティ全体の利益に繋がるような仕組みを、今から作る事ができるわけです。

Jetpackという仕組みをゼロから作ろうとしてる今こそ、過去のアドオンの「Firefoxのバージョンに依存する」「レビューにめちゃめちゃ時間がかかって、いつまでも最新バージョンが公開されない」という問題と決別するチャンスなんですよ。なんでそのチャンスをみすみす見逃して、同じ問題をまたJetpackの世界に持ち込むんですか? と。

だいたい、Jetpackが本体に入った後も既存のアドオンの仕組みは依然として残り続けるわけで、偉い人はXULとXPCOMを全部なくすとか言ってるけど実際にコアのコードを書いてる人曰く「そんなの絶対無理(加藤さん・談)」なわけで、だったら「安定したAPIのJetpackで、まずは作ってみる。それでできない事が出てきたら、自由度の高い(でもAPIが不安定な)既存のアドオンの仕組みで作る方にステップアップする」というスキームでやっていけばいいじゃないですか。と。

他には、プラットフォーム(XULRunner、Geckoのレイヤ)でやるべき事とJetpackがやるべき事はちゃんと切り分けて欲しいという話も出ました。例えば音声取り込み用のAPIなんてのは、Jetpackにプラットフォーム別のバイナリをブチ込むんじゃなくて、Geckoで面倒見るべき話でしょう。そのせいでJetpackの構成ファイルが何MBにもなってダウンロードも起動も遅くなって、その一方で、ほんのちょっと起動を速くするためにFUELを廃止するって、何ですかそれは? 何か大事な事を履き違えてるんじゃあないですか? と。

とにかく、Jetpackというプロジェクトが何にフォーカスしているのか、プロジェクトのポリシーが僕には全然見えない。Jetpackをウォッチし続けてるcon_mameさんもteramakoさんも、Jetpackの方針が揺らいでるように見えるという風におっしゃってました。なので、Mozilla Corporationに行く時にはGomitaさんとあかつかさんにはぜひとも、Jetpackが最優先しようとしているのは何なのか? 他のものを犠牲にしてでも貫かないといけないと考えているポイントはどこなのか? というプロジェクトの指針を明らかにしてきて欲しい、という事をこのミーティングの参加者達の最大の関心事として託しておきました。

余談:イノベーションの話

ミーティングの最中にtwitterで言及されてMicrosoftのAzureの話を読みました。既存の開発者のために腐心しすぎるとイノベーションが起こらなくなってしまう、僕のようなロートルがいつまでもでかい顔して居座っていられるような状況にしてしまっては新しいプレーヤーが参入して来れない、というのは実に耳の痛い話だと思いました。

もちろん将来的に、いつかはJetpack自体も今のアドオンのように「もう時代遅れだ」と冷遇され切り捨てられる時代が来るのかもしれません。が、それはその時に考えればいい事なんじゃないかと僕は思います。

しかし自分が特に耳が痛いのは、既存プレーヤーがデカいツラしやがるという話です。自分の既得権益、自分の居場所を守るために必死に抵抗すればするほど、自分自身が今のまま何も変わらずに一線に立ち続けようとすればするほど、自分がすがりついている物の未来を奪う事になって、自分も他の人も不幸にする。「シーンの最前線から退く覚悟はあるか?」というエントリは、本文の内容は全然この話題と関係ないし趣旨も違うけど、でも僕は最近この事を考えがちなので、タイトル見ただけでこの事に結び付けて受け取ってドキッとしました。みんなのためを思うなら、老兵は黙って去って、不幸になるのは自分だけで終わらせないといけないんじゃないのか。

余談:Mozillaの生き残り戦略について

Microsoftは、Windows 95上でWindows 3.1用のアプリの動作を保証するために、Windowsの側で頑張って対策をしてまで互換性を維持したそうです。VistaのUltimateだったかWindows 7だったかではWindows XPとの互換性を維持するために仮想マシンまで用意しました。昔のAPIでも、「obsolete」という風にはMSDNに書いてあっても、動く事は動くという状態でずっと残ってるそうです。そういう「とにかく過去のソフトウェア資産を使い続けられるようにする」戦略をMicrosoftは取り続けて、製品はいまいち垢抜けない物ばかりになってしまいましたが、その結果としてシェアはものすごい事になりました。圧倒的多数の凡人がちょっとずつ落とすお金のおかげで、Microsoftは食えてます。

Appleは、ジョブズが思い描く「素晴らしいプロダクト」を目指すために、古いAPIを容赦なく切り捨ててがんがんアップデートしてます。Mac OS Xで「obsolete」となったAPIは、2つ後のバージョンくらいではもう綺麗さっぱり消えてしまうそうです。その結果、ついていけない脱落者が多くなるし、世界の過半数を占めるようなものすごいシェアは獲れてない。けれども強烈な信者ができて、彼らのおかげでAppleは食えてるわけです。

Googleは広告のシェアをガッツリ掴む事で、Operaはモバイル市場をガッツリ掴む事で、食っていってますよね。

で、Mozillaはどんな道を歩むつもりなんでしょうか。

今までの路線を見る限り、安定版リリースの寿命は短い(次のメジャーバージョンが出たら前のバージョンは半年で更新が打ち切られる)し、安定したAPIになるとか言ってたFUELもメジャーバージョン2つと保たずに黒歴史になってしまいそうだし、どう見てもゲイツよりはジョブズの生き方に見える。でも、ジョブズがジョブズの生き方を貫けてるのはあくまで、信者がお金を出して高い製品を買ってくれてるからですよね。でもこれって、言ってみればブランド物の生き残り戦略ですよね。Mozillaは物を売ってないから、その戦略じゃあ明日のおまんまが食えなくなるんじゃないの? 開発者を養っていけなくなるんじゃないの? そこが僕は心配でならないです。「いやオープンソースでバザールだから開発者はみんな善意で関わり続けてくれるんだよ」、という反論はすぐに思いつきますけど、今は世間はみんなWebkitに流れてますよね。オープンソースの開発者も、Geckoより将来有望な(ように見える)Webkitに流れていくんじゃないですか? その時、Geckoに関わり続けてくれる開発者はどれくらい残るんでしょうか?

上に挙げた各社のどれとも違う別の道を歩む、というのが多分、Mozillaにとっての模範解答なんでしょうけどね。その「別の道」ってのが一体何なのか、僕にはまだよく分からんです。

HIVの無料検査 - Jan 21, 2010

そういえば、公共広告機構のCMで「彼氏の元カノの元彼の……」というのがありましたね

思う所があって、受けてきましてん。

  • HIV(ヒト免疫不全ウィルス、いわゆるエイズウィルス)は感染してもすぐには発覚しない。感染から2ヶ月が経過した頃にようやく、検査で検出できるようになる。
  • HIVに感染すると、一方ではHIVに対する抗体が猛烈な勢いで作られ、一方ではHIVによって免疫系が猛烈な勢いで破壊され、という平衡状態になる。これが「HIVキャリア」の状態で、この平衡が崩れてHIVの方が勝ったらいよいよ「発症」ということになる。キャリアの状態は、長いと10年にもなる事もある。
  • HIVの検査は、この「HIVに対する抗体」ができているかどうかを見て行う。感染していると上記のように抗体が作られるので、「HIV抗体反応陽性」=「感染してる」、「HIV抗体反応陰性」=「感染してない」という判別ができる。

今は、献血で集めた血からHIV抗体陽性反応が出ても、その血を黙って捨てるだけで本人には絶対に通知しないそうですね。タダで検査結果を知りたい時は、各地でやってる無料検査に行くしかないようです。

  • HIV検査・相談マップを使うと、条件を指定して最寄りの検査所を検索できる。
  • 検査所の中には、いつもやってる所と、月1回検査・月1回結果発表という風なサイクルで時々やってる所がある。

僕の場合は、区役所で月1回やってるという検査に行ってきました。

  • 何はともあれ、まず電話で予約します。名前は聞かれませんでした。何人受けに来るという事だけ把握するみたい。
  • 僕が受けた検査所の場合、検査は月に1回朝9時から10時までの間の受け付けで、来た人から早い者順で受けられるそうです。僕は9時30分頃に行きましたが、同時に受けてた人は1人だけで、すぐに検査してもらえました。
  • 当日検査所に行くと、説明を受けた後に申込書類に記名させられます。本名を書く必要はなくて、偽名でもニックネームでも有名人の名前でもなんでもいいそうです。僕は面倒なので本名を書きましたが。
  • オマケで他の性感染症の検査も一緒に無料で受けられます。僕が受けた説明では、クラミジア、淋病、梅毒の3つが受けられますよとのことだったので、せっかくだから全部受けました。
  • HIVの検査自体は、採血だけです。血を抜いて、血が止まるまでガーゼで押さえておしまいでした。
  • 他の性感染症の検査を受ける場合は、この後検尿があります。小学校の頃とかに言われた「最初の尿は捨てて……」ではなくて、逆に「最初の尿から取って」と言われました。

検査はこれでおわり。後はまんじりともしない気分で検査結果が出る日を待つばかりです。

で、結果発表の日。僕が受けた検査所ではこれも月1回だそうです。

  • 結果発表は個別の面談のみ。電話や郵送では結果を教えてもらえません。行きそびれるとまた1ヶ月まんじりともしない気分で待つことになります。
  • 検査結果を聞きに行く時は、検査を受けた時の申込書類の控えを持って行きます。そこに書いてある番号で結果を見つけてくれます。
  • 僕が受けた日には他にも4~5人受けてたようですね。ファイルを見せてもらう時に見えましたが、僕の検査結果の上下に数名、他の人の検査結果も記載されていたようです。プライバシー保護のためか、全員それぞれの結果には付箋が貼ってあって、説明する時だけその付箋を外して結果が見えるようになってました。
  • 白でした、あるいは黒でした、という風な証明の書類はもらえません。証拠が欲しい時は多分、病院に行って自費でもう一度検査してもらわないといけないみたいです。

検査結果はすべて陰性でした。ただし、HIVについてはあくまで「2ヶ月より前のことについては感染の心配はありません」という言い方なので注意が必要です。

「大丈夫だろ」と思ってる時に限って最悪の結果が帰ってくる、という事があったりなかったりするので結果を聞くまで安心はできないわけですが、試験と同じで受けたらもう結果が出るのを待つしかなくて、祈ろうが呪おうが結果は変わらないので、結果待ちの間は無我の境地でした。検査を受ける前と、結果を聞く直前が、一番gkbrだった気がします。

またネットワークに繋がらなくなった→/etc/network/interfacesを編集したらなんとかなった - Jan 18, 2010

WEPで無線LANに繋がらなくなったのでWPAにしたあと、正常に動いてるように見えたし、ハイバネーションからの復帰後もちゃんと動いてたんだけど、Ubuntuのアップデートがかかってその後再起動したらまたネットワークに繋がらなくなってしまった。

ログビューワでログを見た感じではハードウェア自体は認識されてるようで、 検索結果の見よう見まねで /etc/network/interfaces を以下のように編集してsudo /etc/init.d/networking restartしたら、とりあえずネットワークには繋がるようになった。

auto lo
iface lo inet loopback

auto wlan0
iface wlan0 inet dhcp
wpa-essid ssid
wpa-psk 共有キー

が、この状態だとGnomeパネル上のNetwork Managerアプレットが全く機能しなくなって、無線のアクセスポイントも何も切り替えられない。

キーワードを変えてさらに検索していたら、/etc/network/interfacesを消せばなんとかなるという話があったので、これ危なそうだなーと思いながら試してみた(interfacesを別の名前に変更してみた)ところ、再起動したらNetwork Managerアプレットがちゃんと動くようになった。WPAのアクセスポイントにもつながってる。

でもCtrl-Alt-F2とかでコンソールに切り替えるとログインプロンプトが出てなくて、これでまたトラブルになったら手の施しようがないと思ったのでもう少し検索してみたところ、今度はUbuntuフォーラムのやり取りがヒットした。やっぱりというかなんというか、最低限の記述はないといけないのか。ということでinterfacesの内容を以下のように削って最小限(?)にしてみた。

auto lo
iface lo inet loopback

auto wlan0

再起動したら、Ctrl-Alt-F2でもログインプロンプトがちゃんと出てて、Network Managerで無線LANにも繋がるという状態になった。

汎用的なアンドゥ・リドゥ機能を提供するoperationHistory.jsの、理解しておかないといけない特性 - Jan 18, 2010

前のエントリではoperationHistory.jsの基本的な使い方を説明しましたが、次は、これを使うにあたって理解しておかないといけないポイントを解説しようと思います。


UIに対して行うアンドゥ可能にしたい操作の中には、他のアンドゥ可能にしたい操作を内部で呼び出すものがあるでしょう。例えばブックマークフォルダの内容をまとめてタブで開く時などに使われるtabbrowserのloadTabs()メソッドは、新しい空のタブを開くaddTab()メソッドを内部で呼び出しています。「新しいタブを開く」操作と「ブックマークフォルダの内容をまとめてタブで開く」操作をアンドゥ可能にする際は、これらのメソッドに対してそれぞれアンドゥ・リドゥの処理を定義することになります。

このように「アンドゥ可能な処理」同士が入れ子になっている時、operationHistoryは、それらすべてのアンドゥ可能な処理について、実行が始まった順番通りに履歴に登録を行います。例えば「loadTabs()で3つのタブを開く」という場面では、以下のように処理が行われます。

  1. loadTabs()実行。アンドゥ可能な操作Aが始まる。
    1. 対応する履歴項目A'が登録される。
    2. 1つ目のタブのaddTab()実行。アンドゥ可能な操作Bが始まる。
      1. 対応する履歴項目B'が登録される。
      2. アンドゥ可能な操作Bが完了する。
    3. 2つ目のタブのaddTab()実行。アンドゥ可能な操作Cが始まる。
      1. 対応する履歴項目C'が登録される。
      2. アンドゥ可能な操作Cが完了する。
    4. 3つ目のタブのaddTab()実行。アンドゥ可能な操作Dが始まる。
      1. 対応する履歴項目D'が登録される。
      2. アンドゥ可能な操作Dが完了する。
  2. アンドゥ可能な操作Aが完了する。

この時の操作B~Dは、操作Aが完了する前に、操作Aの中から呼び出されています。そのため、これらに対応する履歴項目B'~D'は、完了していない操作Aに対応する履歴項目A'の子項目として登録されます。つまり、このような親子関係が形成されます。

  1. 履歴項目A'
    1. 履歴項目B'
    2. 履歴項目C'
    3. 履歴項目D'

他の履歴項目の子項目として登録された履歴項目は、親となる項目の一部として扱われます。子項目になった履歴項目は、アンドゥ可能な操作の履歴の一覧には登場せず、「最大100回までアンドゥ可能」といった場合、子項目の数はそのカウントに含まれないことになります。

この履歴項目A'に対してアンドゥを指示すると、operationHistoryは以下の順で処理を行います。

  1. 履歴項目D'のonUndo()
  2. 履歴項目C'のonUndo()
  3. 履歴項目B'のonUndo()
  4. 履歴項目A'のonUndo()

この時の実行順序は項目の登録時の逆順であることに注意して下さい。なお、後で解説しますが、遅延処理のための仕組みによってこの実行順序は保証されます。前の項目のonUndo()が終わる前に次の項目のonUndo()が始まるという事はありません。

逆に履歴項目A'に対してリドゥを指示すると、operationHistoryは以下の順で処理を行います。

  1. 履歴項目A'のonRedo()
  2. 履歴項目B'のonRedo()
  3. 履歴項目C'のonRedo()
  4. 履歴項目D'のonRedo()

今度は、履歴項目の登録順の通りであることに注意して下さい。こちらについても、実行順序はこの通りに保証されます。

操作をアンドゥできるようにする際は、操作の中から呼び出している別の操作がアンドゥ可能である場合、上記の実行順の事を念頭に置いてアンドゥ・リドゥ用の処理を記述する必要があります。例えば上記の例であれば、アンドゥの際は以下の順でアンドゥのための処理が進みます。

  1. 3つ目のタブを開く操作のアンドゥ(タブが閉じられる)
  2. 2つ目のタブを開く操作のアンドゥ(タブが閉じられる)
  3. 1つ目のタブを開く操作のアンドゥ(タブが閉じられる)
  4. 複数のタブを開く操作のアンドゥ

これを見ると、4番目の項目の時点ではもう何もする必要が無いということが分かります。もし4の時点で、3つのタブを開いたのでそのアンドゥ操作としてタブを3つ閉じようとしても、閉じる対象のタブが存在しないためエラーになってしまいます。他のアンドゥ可能な操作を内部で呼び出す操作については、アンドゥ・リドゥの内容が重複しないように注意してください。

Ubuntu 9.10でWEPで無線LANに繋がらなくなったのでWPA2-PSKにした - Jan 15, 2010

なんかどんなにやっても無線LAN繋がらなくなってしまって、以前詰まったステルスモードのアクセスポイントの問題でもないようだし、もう完全に手詰まりになってしまった。

daemon.logを見てみると、昨日のログではNetworkManagerのsupplicant connection stateがdisconnected→scanning→associating→associated→completedになってたのに、今日のログではassociatingの次にdisconnectedに戻ってしまってて、wpa_supplicantが「Associated with……」のログを出してなかった。

で、このあたりのキーワードで検索してたら2chのスレが引っかかった。

45 :login:Penguin:2008/10/05(日) 09:47:09 ID:6n0tInIX
    >>43
    WEP 使っていたら、一度接続された後に
    /etc/init.d/network restart
    入れてやらないと、通信できません > X61@Mo4.1
    素直に WEP 捨てて、wpa_supplicant で
    WPA2-PSK/AES にするのが良いでしょう

今回の現象とはぜんぜん違う話題だけど、WEPじゃダメでWPA2なら問題ないというケースがあるのか。

僕の環境の問題も同じようにして解決されることを期待して、前々からWEP捨てなきゃと思ってたのをやっとWPA2-PSK(WPA2-パーソナル)に変更した。無線ルータの設定を変えた後、Ubuntuのネットワークマネージャで繋ぎ直したら、あっさりと繋がった。

結論:WEPは捨ててWPA2にしましょう。

TortoiseSVNのNautilus(Gnome)向けクローン、NautilusSVNじゃなくてRabbitVCS - Jan 13, 2010

svnをコマンドラインで使うのはどうにも慣れなかったので以前UbuntuにNautilusSVNを入れて使ってたんだけど、リポジトリからアップデートしようとしたらアップデートできなくて、どうした事だと思って目視してみたら、RabbitVCSという名前に変わったよとあったので、そっちから最新版をダウンロードしてインストールした。Ubuntu 9.10でも使えるdebパッケージがあったのでそれを使った。

おおおおお。なんか凄く完成度上がってる。日本語のロケールも入ってるし、メニュー項目にアイコンが付いて、見た目もますますTortoiseSVNそっくりになってる。コミットログに日本語を書けない問題が修正されてるかどうかはまだコミットしてないので分からないけど、日本語ロケールが入ってるくらいだから多分大丈夫なのかなあ。→大丈夫だった。他にも、ログ一覧を見たりタグを簡単に打てたり、TortoiseSVNでよく使う機能がちゃんと移植されてて助かりまくりです。

他の星に行ってきた体験ができる「アバター」 - Jan 12, 2010

Twitterのタイムライン上でみんな見た見た言ってるアバターを見てきた。新宿バルト9で、字幕の3D版。

最初は「3D映像のデモみたいなもんなんじゃないの? まあ映像の派手さだけ楽しんで帰れればいいかなー」と思って行ったんだけど、やられた。予想以上に面白かった。パンフレットの中で「モノクロの映画が今では全部カラーになったように、カラーの映画は次は3Dになる」「よし、カラーで映画を撮るぞ! なんて今の時代に意気込む人がいるかい? それと同じニュアンスで、これからは3Dが当たり前になる」みたいな話が語られてるけど、そういう事を言いたくなる気持ちがよく分かる、技術や表現手法に使われてるんじゃなくてストーリーを演出するために技術や表現手法を使ってる、ちゃんとした真面目なエンターテインメントだった。

シナリオとしてはよくある「文明人が、対立してた未開の民族の中に飛び込むことになって、そこで暮らすうちにそこの娘と恋に落ちて……」という感じの王道なんだけど。3Dの映像だからその世界に自分が実際にいるような感覚になるおかげか、感情移入度がハンパなかった。共に一夜を過ごした幻想的な森がブルドーザーで無残に破壊される様にはものすごいショックを受けたし、自ら縛り上げた主人公らを泣きながら解放する族長の表情にはこちらも感情を揺さぶられた。正直何度かウルッときた。催涙ガス?の弾丸が画面手前に飛んでくるとこでは思わず本気でよけてしまったよ。

  • 機械式の3Dメガネ on 普通のメガネ はなかなか辛い物がありました……重いし締め付けられて痛いし。
  • 字幕が一番手前に出るのならいいんだけど、たまに字幕より前に物が映ることがあって、しかしその一部は字幕に遮られてるという状態になると、これが非常に違和感があって気持ち悪かった。吹き替えで見れるならその方がいいと思う……
  • 他の星での生態系をリアルに描くというと、エイリアン展で買ったE.T.の住む星を思い出す。あれも面白かった。
  • 主演のサム・ワシントンは「ターミネーター4」で初めて知ったんだけど、この映画のキャストに決まったのは、それよりずっと前だったんですってね。
  • 「エイリアン」で異星生物と対決したリプリー役のシガニー・ウィーバーが、ギャラクシー・クエストでは宇宙船の乗組員を演じる女優を演じて、今度は異星生物と共存を願う研究者を演じる、というのも因果なものだなあと思った。

とりあえず、タイタニックとかあの辺の映画を普通に楽しめた人だったら、行ってみて損はないと思いますよ。もちろん3Dの上映で。

汎用的なアンドゥ・リドゥ機能を提供するoperationHistory.jsの基本的な使い方 - Jan 11, 2010

Undo Tab Operationsの核であるoperationHistory.jsは、タブに限らずいろんな操作に対してアンドゥ・リドゥを実装しやすくするための汎用のライブラリとして設計しています(一応)。こいつの使い方を、自分の頭の中の整理も兼ねて少しずつ解説していこうと思います。


  • 最新版はCOZMIX NGにあります。
  • 名前は「UI Operations History Manager」としています。長いので、以下「operationHistory」とだけ呼んでおきます。
  • ライセンスはMITライセンスとします。
  • Firefox 2以降でないと動きません。

読み込み方

まず、読み込みの方法。以下のようにJavaScriptのファイルを読み込ませるだけでOKです。

<script src="lib/operationHistory.js"
        type="application/javascript"/>

複数のアドオンでこのライブラリを読み込んでいる場合、最もリビジョンの新しい物が使われます。今後はAPIは変えないor後方互換を維持していくつもりなので、使う方はあんまり気にしないで使えるはずです。

operationHistoryの各機能には window['piro.sakura.ne.jp'].operationHistory でアクセスできます。以下の説明ではサンプルコードを短くするために、 OH という変数でこれを参照しているものとします。

var OH = window['piro.sakura.ne.jp']
               .operationHistory;

処理をやり直し可能にする

operationHistoryを使って任意の処理をアンドゥ・リドゥ可能にしたい時は、その処理を以下のように実行するようにします。

OH.doOperation(function() {
  // 任意の処理
});

doOperation()の引数に関数を渡すと、それがその場で実行されます。実行時のthisOH自身を指していますが、普通に分かりにくいんで、クロージャを使うなり何なりして好きなように書くといいと思います。

var MyAddon = {
  myFeature : function() {
    var self = this;
    OH.doOperation(function() {
      self.myInternalMethod();
    });
  },
  myInternalMethod : function() {
    // 何かの処理
  }
};

で、これだけだとまだアンドゥ・リドゥはできません。doOperation()に対して以下の引数をさらに指定してやる必要があります。

  • 履歴の名前(文字列、省略可能)
    • "MyAddonOperations" とかそんな感じで好きに名前を付けて下さい。省略すると、履歴の対象のウィンドウが指定されている場合は "global" 、そうでなければ "window" になります。
    • Undo Tab Operationsでは "TabbarOperations" という名前を指定してます。
  • 履歴の対象になるウィンドウ(nsIDOMChromeWindow、省略可能)
    • 拡張機能の名前空間で普通に見える所のwindowです。省略すると、ウィンドウ単位の履歴ではなく、クロスウィンドウな単一の履歴となります。が、動作が怪しいので今の所はウィンドウ単位での使い方だけ推奨しておきます。
  • 履歴エントリ(オブジェクト、必須)
    • オブジェクトリテラル、カスタムクラスなど、何でもOKです。詳しくは後述。

やり直し可能にしたい処理自体と合わせると、doOperation()は最大で4つまでの引数を取るという事ですね。引数は全部型が違う(関数、文字列、DOMWindow、オブジェクト)ので、doOperation()はそれらを受け取った後に、どれがどれなのかを自動的に判別します。なので引数はどの順番で指定しても構いません。

実際のアンドゥ・リドゥ処理を書く(関数を使うやり方)

実際のアンドゥ・リドゥ処理は、履歴エントリになるオブジェクトのプロパティとして関数で定義します。

var entry = {
  // 内部名
  name   : "undotab-addTab",
  // メニュー等に表示する「やり直す処理の名前」
  label  : "タブを開く",
  // アンドゥ時に実行される内容
  onUndo : function(aParams) {
    gBrowser.removeTab(this.tab);
  },
  // リドゥ時に実行される内容
  onRedo : function(aParams) {
    this.tab = gBrowser.addTab();
  },
  // 以下、任意のプロパティを好きなようにどうぞ
  tab : null
};

OH.doOperation(
  function() { // やり直し可能にする処理
    entry.tab = gBrowser.addTab();
  },
  'MyAddonOperations', // 履歴名
  window,              // 処理対象ウィンドウ
  entry                // 履歴エントリ
);

onUndoという名前のプロパティで関数を定義しておくとアンドゥ時にそれが実行されます。onRedoはリドゥの時に実行されます。どちらもthisは履歴エントリのオブジェクト自身になりますので、まあ見た通りで分かりやすいんじゃないかと思います。クロージャ使って書いても全然構いません。

namelabelは、文字列で好きなように名前を付けて下さい。定義しなくても使えますが、デバッグの時にはあると便利ですし、DOMイベントを使った記法(後で解説します)の時には無いと困ります。

アンドゥする・リドゥする

上記のようにして履歴に登録した処理は、以下のようにしてアンドゥ・リドゥできます。

// アンドゥ
OH.undo('MyAddonOperation', window);
// リドゥ
OH.redo('MyAddonOperation', window);

undo()redo()の引数には、doOperation()に対して指定したものと同じ履歴名と処理対象のウィンドウを渡します(こちらも引数の指定順は任意です)。ここではまだ「タブを開く操作」しか書いていませんが、同じ履歴名で「タブを閉じる操作」「タブを移動する操作」などに対してそれぞれアンドゥ・リドゥの処理を書いてやれば、線形にそれらをアンドゥ・リドゥできるようになります。

また、「戻る」「進む」のドロップダウンメニューで項目を指定してそこまで一気に飛ぶのと同じように、goToIndex()で履歴項目のインデックスを指定してそこまで一気にアンドゥする・リドゥする事もできます。

// 現在の位置を得る
var history = OH.getHistory('MyAddonOperation', window);
var current = history.index;
OH.goToIndex(current-3, 'MyAddonOperation', window);

getHistory()は、登録済みの履歴項目の全エントリを格納したオブジェクトを取得するメソッドです。それで取得したオブジェクトのindexプロパティで現在のフォーカス位置を得られるので、上の例ではそこから3つ手前に飛ぶ事になります。

要素やウィンドウに固有のIDを使う

ここまでの説明で既に疑問に思った人もいると思いますが、例えばこんな場合。

function NewTab() {
  var entry = {
    name   : "undotab-addTab",
    label  : "タブを開く",
    onUndo : function(aParams) {
      gBrowser.removeTab(this.tab);
    },
    onRedo : function(aParams) {
      this.tab = gBrowser.addTab();
      gBrowser.selectedTab = this.tab;
    },
    tab : null
  };
  OH.doOperation(
    function() {
      entry.tab = gBrowser.addTab();
      gBrowser.selectedTab = entry.tab;
    },
    'MyAddonOperations',
    window,
    entry
  );
}

function MoveTab(aTab) {
  var entry = {
    name   : "undotab-moveTab",
    label  : "タブを移動する",
    onUndo : function(aParams) {
      gBrowser.moveTabTo(this.tab, this.oldPosition);
    },
    onRedo : function(aParams) {
      gBrowser.moveTabTo(this.tab, this.newPosition);
    },
    tab : null
  };
  OH.doOperation(
    function() {
      entry.tab = aTab;
      entry.oldPosition = aTab._tPos;
      gBrowser.moveTabTo(aTab, 3);
      entry.newPosition = aTab._tPos;
    },
    'MyAddonOperations',
    window,
    entry
  );
}

NewTab()を実行→それで開かれたタブに対してMoveTab()を実行→アンドゥ→アンドゥ→リドゥ→リドゥ という順に操作すると、2つ目の履歴項目のリドゥ時にタブが見つからないせいでエラーになってしまいます。こうならないように、処理対象の要素は固有のIDなどで識別してやらないといけません。

operationHistoryにはそのために、要素に対して一意なIDを自動的に付与してそれを元に要素を検索する仕組みがあります。先の例を安全に書くと、以下のようになります。

function NewTab() {
  var entry = {
    name   : "undotab-addTab",
    label  : "タブを開く",
    onUndo : function(aParams) {
      var tab = OH.getElementById(this.tab,
                   gBrowser.mTabContainer);
      gBrowser.removeTab(tab);
    },
    onRedo : function(aParams) {
      var tab = gBrowser.addTab();
      OH.setElementId(tab, this.tab)
      gBrowser.selectedTab = tab;
    },
    tab : null
  };
  OH.doOperation(
    function() {
      var tab = gBrowser.addTab();
      entry.tab = OH.getElementId(tab);
      gBrowser.selectedTab = tab;
    },
    'MyAddonOperations',
    window,
    entry
  );
}

function MoveTab(aTab) {
  var entry = {
    name   : "undotab-moveTab",
    label  : "タブを移動する",
    onUndo : function(aParams) {
      var tab = OH.getElementById(this.tab,
                   gBrowser.mTabContainer);
      gBrowser.moveTabTo(tab, this.oldPosition);
    },
    onRedo : function(aParams) {
      var tab = OH.getElementById(this.tab,
                   gBrowser.mTabContainer);
      gBrowser.moveTabTo(tab, this.newPosition);
    },
    tab : null
  };
  OH.doOperation(
    function() {
      entry.tab = OH.getElementId(aTab);
      entry.oldPosition = aTab._tPos;
      gBrowser.moveTabTo(aTab, 3);
      entry.newPosition = aTab._tPos;
    },
    'MyAddonOperations',
    window,
    entry
  );
}

getElementId()は、要素に一意なIDが付いていなければ新しいIDを生成て設定した上でそのIDを、既にIDが付いていればその値を、文字列として返します。IDは普通のid属性ではなく別の属性名で保存されるので、通常の動作を破壊することはありません。

getElementById()は、そのID文字列をキーとして要素を検索するメソッドです。tabbrowserの場合はタブなどの内部の要素は普通のdocument.getElementById()等では取得できないのですが、getElementById()はID名の文字列以外に要素ノードを渡すと、その要素の子孫だけを検索するようになります。

ここでは、タブを開く操作のリドゥにおいてsetElementId()も使用しています。これは、既に生成されたID文字列を新しく復元された要素に付与することで、その要素を元の要素の代わりとして参照できるようにするためです。


とりあえず、まずはこの辺だけ解説しておきます。

→続き

Page 31/239: « 27 28 29 30 31 32 33 34 35 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき

オススメ

Mozilla Firefox ブラウザ無料ダウンロード