SafariとChromeの判別があやしくなったので改善してみる2011年08月25日 20時10分51秒

夏も終わり間近というこのタイミングで今年最初のエントリになっちゃうんだけども、デスクトップ版Safariが5.1になったことで以前書いた「SafariとChromeを判別してみる」の方法が通用しなくなっちゃったのであわてて更新してみる。ほんとは中華パッド3号とか4号とかのこと書きたかったんだけども。

前回のおさらい

前回のアプローチは、SafariとChromeでwindow.constructorが違っている(SafariはObject、ChromeはDOMWindow)ことを利用してこんなアプローチをしてた。

// Safariはtrue、Chromeはfalseを返す関数
<script type="text/javascript">
window.check1 = function() {
  try {
    return window.constructor.prototype.alert == undefined;
  } catch(e) {
    // IEとかエラーでるし。
    alert(e.message || e.description);
  }
}
</script>

<button type="button" onclick="alert(check1())">check1</button>

ところが、Safari5.1からはwindow.constructorがDOMWindowConstructorとやらに変わっちゃったので、Chromeと判別されちゃう。さて、困りました。

Safari Developer Libraryを探したら

んで、急いでAppleのSafari Developer LibraryDocument Additions Referenceプロパティを確認したところ、「webkitCurrentFullScreenElement」「webkitFullScreenKeyboardInputAllowed」「webkitIsFullScreen」なんてのが見つかった。

念のためChromeのJavaScriptコンソールで「document.webkit」まで入力してタブキーで候補をさらってみたところ「Current~」とか「FullScreen~」、「Is~」とかは表示されなかったのでなんとなくで「webkitIsFullScree」を採用することに決定。

ただし、プロパティの名前からしてbooleanを返すだろうから、単純に

!document.webkitIsFullScreen

なんて試しても判別がつかないので、undefinedかどうかをテストすることにして、こんな感じに。
<script type="text/javascript">
window.check2 = function() {
  try {
    return window.constructor.prototype.alert == undefined ||
           document.webkitIsFullScreen !== undefined;
  } catch(e) {
    return e.message || e.description;
  }
}
</script>

<button type="button" onclick="alert(check2())">check2</button>

で、こうなりました。

この変更を適用すると、こんな感じに。前回同様is_webkitとis_mobileの判定が出来る前提で。

<script type="text/javascript">
// Safariかどうか
window.is_safari2 = (function() {
    // WebKitじゃなきゃ当然Safariじゃないわな
    if(! window.is_webkit) return false;
    if(window.is_mobile) {
        // モバイル版の場合、SVGをサポートしてたらSafari
        return !! window.SVGColor;
    } else {
        // デスクトップ版の場合、windowコンストラクタのプロトタイプで判別
        try {
            // * ココ修正!! *
            // どっちかtrueならSafari
            return window.constructor.prototype.alert == undefined ||
                   document.webkitIsFullScreen !== undefined;
        } catch(e) {
            // そもそもwindow.constructor とか そのプロトタイプにアクセスできない
            // ブラウザもあるので try - catch しとく
            return false;
        }
    }
})();

// Chromeかどうか
window.is_chrome2 = (function() {
    // WebKitじゃなきゃ(ry
    if(! window.is_webkit) return false;
    // 後は基本的にSafariと逆
    if(window.is_mobile) {
        return ! window.SVGColor;
    } else {
        try {
            // * ココ修正!! *
            return window.constructor.prototype.alert != undefined &&
                   document.webkitIsFullScreen === undefined;
        } catch(e) {
            return false;
        }
    }
})();

</script>

<button type="button" onclick="alert(window.is_safari2)">Safariっすか?(改)</button>
<button type="button" onclick="alert(window.is_chrome2)">Chromeっすか?(改)</button>

Chrome 13まではこれで大丈夫だけど、フルスクリーンがどうのこうのなんて機能はOS X Lion向けっぽいのでいずれこれでも判別できなくなっちゃいそうではあるが。

つか、そろそろ中華パッドネタ書いときたいなぁ。もうすでに旬をすぎちゃってるんだけども。

追記

Safari且つChromeとか判定されたり、前回の記事と同時に表示すると上書きされちゃったりなど細々と考慮漏れがあったりしたのでちくちく修正してました。もう平気かな。

追記2(2011.12.28)

ありゃ、気付いたらChromeもdocument.webkitIsFullScreenとかサポートしちゃってるしorz さて、どうするべ…

→ window.chrome が使えそう。なぜこれに気付かないし。