Home > Latest topics

Latest topics 近況報告

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

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

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

Page 28/80: « 24 25 26 27 28 29 30 31 32 »

Firefox 3.1ではSQLite Managerでplaces.sqliteにアクセスできなくて困る - Jan 29, 2009

Firefox 3.1での仕様変更以来、SQLite Managerでplaces.sqliteを開けなくなってる件について、ホント困ってる。XUL/Migemoのデバッグとかに使いたいのに。問題として報告はされてるけどWontFix(修正予定無し)になってるし……

もう、SQLite Manager用のアドオンでも作るしかないか?

こうすればいいんじゃね?というコードの例をコメントに付けてみた

追記。作者の人から早速反応があった。なんだ、単にやり方に気付いてなかっただけなのか…… コメントにも書いたけど、Cookieのデータベース(cookies.sqlite)はplaces.sqliteと同様にロックがかかってるにもかかわらず、コネクションオブジェクトが公開されてないから今の所まだアクセス不能のままだ。こればっかりはどうにもならない……Bugzillaの方にバグを立てて上手いこと説得できたら、Firefox 3.2とかそれ以降でなら対応してもらえるだろうか?

追記。バグ立てた。例によってC++のコードは僕は書けないので、どなたかヨロシク……

安全なタブの取得方法 - Jan 24, 2009

前のエントリでも触れてるけど、Firefox 3.1ではタブでない要素がタブバーに入る可能性が出てきたので、安全なタブの取得方法を色々考えてみた。

まず、すべてのタブのリスト。

function getTabs(aTabBrowser) {
  return aTabBrowser.ownerDocument.evaluate(
    'descendant::*[local-name()="tab"]',
    aTabBrowser.mTabContainer,
    null,
    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
    null
  );
}

var tabs = getTabs(gBrowser);
for (var i = 0, maxi = tabs.snapshotLength; i < maxi; i++) {
  alert(tabs.snapshotItem(i).label);
}

配列でないと困る時はこう。

function getTabsArray(aTabBrowser) {
  var tabs = getTabs(aTabBrowser);
  var array = [];
  for (var i = 0, maxi = tabs.snapshotLength; i < maxi; i++) {
    array.push(tabs.snapshotItem(i).label);
  }
  return array;
}

特定のタブの「次のタブ」。

function getNextTab(aTab) {
  return aTab.ownerDocument.evaluate(
    'following-sibling::*[local-name()="tab"][1]',
    aTab,
    null,
    XPathResult.FIRST_ORDERED_NODE_TYPE,
    null
  ).singleNodeValue;
}

特定のタブの「前のタブ」。

function getPreviousTab(aTab) {
  var tabs = aTab.ownerDocument.evaluate(
    'preceding-sibling::*[local-name()="tab"]',
    aTab,
    null,
    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
    null
  );
  return tabs.snapshotItem(tabs.snapshotLength-1);
}

preceding-sibling軸を使った時の返り値のノードの並びは軸方向の出現順ではなく文書順になるので、注意がいる。

function getPreviousTab(aTab) {
  return aTab.ownerDocument.evaluate(
    'preceding-sibling::*[local-name()="tab"][1]',
    aTab,
    null,
    XPathResult.FIRST_ORDERED_NODE_TYPE,
    null
  ).singleNodeValue;
}

タブの個数、最初のタブ、最後のタブも。

function getTabCount(aTabBowser) {
  return aTabBrowser.ownerDocument.evaluate(
    'count(descendant::*[local-name()="tab"])',
    aTabBrowser.mTabContainer,
    null,
    XPathResult.NUMBER_TYPE,
    null
  ).numberValue;
}

function getFirstTab(aTabBowser) {
  return aTabBrowser.ownerDocument.evaluate(
    'descendant::*[local-name()="tab"][1]',
    aTabBrowser.mTabContainer,
    null,
    XPathResult.FIRST_ORDERED_NODE_TYPE,
    null
  ).singleNodeValue;
}

function getLastTab(aTabBowser) {
  return aTabBrowser.ownerDocument.evaluate(
    'descendant::*[local-name()="tab"][last()]',
    aTabBrowser.mTabContainer,
    null,
    XPathResult.FIRST_ORDERED_NODE_TYPE,
    null
  ).singleNodeValue;
}

こういう時自分はついついXPathを使ってしまうんだけど、速度的にはどうなんだろう。ちゃんと計測してないから分からない。Array.slice(gBrowser.mTabContainer.childNodes).filter(function(aNode) { return aNode.localName == 'tab'; })とかの方が普通に速かったらごめんなさい。

childNodesを参照してるコードがヤバイというのはホントに酷い話だなあと思うけど、Google ChromeやIE7以降と同じユーザ体験を実現しようと思ったらどっかの時点でこれには手を出さなきゃいけなかった訳で、もうみんな腹括って粛々と受け入れるしかないんじゃないかと思うんだなあ僕は。

追記。例によってきっとガン無視されるだろうけどバグ立ててみた

追記。どうやら僕が立てたバグに関しては杞憂だったみたい……そもそもこのエントリに書いた話も今回の修正以前から潜在的にはあった問題のようだし。むしろヤバイのはalice0775氏が着目してる問題で、実際のノードの並び順と表示される順番とが食い違うことがあるようだ。この手の問題は僕も過去にXBLで色々試してた時に遭遇して、諦めて「こういう事はしない」という風に自分ルールで決めた記憶がある。バックアウトするのもいいけど、そもそもこれはXBLの匿名内容のレイアウトに絡む根深い問題に起因してるようなので、ここらで誰かが本気出して低層の所を直してくれないことにはどうにもならん気がする。

26日追記。「実際のノードの並び順と表示される順番とが食い違う」件は、新しいNightlyを試したら再現しなくなった。僕の全面的な勘違いだったのか、それとも別の所で修正されたのか…… あとgetBrowser().mTabContainer.selectedIndex プロパティと getItemAtIndex メソッドじゃあダメなのかなと言われたので調べてみたけど、現状のgetItemAtIndex()childNodes.item()のエイリアスに過ぎないようなので、やはり万全を期すなら別の手(このエントリに書いたような)を考えておいた方がいい気はする。

Firefox 3.1に向けてまたタブ回りが色々変わったのと、XUL要素のdisplayプロパティの値 - Jan 24, 2009

タブのドラッグ&ドロップに関する色んなバグを一挙に解決するパッチ最後のタブの右に「新しいタブ」ボタンを表示するようにするパッチの両方が入って、タブ回りが色々変わった。何はともあれ、タブをクリックしようとしただけなのにうっかりドラッグになってしまって別ウィンドウが開かれてムキー、という事がなくなってよかった。

とりあえず自分が把握してる限りでは、ツリー型タブ等でscrollbox内の方の「新しいタブ」ボタン(今回追加された奴)をdisplay: none;で消してるせいか、ボタンを再表示させた時や新しいタブを追加した時などにタブやボタンの並び順が盛大にぶっ壊れるようになった。display: -moz-box; visibility: collapse;にしておくとこの問題は起こらないっぽいので、次版ではそうする予定。(コードはもうコミットしてある

あと、gBrowser.mTabContainer.childNodesが返す内容がタブとは限らなくなった(どんな要素でもタブバー内に置けるようになったので)ということで、タブを取得するのにこのプロパティを使ってる人は一応気をつけといた方がいいと思う。てかtabbrowser要素のmTabs自体がこれを参照してるし、現実的にはタブ以外を置いたら色んな所がぶっ壊れる事が予想されるから「置くなよ! 絶対置くなよ!!」って言ってるのと同じだよなあ。まあ一応対応しとくけどさ……

またさらに気付いたけど、タブのnextSiblingpreviousSiblingタブでない値を返す可能性がある状態になってる。XBLのソースに埋め込まれてるコメントノードの位置もタブの間に何故か移動してしまったりする事があるようで、前後のタブをこのプロパティで参照してる場合には被害を受ける事になる。ここも注意が必要だ。

全然話は変わるけど。

アドオンで要素の表示・非表示をCSSのdisplayプロパティで制御するにあたって、display: none;で非表示にするのはセオリー通りで別にいいんだけど、表示させる時にdisplay: inline;とかdisplay: block;とかにしてる人がたまにいてもにょる。Web上のCSSではそれで正解なんだけど、XULでこれをやるとボックスの並び順がぶっ壊れたりレイアウトがおかしくなったりする事があるので、よっぽどの事情(タブバーを多段表示させる時とか)がない限りはあくまでdisplay: -moz-box;の方を使って欲しい。最近見かけたものではPathtraqがそうだった。

XUL要素の表示・非表示を制御するには大別して3つ、細かく分けると7つの方法がある。

  • 要素を完全に消す(レイアウトのフローから完全に除外する)
    • node.hidden = truenode.hidden = false
    • node.setAttribute('hidden', true)node.removeAttribute('hidden')
    • node.style.display = 'none'node.style.display = '-moz-box'
  • 表示上見えなくする(レイアウト上は幅・高さ0でその位置にある物として扱う)
    • node.collapsed = truenode.collapsed = false
    • node.setAttribute('collapsed', true)node.removeAttribute('collapsed')
    • node.style.visibility = 'collapse'node.style.visibility = 'visible'
  • 表示上見えなくする(レイアウト上もその位置に本来の幅・高さで要素がある物として扱うが、その領域には何も描画しない)
    • node.style.visibility = 'hidden'node.style.visibility = 'visible'

いくつかのXUL要素では、hiddenプロパティやcollapsedプロパティに真偽値を代入しても何も起こらないので、setAttribute()removeAttribute()とした方がより確実ではある。プロパティでの代入にせよDOMの属性値での指定にせよ、最終的にはCSSでの指定と同じ物として扱われる。xul.cssの頭の方を見れば、どういう事かよく分かると思う。

上の例でnode.setAttribute('hidden', false)ではなくnode.removeAttribute('hidden')と書いているのにも理由がある。テーマやアドオンの中には「要素のhidden属性の値がtrueであるかどうか」ではなく「hidden属性に何らかの値がセットされているかどうか」しか考えてない場合があって、falseを設定したのに非表示のままになってしまう、というような事がたまにあるから。collapsedにも同じ注意が必要。

XULの世界的には物凄く基本的な事なんだけど、HTML+CSSの世界から入ってきたばっかりの人はこの辺の事を知らないままでいるかもしれないので、一応書いてみた。

こういう事(why:何故そう書かねばならないか)って、アドオンの実際のコード(how:どう書いたらよいか)をいくら見てても分からないんだよなあ……ほんとXULは地獄だぜ。

スマートロケーションバー周りの設定が少し分かりやすくなった - Jan 21, 2009

browser.urlbar.search.sourcesとbrowser.urlbar.default.behaviorという似たような設定が2つもあってわけわからん!!という話をこの間書いたけれども、新しいパッチが入って、browser.urlbar.search.sourcesは廃止された

  • スマートロケーションバーの検索機能のON/OFFはbrowser.urlbar.autocomplete.enabledという真偽型の設定で制御される。
  • スマートロケーションバーの検索対象をブックマークにするか・履歴にするか・両方を横断検索するかについてはbrowser.urlbar.default.behaviorで制御される。

ということで割としっくり来る所に落ち着いたみたい。search.sourcesのために色々調べたり実装を直したりしたのはまるっきり無駄になってしまったけど、しょうがない(異議申立てをした本人だから文句は無い)。

29日追記。1.9.1ブランチ(Firefox 3.1)にも無事反映されたようです。

2つ目のパッチが取り込まれたよー - Jan 16, 2009

前のエントリに追記した通り、HTMLメールのデフォルトのフォントに日本語の名前のフォントを使えない問題で書いたパッチが採用されたんだけど、それに続いて設定ダイアログを開いた時に前回選んだフォントが選択されない問題のパッチも採用された。(ただしどっちもShredderの話で、Thunderbird 2.0.0.xに入れてもらうにはまだかかりそう。)

今までずっとアウトローな感じで野良パッチを垂れ流してた状態だったけど、こうしてちゃんとアップストリームに還元できるようになると、嬉しいものだなと思いました。

Firefox 3.1で新しいタブを開く位置を変更する機能が入るかも? - Jan 12, 2009

そういう機能が入ること自体は、別に悪い事ではない(ていうかIE7が標準でこの機能を持ってる以上は入れといた方がいいだろう)と思うんだけど、実装がなんだか……addTab()の第1引数がabout:blankかどうかで挙動を変えるとか、ちょっとひどすぎない?

本気でこのあたりの挙動をちゃんとしようと思ったら、ツリー型タブ等のようにタブの親子関係をどっかに保持しておかないといけないと僕はずっと思ってる。それを避けて最小限の変更でそれらしい挙動を実現しようとしているから、余計にややこしい事になってるんじゃないかって気がする。

議論をよく読まないままBugzillaにコメントしてしまったんだけど、僕がコメントに書いた事のうち1つ(ブックマークを開く時にこれが働くのはなんか変じゃね?という件)は、すでに俎上にのぼって議論され尽くしてたみたいだ。

タブを開く、閉じるときの動作に関しては多くの議論が行われてきましたが、結局、「ユーザより賢くなろうとはしないこと(do not to try to be more clever than the user)」というガイドラインに従うことになりました。言い換えると、経験則に基づく自動動作がユーザの意図した動作に合致すると確信できないときは、自動動作を行わないということです。

追記。誰か分からんけど「feature freezeなのに何やってんだ!」という指摘をしている人もいたので、その辺の事も入れてコメントしてみた。

しかしまあこんな事ばっかやってるとますます「手は動かさないくせに口だけ出しやがるウゼエ奴」度が増していきますなあ……

1月15日追記。新しいパッチが提出された。addTab()に引数を一つ増やして、それで新しい挙動を使うかどうかを制御するというもので、他に与える影響はだいぶ小さくなってると思う。引数の個数がどんどん増えていくのは見てて頭クラクラしてくるけど、これ以上のことをやろうとすると話がもっとでかくなりそうだから、落とし所としては無難な線じゃないかと思う。

MozStorageを使う時にメモリリークを防いだりオーバーヘッドを減らしたり - Jan 09, 2009

mozIStorageStatement.finalize() メモ - 1/4ガロン

うっ。僕の知識は古かった。Firefox 3 Hacksで、createStatement()で作ったステートメントは使い終わったらstatement.reset()、と書いてましたが、statement.finalize()が正解だったようです。

が、一律にこう置き換えるとよい、というわけでもないのがややこしい所です。mozIStorageStatementのfinalizeメソッドはどうやらFirefox 3.0.x(Gecko 1.9)で導入された物のようで、Gecko 1.8系では存在しません。なのでメソッドを呼ぶ前に存在確認をしておかないといけない。Firefox 2なんてもうサポート終了してんじゃん!と思うかもですが、Thunderbirdはまだ2.0.0.xが現役なのでもうしばらくは気をつけないといけないんですハイ。

ところで、僕はずっと誤解してしまってたんですが、ステートメントはstatement.reset()でリセットすると、バインドするパラメータを変えて何度も使い回せるんですね。createStatement()のオーバーヘッドがどのくらいなのかよく分からないのでアレなんですが、SQL文が変わらない時はキャッシュしたステートメントを使い回すようにするという形で、高速化を図れるでしょうか。XUL/Migemoに早速活かしてみたいと思います。

Firefox 3.1のスマートロケーションバーまわりがわけわからん! - Jan 09, 2009

現時点までで、以下の設定項目が新設されたところまでは把握してる。

  • browser.urlbar.restrict.history(文字列型)
  • browser.urlbar.restrict.bookmark(文字列型)
  • browser.urlbar.restrict.tag(文字列型)
  • browser.urlbar.restrict.typed(文字列型)
  • browser.urlbar.match.title(文字列型)
  • browser.urlbar.match.url(文字列型)
  • browser.urlbar.default.behavior(整数型):Bug 463459 – Use a separate pref instead of empty restrict/match values to specify defaults により追加された。restrictとmatchの値が「空の場合は」云々の特例的な処理を一本化するための物。
  • browser.urlbar.search.sources(整数型)

以下は削除された、と。

  • browser.urlbar.matchOnlyTyped(真偽型)

が、どれがどんな風に働くのかがごちゃごちゃして分からんようになってきた……

browser.urlbar.default.behavior(フラグを指定しておくことで、restrictとかmatchとかの指定をしたのと同じ状態から検索をスタートする)に3を指定するのと、browser.urlbar.search.sourcesに3を指定するのとの、違いがいまいち分からない。ので、ソースをあちこち辿ってみた。見てみた感じでは、どうやらnsNavHistoryのProcessTokensForSpecialSearchメソッドが鍵になってるっぽい。

検索対象のテーブルの指定や絞り込みの条件は、すべてmAutoCompleteCurrentBehaviorという1つの変数にフラグとして格納される。

  • 1(最下位ビットがON)は、履歴だけを検索対象にする。
  • 2(下から2番目のビットがON)は、ブックマークだけを検索対象にする。
  • 4(下から3番目のビットがON)は、タグ付けされている項目だけを検索対象にする。
  • 8(下から4番目のビットがON)は、タイトルにマッチする。
  • 16(下から5番目のビットがON)は、URIにマッチする。
  • 32(下から6番目のビットがON)は、ユーザがロケーションバーから手動操作で訪問した項目だけを検索対象にする。

これらを踏まえて、以下の順で処理されている。

  1. browser.urlbar.default.behaviorの指定でmAutoCompleteCurrentBehaviorを初期化する。
  2. browser.urlbar.search.sourcesを見て、
    1. 1だったらmAutoCompleteCurrentBehaviorの最下位ビットをONにする。
    2. 2だったら下から2番目のビットをONにする。
    3. それ以外の時(0や3)は何もしない。(browser.urlbar.search.sourcesが0の時、つまりスマートロケーションバーの検索機能自体を無効にしている時は、ここにそもそも処理が回ってこない?)
  3. スマートロケーションバーに入力中の文字列をトークンごとに分割して、restrictやmatchで設定されている文字列と比較する。一致したらその都度、mAutoCompleteCurrentBehaviorの対応するビットをONにしていく。
  4. 入力中の文字列が空の時は、最下位ビットと下から6番目のビットをONにする。(Bug 426864 – Only show user typed history pages for the urlbar dropdown によって追加された処理で、ユーザが何も入力してない状態でドロップダウンリストを開いたら過去の入力履歴だけを表示する、という挙動をこれによって再現する。)
  5. ここまでの結果のmAutoCompleteCurrentBehaviorを見て、以下の順で、どのSQL文を使うかを決定する。これは排他的な選択なので、どれかの道に分岐したらその時点で検索条件が確定する。
    1. 下から3番目のビットがONの場合、タグ付けされた項目だけを検索するSQL文を使う。
    2. 下から2番目のビットがONの場合、ブックマークだけを検索するSQL文を使う。
    3. 下から6番目のビットがONの場合、ユーザがロケーションバーから手動で訪問した項目だけを検索するSQL文を使う。
    4. 最下位ビットがONの場合、履歴だけを検索するSQL文を使う。
    5. 上記ビットがいずれもOFFの場合、履歴とブックマークの両方を対象に検索するSQL文を使う。
  6. 下から4番目のビットと下から5番目のビットは、次の段階での絞り込みに使われる。

ああややこしい……

  • 5のステップでは排他的な選択になっているので、例えば「タグ付けされた項目で、且つ、ロケーションバーから訪問した事がある物だけを対象に検索する」という風なことはできないようだ。
  • 条件を指定する方法には、browser.urlbar.search.sources、browser.urlbar.default.behavior、検索時のキーワード入力の3つがあるが、これら3つの間には優先順位は無い。優先順位は各ビットの方にあって、常に5-1から5-5の順番に従って判定される。なので、以下のような不可解なことが起こる。
    • browser.urlbar.default.behaviorを使って、ブックマークからのみ検索を行うようにした状態(下から2番目のビットがON)で、検索時語句の中に「^」を含めて履歴のみの検索を指示した(最下位ビットがON)、という場合、手動で指示した検索条件はまるっきり無視されて、あくまでブックマークからのみ検索が行われる。
    • browser.urlbar.default.behaviorを使って、ユーザがロケーションバーから手動で訪問した項目だけを検索対象にするように指定(下から6番目のビットがON)していても、検索時語句の中に「+」が含まれていた(下から3番目のビットがON)場合には、手動で指定した方の条件が優先されて、タグ付けされた項目からのみ検索が行われる。
  • browser.urlbar.default.behavior=3とbrowser.urlbar.search.sources=3の違いは、前者は「ブックマークされていて且つ履歴にも含まれている(=訪問済みのブックマーク)」項目だけが検索対象になり、後者は「ブックマークと履歴の全体」が検索対象になる、という点。search.sourcesが0(検索機能自体が無効になっている)以外で、default.behaviorが3の時は、両方の条件がMIXされて、browser.urlbar.default.behavior=3の条件と同じ(ブックマークと履歴の全体から訪問済みのブックマークだけを検索するのも、ブックマークから訪問済みのブックマークだけを検索するのも、履歴から訪問済みのブックマークだけを検索するのも、全部同じ事ですね)になる。

その場での入力とデフォルト設定のどっちが優先されるのか、がパッと分からないのってどうかと思うんだけど……XUL/Migemoのスマートロケーションバー周りの挙動をこれに合わせないといけないんだけど、こういうわかりにくい挙動をそのまま再現するというのは、モチベーションが上がらないなあ。(ていうかバグ立ってそう)

21日追記。browser.urlbar.search.sourcesが廃止されてこのエントリの内容のかなりの部分は無駄になりました。

ThunderbirdでHTMLメールの初期状態のフォントに日本語の名前のフォントを指定しても期待通りに動かない件 - Jan 08, 2009

別に特殊な文字なんか使ってないのに、メールを送信しようとすると「変な文字が入ってるからISO-2022-JPじゃ送れないよ! UTF-8にする?」みたいな確認が出る、という問い合わせを受けて調査をしてたら、原因は表題の箇所にあった。

「MS P明朝」みたいに非ASCIIな文字を名前に含むフォントを使おうとすると、フォント名自体が文字化けしてしまって、その化けた文字がISO-2022-JPの範囲外なので上記の確認が表示されてしまう、というのが事の真相だった。

で、検索してみたらMozilla Japanのナレッジベースが引っかかったんだけど……

Mozilla Japan - Thunderbird サポート - ナレッジベース - HTML 形式のメッセージを作成中にフォントを変更できない

日本では HTML 形式のメッセージはあまり好まれませんので、シンプルなテキスト形式で作成していただくという方法もあります。

ちょwwwwwwwそりゃないよwwwwwwwwwwww

ナレッジベースからリンクされてたバグはEditorコンポーネント扱いになってたんだけど、自分が特定した限りでは原因箇所はThunderbird固有のフロントエンド部分だったので、分かりやすいようにと思って新しくバグを立てた。

Bug 472621 – Thunderbird fails to use some fonts for the default font of HTML messages, if the font has non-ASCII name.

パッチを見ての通り、修正点自体はほんとに些細です。なのに何年も見過ごされてたっていうのが、なんだかなぁ……

1月13日追記。池添さんに教えてもらいながらレビュー依頼したりとかなんとか。checkin-neededキーワードが付いて、どうやらパッチ採用してもらえそうな感じ? そして関連する別のバグにもパッチを書いてみた。

1月15日追記。Trunkにチェックインされたよ! これで僕もThunderbirdコントリビュータ!(←クレジット入れ忘れてるのできっと誰にも知られないまま)

2月23日追記。重要なバグじゃないからパッチは2.0.0.xには入れないと言われてしまいました。重要じゃないのか……最初から付いてる機能が最低限すらまともに働いてない事がそんなに些細な問題ですか……。

Page 28/80: « 24 25 26 27 28 29 30 31 32 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき