【问题标题】:Is it possible to open custom URL scheme with Google Chrome?是否可以使用 Google Chrome 打开自定义 URL 方案?
【发布时间】:2011-01-20 19:03:07
【问题描述】:

我有协议(如 http),其方案由在 Mac OS X 中注册的第 3 方应用程序管理。 即 x-someapp://someaction 或类似的东西。

如何使用谷歌浏览器打开这个 URL? 默认情况下,Chrome 开始在 Google 引擎中搜索,而不是启动 App 并将 URL 处理传递给它...

Safari 启动一些已注册的应用程序。这是正确的事情。

Firefox 和 Opera 询问该怎么做...我也可以启动 App。

但是 Chrome... 不问。

我什至尝试用 JavaScript 编写一些 HTML 页面来发送 XHttpRequest:

function _httpExecuteCallback()
{
 if (httpRequestCallbackFunction != null) {
  if (httpRequest.readyState == 4) {
   if (httpRequest.status == 200) {
    httpRequestCallbackFunction();
    httpRequestCallbackFunction = null;
   }   
  }
 }
}

function _httpGet(url, callbackFunction)
{
 httpRequest = false;
 httpRequestCallbackFunction = callbackFunction;
 httpRequest = new XMLHttpRequest();
 httpRequest.onreadystatechange = _httpExecuteCallback;
 httpRequest.open('GET', url, true);
 httpRequest.send(null);
}


_httpGet('x-someapp://test',function(){})

也没有结果...

【问题讨论】:

    标签: ajax macos google-chrome


    【解决方案1】:

    当前接受的解决方案在 Chrome for SSL https 方面存在问题。查看控制台日志,Chrome 会阻止请求,因为它认为自定义 url 协议不安全:

    [blocked] The page at reports blah blah ran insecure content from customproto//blah blah
    

    这是一个解决方案(这花了我几天时间研究):

        <input type='button' value='Test Custom Url' onclick='exec()'>
    
        <script>
        function submitRequest(buttonId) {
            var d = (window.parent)?window.parent.document:window.document
            if (d.getElementById(buttonId) == null || d.getElementById(buttonId) == undefined) return;
            if (d.getElementById(buttonId).dispatchEvent) {
                    var e = d.createEvent("MouseEvents");
                    e.initEvent("click", true, true);
                    d.getElementById(buttonId).dispatchEvent(e);
            } 
            else {
                    d.getElementById(buttonId).click();
            }
        }
    
        function exec(){
            var d = (window.parent)?window.parent.document:window.document
            var f = d.getElementById('customUrlLink')
            if (f ) {f.parentNode.removeChild(f);}
            var a = d.createElement('a');
            a.href =  'mycustomproto://arg1';    
            a.innerHTML = "Link"                                    
            a.setAttribute('id',        'customUrlLink');
            a.setAttribute("style", "display:none; "); 
            d.body.appendChild(a); 
            submitRequest("customUrlLink");
        }
        </script>
    

    此代码不适用于 IE。我发现使用这种技术 IE 将自定义协议的参数限制在 1000 以下,而使用 iFrame 技术 IE 将允许 2083 个字符。

    克服 javascript 中的 url 限制的唯一方法是抓取数据并多次调用。如果有人想尝试一下,请告诉我进展如何。我想用它。

    要在正在执行的应用程序中处理长 url,请将令牌传递给应用程序并让它从 url GET 中获取数据。

    所以现在我正在为 Chrome/FF 使用一个功能,为 IE 使用另一个功能。

    这些链接帮助我开发了这个解决方案:

    https://superuser.com/questions/655405/custom-protocol-handler-not-working-in-chrome-on-ssl-page

    Simulating a click in jQuery/JavaScript on a link

    (希望我几天前就知道这一点……希望这对某人有所帮助)

    ================================================ ===

    更新:(8 小时后)

    ================================================ ===

    Jake 发布了一个很棒的 chrome 解决方案:https://superuser.com/questions/655405/custom-protocol-handler-not-working-in-chrome-on-ssl-page

    这仅适用于 chrome:

     window.location.assign("customprotocol://");
    

    它会在 iframe 中失败,所以这是有效的:

    var w = (window.parent)?window.parent:window
    w.location.assign(service + '://' +  data)
    

    ================================================ ===

    更新:(几周后)

    ================================================ ===

    所有打开自定义协议的例子,包括我自己的,在 url 中都有一个“://”。这就是导致 SSL 警告的原因。

    原来的解决方案是将“://”更改为“:”

    这样做:

    src="x-myproto:query"  .....
    

    SSL 警告将消失。

    ================================================ ===

    关注:(经过数月的生产使用)

    ================================================ ===

    这对 chorme 来说效果很好。检测浏览器,如果 chrome 这样做:

    var w = (window.parent)?window.parent:window
    w.location.assign('myproto://xyzabcdefetc')
    

    对于 IE 和其他浏览器,我的做法略有不同。

    请注意,浏览器确实对您可以在自定义 url 协议中放入多少数据施加了限制。只要您的字符串少于 800 个字符,这似乎就是适用于所有浏览器的神奇数字。

    【讨论】:

    • Brian,感谢您的帖子,但我看不到这如何解决 Chrome 中的问题。我们的应用程序为其他浏览器使用 iframe 以避免导航离开应用程序,同时仍启动 URL 处理程序(在我们的例子中为 SSH)。这曾经在 Chrome 上工作,但现在被打破了。当我使用您的解决方案(没有 iframe)时,它会在启动 URL 处理程序时导致导航离开我们的应用程序。所以我不确定上面的答案是如何解决问题的。我错过了什么吗?
    • @brettw,我已经为答案添加了更新。真的,它说的是几乎相同的东西。我发布的内容是在 chrome 中为我工作。这已经生产了一段时间了。如果此解决方案正在导航,请尝试使用 href 调用诸如 test 之类的 js 函数,然后将解决方案中的代码放入 test() 函数中。
    • @BrianMcGinity - 在 chrome 中执行 window.location.assign 正在更改选项卡内容以返回上一页(这是不再有效的授权/登录页面)。有没有办法让它留在那个页面上?
    • 我能够在第二次卸载时使用 beforeunload 提示保持在页面上(因为第一次卸载转到自定义协议以启动)使用此代码 - gist.github.com/Noitidart/e898a84a4f72e1b4c11ff7ca11a46bf7 - 但是当第二次卸载发生时显示提示,它将焦点带回浏览器:(
    • 对于 iOS,window.location.assign 是唯一在 2021 年似乎不再有效的解决方案,谢谢。
    【解决方案2】:

    看起来好像是 Google 的位置栏解析遇到了阻碍。

    不过,浏览器似乎可以正确处理自定义 URL 方案。在你的地址栏中试试这个:

    javascript:document.location = 'myscheme://whatever'
    

    您页面上使用自定义方案的任何链接也应该做正确的事情。

    【讨论】:

      【解决方案3】:

      我找到了适用于 Chrome 的解决方案。 我使用 IFRAME 方式。

      示例(使用 JQuery):

      $("body").append('<span id="__protoProxy"></span>');
      
      function queryWord(aWord)
      {
       var protoProxy = document.getElementById('__protoProxy');
       if (protoProxy)
       {   
        var word = aWord.replace('"','\"');
        protoProxy.innerHTML = '<div style="display:none;"><iframe src="x-myproto://query?' + word + '"></iframe></div>';
       }
      }
      
      queryWord('hello');
      

      【讨论】:

      • 哦,所以不是在地址栏中输入x-myproto://query?furries,而是使用它打开一个 iframe,然后 Chrome 使用现有的注册应用程序获取要在 iframe 中显示的内容?
      • 这是我们的Chrome插件所必需的,没有人直接在用户的地址栏输入地址,所以隐藏iframe确实是最好的解决方案。
      【解决方案4】:

      如果用户没有应用,这里的解决方案还包括重定向到 App Store / Play Store。它为此使用了 setTimeout。它还利用 iframe 来支持更多浏览器。所以这适用于 Chrome 和任何其他移动浏览器。我们将其用作我的公司,Branch。只需修改以下两个链接以对应您的 URI 和 App Store 链接。

      <!DOCTYPE html>
      <html>
          <body>
              <script type="text/javascript">
                  window.onload = function() {
                      // Deep link to your app goes here
                      document.getElementById("l").src = "my_app://somepath";
      
                      setTimeout(function() {
                          // Link to the App Store should go here -- only fires if deep link fails                
                          window.location = "https://itunes.apple.com/us/app/myapp/id123456789?ls=1&mt=8";
                      }, 500);
                  };
              </script>
              <iframe id="l" width="1" height="1" style="visibility:hidden"></iframe>
          </body>
      </html>
      

      同样,这应该可以在任何浏览器上运行,这要归功于 iframe。

      【讨论】:

        【解决方案5】:

        如果 Chrome 无法识别 URL 方案,则默认为搜索。

        这是我在 Safari 中看到的: alt text http://img62.imageshack.us/img62/6792/clipboard02oh.jpg

        在 Firefox 中:

        alt text http://img138.imageshack.us/img138/9986/clipboard04xk.jpg

        我认为 Chrome 默认搜索的原因是有特殊的 google 搜索使用冒号。

        例如:

        • 定义:字典
        • 文件类型:pdf 谷歌铬

        这是我对 Firefox 的烦恼之一,我必须跳转到“搜索框”而不是地址栏来执行这些类型的搜索。由于 Chrome 没有像 Firefox、IE 和 Safari 那样的单独搜索框,因此需要此功能。

        Ajax 请求无法解决这个问题。

        【讨论】:

        • 我不知道它在 Windows 上是如何工作的,我将此问题标记为 Mac OS X。因此,在 Mac OS X 世界中,任何应用程序都可以在 Info.plist 文件中注册自己的互联网方案(其中包含在 App Bundle 中)。因此,Safari 将始终了解 3rd 方协议,因为只有安装了新应用程序,即使 Firefox 和 Opera 也会知道,但 Chrome 似乎不会从系统中读取此信息。例如,如果我安装了 SpamSieve,我可以直接从 Safari 打开 x-spamsieve 协议并注册软件... Safari 可能只是将此 URL-scheme 查询重定向到 NSWorkspace...
        • 此外,我在 Mac OS X 上成功地使用了来自 Firefox 的 AJAX(请参阅我的问题中的代码示例)来请求第 3 方协议(不是 http/ftp)。
        • 这里是额外的例子mac.gettranslateit.com/integrationFireFox.shtmlmac.gettranslateit.com/integrationOpera.shtml 我只是想写 Chrome 扩展,除了沙盒限制外,我一般都是这样做的——现在我需要调用 3rd 方协议(我自己的),但我不能。
        • Chrome 应该能够识别在操作系统中注册的协议。我相信这可能是 Mac 特有的错误。请将此作为 Mac OS X 错误提交至crbug.com。谢谢。
        【解决方案6】:

        几周后......

        看起来 window.location.replace('myscheme://whatever') 具有完整的跨浏览器支持,适用于 chrome、firefox、safari、edge、opera 参见 https://developer.mozilla.org/en-US/docs/Web/API/Location/replace

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-13
          • 2016-01-30
          • 2014-02-20
          • 2014-05-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多