ラベル chrome の投稿を表示しています。 すべての投稿を表示
ラベル chrome の投稿を表示しています。 すべての投稿を表示

2012/07/11

Google Chrome拡張を{ "manifest_version": 2 }に対応させてみる

気がついたらGoogleから「マニフェストのバージョンが2になったから対応よろしくね」、という旨のメールが届いていた。 まぁ8月中旬から新規の登録受付を中止して、年内には更新の受け付けができなくなるスケジュールが引かれていたので、 使うだけのユーザーなら影響がでるのは来年以降ですね。

今回はmanifest.jsonファイルを変更して気になった点をまとめていきます。

ちなみに変更は動作確認が終り次第、gitoriousにあるコード(Japan Postal Code Search, Open PinnedTab Link, etc...)に反映させます。

参考にしたページ

Googleのガイドはとてもまとまっているので、あまり他のサイトを調べる必要性を感じないのですが、 さすがに今回はStackOverflowなどのサイトにお世話になりました。

とはいえ、まず抑えておかなければいけないのはGoogleのmanifest.jsonの"manifest_version"の説明ページです。

ここで、全体のスケジュールと全体の変更の概要が書かれています。 しかし、ここだけでは具体的にアプリケーションにどんな変更が必要か把握するのは難しかったです。

具体的な変更作業

とりあえず作成しているOpen PinnedTab LinkJapan Postal Code Searchの2つは、比較的簡単なアプリケーションです。

このアプリケーションを修正した際に必要な修正は以下のようになりました。 まだ稼働確認が終っていないので、追加で必要なものもありそうですが、とりあえずまとめます。

HTML中にonclick, onload属性は書けなくなった

scriptタグを使ったjQueryの$(function() {...});表記などは、そのまま使えますが、(x)HTML上のタグにあるonclick="..."やonload="..."の表記を埋め込む事ができません。

基本的なコードはGoogle ChromeガイドのContent Security Policy (CSP)ページに記載されています。

onloadについは書かれていませんが、onclickと同様にdocument.addEventListener('DOMContentLoaded', function () { ... };の...部分にonloadで行なっている関数呼び出しなどをコピーすれば動きます。

ここで問題になったのはJavaScriptのコード中で、明示的に文字列としてonclick属性を追加している場合でした。

変更前のコード:文字列としてonclick属性を追加している例

...
td4_span.setAttribute("onclick","showMapImg('" + center + "')");
...

変更後のコード:addEventListenerに書き換えた例

...
td4_span.addEventListener('click', function(){showMapImg(center);});
...

元々変更後のように組むべきだったとは思います。 とはいえ文字列で解決するのは単純で簡単だったので、使っている方もいそうです。

動的なアクションはすべからくaddEventListener関数で指定する事になると思われます。

background処理をhtmlからjsファイルへ移動

manifestのbackgroundで指定する対象がhtml("page":文字列)とjavascript("scripts":文字列配列)の2つが準備されています。

これまではhtmlで記述していたので、manifest.jsonを書き換えて、そのまま流用すれば良いと思っていたのですが、どういう分けか、うまく動きませんでした。

変更前:version 1のmanifest.jsonから抜粋

...
  "background_page": "background.html",
...

元々background.htmlは本文のない、scriptタグの中に処理が記述されているだけだったので、その中身をjsスクリプトファイルに分割して、manifest.jsonの表記を書き換えました。

変更後:version 2のmanifest.jsonから抜粋

...
  "background": { 
     "scripts": ["scripts/background.js"]
  },
...

jsファイルを指定した場合でも、内部では空のhtmlファイルが生成されて組み込まれているだけのようなので、今回の挙動はおかしいと思います。 おそらくhtmlファイルのまま移行できるように作られているはずなので、早晩このワークアラウンドは不要になるでしょう。

まとめ

いろいろ書こうと思ったのですが、うまく動かない処理を発見したりして別の記事にまとめる事にして、とりあえず今回はここまでで終りです。

今回取り上げなかったのですが、外部サイトからのJavaScriptファイルのロードなどもデフォルトではできなくなっています。 オプションページのためにjQueryのコードをCDNからダウンロードしたいような場合にも対応が必要そうです。

単純なmanifest.jsonの書き換えで対応できるアプリケーションは少ないのではないでしょうか。

とはいえ、変更内容を確認する限り、機能が制限されているものはないので、既存の"manifest_verison":1アプリは全て、ちゃんと書き換えれば動くはずです。

この「ちゃんと」という部分が曲者ですが、今回の経験からは、新ルールに矯正された事によってアプリケーションのコード全体は良くなっていると思います。

Chrome拡張のAPIについてはいろいろ疑問に思うところもあったので、これから始める方々には、面倒は増えるでしょうが、よりよいコードになっているとは思います。

これがどれくらい面倒かは…、なんともいえませんが、少なくとも既存の開発者は、どこに問題があるか調べるだけで面倒そうです。

2012/04/17

データベースに格納されている画像データをWebページに表示する

これまでWebアプリケーションを作る際のサムネイルデータなど、サイズのごく限られた画像ファイルをBLOBデータとしてデータベースに格納してきました。こういったケースは比較的よくあると思います。 最近では比較的大きなサイズの画像ファイルでもBLOBとして格納してしまうかもしれません。

今回は比較的サイズの小さな画像データをWebページに大量に貼り付けたい場合のお話しです。

背景

これまでは、DB上にあってファイルとしてアクセスできない画像を表示するために、画像データのストリームを返す小さなWebアプリケーションを準備してきました。

これだと画像ファイルの数が多くなった場合には、画像のデータ分だけのコネクションが必要になります。 keep-aliveが使えて実際のコネクション数が参照数と同じではないとしても、同一ページに小さな画像を大量に表示する事 は全体のパフォーマンス上の懸念材料になってきました。

いままでのベストプラクティスであれば、1ページは30kbyte以下に抑えるとか、画像データの取り扱いについてもいろいろありましたが、デスクトップアプリケーションの代りとしてWebアプリを作る場合には、これまでのルールが当てはまらない場合もでてきました。

HTMLに画像データを埋め込む技術的な話し

これまでの手法だとimgタグのsrc属性に画像表示用のURLを指定してidなどで画像を指定するようにしてきましたが、直接に画像データを指定します。

データを埋め込む例

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAABLCAIAAAA06NSGAAAACXBIWXMAAABI
AAAASABGyWs+AAAACXZwQWcAAAB4AAAASwDhLqRrAAAki0lEQVR42u18a5Bc
..." />

いままで試したプログラミング言語毎の例を載せておきます。

RubyでBase64を扱う方法

いま手元にあるのはRuby 1.9.3-p125ですが、方法は共通のはずで、だいたい次のようなコードになっています。

Base64の文字列を得るのにpackを使っています。

rubyでのイメージファイルのbase64化


## この例ではオリジナルデータをファイルにしています
@filepath = "/somewhere/foo.jpg"

@prefix = "data:$MIME_TYPE;base64,"

## この戻り値をimgタグのsrc属性に指定します。
def getSrcData(data)
  ret = @prefix.sub("$MIME_TYPE", getMimeType())
  ret += [IO.read(@filepath)].pack("m")
  return ret
end

def getMimeType()
  ext = File.extname(@filepath).downcase.sub("\.","")
  ext = "jpeg" if ext =~ /jpg/i
  return format "image/%s", ext
end
JavascriptでBase64を扱う方法

以前、Google Chromeの機能拡張でExifの情報を扱うアプリケーションを作成しました。 Chromeでは同じ機能拡張の中でもメインのタブとポップアップウィンドウの間ではデータ参照が制限されているので、メインコンテンツの画像を機能拡張のポップアップウィンドウの中で表示するには、外部参照のURLを渡すか、データ列を渡すかの方法をとることになります。

その時はExifを解析するためにメインコンテンツ側でダウンロードしたデータをBase64で渡して、ポップアップウィンドウ側に表示させました。これはダウンロード回数を最小にするべきだろうという理由での判断でした。

Javascript自身にはbase64化の手段がないので、Masanao Izumoさんが公開されているbase64.jsを利用しました。

Javascriptでのbase64化


  imgtag_data_list.push("data:image/jpeg;base64,"+base64encode(EXIF.getRawData(node)));

この時はいくつかbase64化のライブラリを試しましたがテキストではなく、バイナリに対応しているのはIzumoさんのコードしか見つけられませんでした。コード中のEXIF.getRawData(node)で参照しているデータはXMLHttpRequestのresponseBodyです。

考慮点

同じ画像を大量に表示するような場合は、テキストファイルに埋め込むよりも、アプリケーション側でLast-ModifiedCache-Controlヘッダーをちゃんと扱うようにするのが最も経済的です。

安易にCGIやらで組むと動的アプリケーションの特性としてCache-Control: no-cache付く事になるので、キャッシュが有効になりませんが、これに気をつけるだけでブラウザが適切に繰り返しの読み込みを効率化してくれます。

他には画像データのサイズが比較的大きい場合は、HTMLファイルのダウンロードに時間がかかる事になるので、最初の画面描画が遅くなる欠点があります。ここ最近のブラウザはレンダリング途中から表示が始まるので、問題にならないかもしれませんが、いずれにしろサイズの大きなファイルを大量に表示するのは、もともとの設計に問題があります。

画像データの埋め込みはあくまでもサムネイルや、HTMLメールなどの用途に限定するべきでしょう。 よくよく考えて使わないと、策に溺れる事になります。

2012/03/22

EXIF Geotag Checker Chrome機能拡張を作った時の変更点まとめ

画像ファイルにGPSの位置情報が入っていたら気持ち悪いなぁと思って、いくつかChrome機能拡張を探してみました。 ちゃんとExif情報を表示するものはいろいろあったのですが、その中からプライバシー情報を見つけるのは面倒で、汎用的なViewerはあったのですが、適当なものがみつかりませんでした。

Exif Geotag Checker Window

EXIF情報が常に悪いかというと、写真なんかを扱う人であれば、管理上は間違いなく重要な情報で、画像ビューアーがいつの間には画像を上書き保存していてEXIF情報が失われたと知れば怒る人もいるでしょう。

iPhoneであれば画像をメーラーで添付する時にEXIF情報は削除してくれますが、iPhoto経由なんかで普段とちょっと違う方法で画像をアップロードしたらGPS情報がばっちり残っている可能性もあります。

今回は思い切ってEXIFの数あるエントリの中から、GPSだけ、それも時刻、緯度、経度情報の3点だけを表示するツールを作成してみました。 EXIFの時刻情報のDateTimeOriginalもみるべきなのかもしれませんが、それはツールが勝手に改竄したとかいう主張も通りそうに思えるので今回は省きました。

興味のある方は、Gitoriousでコードをforkして機能を追加してみてください。

今回作成した機能拡張の機能そのものもはライブラリに頼っていますが、それ以外の基本的なところでいろいろ壁にぶつかったのでまとめておくことにしました。

作成したChrome機能拡張について

DateTimeOriginalについてのところで書きましたが、今回はGPS情報の3点だけを表示するようにしました。 EXIFのコメント欄にメールアドレスなんかが入っている可能性もあります。
とはいえ、全部をチェックするのは時間がかかる上に、現実的には問題が発生する可能性は低そうです。

それが必要であればEXIFのViewerを使ってください。

制限事項

今回作成したアプリケーションは、Ajaxなどでブラウザに動的に表示している画像には対応できません。

その他にもいくつか制限はあるものの、本格的なExifViewerはむしろ余計に混乱するので、いくつかの技術的なポイントの解決策の模索と合わせて、ニッチな需要を探してみる事にしました。

技術的なポイント

機能的の中心になるEXIF情報の取得には、既に公開されている外部ライブラリを使っています。 README.mdにも含めていますが、中心となる機能部分にはJacob Seidelinさんのexif.js(+binaryajax.js)を使用しました。

この他にもContent Scripts側での非同期処理を扱うために、jsDeferredライブラリ(jsdeferred.nodoc.js)も使用しています。

いろいろライブラリは使用しましたが、最終的にはexif.jsとbinaryajax.jsには、次のような変更を加えています。

  • IEに特化したコードをロードする個所のコメントアウト
  • 起動時の自動ロード(loadAllImages)の停止
  • exif属性のあるimgタグだけを対象にしていた処理のスキップ
  • 画像データを入手するためにメッセージボディ全体を入手するコードの追加

作業の中心はEXIFについてではなく、できるだけドキュメントのDOMの影響を受けないようにしたり、非同期呼び出しの内部構造作成に時間を取るようにしました。

取り組んだいくつかの課題

開発の前の調査段階と開発初期の試行錯誤の時期では次のような、課題を感じました。

Chrome機能拡張に固有な課題

画面に表示されているデータはDOMとして入手が可能ですが、Chromeで直接にDOMを操作するためにはContent Scriptsと呼ばれるコードインジェクションの手段を使う必要があります。 BackgroundタイプやBrowser Actionタイプからは非同期(コールバック)通信の仕組みを利用して、その結果だけを受け取る事になります。

またContent Scriptsは、画面に表示されているドキュメントの構造(DOM)の影響を受けます。 例えば、Content Scriptsを使って画面上にjQuery UIのポップアップウィンドウを表示させようとすると、コンテンツが既にロードしていたCSSの影響などを受ける可能性があります。

他のExifViewerを使って感じた課題

EXIF Viewerと呼ばれるようなアプリケーションをいくつか触ってみた時に、画像を解析するために外部のCGIを呼んでいるものがありました。

Browser Actionであるポップアップウィンドウから画像データにアクセスするのは面倒なのでリーズナブルな方法ではありますが、データを送信したCGIから画像データにアクセスするため、外部に公開されているサイトでないと正常に動かない課題があります。

このため、NATの中にいる自宅やイントラネットなどからはうまく動かない事になります。 また場合によっては画像が外部サイト上にキャッシュされる事を問題視する事もあるでしょう。

解決するべき課題

ざっと感じた点をまとめて、以下のようなポイントに注意して作業を進めました。

  • 外部サイトのCGIなどに頼らず、Chromeブラウザで完結した処理を実現する
  • アドレスバーの横にアイコンを出し、ポップアップした画面に結果を表示する
  • 問題があるか、ないか、ひと目で判断できるようにする

とはいえ画像データを2重にダウンロードする課題はあります。そのためJPEG画像のみをロードするようにPNGやGIFは無視する仕組みを入れています。そのためにexif.jsにもともとあった、読み込む対象をexif属性で指定する処理と、全ての画像データにアクセスする処理は動かないようにしています。

その他にも、ポップアップ画面で画像を表示させる時にもBasic認証が必要なページや相対URLから絶対URLへの変換といった面倒な処理への対応が必要になります。

こんな感じで、解決するべき課題はありました。 しかしなんとか、荒削りですが、一通り動かすことができるものを作る事ができました。

作成したコードはGitoriousから入手する事が可能です。

また機能拡張自体はChrome Webストアから入手する事ができます。 [ EXIFジオタグチェッカー ]

Browser Actionとしてポップアップ画面からコンテンツの画像を表示する方法

Chrome機能拡張についていえば、アクセスしているタブページとBrowser Actionでアドレスバー横のボタンを押して表示されるポップアップ画面とは完全に独立しています。

この環境でポップアップ画面に画像データを表示するためには、imgタグのsrc=...に次の2つの方法で画像ファイルを指定する必要があります。

  • httpから始まるURLで画像ファイルの場所を指定する
  • Base64でエンコードされたデータそのものを指定する

データそのものを指定する方法は、情報量が増えるので普通は使いません。

どちらでも良さそうだと思ったのですが、認証が必要なページの画像をURL指定でポップアップ画面からアクセスした時には認証ダイアログは出ずにアクセスが拒絶されました。 そんな分けでBase64を使って、タブページから画像データの情報そのものを入手できるようにContent Scriptsを作成しました。

扱うデータの量が増えたので、少し負荷テストらしき事をしてみました。 この段階ではSpeed Tracerのために開発版のChromeを使う必要があって準備していないので、細かい時間の測定は後回しにして、印象だけで書いています。

負荷テスト1

バックグラウンドでexif情報をチェックするスクリプトを動かして画面のレンダリングに異常がないか、確認しました。

テストのためにWebサイトの画像作成用に持っているイメージ素材集のJPEGイメージをいくつか使い、一つのindex.htmlの中にimgタグを2600以上配置させる負荷テストを行ないました。

この中にgeotag情報を持ったJPEG画像を配置しましましたが、時間がかかったものの、ローカルのWebサーバを経由させた事を考えても、思ったよりも早いスピードで処理を行なう事ができました。

負荷テスト2

次にGPS情報を持ったJPEGファイルのコピーを100件作成し、index.htmlに100件のimgタグを書き込んで、このファイルをロードするテストを行ないました。

この記事を書きながらテストしている今は、結果を表示するまでに1、2秒程度のタイムラグがあります。 デフォルトのページの内容が更新されないと、読み込み中なのかどうか、そのステータスを表示することができていません。

機能拡張を入れることでJPEGデータのロードは2倍発生するので、その分の処理時間は単純に倍かかります。 その予測とほぼ同じ変化がある事はわかりました。

ブラウザが表示した画像データのキャッシュにアクセスできれば良いのですが、そうするとCaptchaや乱数表のようなアクセスする度に変化する事でセキュリティを保っているようなアプリケーションの脅威になってしまうので、永遠にそんな事はできないでしょう。

そんな分けで、JPEGファイルについて再読み込みを許可、あるいは予測していない場合には、JPEGファイルに2回アクセスする事で問題が発生する可能性はあります。

今後Chrome機能拡張を作成する時に気をつけること

今後も気が向けば機能拡張を作ったり、現状のアプリケーションに変更を加える事もあるでしょう。

タブに開いているコンテンツ(のDOM)にアクセスするタイプのアプリケーションは、その解析にContent Scriptsを使い、そのデータの取得に非同期(コールバック)通信の仕組みを使う事になります。

そういった全体の構造を考えて、どういうコードをどこで使うか、そういう判断というか、全体の構成と楽をするための手段について検討することが必要でしょう。

JavaScriptを使う時にはライブラリを使わなくとも似たような処理はいろいろな方法で可能になります。 しかしコードが長くなって読み難くなってしまうところが難点だと思っています。

苦労すれば最終的に同じ(ような)機能の実装はできるけれど、それを高いメンテナンス性を保って作る事は、相当な知識と面倒な作業が発生するでしょう。JavaScriptの手軽さと難しさはそういうところにあると思います。

余談ですが、JavaScriptを学校で教えるべき言語に上げる人は多いそうですが、かなり特定の問題領域(ドメイン)に特化した知識+経験になりそうな点が心配です。

情報系の大学であれば、同じものを別の角度でみるためにも、JavaとScalaを合わせて教えて、同じ機能を別々の方法で実装させたりするのが、時間はかかっても最終的には良いJavaScriptプログラマを生み出すような気がします。

創造性っていうのは応用力の積み重ねでしかないので、思ったものが作れれば何でもいいんですけどね。

JavaScriptの需要が多いのは確かですが、最初からJavaScriptだと、苦労をしてもJavaScriptしか使えない人間になりそうに思えるのが怖いところです。

2011/04/02

Make Permanent Pinned Tabs with Google Chrome

Google Chrome 10 has a great feature about the pinned tab. Before that, some people uses the "--pinned-tab-count" command line option to create the pinned tab.

But some problems are still remaining if you want to use a permanent pinned tab like as the bookmark manager page.

The "permanent pinned tab" will open a link in new tab. The "Open PinnedTab Link" extension provides this feature.

The extension opens a link in new tab and has some options to control the behavior.

The "Google News" page, for instance, will open the external link in new tab and opens the link of the same site within the pinned tab.

This extension also provides the similar feature through the context menu. After checking the "Exclude links in same domain" of the context menu, the link behavior of the page is similar to the Google News page.

Options

Extensions page, chrome://extensions/, has a link to the option page of Open PinnedTab Link. The default settings of context menu can be changed from this page.

Open PinnedTab Link - Options page

L10N Messages

The google chrome extension framework is internationalized, so this extension uses this feature for the message translation.

Currently, English and Japanese message catalog is provided.

Known issues

I tried to close the context-menu on the no pinned tab page.

Platforms

This extension should work on every platforms supported by google chrome. It is tested on following platforms:

  • Windows Vista SP2 (32bit)
  • Windows XP SP3 (32bit)
  • Ubuntu 10.04 LTS 64bit
  • MacOS 10.6

Installation

This extension is available from the chrome web store.

Source Codes

The source code is hosted at Gitorious : https://gitorious.org/open-pinnedtab-link

2011/03/31

chrome.tabsイベントの動きを追って、graphvizで図にしてみた

Open PinnedTab LinkというGoogle chromeの機能拡張を作成したので、 Google Chrome Extensionsのデベロッパーガイドを読む必要がありました。

特に Browser Interaction/Tabs (chrome.tabs package)にあるイベントハンドラーの動きがちょっと分かりづらかったので、備忘録的にどういう風に呼ばれるのか図にしてみました。

各ハンドラーの先頭にconsole.log()を入れるローレベルな方法で動きを追ったので、事前条件やテストの方法がまずかったりして違う動きになるかもしれません。

まずは、Graphviz(dot)で図にしてみた

タブを開くたびに上からNormal stateまでのevent handlerメソッド(chrome.tabs.on*())が呼ばれます。

"Normal state"は通常のWebブラウジングをしている状態です。

Statechart diagram of chrome.tabs event handlers

遷移するアクションの説明

説明のない矢印は自動で次の状態に遷移する事を示していて、Chromeのイベントは楕円で示しています。

  • create_tab(): Chrome上で新しいタブを開いたり、"Open Link in New Tab"を選択した場合のアクション
  • (un)pin_tab(): Pinを固定したり、外したりを選択した場合のアクション
  • reloase(): C-rや"Reload"などで明示的にページを更新した場合のアクション
  • close_tab(): C-wや"Close Tab"を選択した場合のアクション
  • (un)dock_tab(): タブをドラッグして、別ウィンドウに開いたり、別ウィンドウに統合した場合のアクション
  • change_focus(): 単純にタブを選択したり、別のタブを閉じたりした事でフォーカスが当った場合のアクション

chrome.tabs.OnRemovedが呼ばれた時には、そのタブは閉じますが、別のタブにフォーカスが当たるので、矢印が2つ出ている事になります。

明示的にTabIDやガード条件のようなものは書いていませんが、適当に読み取れると思います。

楕円で示したところは Events を示していますが、念のため対応する完全修飾のイベント名を列挙しておきます。

  • onCreated(): chrome.tabs.onCreated イベント
  • onUpdated(): chrome.tabs.onUpdated イベント
  • onSelectionChanged(): chrome.tabs.onSelectionChanged イベント
  • onDetached(): chrome.tabs.onDetached イベント
  • onAttached(): chrome.tabs.onAttached イベント
  • onMoved(): chrome.tabs.onMoved イベント
  • onRemoved(): chrome.tabs.onRemoved イベント

図を生成する元のdotファイル

図を生成するためのa.dotファイル



// Statechart diagram of chrome.tabs.on*()

digraph G {

  start [shape=circle, label="", style=filled];
  normal [shape=rect label="Normal state"];
  closed [shape=doublecircle, label="", style=filled];

  onCreated [label="onCreated()"];
  onSelectionChanged [label="onSelectionChanged()"];
  onSelectionChanged_ [label="onSelectionChanged()"];
  onUpdated [label="onUpdated()"];
  onRemoved [label="onRemoved()"];
  onMoved [label="onMoved()"];
  onDetached [label="onDetached()"];
  onAttached [label="onAttached()"];

  start -> onCreated [label="create_tab()"];
  onCreated -> onSelectionChanged_;
  onSelectionChanged_ -> onUpdated;
  onUpdated -> normal;

  // normal state
  normal -> normal;
  normal -> onSelectionChanged [label="change_focus()"];
  onSelectionChanged -> normal;

  // change tab position
  normal -> onMoved;
  onMoved -> normal;

  // pin or unpin tab
  normal -> onUpdated [label="(un)pin_tab() /\nreload()"];

  // dock or undock tab
  normal -> onDetached [label="(un)dock_tab()"];
  onDetached -> onAttached;
  onAttached -> onSelectionChanged [label="change_focus()"];

  // close tab
  normal -> onRemoved [label="close_tab()"];
  onRemoved -> onSelectionChanged [label="change_focus()"];
  onRemoved -> closed;
}

これを図にするには、dotコマンドを使って次のようなコマンドラインを使っています。

$ dot -Tpng -o a.png a.dot

困ったこと

複数のタブを保存して開いた時に、chrome.tabs.onUpdated が呼ばれずに、いきなり chrome.tabs.onSelectionChanged が呼ばれる場合がありました。

さらに悪いことに、この場合には Pin Tab かどうか確実に判別することができませんでした。

そのためタブを保存した状態のChromeを起動して、偶然この問題に遭遇するとPin/Unpinを判別するような機能拡張がうまく動作しない場合があります。

Open PinnedTab Linkでは、この他にもUnpinの場合にContext Menuを無効にするようにしたかったのですが、いまのところ良い手がなく全てのタブの中にメニューを表示しています。

問題はいろいろありますが、タブをブックマーク的に使う初期の目標は達成できたので良しとしましょう。 でも当然ユーザーは不満に思いますよね、「無駄なら消してよ」って。うーん、困ったなぁ。

2011/03/29

Google Chrome用の機能拡張 "Open PinnedTab Link" を作ってみた

結論からいうと、この記事ではGoogle Chrome用に作成したOpen PinnedTab Linkという拡張機能を紹介しています。

ブックマーク代りのピン化したタブ

いまのところLinux 64bit版のGoogle Chrome 10.0.648.204をメインに使っています。

Ubuntu 10.04ではmozilla-daily-ppaを経由してFirefox 4を導入していますが、ピンにしたタブから開くリンクは新しいタブで開くところがとても便利だと思っています。

Google Chromeでもタブをピンにすることはできますが、標準ではピンになったタブの中でリンクが開いてしまい、ブックマーク代りに使うには適していません。

TabLinkは全部のリンクを書き換えてしまう…

似たようなことを考える人はいて、Pin Tab Links should open new windowというHelp forumのトピックからTabLinkという機能拡張を試してみました。

TabLinkは問題なく動いたのですが、全部のリンクが書き変わってしまうので、自分の目的には合いませんでした。 そのため今回はピン化したタブからのリンクだけは新しいタブで開くというOpen PinnedTab Linkを作りました。

特別なことはしていません。内部的にはピン化したタブかどうかを判断する処理の後はTabLinkと同じことをしています。

ただし、ピンを外した後は全リンクの"target"属性を空にすることをしているので、元々新しいタブを開くリンクは違う動きをするかもしれません。

さいごに

ピンタブを使うと、アイコンでその機能を見分ける必要がでてくるので、サイトがfavicon.icoを設定していないと微妙に不便になるでしょう。