gadgets.ioのOAuth問題のpatchについて

はじめに
この記事で紹介するパッチは、以下に報告した問題に対処するものです。
2つ以上のOAuth認可をもつガジェットで遭遇した問題と対処

MA6表彰式で、nakajimanさんにお会いしたおり、スコープのために頓挫した以前に変わるアプローチ法などをご教示いただきました。
ありがとうございました。


パッチとパッチ検証用ガジェット
こうして作成したパッチと、パッチの検証用のガジェットはこちらになります。
overrideIO.js @GoogleCode
OAuthPatchTest

パッチ検証用ガジェットは前回制作したOAuth問題の確認用のガジェットにパッチを適用したものです。

パッチによって、clearOAuthState()を実行しなくても、予期したとおりの動作が得られるのを確認できると思います。
拙作ガジェットOSでも、問題は起きていません。

パッチの使いどころ
このパッチはOpensocialの修正提案用として制作していますが、現状ほとんどのガジェットにとっては不要だろうとも思います。
でもごくまれに、OAuth認可をバリバリ使うガジェットを明日までにうまく動かさないと切腹、といった状況の方は以下の解説を読みつつ導入を検討してみてください。


パッチの解説
上記リンクで報告したとおり、OAuth認可は複数を平行してやり始めたりするととたんにエラーが返ってくるようになります。

これは、あるOAuthサービス用のトークンが別のOAuthサービス使われてしまっているのが原因で、OAuthサービス毎にトークンを保持したり、リクエストのときには復帰してやればバッチオーライです。多分。

そこでgadget.ioの該当部分を次のように書き換えています。

// 変更箇所
var oauthState = {};
// 元
//var oauthState;


// 変更箇所
if (data.oauthState && params && params.OAUTH_SERVICE_NAME) {
 oauthState[ params.OAUTH_SERVICE_NAME] = data.oauthState
}
// 元
//if (data.oauthState) {
// oauthState = data.oauthState
//}


// 変更箇所
if (preload.oauthState && params && params.OAUTH_SERVICE_NAME) {
 oauthState[ params.OAUTH_SERVICE_NAME] = preload.oauthState;
}
// 元
//if (preload.oauthState) {
// oauthState = preload.oauthState
//}


// 変更箇所
if (params && params.OAUTH_SERVICE_NAME) {
 paramData.oauthState = oauthState[ params.OAUTH_SERVICE_NAME] || "";
} else {
 paramData.oauthState = "";
}
// 元
//paramData.oauthState = oauthState || "";


clearOAuthState: function(){
 // 変更箇所
 oauthState = {}
 // 元
 //oauthState = undefined
},

以上の変更は、ガジェットが読み込まれたあと、
gadgets.util.registerOnLoadHandler( overrideIO);
で、gadgets.ioをすべて上書きしています。参照

なのでパッチを用意する場合、まずはコンテナの吐き出したjsのgadgets.io部分をコピーして適宜書き換えてやる必要があるかもです。

また、gadgets.ioのイニシャライズのあとに、gadgets.config.init()でio含めそれぞれのパートにコンテナ依存の定数を渡しています。多分。

gadgets.config.init(~略~"core.io":{"proxyUrl":"//www.gmodules.com/gadgets/proxy/refresh=%refresh%&container=%container%%rewriteMime%&gadget=%gadget%/%rawurl%","jsonProxyUrl":"//%host%/gadgets/makeRequest"}});

この定数を新しいgadgets.ioパッチに渡してあげます。
とりあえず、core.io(gadgets.io)に渡す二つの値、proxyUrl:とjsonProxyUrl:は、次のようにして直に書いています。

// 手当て
var proxyUrl = "//%host%/gadgets/makeRequest".replace("%host%", document.location.host);
// 元
//var proxyUrl = config.jsonProxyUrl.replace("%host%", document.location.host);

// 手当て
var ret = "//www.gmodules.com/gadgets/proxy/refresh=%refresh%&container=%container%%rewriteMime%&gadget=%gadget%/%rawurl%".replace("%url%", encodeURIComponent(url))..~略~;
// 元
//var ret = config.proxyUrl.replace("%url%", encodeURIComponent(url)).~略~;

gadgets.configのソース