Home > Latest topics

Latest topics 近況報告

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

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

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

Page 1/248: 1 2 3 4 5 6 7 8 9 »

Some reasons why I say that eval is not absolutely dangerous than other hacks. - Feb 08, 2010

This is an translated version of my another entry, evalが危険でそれ以外の方法が安全だと思ってる人へ . This is an objection for the entry: Five wrong reasons to use eval() in an extension written by Wladimir Palant.


Recently I updated Source Viewer Tab and Tree Style Tab. However, when I uploaded the latest version to AMO, both files were retained in the sandbox, never made public by AMO editors. They said with one mouth: "Your add-on uses the 'eval' function unnecessarily, which is something we normally don't accept. There are many reasons *not* to use 'eval', and also simple alternatives to using it. You can read more about it here: http://adblockplus.org/blog/five-wrong-reasons-to-use-eval-in-an-extension"

I know the point of their blames very well, because I read and translated the entry to Japanese for my understanding. When I got a rejection about another addon, I got just same comment.

Now I have an objection about indiscriminate rejections by "too many eval()s" like this.

Both "wrong" and "right" are infelicitous adjectives about eval.

First of all, there is no "wrong" use of eval in any JavaScript codes (not only my addons). All of evals are "right" if it does its own work correctly.

For example, by the HTML specification, <em> is defined as "means emphasizing", "cannot appear in <title>", and so on. If you write <em> against the definitions, your HTML will be "invalid".

How about eval? 15.1.2.1 eval (x) in the ECMAScript specification describes about the function. It just says: runs the specified string as a script. There is no cautionary statement about the purpose of using eval.

There is no "wrong" use, it is just "dangerous" use. There are many usecases: some is high-risk, some is low-risk. But, they all evals are "right" use if it works as required by the spec. So, I think that it is a suitable subject for the entry: "Five dangerous use of eval() in an extension".

Risks of eval have to be managed, in other words, risk-managed evals are useful tool to extend Firefox. For end users, I think some eval should be allowed if it is safe enough in the case. "Eval? No, no, it is evil function! Don't use it anyway!" - I think that is slapdash work.

When you get 5-minute recipes via HTTP, do you untrust it anyway? Because it is insecure protocol, you cannot trust any information without SSL? Note, VeriSign certifies that the website you are accessing via HTTPS is surely hosted by the author, but he doesn't certify that the author is not evil. If you cannot trust any people via internet, you have to live offline - it's a internet phobia. In many cases you maybe trust them anyway if it is low-risk.

In the entry, he negates any eval without considering about its risk if it is out of the "valid uses". I think it is just a eval phobia.

Can the eval eat codes from the Web, really?

I agree to blame some cases of 5 cases in the entry. The 1st (parsing JSON), the 2nd (accessing to properties dynamically), and the 4th (running event handlers of HTML or XUL elements) - those three cases must be blamed because they possibly run untrusted scripts from the Web as privileged. This is just same to caution about SQL injections for web apps.

I totally agree this topic. I also think any developer must be careful to make eval isolated from the Web. If my addons are rejected because they have this security issue, I totally back the judgment up.

So, how about my cases?

Both addons, Source Viewer Tab and Tree Style Tab, use eval only for injecting codes to functions in Firefox (and other addons). They never get codes from the Web. If editors decided to reject those addons by the reason, like "This is dangerous because it includes eval! Eval can run codes from the Web!", then it means: they reviewed addons without reading codes, and just checks warnings by the "not perfect" validator.

If so, I cannot agree to the decision. We shouldn't overestimate the power of the validator on the AMO system, because it can detect only a few patterns which are defined as "dangerous". It doesn't parse the JavaScript, it only reports the matching result about simple regular expressions, it cannot detect dangerous codes from obfuscated programs.

You have to judge case by case whether the eval is danger or not. Same about XBL hacks, CSS hacks, replacing of functions, and others. "Yes, this doesn't use eval. I accept it." "Oh, this uses eval. This is wrong. I reject it." Such a rash judgment possibly jeopardize people who download addons from AMO. I believe that we should review sources by our eyes to detect dangerous code cleverly obfuscated, even if it take time.

Is injection by eval absolutely dangerous than other hacks?

All of evals in Source Viewer Tab and Tree Style Tab are used to inject codes to functions of Firefox, it is the 5th case described in the entry. In the entry, he blames this use because:

  • When the definition of the target function changed, terrible problem (crashing, data loss, etc.) possibly appear.
  • It possibly invites "already fixed" security issues again.

And, he said that we should use "less dangerous" ways like:

  • Use closure, and wrap up the original function by a new function. In the function, call the original function by func.apply(this, arguments).
  • Watch changes of values of some property by Object.watch().
  • If you cannot do it with those safer ways, you should not do it. Give up.

In other words, in the entry he said that "those ways are safer than eval".

I think it is an unfair suggestion. If you talk about risk of those cases, you should think other risks too, which are not listed in the entry. We also would like to avoid eval if at all possible. However, in our cases eval is the way really better than others.

Risk: possibilities of conflicting to Firefox features and other addons

Methods to extend Firefox can be sorted as:

  1. Using stable APIs provided by Firefox or other addons. (Toolbar buttons, sidebar panels, contents filtering by nsIContentPolicy like AdBlock Plus, Jetpack Features, etc.)
  2. Using other unstable ways.
    1. Using XBL hacks.
      1. Applying new XBLs.
      2. Replacing existing XBLs. (Tab Mix Plus, etc.)
    2. Using JavaScript hacks.
      1. Replacing existing functions. Using closure, wrapping up original functions in new functions.
      2. Hooking operations of existing functions by Object.watch() or other ways.
      3. Injecting codes to existing functions by eval.
    3. Using CSS hacks. (Personas, third-pirtys' themes, etc.)

One addon can use multiple ways above, but we can call it "safe" addon if it uses only "stable APIs". Otherwise they are possibly unstable. Any addon using unstable ways possibly breaks Firefox and other addons. Themes also.

He said that the "less dangerous" way is safer than eval. But, actually it possibly isn't. For example, I tried to watch the toggling of the Sidebar in Firefox 3.6, by document.getElementById("sidebar-box").watch("hidden", ...). Then it breaks the original behavior of XUL element - the Sidebar was never toggled. (So I had to use an event listener for the "DOMAttrModified" generic event.)

Another case, if you wrap the original function by a new function, any other addon which aimed to inject codes to the original function will never work. Hmm, "Because it is evil. Evil addons using eval must die!" Don't say that. It is the fact, you didn't take care about people who use addons with eval.

By the way, there are features which cannot be implemented without injecting codes into existing functions. Dorando told about those addons in the comments to the entry. The conclusion of the entry is "don't do it, you should not do it". However, if you cannot explain how dangerous eval is than others, it is just a tautology: "you should not do it, because it is wrong use of eval." and "it is wrong use of eval, because you should not do it."

Risk: possibilities of causing troubles with updating of Firefox

On this point, both methods (eval and the "less dangerous" way) have same risk. He said that eval will never work if the definition of the function changed. However, the "less dangerous" way will collapse too if the original function is renamed. It is just a bias that functions will be never renamed in security updates. There is no "rule" like this.

Moreover, if you wrapped two functions A and B, expecting they work as "A-mod => B-mod", the hack will break down if only one mate changed by security fix. We cannot imagine how terrible thing caused is. Not only updating of Firefox, but conflicting to other addons too.

Anyway, we addon developers must catch up changes in any update of Firefox. It is the common issue for any addon which uses unstable ways to extend Firefox. I think blaming like "how terrible eval is than wrapping original functions" is nonsense. More importantly, I believe that we should talk about providing failovers for unexpected matters.

To put it bluntly, any addon is just a "dynamic patch". If you use Linux, you possibly download patches from ML or other places, apply it to the source, and build binaries. It is not uncommon sight. And, it is also important note in those cases: Don't apply the patch to any revision different from the base of it. Using addons on unverified versions of Firefox is just same to that.

Risk: possibilities of less maintainability and/or readability

If we use eval hack, only "codes should be replaced" and "codes should be injected" will appear in the source.

Generally reading source codes like this is certainly hard, because we have to refer the codes of the function which is being overwritten. Instead, there are less codes and sources become compact. If it is very simple like replacing from "width" to "height", it will be human readable enough. So know-how to keep maintainability and compatibility is important for this hack.

Even if you choose the way to wrap original functions, only fragmentary codes will appear in the source too. "Pre-operations", "post-operations", "wrapping functions", "watching functions for property changes", and others. Moreover, if you cannot get the result of operations by the original function as its returned value, eventually you have to know well how the function work.

In this case, if you want to implement a feature which require injection of some codes into the logic of an existing function, you need to copy the complete codes of the original function into your addon (of course you have to modify it.) Then, too many codes are possibly duplicated, so:

  • You possibly cannot include the codes of the original function because their licenses conflict.
  • It possibly re-invite security issues fixed by updates of Firefox, as told in the entry.
  • Too many codes simply make themselves hard to be read.

Risk: possibilities of rejection by editors

This is common to the topic about maintainability. AMO editors finally have to review addons with reading of their sources. If there are tricky codes or too many/long lines, then the cost of reading source codes increases. On this point, both eval hacks and wrapping hacks are similarly tricky.

Although if updates of addons are always rejected by the reason: "there is any eval", then, it becomes a new common practice: writing codes without eval anyway, with tricky hacks, even if they become hard to read. Otherwise the update won't be accepted. It is also a tautology: "we should not use eval, because they never accept codes including eval." and "they don't accept eval hacks because we should not use it."

The conclusion

As I described, I think evals in Source Viewer Tab and Tree Style Tab are not unnecessarily. In other words I believe that those evals are the best way to implement the feature with keeping compatibility. I think those evals are not absolutely dangerous than the "less dangerous" ways described in the entry, and I also think there are no alternative ways to do it.

How many people who says "eval is dangerous than others" actually read and reading the source codes of Mozilla products? Trying to extend Firefox even if there is no stable API? Catching up updates of Firefox constantly? Trying to solve compatibility problems with other addons? I'm feeling blue.

Only XPCOM components are really stable APIs, which are marked "FROZEN" in their IDL files. Otherwise they are absolutely unstable. There are only a few "FROZEN" APIs, preferences I/O, W3C DOM, etc. JavaScript functions in the browser window are very unstable. Even the FUEL - which was the component advertised as providing stable APIs independent from Firefox versions - is possibly removed from the next major release of Firefox. Yes, this is the Mozilla. I think it is just a kidding: "eval is dangerous, wrapping original functions by new functions with the name same to originals is safer than it."

In conclusion, I think it is unjust treatment that addons are retained in the sandbox because "they have evals".


To reject spams, you have to answer a quiz to comment to this entry. "今の日本の首相の名字(ひらがなで回答)" means: the family name of the current prime minister of Japan, in "hiragana". You'll see the answer from wikipedia (Japanese version of the page).

evalが危険でそれ以外の方法が安全だと思ってる人へ - Feb 08, 2010

先日、ソース表示タブのアップデート版をAMOにアップロードしたところ、公開申請が却下されました。「不必要なeval()が多すぎる。拡張機能におけるeval()の5つの間違った使い方(原文:Five wrong reasons to use eval() in an extension)をよく読んで出直してこい。(大意)」という感じのコメントが添えられていました。

また、ツリー型タブのアップデート版も別の人から同じコメント付きで公開申請を蹴られました。

全文+コメントを翻訳するくらいには当該エントリを読んだ僕ですから、今更読み返すこともないのですが、こう何度もこのエントリを引き合いに出して申請を蹴られると正直腹に据えかねる物がありますので、自分の考えをちょっとまとめておきたいと思います。

つたない英語力で頑張って英語に翻訳してみました。

evalの使い方に「正しい」も「間違っている」もない

まず何より明らかにしておきたいのは、言葉尻を捉えて反論するのもどうかと言われそうですけれども、evalの使い方には「正しい」も「間違っている」も無いということです。

例えばHTMLの仕様書には、em要素は強調を意味するとか、この要素はこの要素の中には記述できないとかの、色々な定義が書かれています。その定義から外れた使い方をすれば、確かにそれはinvalidな(間違っている)HTMLと言っていいでしょう。

では、evalはどうか。ECMAScriptの仕様書(リンク先のページには3rd Editionと書いてあるけどPDFは5th Editionです)15.1.2.1 eval (x)の項には、evalの仕様としては「与えられた引数をスクリプトとして実行する」という、挙動についての取り決めだけが書かれています。「何のためになら使ってよい」という風な記述は一切ありません。当たり前といえば当たり前ですが。

そこにあるのはただ、「その仕様の通りに動作した結果、何が起こるのか?」という結果についてのリスクの高低だけです。多大なリスクを伴う使い方、全くリスクを伴わない使い方、色々な使い方が考えられますが、動作する限りはそれらはすべて「仕様通りの正しい使い方」です。なので当該エントリのタイトルも本当は「evalの5つの危険な使い方」などとするのが妥当だと僕は思っています。

こういう場合にこういうデメリットがあること考えられる、だからこのような対策が必要だ、あるいはメリットとデメリットを天秤にかけないといけない、というのがリスク管理の考え方です。「間違っているから駄目だ」と思考停止するのは、天秤にかける事すら否定するということです。

例えばSSLを使っていない普通のHTTP接続で閲覧しているWebページの内容は、「第3者によって改竄されている可能性」を完全には否定できません。だからといって、そのページに書かれている情報は一切全く信用してはいけない、ニュースだろうが料理のレシピだろうが一切アテにしてはいけない、という考え方が健康的と言えるでしょうか? また、SSLは接続している先のWebサイトが本当にその運営者が運営するものであるかどうかということは保証してくれますが、運営者が善人か悪人かということまでは保証してくれません。相手が善人であると保証されないのだからネットで買い物はしたくない、カップラーメンもマンガの本もホッチキスの針も、詐欺に遭うのが怖いからネット経由では絶対何も買わない、という考え方は妥当でしょうか? そこまで行くともはやインターネット<ruby><rb>恐怖症</rb><rp>(</rp><rt class="読み">フォビア</rt><rp>)</rp></ruby>でしょう。

前出のエントリで「この使い方は正しい」とされている以外の使い方がされているevalを、個々のケースごとのリスクの高低を無視して一律で否定するのは、僕には単なるeval<ruby><rb>恐怖症</rb><rp>(</rp><rt class="読み">フォビア</rt><rp>)</rp></ruby>としか思えません。

そのevalには本当に、Webからやってきたコードが混入する恐れがあるのか?

前出のエントリで挙げられている5つのケースのうち、1番目(JSON形式のデータのパース)、2番目(プロパティ名が動的に変化する時に、そのオブジェクトのプロパティにアクセスするため)、4番目(HTMLやXULにインラインで記述されたイベントハンドラの実行)の3つのケースでは、Webからやってきた信頼されていないコードを特権付きで実行してしまう可能性があることに触れています。これはWebアプリケーションにおいてのSQLインジェクションに対する注意喚起と同様の物と言えます。

この観点でevalの使い方に神経質になることは大事です。僕も、evalを使うすべての人は、この点に気をつけなくてはならないと思います。この理由で公開申請が却下されたのであれば、その判断は実に妥当だと思いますし、反論の余地は全くありません。

では、今回のケースはどうでしょうか。

ソース表示タブツリー型タブでは、evalはFirefox本体の関数を書き換えるためにだけ利用しており、そこにWebから取得したコードが混入するとは考えにくいです。もしこの理由で申請が却下されたのであれば、それは、レビュアーがきちんとコードを読まずに、単に機械的チェックにおけるevalの警告だけを見て判断を下したという可能性が出てきます。これは言い換えると、「evalが機械的チェックで検出されたからNG、検出されなかったからOK」という風な安直な判断を下すようになっている可能性があるということです。

もしそうなのであれば、そのようなレビュー姿勢は宜しくないものだと自分には思えます。そういう機械的なチェックをくぐり抜けるための抜け道はいくらでもあります。難読化されたコードなどはその典型ですし、難読化されていない「読みやすそうなコード」でも、ぱっと見分からないようにごまかすのは簡単です。もし機械的なチェックの結果だけを見て判断を下しているのであれば、そういうケースによる危険なコードの混入の可能性は否定できないことになります(そういう場合、時間をかけてでも・判断が遅くなってでもきちんと精査するべきでしょう)。そういうケースに対しても対処できるようにというのが、わざわざ人の手でレビューすることになっている理由の1つであると自分は信じています。

evalによる関数の書き換えのリスクは、それ以外の方法のリスクと比べてそんなに高いのか?

ソース表示タブツリー型タブで使われているevalはすべて、前出のエントリで挙げられている5つのケースのうち5番目のケース、「Firefox内で使われている関数の内容を書き換えるため」に該当するものです。前出のエントリでは、この使い方を以下の理由から非難しています。

  • 書き換える対象の関数の内容が変化した時に、ブラウザ自体がまともに動作しなくなってしまう恐れがある。
  • せっかく修正されたセキュリティ上の問題を、再び持ち込んでしまう恐れがある。

そして、代わりに推奨するやり方として以下のような「無理のないやり方」を挙げています。

  • 関数を別の関数で置き換えた上で、置き換え後の関数内で元の関数をfunc.apply(this, arguments)で呼ぶ。
  • Object.watch()を使って、特定の変数やプロパティの値が変化したタイミングで処理を行う。
  • そういう「無理のないやり方」では実現できないことをしようとしているのであれば、もう素直に諦める。

換言すると、前出のエントリの筆者は「このような無理のないやり方の方が、evalによる関数の置き換えに比べて、前述のような事態が発生するリスクが少ない」と述べていると言えます。

僕には、これはアンフェアな言い方と思えます。リスクの多寡で問題を語るのであれば、ここに挙げられていないリスクについても考慮するべきでしょう。そうすることで初めて、僕のような人が「evalによる関数の書き換え」という手法を選択している理由が明らかになります。僕だって、考えなしにevalを使っているわけではありません。メリットとデメリットを天秤にかけた上で、その方がリスクが小さいと考えてevalを使っているのですから。

リスク:Firefox自身の機能や他のアドオンと競合する可能性について

アドオンを「機能を実現する方法」の観点で見ると、以下のように分類できます。

  1. Firefoxや他のアドオンが提供するAPIに則ったアドオン。ツールバーへのボタン追加、サイドバーパネルの追加、nsIContentPolicyによるコンテンツフィルタリング(AdBlock Plus)、Jetpack Featureなど。
  2. Firefoxや他のアドオンがAPIを提供していない箇所に改変を加えるアドオン。
    1. XBLを使って機能を加えるアドオン。
      1. 新規にXBLを適用するアドオン。
      2. 既存のXBLを上書きするアドオン。Tab Mix Plusなど。
    2. JavaScriptの関数のはたらきを変更して機能を加えるアドオン。
      1. 関数を置き換えるアドオン。
      2. Object.watch()等で本来の処理に割り込むアドオン。
      3. 関数をevalで書き換えるアドオン。
    3. CSSでXUL要素の見た目を変えるアドオン。Personas、テーマなど。

1つのアドオンが複数の分類にまたがる場合も多いのですが、このうち「他のアドオンとの競合の可能性」という点で本当に低リスクであると言い切れるのは、1の「APIに則ったアドオン」の枠から外れないものだけです。それ以外はどんなアドオンであっても、Firefox自体の挙動や他のアドオンに何らかの影響を与える可能性があります。テーマですら例外ではありません。

前述の「無理のないやり方」の説明では、さもそのようなやり方を採用することによって競合のリスクが全面的に低減されるかのような書き方がなされていますが、場合によってはこの方が却って競合してしまう場合すらあります。実際、Firefox 3.6上でサイドバーの開閉状態の変化を捕捉するためにIDがsidebar-boxである要素のhiddenプロパティに対してObject.watch()で監視を行おうとしたところ、XUL要素の挙動が破壊されて、サイドバーの開閉自体が行われなくなってしまいました。(これは結局、DOMAttrModifiedイベントを監視してhidden属性の値の変化を見るという方法で回避することにしました。)

別の例として、「無理のないやり方」で関数を丸ごと置き換えられてしまうと、evalで元の関数を書き換えようとしていた他のアドオンが、関数を書き換えられないせいで期待通りに動作しなくなってしまうということも考えられます。……「そんな邪道なやり方をしている方が悪いのだ」という非難は無しですよ? 他のアドオンに与える影響を考えていないのは、お互い様なのですから。

また、これはリスクとは別の話ですが、「evalによって特定の箇所に特定のコードを注入することによって関数の定義内容を変えてしまわなければ実現できない機能」というものもあります(前出のエントリに対するコメントでも、Dorando氏が例を示しています)。そのような「無理なやり方」でやらなければならない事はするべきではない、というのが前出のエントリの著者の結論のようですが、後述する物も含めたリスクの点で明らかな優位性を主張できないのであれば、「無理なやり方はするべきでない、なぜならevalの間違った使い方だからだ」「evalの間違った使い方はするべきでない、なぜならそれは無理なやり方だからだ」というトートロジーに過ぎません。

リスク:Firefoxのバージョンが変わると予期しない結果になる可能性について

この点のリスクは、evalによる関数の書き換えでも、「無理のないやり方」と呼ばれている関数の置き換えでも、同様に存在します。前出のエントリでは「置き換え対象の関数の内容が変わったらどうするんだ」ということを指摘していますが、それを言えば、関数の名前が変われば「無理のないやり方」も破綻します。セキュリティアップデートでは関数の名前やそれぞれの働きが変わることはない、というのはただの思い込みです。そんなルールはどこにもありません。

また、「置き換えた関数A」→「置き換えた関数B」の順で処理が行われることを期待してコードを書いてる場合に、「置き換えた関数A」だけが実際には置き換えられなかったとすると、「置き換えた関数B」が動作する上での前提が崩れますので、その時どんなトラブルが起こるかは予想できません。これはFirefoxのバージョンが変わった時だけでなく、他のアドオンと同時に利用した時の競合についても全く同じ事が言えます。

いずれの場合にせよ、Firefox本体や他のアドオンのバージョンアップに対して、改変を加える箇所のソースコードをその都度調査し直さなければならないという、メンテナンスのコストの問題は、どちらにも共通して存在しています。「evalと関数置き換えのどちらの方が元のコードの変化に強いのか」ということを論じてもあまり意味はなく、どちらの手法を使うにせよ、Firefoxのバージョンアップに際してきちんと動作を検証しているかどうかや、前提が崩れた時のためのフェイルセーフがきちんと考えられているかどうかの方が、リスクに対する備えとしては重要且つ効果的なのではないか? というのが僕の考えです。

Firefoxのアドオンやテーマの正体は「動的に適用されるパッチ」です。ソースコードに対して、そこら辺に転がってる野良パッチをあててビルドする、というのはLinuxを使ってる人にはよくある光景ではないかと思いますが、「パッチが書かれた時のバージョンと違うバージョンのソースにパッチを当てること」がいかに危険かは、言うまでもないでしょう。Firefoxのアドオンを「アドオン作者によって動作確認されたバージョン」以外のバージョンにインストールすることは、それと全く同じ事です。

リスク:メンテナンス性、ソースの可読性が低下する可能性について

evalによる関数書き換えの場合、ソース中には「書き換える対象の関数名」「書き換えたい前のコード片」「書き換え後のコード片」だけが書かれることになります。

このコードを解読するためには「書き換える対象の関数」の内容を参照する必要があるため、その内容が頭に入っていない場合(大抵はそうでしょう)、解読が難しくなりがちです。その代わり、ソースコードの量自体は必要最低限になります。また、書き換える対象がロジックに絡まない「widthをheightに書き換える」という風な部分なのであれば、コードの読みやすさという点でもさほど問題は無いと言えます。このあたりは、「evalで関数を書き換える時の、互換性や後々のメンテナンス性を高く保つためのノウハウ」が重要になってくる所です。

関数の置き換えを行う場合も、ソースコードは結局は断片的な物になります。「前処理の関数」「元の関数をラップする関数」「後処理の関数」「元の関数の中で特定のプロパティに変更が加えられた事を捕捉して処理を割り込ませる関数」などが細切れに定義されますし、また、元の関数の処理結果の受け取り方法として「戻り値」以外の情報を使うのであれば、結局は元の関数の内容が頭に入っていないといけないことになります。

元の関数の中に変更を加えなければどうにもならない機能をどうにかして実現したい場合(前出のエントリのコメントで指摘されているようなケースなど)、こちらの手法にこだわるのであれば、「元の関数に必要な変更を施した後の関数」をアドオンの中で定義しておく以外に手はありません。そうなると、Firefoxや他のアドオンのコードと全く同じコードがそのアドオンの中に大量に含まれるようになってしまいます。これは、以下のような問題に繋がります。

  • それぞれのライセンスが衝突してしまうために、コードを丸ごと引用できないという事態が起こり得る。その機能を実現できない、という苦渋の決断を迫られる。
  • 前出のエントリ内でも指摘されている「せっかくFirefox(や他のアドオン)の側でセキュリティ上の問題が修正されても、関数を古いバージョンのそれに基づいた改変版に丸ごと置き換えてしまうことで、再びセキュリティ上の問題が持ち込まれてしまう」問題が起こり得る。
  • 単純にソースの行数が増加する事それ自体も問題となる。

リスク:公開申請時のレビューが通りにくくなる可能性について

これは「メンテナンス性、ソースの可読性が低下する可能性」にも共通する話です。AMOのエディターは最終的にはコードレビューによってそのアドオンの安全性を精査する必要があり、コードがトリッキーなものであればあるほど、また、コードの行数が増えれば増えるほど、コードレビューは大変な物になります。その意味で、関数の部分的な書き換えも関数全体の置き換えも、コードレビューの手間が増えるという点では一長一短です。

もっとも、今回の事例のように「evalを使っていること」を理由に公開申請が却下されることが相次ぐのであれば、eval無しでトリッキーで可読性の低い分量の多いソースコードの方が、比較的レビューが通りやすいという事になるのかもしれませんけれどもね。その場合、これもやはり「レビューを通してもらうためにはevalを使わない方がいい、なぜなら、evalを使っているとレビューが通らないからだ」という、何の説明にもなっていないトートロジーになる訳ですが。

まとめ

上記のような理由で、僕はソース表示タブツリー型タブの中で使われているevalが不必要な物ばかりであるとは考えていません(むしろどれも必要だからそうしているというのが自分の立場です)し、それらのevalの個々の用法が「これを読んで出直せ」と提示されたエントリの中で書かれている「代替案」に比べて目立ってリスキーであるとも思っていませんし、その「代替案」で代替できるとも思えません。

「evalの方が危険だ」と言っている人のうち何割の人が、本当にMozillaのコードを読んだことがあるのか、読み続けてきたのか、APIが用意されていない箇所でブラウザの機能を拡張する事に取り組んできたのか、継続的にFirefoxのバージョンアップに追従し続けたことがあるのか、他のアドオンとの競合を解消する方法を模索し続けてきたのか、僕には疑問に思えます。

XPCOMコンポーネントのIDL定義で「FROZEN」というフラグが立っている物以外のすべてのAPIは、いくらでも変更される可能性があります。FROZENになっているAPIは、Preferenceの読み書き、W3CのDOM関連など、全体から見れば本当にごく一部だけです。ブラウザ内のJavaScriptのレイヤで定義された関数に至っては、それが変更されない保証などどこにもありません。「Firefoxのバージョンに依存しないAPIが提供される」と思われていたFUELですら廃止される可能性が出てきている、Mozillaはそんな世界なのです。それで「evalの方が危険だ、同じ名前の関数で置き換える方がマシだ」と言うのがどれほど馬鹿げた話か。

ですので僕にとっては、evalの使用を理由として公開申請が却下された今回の出来事に対しては、不当な判断を下されたという思いが強いです。

プラットフォームのデフォルトの文字エンコーディングを取得する方法を調べようとして挫折したことのまとめ - Jun 06, 2009

ソース表示タブの障害として、「外部のテキストエディタを使う設定にしてる時に、Windowsのアカウント名が日本語だったりするとファイルを開けない」という報告を受けた。それを修正しようとして挫折した。以下はそのまとめ。

Webページのソースをテキストエディタで開く処理について

当該機能は実はソース表示タブ自身が提供しているわけではなく、Firefox 2以降くらいからFirefox自体に元々備わっている隠し設定のための設定UIを提供しているだけで、実際の処理はFirefox本体の物に丸投げしている。具体的にはviewSourceUtils.jsopenInExternalEditor()とかそこら辺。

ただ、Firefox本体のこのコードは国際化のことをきちんと考えられていないようで、テキストエディタの実行ファイルのパスに日本語の文字などが含まれているとダメという既知のバグがある(原因はgetExternalViewSourceEditor()の中でgetCharPref()で取得したパス文字列をUTF-8バイト列からUCS2のUnicode文字列に変換していないせい)。なのでソース表示タブではこの部分に動的にパッチを当てる形で問題を回避するようにして、もう少し実用に耐えるようにしようとしてみている。

今回の問題の原因は、エディタの実行ファイルではなく、開こうとしている対象のファイルのパスの扱いにある。

Firefoxは、ソースを表示しようとしている対象がローカルのファイルだとそれをそのまま、Web上のファイルであればそれをダウンロードしたテンポラリファイルを、エディタに渡そうとするんだけど、どうもその時にnsIProcessrun()メソッドで渡す引数がUCS2のままなのがいけないらしい。試しに自分の環境(Windows Vista日本語版)で試したところ、引数のeditor.run(false, [path], 1);とか書かれてる箇所で渡されてるパス文字列をnsIScriptableUnicodeConverterあたりでShift_JISに変換してやったらうまく動いた。IDL定義ではstringの配列としか書かれてないけど、ここはプラットフォームごとのデフォルトの文字エンコーディングにしておかないといけないようだ。

実験段階で明らかなように、nsIScriptableUnicodeConverterで適切なエンコーディングに変換してやれば問題は解決できる。残る問題は、じゃあ一体どのエンコーディングに変換すればいいのか、ということだ。

設定UI上にエンコーディング選択用のドロップダウンリストを付けるという手もあるけど、ユーザにそんな事を意識させるのはダサイ。なるべくなら自動で判別できるようにしておきたい。ということでその方法を模索してみた。

nsIFileのnativePathから辿ってみた

現在のFirefoxでは、ローカルファイルはnsIFileインターフェースで処理されている。このIDL定義を見ると、プラットフォームのデフォルトのエンコーディングでのパス文字列をそのまま保持しているとおぼしきnativePathプロパティの定義には[noscript]と書かれていて、JavaScriptからはアクセスできないようになっている。実際、試してみても無理だし。

ちなみに、昔おそらくnsIFileの代わりに使われていたと思われるnsIFileSpecだとnativePathには[noscript]が付いてない。なので、これを使ってやればいいか?と思ったけど、リンク先のソースの位置を見ると分かる通りこれは既に廃止されたモジュールで、今のFirefoxのバイナリには入ってないっぽい。インスタンスを作ろうとしてもエラーになる。

nsIFile/nsILocalFileを実装してるWindows用のコード(nsLocalFileWin.cpp)GetNativePath()の定義を見ればヒントを掴めるんじゃないか?と思ってみてみたら、CopyUnicodeToNativeという関数?が使われてた。コードが書かれてるnsNativeCharsetUtils.cppを見てみると……おおお、なんか答えっぽい物があるぞ。ifdefでプラットフォームごとに関数の中身の定義をそれぞれ変えてて、例えば頭の方を見てみると、Mac OS XとBeOSでは単純にUTF-8に変換してるという事が分かる。

ただ、下の方に書いてあるWindows用とUnix/Linux用の処理は、見ても訳が分からんかった……単純にこのエンコーディングに決め打ち、という訳にはいかないみたいで、ここからさらに色んな所のコードを見に行かなきゃいけないようだったので、この時点で挫折した。

nsIScriptableUnicodeConverter関係から辿ってみた

nsIScriptableUnicodeConverterはエンコーディング名を指定してUCS2との間で相互変換するものだけど、その時に「プラットフォームのデフォルトのエンコーディング」を指すようなキーワードがあったりしないしないか?と思って、そっち関係のコードも見てみた。

nsICharsetConverterManager.idlとかnsUConvModule.cpp見てて、どこをどう辿ったのか忘れたけど、GetDefaultCharsetForLocale()というメソッドがnsIPlatformCharset.hで定義されているという所まで辿り着いた。

メソッド名から見て、ロケールを指定しないといけないようだけど、それさえなんとかなればこれでいけるか? と思ってこれにJavaScriptからアクセスできないか試してみたけど、ダメだった。Components.classes['@mozilla.org/intl/platformcharset;1']にはアクセスできるんだけど、QueryInterface(Components.interfaces.nsIPlatformCharset)してみたら「そんなインターフェースねえよ」と怒られてしまった。検索してみても、どうもC言語用のコードしか無いみたい。

結論

無理でした。以上。

C(C++?)を書けるようになって、上で辿り着いたメソッドの実行結果を返すだけのコンポーネントでも書けば、サクッと解決できるのだろうか。もう勉強するしかないのか?

おまけ:文字コード選択のUI

コンテキストメニュー拡張で使ってるけど、文字コードを選択するドロップダウンリストは以下のようにすれば作れる。

<menulist id="charset"
  label="(choose an charset)"
  datasources="rdf:charset-menu"
  ref="NC:DecodersRoot">
  <template>
    <menupopup>
      <menuitem uri="..."
        label="rdf:http://home.netscape.com/NC-rdf#Name"
        value="..."/>
    </menupopup>
  </template>
</menulist>

ただし、XULにこれを書いただけだと空のリストになってしまう。onloadとかそこらへんでCc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService).notifyObservers(null, 'charsetmenu-selected', 'other');とすればポップアップの中身が生成される。設定ダイアログで使う時なら、その後でpreference要素のvalueを見るなどして、前回の選択状態を復元してやる必要がある。

他のアドオンと衝突しないように心がけたいし、心がけて欲しい - Apr 17, 2009

「次のエントリで書く」なんて予告じみたことを書いてはみたものの、どうも話がまとまらない。もう、思ったことを箇条書きで書くだけにする。

現実的に言って、1つのアドオンであらゆる人のニーズを満たすことは不可能だと思うし、そういう方向での努力はしない方がいいとも思う。何でもかんでも……と際限なく詰め込んでいくと、どこかで破綻すると思う。機能の詰め込みは、ある時点までは効率がいいんだけど、ある時点を超えてしまうと、デメリットの方が大きくなってくる。「Piro拡張化」なんて言われるようになる。

作る側の心理として、どうして機能を増やしたくなるのか。他の人はどうか知らないけど、僕はこんな感じだった。

  • デバッグより、新機能を実装する方が楽しい。モチベーションが高まる。
  • 大は小を兼ねる。大きいことはよいことだ。みたいな。
    • 「こんな小さな物をたくさん作りました」よりも「こんなデカい物をたった一人で作りました」の方がなんかすごそう。
    • より多くの人のニーズを満たせば、より多くの称賛を得られる。誉められて嬉しい。
  • それまでに作った部分を土台や部品として使えるので、新しい別個のアドオンにするのに比べてはるかに楽に「すぐ動く物」ができる。
    • 共有できる部分が多ければ、それだけ「無駄が無い」と言える。同じことをするコードが複数のアドオンにあるのは、無駄なことで、気持ち悪いと感じる。
    • 複数の機能を有機的に連携させて、「100%ぴったり、思い通り」の挙動を実現できる。

そんな感じの理由でどんどん機能を加えていく。ある時点までは、それでうまく回る。応援してくれる人とか感謝してくれる人とか、モチベーションを高めてくれる声も寄せられる。でも、なんかの閾値を超えたところで、あらゆる物事が下り坂に転じる。

  • 目が行き届かない所が出てくる。
    • 自分が使う物は目が届くけど、使ってない機能には目が届かない。
    • 自分の環境では問題ないのに他の環境では問題が起こる、というケースが頻発するようになる。
  • 機能同士が複雑に絡み合っているので、原因の特定がどんどん困難になる。
  • 既にある機能との整合性を常に考えないといけないため、新しい機能を加えにくくなってくる。新しい機能を加えることに物凄くエネルギーを使わないといけなくなる。
  • 作り込めば作り込む程、前提とする環境への依存が強くなる。
    • 前提がちょっと変わるともう全然動かなくなる。Firefox 1.5向けに作り込んでいたから、もはやFirefox 2に対応できない。
  • 最初の頃は「こんなの今まで無かった! これがあると大違い! 素晴らしい!」と称賛されていたのに、だんだんそれがなくなってくる。
    • 「定番だよね」「むしろ当たり前だよね」と言われるようになってくる。
      • 使う側から見たら「あって当たり前」という感覚だから、感動なんてしない。最初の時点で「とりあえず入れとけ」みたいな感じで勧められるから、それが無い時の不便さも、それを導入することで起こる変化にも、気がつかない。
      • 本当だったら使わなくてもいいはずの人まで、「なんかみんな使ってるみたいだし、入れとくか」という感じで使うようになる。
      • アドオンは薬のようなもので、導入するのは薬効と副作用のトレードオフ。どうしても必要な薬効があるから副作用を我慢して使う、というのが本来そうあるべき使い方なのに、薬効をそもそも知らないまま流されて服用して、副作用に苦しむことになる。
        • 「バグが多い」「不具合ばっかり」「他のアドオンと衝突しまくる」などのデメリットばかりがとりあげられるようになってくる。
      • 「定番なんだから責任持って作れよ」「こんな事もできないの? 定番なんだからできて当然なんじゃないの?」みたいな、お客様気分の声が増えてくる。やる気を削がれてくる。

そんなわけで、精神的な負荷と時間的なコストがどんどん大きくなっていって、タブブラウザ拡張は破綻した。Firefox 1.5のサポート完全終了と共に、過去の遺物となった。

  • かといって、Firefox 2デフォルトの状態で我慢できるわけもなくて。
  • でも、タブの複数行表示機能をやめてツリー表示しか使わなくなってしまっていた自分には、今更Tab Mix Plusに乗り換えるというのも考えられなかった。
    • 感情的な理由もあった。後から来て追い抜いていった(と同時に、良い評価もかっさらっていった)相手に自分が依存するのは屈辱だと思った。
    • TMPも「Piro拡張化」の行き着く果てまで来ているように思えた。ここから先は下り坂だと思った。

そういうわけで、過去の自分の失敗を徹底的に反省して、ゼロからやり直すことにした。

  • 全部詰め込むのはやめる。1つ1つのアドオンを可能な限り単機能に保つようにする。
    • 多少効率が悪くても、重複する部分があっても、個別のアドオンに分ける。
    • 重複する部分がデカくなるようだったら、ライブラリにする。
      • ライブラリはファイル単位で上書きできるようにする。ファイルの中を見て必要な箇所を切り貼りして……という風なことはミスの元になるから、やらない。
      • 複数の異なるバージョンの同じライブラリが同時に入っていても、問題なく動くようにする。
      • という考えで作ったライブラリをリポジトリにまとめてある
    • 関係ない機能を含めない。コンセプトが合わない機能は、簡単に実装できそうであったとしても、加えない。
      • これはユーザにもメリットがある。
      • 多機能で「とにかく便利」なんてコンセプトだと、ユーザは入れてみるまで薬効と副作用の比較ができない。入れた後も、どれが薬効でどれが副作用なのか分からない。
      • 単機能なら、薬効と副作用を比較しやすい。「この機能はいらないから、入れない」という判断ができる。「よく分からんけどとりあえず入れてみる」という選択を防ぐ圧力が生じる。
        • 多機能にするよりユーザ数は多分減る。でもそれでいい。薬効が必要なくて副作用しか得られない人にまで、使ってもらいたくない。
  • 主要な機能を、他のアドオン(自分が作る物も含めて)から使いやすいように「API」として公開する。
    • といっても、物自体は変わらない。あくまでただのメソッド。ただ、作る時の心構えを変える。
      • 自分だけが使うものだから……と思っていると、メンバ変数とかをがんがん使った、実装するのが楽な、結合が密な設計にしてしまいがち。
      • 結合が密だと、100%全ての情報の流れを理解している人間でなければメソッドを使えない。
      • 半年くらいして自分でもすっかり忘れた頃にもう一度見て、すぐに理解できるか? 理解できなさそうなら、それは駄目な設計。
      • 結合をなるべく疎にする。密な結合にしないといけない時は、せめて、情報が双方向に流れないようにする。一方通行に処理を追いかけるだけで理解できるようにする。
    • インターフェースを公開して、ドキュメントも作る。
      • 既に公開してしまっている物だから、安易に変更できないというプレッシャーがかかる。APIの互換性を維持する力が働く。
    • 機能同士の連携は、必ず公開APIを経由して行う。
      • APIでできないことはしない。
      • 必要なら新しいAPIを考える。やっつけ仕事ではなく、ちゃんとした設計で。
  • TBEでやってたような、ガチガチの作り込みはしない。
    • 泥臭くてカッコ悪くても、フレキシブルな対応が可能なやり方を取る。
      • XBLでスッキリ書くより、DOMでゴリゴリ書く。
    • なるべく、Firefox自体が持つ構造を壊さない。
      • 要素構造を自分好みにすっかり作り替えてしまえば、自分は楽になる。でも、ユーザが困る。他のアドオン作者も困る。要素構造を変えると他のアドオンと衝突しやすくなる。
    • XBLの使用はできるだけ避ける。
      • 特に、既存のバインディングの「置き換え」は「最後の手段」「禁じ手」と考える。
      • 「まだバインディングが行われていない部分への追加」だったら、使ってもいい。
      • どうしてもXBLじゃなきゃ実現できない、という部分だけに限って使う。それ以外でXBLを使うのは、極論すれば「珍しい技術を使ってる自分」に酔っぱらってる自己満足な行為でしかない、と考える。
    • メソッドを丸ごと置き換える、という事はできる限り避ける。
      • やるのなら、eval()による部分的な書き換えで対処する。
      • やりたいことの大半は、元のメソッドの最初か最後に処理を追加するだけ。メソッドを丸ごと全部別物に置き換えてしまう必要は本来無い。
      • 見通しは悪くなるけど、他のアドオンとの競合は起こりにくくなる。と思う。
      • これによる開発効率・メンテナンス効率の低下は、個々のアドオンを単機能に・シンプルに保つという前提によって相殺する。
  • 他のアドオンでできることはしない。
    • 自分一人で抱え込まない。他の人がやってることをわざわざ自分でやり直そうなんてことはしない。
    • 組み合わせて使うことを積極的に推奨する。自分自身も、他のアドオンと組み合わせて使う。
      • 組み合わせて使って問題が起こりにくい設計にしないといけない、という圧力が自然とかかる。

こういう考えに基づいて作ったのが、マルチプルタブハンドラ情報化タブツリー型タブソース表示タブという4つのアドオンだ。上に書いたことを完全に守れてるとは言えない部分もあるけど、昔に比べれば遙かにマシになってると思う。

作る側としても、使う側としても、僕は今の方がずっと楽だ。

「多機能に」「1つだけで様々なニーズに応えられるように」という方向に頑張ると、縛りがどんどんきつくなってくる。1つのアドオンだけでできることを増やしていこうとすると、妙な話だけど、他のアドオンに頼れなくなっていく。作り込むほどに、そのアドオンを入れた結果が素のFirefoxとかけ離れてしまうから、他のアドオンとの互換性がどんどん失われていく。だから、1つのアドオンだけでしなきゃいけない事がイモヅル式にどんどん増えてくる。

ユーザの視点から見ると、「多機能なアドオン1つだけの世界で完結した使い勝手を享受する」か、「いろんなアドオンを組み合わせて使う」かの、どっちかを選ばないといけないということでもある。両立はできない。

ここで改めて念を押すけれども、僕は、Tab Mix Plusと上記のタブ系アドオンの組み合わせは推奨していない。一応TMPで動くようにはした、けれども、継続的に追っかけ続けるモチベーションが無い。何故なら、僕はTMPユーザではなく、TMPと組み合わせて壊れるようであっても僕自身は全く困らないから。TMPユーザでない他のアドオンの作者の中には、同じように感じてる人もいるんじゃないかと思う。自分が使ってもいないのに対応を迫られるなんて、厄介な奴だ、目障りな奴だ、みたいな。閑話休題。

「多機能なアドオンで、部分的には、痒い所に手が届くような感覚がある。でも、足りない部分もある。それを補うための他のアドオンと組み合わせて使うことは、残念ながらできない。」「単機能のアドオンをたくさん入れていて、それぞれはそれなりに便利。でも、いまいち連携が取れてなくて、痒い所に手が届かない。」そのどっちかを選ばないといけない。

一人あるいは少数の作者の頑張りだけに期待しなきゃいけない、期待して待ってなきゃいけない。多機能長大路線を歩むという事は、ユーザにそれを強いるという事だと思う。僕はそれが嫌になった。

多分、多機能な物を「作る」だけなら、誰にでもできるんだと思う。時間さえかければ。当時の僕にもうなる程の時間があった(大学生で、レベルもそんなに高くなかったから楽に単位を取れて、その分自由に時間を使えた)から、できてたんだと思う。でも、より大きな問題は「作った」の後にあると思う。メンテナンスし続けられるのか? 他のアドオンと協調させられるのか? 多機能長大路線ではそれは難しいと、僕は思った。

タブ系拡張機能 - Oct 16, 2008

そんなわけで(?)、TBE3に含まれる4つともアップデートした。

情報化タブの機能として、Firefox 3.1向けに、最後のタブのクローズボックスを強制的に表示させるオプションを加えた。本体の方でまた隠し設定がどうとか色々変わりそうな気もするけど、とりあえず現時点での仕様に合わせておく。不要になったら機能自体削除の可能性もある。

ソース表示タブは、機能は変わってないんだけど、動的に書き換えてるメソッド類がMinefieldでだいぶ変わってるようだったので、その修正が主。

マルチプルタブハンドラは、ツリー型タブの修正で書いたのと同じ要領でMenu Editorとの競合を解消したり、ツリー型タブと組み合わせた時の地味なトラブルを直したり、といった程度。

タブブラウザ拡張3 - Oct 27, 2007

タブブラウザ拡張3を公開しました。

……といっても実際にタブブラウザ拡張のバージョン3を作ったわけではなくて、情報化タブマルチプルタブハンドラツリー型タブソース表示タブ以前訳したマルチアイテムパッケージの作り方のまんまで一つにパッケージングしただけですハイ。「TBE3」をインスコすると上記4つのアドオンがアドオンマネージャに普通に並びます。

まあ、色々要望等はあると思うけど、僕にとってはこれだけ揃ってたら「TBE3」と名前を付けてもべつにいっかなーと思えている、僕にとっての「タブブラウザ拡張」の「他では替えが効かないもの」はこういう事かな、という感じです。

僕自身はこれに加えて以下のアドオンを組み合わせて、旧TBEで使ってた操作感をなるべく再現して使ってる。

  • Undo Closed Tabs Button:閉じたタブを一覧からすぐに開き直せるように。(複数のセッションの管理は実際の所あんまり使ってなかったんで……セッション管理もしたい人はSession Managerあたりをどうぞ)
  • Tab Clicking Options:タブバー上でのダブルクリックで新規タブ、タブバー上での中クリックで閉じたタブを復元、という操作をするため。それ以外の機能は使ってない。
  • Adaptiva Referer Remover:127.0.0.1とかlocalhostとかからのリファラ送信をカットするために。

逆に、TBEが持ってた機能で今の環境(他のアドオンとの組み合わせも含めて)に欠けてるのは、タブの複数行表示、タブの色分け、フォーカスの詳細な制御、タブのロック、自動リロード、別サイトへのリンクを常に新規タブで開く(別サイトへのリンクをタブで開く機能はツリー型タブ 0.3.2007102902に実装した)リファラの送信禁止(Adaptiva Referer Removerで代用可能)、JavaScript・Cookie・Refreshによる自動リロード・プラグイン・画像表示それぞれのタブごとの有効無効の設定、それらの情報をブックマークに保存する、といった機能か。

また後で改めて書くけど、タブブラウザ拡張いっこのためにOSのアップグレードすら半年以上(Firefox 2リリースの時から数えれば1年近く)できずにいたので、ついにここまで来たかぁ、と感無量です。

なお、TBE3に含まれている4つのアドオンはどれも一応最近のMinefieldで動作確認はしてるので、次のFirefoxメジャーアップデートの時には今回よりはすんなり移行できるんじゃないかなと思ってる。まあまだUIまわりが(特にタブが)色々変わる可能性はあるようなので安心はできないけど。

タブでソース表示 - Oct 24, 2007

View Source in Tab。その名の通り、ソースの表示をタブで行うようにするだけという物。ツリー型タブの機能として加えようとしてて、よく考えたらこれツリー関係の機能関係なくね? と思ったので別途リリースすることにした。

作り始める前に「そういえばそんな名前のアドオンがすでにあったような気がするんだが……」と思って「View Source in Tab」で検索してみたけど見あたらなかったのでそれなりに作り込んでさあそろそろ公開するか、と思ったところでふと「Open Source in Tab」で検索してみたらあっさり見つかったし

まあそれでもせっかく作っちゃったから公開しておく。一応、Open Source in TabやView Source Choiceに比べて以下の点でView Source in Tabの方が高機能ではあります。

  • 「ページのソース」だけでなく「選択範囲のソース」もタブで開くことができる。
  • 通常の「ソースを表示」ウィンドウと同じUIを持った物がタブで開かれる(Open Source in Tab、View Source ChoiceだとUIなし)ので、メニューからハイライトの機能の有効無効を切り替えたり、現在の行数・桁数が表示されたり、といった元々の「ソースを表示」機能の便利なところをそのまま使い続けられる。
  • Firefox 2のセッション保存のAPIを利用しているので、タブを閉じた後もう一度開き直しても、選択範囲まで含めてちゃんとタブが復元される。
  • ツリー型タブのAPIを利用しているので、一緒に入れとくと現在のタブの子タブとしてソース表示のタブが開かれる。
  • Firefox 2(Firefox 1.5からだったか)の隠し機能でソース表示に外部のエディタを使う機能があるけど、実行ファイルまでのパスの中に日本語が入ってるとエラーで起動に失敗するので、独自にパッチを当てて、日本語を含むパスでも問題なく外部エディタを起動できるようにした。(外部エディタを使う場合は選択範囲のソースは今まで通り内部のビューワで表示される)

でも徹底的に探したわけではないので、これで後から「実はすでにView Source in Tabという名前のアドオンがあるんだが」という風に気がついたら、もうどうしようもない。→ありました

25日追記。無難なところで「Source Viewer Tab(ソース表示タブ)」に改名しておきました……

タブでソース表示 - Jan 01, 1970

View Source in Tab。その名の通り、ソースの表示をタブで行うようにするだけという物。ツリー型タブの機能として加えようとしてて、よく考えたらこれツリー関係の機能関係なくね? と思ったので別途リリースすることにした。

作り始める前に「そういえばそんな名前のアドオンがすでにあったような気がするんだが……」と思って「View Source in Tab」で検索してみたけど見あたらなかったのでそれなりに作り込んでさあそろそろ公開するか、と思ったところでふと「Open Source in Tab」で検索してみたらあっさり見つかったし

まあそれでもせっかく作っちゃったから公開しておく。一応、Open Source in TabやView Source Choiceに比べて以下の点でView Source in Tabの方が高機能ではあります。

  • 「ページのソース」だけでなく「選択範囲のソース」もタブで開くことができる。
  • 通常の「ソースを表示」ウィンドウと同じUIを持った物がタブで開かれる(Open Source in Tab、View Source ChoiceだとUIなし)ので、メニューからハイライトの機能の有効無効を切り替えたり、現在の行数・桁数が表示されたり、といった元々の「ソースを表示」機能の便利なところをそのまま使い続けられる。
  • Firefox 2のセッション保存のAPIを利用しているので、タブを閉じた後もう一度開き直しても、選択範囲まで含めてちゃんとタブが復元される。
  • ツリー型タブのAPIを利用しているので、一緒に入れとくと現在のタブの子タブとしてソース表示のタブが開かれる。
  • Firefox 2(Firefox 1.5からだったか)の隠し機能でソース表示に外部のエディタを使う機能があるけど、実行ファイルまでのパスの中に日本語が入ってるとエラーで起動に失敗するので、独自にパッチを当てて、日本語を含むパスでも問題なく外部エディタを起動できるようにした。(外部エディタを使う場合は選択範囲のソースは今まで通り内部のビューワで表示される)

でも徹底的に探したわけではないので、これで後から「実はすでにView Source in Tabという名前のアドオンがあるんだが」という風に気がついたら、もうどうしようもない。→ありました

25日追記。無難なところで「Source Viewer Tab(ソース表示タブ)」に改名しておきました……

タブでソース表示 - Jan 01, 1970

View Source in Tab。その名の通り、ソースの表示をタブで行うようにするだけという物。ツリー型タブの機能として加えようとしてて、よく考えたらこれツリー関係の機能関係なくね? と思ったので別途リリースすることにした。

作り始める前に「そういえばそんな名前のアドオンがすでにあったような気がするんだが……」と思って「View Source in Tab」で検索してみたけど見あたらなかったのでそれなりに作り込んでさあそろそろ公開するか、と思ったところでふと「Open Source in Tab」で検索してみたらあっさり見つかったし

まあそれでもせっかく作っちゃったから公開しておく。一応、Open Source in TabやView Source Choiceに比べて以下の点でView Source in Tabの方が高機能ではあります。

  • 「ページのソース」だけでなく「選択範囲のソース」もタブで開くことができる。
  • 通常の「ソースを表示」ウィンドウと同じUIを持った物がタブで開かれる(Open Source in Tab、View Source ChoiceだとUIなし)ので、メニューからハイライトの機能の有効無効を切り替えたり、現在の行数・桁数が表示されたり、といった元々の「ソースを表示」機能の便利なところをそのまま使い続けられる。
  • Firefox 2のセッション保存のAPIを利用しているので、タブを閉じた後もう一度開き直しても、選択範囲まで含めてちゃんとタブが復元される。
  • ツリー型タブのAPIを利用しているので、一緒に入れとくと現在のタブの子タブとしてソース表示のタブが開かれる。
  • Firefox 2(Firefox 1.5からだったか)の隠し機能でソース表示に外部のエディタを使う機能があるけど、実行ファイルまでのパスの中に日本語が入ってるとエラーで起動に失敗するので、独自にパッチを当てて、日本語を含むパスでも問題なく外部エディタを起動できるようにした。(外部エディタを使う場合は選択範囲のソースは今まで通り内部のビューワで表示される)

でも徹底的に探したわけではないので、これで後から「実はすでにView Source in Tabという名前のアドオンがあるんだが」という風に気がついたら、もうどうしようもない。→ありました

25日追記。無難なところで「Source Viewer Tab(ソース表示タブ)」に改名しておきました……

Page 1/248: 1 2 3 4 5 6 7 8 9 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき