

### やりたいこと

WebExtensionsのchrome.tab.createに独自プロトコルのURLを渡してタブを作成した後、OSが独自プロトコルに対応したアプリを起動する。

その後、不必要なタブを削除したい。

### 問題

chrome.tab.create の第二引数に渡したコールバックメソッドが呼び出されない。

### サンプルコード

[code]

    /** background.js **/
    
    function OpenNiconicoProtocol(niocnicoUrl = "niconico://sm9")
    {
        chrome.tabs.create({url: niocnicoUrl, active:false}, OnTabCreated);
    }
    
    function OnTabCreated(tabInfo)
    {
        console.log("tab id " + tabInfo.id);
        chrome.tabs.remove(tabInfo.id, () => 
        {
            if (chrome.runtime.lastError) {
                console.log("failed: " + chrome.runtime.lastError);
            } else {
                console.log("removed tab");
            }
        });
    
    }
    
[/code]

独自プロトコルのURLではtabs.createのコールバックを受けられないのでしょうか？

manifest.jsonを含めたソースコード  
<https://gist.github.com/tor4kichi/5ea925832be5887a873ac8e7c8394ba5>

テスト環境  
Windows 10 AU適用済み  
Firefox Developer Edition 51.0a2 (2016-10-27) (32-bit)


CC BY-SA 3.0
2016-10-28T09:32:16.233
29964
2016-10-28T09:32:16.233
2020-06-17T08:14:45.997
-1
17112
question
firefox-webextension
独自スキーマURLを開く chrome.tab.create のコールバックが呼び出されない


自己解決しました。

## 原因

カスタムURIスキーマの場合、chrome.tabs.createの第二引数に渡されるコールバックは呼び出されません。（これがバグか仕様なのかは調べがつきませんでした。）

## 回避方法

カスタムURIスキーマを指定して作成したタブを、chrome.tabs.queryで取得して手動で閉じるようにします。

注意点として、カスタムURIスキーマにhost要素が含まれない場合、chrome.tabs.query( {url: urlPattern} )
のurlPatternの判定で invalid pattern の判定がされる場合があります。

## サンプルコード

[code]

        function OpenNiconicoProtocol(niocnicoUrl)
        {
            chrome.tabs.query({ currentWindow: true, active: true }, function (maybeCurrentTab) {
                var currentTab = maybeCurrentTab[0];
    
                // 新しいタブとして開く
                chrome.tabs.create({url: niocnicoUrl, active:false});
    
                // カスタムスキームURLは tabs.create のコールバックが呼ばれない
                // 少ししてから不要なタブを閉じる処理を実行する
                setTimeout(function() {
                    // queryに 渡す url がカスタムスキームかつ
                    // host部分がないURLパターンの場合
                    // invalid patternとなり対応していない
                    // すべてのタブを取得して不要なタブを逐次判断する形で回避する 
                    chrome.tabs.query( {}, (tabs) => 
                    {
                            if (tabs && tabs.length)
                            {
                                for (var tabIndex in tabs)
                                {
                                    var tab = tabs[tabIndex];
                                    var isRemoveTarget = false;
                                    if (tab.url && isNiconicoSchemeUrl(tab.url))
                                    {
                                        isRemoveTarget = true;
                                    }
                                    else if (currentTab.index < tabIndex)
                                    {
                                        // httpとしてレンダリングが実行されてないページは
                                        // tab.urlがabout:blankのままっぽい (firefoxで確認)
                                        // 現在のタブより新しく開いたっぽい空ページタブを対象として判断
                                        if (tab.url && tab.url == "about:blank")
                                        {
                                            isRemoveTarget = true;
                                        }
                                    }
                                    
                                    if (isRemoveTarget)
                                    {
                                        chrome.tabs.remove(tab.id, () => 
                                        {
                                            if (chrome.runtime.lastError) {
                                                console.log("failed: " + chrome.runtime.lastError);
                                            } else {
                                                console.log("removed tab");
                                            }
                                        });
                                    }                               
                                }
                            }
                    });
                }, 1000);
            });
            
        }
    
[/code]

**参考**

Chrome拡張機能から外部プログラムでリンクを開く前にタブを閉じるには（英語）  
<https://stackoverflow.com/questions/18564750/chrome-extension-close-tab-that-
opened-an-external-program-before>

chrome.tabs.query  
<https://developer.chrome.com/extensions/tabs#method-query>

url pattern  
<https://developer.chrome.com/extensions/match_patterns>


CC BY-SA 3.0
2016-10-28T09:32:16.233
29965
2016-10-28T09:32:16.233
2020-06-17T08:14:45.997
-1
17112
29964
answer