【问题标题】:Accessing Google Drive from a Firefox extension从 Firefox 扩展访问 Google Drive
【发布时间】:2014-09-11 14:07:43
【问题描述】:

我正在尝试从 Firefox 扩展程序访问 (CRUD) Google Drive。扩展是用 Javascript 编码的,但现有的两个 javascript SDK 似乎都不适合;客户端 SDK 期望“窗口”可用,而扩展中不是这种情况,并且服务器端 SDK 似乎依赖于特定于节点的设施,因为在节点中工作的脚本在我加载时不再执行通过browserify运行它后它在chrome中。我是否卡在使用原始 REST 调用? 运行的 Node 脚本如下所示:

var google = require('googleapis');
var readlineSync = require('readline-sync');

var CLIENT_ID = '....',
    CLIENT_SECRET = '....',
    REDIRECT_URL = 'urn:ietf:wg:oauth:2.0:oob',
    SCOPE = 'https://www.googleapis.com/auth/drive.file';

var oauth2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL);

var url = oauth2Client.generateAuthUrl({
  access_type: 'offline', // 'online' (default) or 'offline' (gets refresh_token)
  scope: SCOPE // If you only need one scope you can pass it as string
});

var code = readlineSync.question('Auth code? :');

oauth2Client.getToken(code, function(err, tokens) {
  console.log('authenticated?');
  // Now tokens contains an access_token and an optional refresh_token. Save them.
  if(!err) {
    console.log('authenticated');
    oauth2Client.setCredentials(tokens);
  } else {
    console.log('not authenticated');
  }
});

我在这个脚本上使用 browserify 包装了节点 GDrive SDK:

var Google = new function(){
    this.api = require('googleapis');
    this.clientID = '....';
    this.clientSecret = '....';
    this.redirectURL = 'urn:ietf:wg:oauth:2.0:oob';
    this.scope = 'https://www.googleapis.com/auth/drive.file';
    this.client = new this.api.auth.OAuth2(this.clientID, this.clientSecret, this.redirectURL);
  }
}

然后在单击按钮后调用它(如果文本字段没有代码,它会启动浏览器来获取):

function authorize() {
  var code = document.getElementById("code").value.trim();

  if (code === '') {
    var url = Google.client.generateAuthUrl({access_type: 'offline', scope: Google.scope});
    var win = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('navigator:browser');
    win.gBrowser.selectedTab = win.gBrowser.addTab(url);
  } else {
    Google.client.getToken(code, function(err, tokens) {
      if(!err) {
        Google.client.setCredentials(tokens);
        // store token
        alert('Succesfully authorized');
      } else {
        alert('Not authorized: ' + err); // always ends here
      }
    });
  }
}

但这会产生错误Not authorized: Invalid protocol: https:

【问题讨论】:

  • @friflaj 您是否尝试模仿窗口 obj ? window = Window = {} 形成一个高层次,看起来他们只使用 winodw obj 来存储全局变量
  • 这就是我现在正在尝试的。 Node 版本使用一种动态模块加载的形式,似乎可以避开 browserify,所以我已经放弃了。
  • 您是否尝试过使用 iFrame?我相信在 Firefox 中您可以访问“背景脚本”。这基本上是您的代码在其上执行的无头 html 页面。您应该能够在此处生成 iFrame。 (只是吐口水,我以前做过这个工作,但不记得是怎么做到的)
  • 我想知道这是否有帮助:stackoverflow.com/questions/8915087/…
  • 我只是想添加一个警告,您不应该尝试完全在客户端执行此操作,因为这将涉及(如您在上面发布的)在您的源代码中公开您的客户端密码附加组件(可通过文件系统访问)。这会给附加组件的用户带来安全风险。相反,我会在您的插件可以调用的单独服务器上托管一个小型应用程序,该应用程序将使用标准 OAuth 方法(回调 URL 等)对用户进行身份验证。

标签: javascript firefox-addon google-drive-api xul


【解决方案1】:

但也有可能,具体取决于用例,它的兴趣也可能有限。

Firefox 附带一个很小的 ​​http 服务器,只是最基本的。它是出于测试目的而包含在内的,但这不是忽略它的理由。

让我们关注quickstart guide for running a Drive app in Javascript

棘手的部分是设置重定向 URI 和 Javascript 源。显然正确的设置是http://localhost,但是你怎么能确定每个用户都有可用的80端口呢?

您不能,除非您可以控制您的用户,否则没有任何端口可以保证对所有人都有效。考虑到这一点,让我们选择端口 49870 并祈祷。

所以现在重定向 URI 和 Javascript 源设置为 http://localhost:49870

假设您使用插件 SDK,请将 quickstart.html(记得添加您的客户端 ID)保存在扩展程序的 data 目录中。现在编辑你的main.js

const self = require("sdk/self");
const { Cc, Ci } = require("chrome");
const tabs = require("sdk/tabs");
const httpd = require("sdk/test/httpd");

var quickstart = self.data.load("quickstart.html");

var srv = new httpd.nsHttpServer();

srv.registerPathHandler("/gdrive", function handler(request, response){
  response.setHeader("Content-Type", "text/html; charset=utf-8", false);

  let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
  converter.charset = "UTF-8";
  response.write(converter.ConvertFromUnicode(quickstart));
})

srv.start(49870);

tabs.open("http://localhost:49870/gdrive");

exports.onUnload = function (reason) {
  srv.stop(function(){});
};

请注意,quickstart.html 不是作为本地文件打开的,而是带有 resource: URI。 Drive API 不喜欢这样。它在 URL http://localhost:49870/gdrive 上提供。不用说,我们可以使用模板或其他任何东西来代替静态 html。 http://localhost:49870/gdrive 也可以使用常规的 PageMod 编写脚本。

我不认为这是一个真正的解决方案。有总比没有好。

【讨论】:

  • 碰巧我正在为一个 zotero 扩展做这个,......并且 zotero 附带了一个可服务的 http 服务器,所以这应该可以工作。我没想到谷歌会接受 localhost 重定向 URIs
【解决方案2】:

从这里https://developer.mozilla.org/en/docs/Working_with_windows_in_chrome_code 你可以试试window = window || content || {}

使用 JavaScript 客户端 API 而不是 node.js 客户端。虽然 browserify 会让它工作。您将不得不在后者中公开您的客户机密。客户端身份验证的流程与服务器端非常不同。参考https://developers.google.com/accounts/docs/OAuth2

说了这么多。使用基于 REST 的调用来实现应用程序并不难。所有客户端库中的方法都模仿相应的 REST URL。您可以设置自己的一些函数来处理请求和响应,其余的感觉都一样。

【讨论】:

  • @friflaj 感谢您标记为正确。上面的代码 sn-p 是否适合您,或者您是否尝试过原生 REST?
猜你喜欢
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
  • 2011-10-24
  • 2010-11-29
  • 2010-12-03
  • 1970-01-01
  • 2012-01-09
相关资源
最近更新 更多