d.hetima RSSフィード

2010-06-14

終了時の状態を復元するSafari機能拡張 HsRestoreSession 公開

終了時の状態を復元するSafari機能拡張、HsRestoreSession を公開しました。SafariStandのRestore Last Workspaceと似たような機能です。問答無用で復元するのではなく、どのタブを復元するか選択できるページを表示します。

できないこと:

・履歴の復元

・fileプロトコルを表示しているページの復元

この辺はSafari機能拡張からアクセスすることができません。セキュリティはかなり厳しい。

・ページのサムネイルを表示

表示しているページのサムネイルを取得することはできるんだけどかなり大きなpngbase64エンコードした文字列のみ。開いているタブ全部を記録するのは厳しいので見送りました。ローカルにあるキャッシュを使う手もあるけれど、ファイル参照やfileプロトコルを扱えないので駄目。websnapr 系のサービスを使うのは検討中。

・ウィンドウの位置・サイズの復元

これはできそう

・復元前にタブの順番を入れ替える

これはJavaScriptを使いこなせればできるんだが!

結果的に SafariStand から機能を切り出したものになったけれど、すべての機能を移植するのは無理です。いや、ほとんどの機能は移植無理です。SIMBLが劇的ビフォーアフター並みに改造できるのに比べて、Safari機能拡張で出来るのは部屋の模様替えくらい。そのかわり安全性はずっと高いし、Windows版でも動く。

2010-06-12

Safari Extension のクラスリファレンスのようなもの

Safari Extensions Reference を参考に一瞥しやすいようにまとめました。言語仕様を無視したオレオレ表記方法ですみません。

global.html

終了時に body onunload で処理可能(アンインストール時にも呼ばれる)。

SafariExtensionSettings の値は Safari の初期設定ファイルに保存される(com.apple.Safari.plist に ExtensionSettings-extension.bundle.id-DEVELOPERID として)。

safari.application == SafariApplication
safari.extension == SafariExtension
safari.self == SafariExtensionGlobalPage

class SafariExtension{
  (readonly array)bars;
  
  //safari-extension://extension.bundle.id-DEVELOPERID/
  (readonly DOMString)baseURI;
  (readonly array)toolbarItems;
  (readonly SafariExtensionGlobalPage)globalPage;
  (readonly SafariExtensionSecureSettings)secureSettings;
  (readonly SafariExtensionSettings)settings;

  //whitelist と blacklist は optional
  //runAtEnd が true ならページのスクリプトを実行した後、false なら実行前にロード
  //add の返り値は remove するときに使う
  DOMString addContentScript(DOMString source, array whitelist, array blacklist, boolean runAtEnd);
  DOMString addContentScriptFromURL(DOMString url, array whitelist, array blacklist, boolean runAtEnd);
  void removeContentScript(DOMString url);
  void removeContentScripts();
  DOMString addContentStyleSheet(DOMString source, array whitelist, array blacklist);
  DOMString addContentStyleSheetFromURL(DOMString url, array whitelist, array blacklist);
  void removeContentStyleSheet(DOMString url);
  void removeContentStyleSheets();
}

class SafariApplication{
  (readonly array of SafariBrowserWindow)browserWindows;
  (readonly SafariBrowserWindow)activeBrowserWindow;

  SafariBrowserWindow openBrowserWindow();
  void addEventListener(DOMString type, function, boolean useCapture);
  void removeEventListener(DOMString type, function, boolean useCapture);
}

class SafariExtensionGlobalPage{
  (readonly DOMWindow)contentWindow;
}


class SafariBrowserTab{
  (readonly SafariBrowserWindow)browserWindow;
  (readonly SafariWebPageProxy)page;
  (readonly DOMString)title;
  (DOMString)url;

  void activate();
  void close();
  //base-64 でエンコードされた png データ。でかい。
  DOMString visibleContentsAsDataURL();
}

class SafariBrowserWindow{
  (readonly array of SafariBrowserTab)tabs;
  (readonly SafariBrowserTab)activeTab;
  (readonly boolean)visible;

  void activate();
  void close();

  //index がマイナスか大きすぎたら右端に追加
  //visibility = "foreground" or "background"
  SafariBrowserTab openTab (Optional DOMString visibility, Optional long index);
  void insertTab (SafariBrowserTab tab, long index);
}

class SafariWebPageProxy{
	void dispatchMessage (DOMString name, any message);
}
//設定の読み書き
safari.extension.settings.key = value;
var value = safari.extension.settings.key;

//inject.js からの message は target に SafariBrowserTab が入っている
safari.application.addEventListener("message", function(messageEvent) {
  if(messageEvent.name === "hoge") {
    messageEvent.target.page.dispatchMessage("re-hoge", "ok");
  }
},false);

//bundle 内のリソースのURL
var imageUrl = safari.extension.baseURI+"image.png";

inject.js

inject.js はフレームや iframe にもそれぞれ読み込まれる。

「スクリプトを開始:」に指定するとページのスクリプトを実行する前に、「スクリプトを終了:」に指定するとページのスクリプトを実行した後にロードされる、と Safari Extensions Development Guide に書いてあった。正確なタイミングはよく分かりません。

safari.extension == SafariContentExtension;
safari.self == SafariContentWebPage;

//global.html の safari.extension と比べるとかなり制限されている。
class SafariContentExtension{
  (readonly DOMString)baseURI;
}

class SafariContentWebPage{
  (readonly SafariContentBrowserTabProxy)tab;
  void addEventListener(DOMString type, function, boolean useCapture);
  void removeEventListener(DOMString type, function, boolean useCapture);
}

class SafariContentBrowserTabProxy{
  //同期メッセージを送る messageEvent.name==="canLoad"
  any canLoad(BeforeLoadEvent event, Optional any message);
  //通常の dispatchMessage は非同期
  void dispatchMessage (DOMString name, Optional any message);
  void setContextMenuEventUserInfo(MouseEvent event, any userInfo);
}

//inject.js はフレームや iframe にもそれぞれ読み込まれる。メインのdocumentだけでやりたい処理は
if(window.top===window){
  
}
//とかするとよい

//上記 global.html のサンプルに対応するコード
safari.self.addEventListener("message", function(messageEvent) {
  if(messageEvent.name === "re-hoge") {
    alert(messageEvent.message);
  }
},false);
safari.self.tab.dispatchMessage("hoge");


extension bar.html

表示していなくてもロードはされる。

safari.extension == SafariExtension;
safari.application == SafariApplication;
safari.self == SafariExtensionBar;

class SafariExtensionBar{
  (readonly SafariBrowserWindow) browserWindow;
  (readonly DOMWindow)contentWindow;
  (readonly DOMString)identifier;
  (DOMString)label;
  (readonly boolean)visible;
  void hide(boolean doNotRemember);
  void show(boolean doNotRemember);
  void addEventListener(DOMString type, function, boolean useCapture);
  void removeEventListener(DOMString type, function, boolean useCapture);
}

2006-07-21

SafariでYouTubeのflvがキャッシュされる場所

SafariやWebKitベースのブラウザでは、プラグインのキャッシュは、/tmpフォルダに「WebKitPlugInStreamXXXXXX」という名前でキャッシュされます(XXXXXXはランダム)。YouTubeのflvデータも例外ではなく、再生バーのダウンロード進捗が完了した時点でファイルが生成されます。そしたら/tmpフォルダを開いてファイルサイズや日付から類推して、それらしいファイルを別の場所にコピーすればOKです。

finderで不可視のtmpフォルダを開くには「フォルダへ移動...」メニューを実行して「/tmp」と入力すればよいです。


以上はFlash Playerプラグインのバージョン8での情報です。バージョン9では

/private/var/tmp/folders.501/TemporaryItems/FlashTmpX

に生成されるようです(末尾のXは数字。0からはじまる)。