またニコニコ動画見てるグリモンをSeaHorseに移植したい
とりあえずイベント処理やflvplayerの取得などをIEコンポーネント対応するのは出来て、
GM_xmlhttpRequestのダミーで本来POSTすべき内容をalertで表示するところまでは出来た。
// ==UserScript== // @name mata nicovideo // @namespace http://d.hatena.ne.jp/monjudoh/ // @include http://www.nicovideo.jp/watch/* // @author monjudoh // @description Original Greasemonkey script : http://muumoo.jp/news/2008/01/28/0matanicovideo.html // @version 0.2 // ==/UserScript== (function(){ function GM_xmlhttpRequest(params){ alert('url:' + params.url + '\ndata:' + params.data); } Number.prototype.z = function(len){ var s = '0'.fill(len) + this.toString(); return s.substr(s.length - len); }; String.prototype.fill = function(len){ var result = ''; for(var i = 0; i < len; i++) result += this; return result; }; var h1 = document.getElementsByTagName('h1')[0]; if(!h1) return; var span = document.createElement('span'); h1.parentNode.insertBefore(span, h1); var a = document.createElement('a'); a.appendChild(document.createTextNode('[\u307e\u305f\u898b\u3066\u308b]')); a.href = 'javascript:void(0);'; a.attachEvent('onclick', function(){ var srcElem = window.event.srcElement; srcElem.parentNode.removeChild(srcElem); var text = document.createElement('input'); text.type = 'text'; text.value = ''; text.size = 20; text.setAttribute('maxlength', 10); var a = document.createElement('a'); a.appendChild(document.createTextNode('[\u307e\u305f\u898b\u3066\u308b!]')); a.href = 'javascript:void(0);'; a.attachEvent('onclick', function(){ var subject = h1.getElementsByTagName('a')[0].innerHTML; var url = location.href; var flvplayer = document.getElementById('flvplayer'); var len = flvplayer.GetVariable('ContentLength'); var lmin = Math.floor(len / 60); var lsec = len % 60; GM_xmlhttpRequest({ method: 'POST', url: 'http://twitter.com/statuses/update.json', headers: { 'Content-type': 'application/x-www-form-urlencoded' }, data: 'status=' + encodeURIComponent( '\u307e\u305f\u30cb\u30b3\u30cb\u30b3\u52d5\u753b\u898b\u3066\u308b : ' + subject + ' ' + url + ' (' + lmin.z(2) + ':' + lsec.z(2) + ')' + ((0 < text.value.length) ? ' ' + text.value : '') ), onload: function(res){ GM_log('\u6295\u7a3f\u3057\u307e\u3057\u305f\u3002'); }, onerror: function(res){ GM_log(res.status + ':' + res.statusText); } }); var srcElem = window.event.srcElement; srcElem.parentNode.parentNode.removeChild(srcElem.parentNode); }); span.appendChild(a); span.appendChild(text); text.focus(); }); span.appendChild(a); })();
GM_xmlhttpRequestの代わりはどうするかというと、
iframeを使用したクロスドメインPOSTでできるんじゃないかと高をくくってた。
実際APIにPOSTするところまでは上手くいったものの、↓こんなエラーメッセージが帰ってきた。
Sorry, due to abusive behaviour we have been forced to disable posting from external websites. If you are posting from an API tool please ensure that the HTTP_REFERER header is not set.
src属性を設定しないでこしらえてやったiframeの中のformからPOSTすると、
リファラがiframeを持ってる画面のURLになってしまうようなのだ。
で、twitterの投稿APIはリファラがよそのサイトになってると投稿を受け付けないので失敗してしまった。
ということなのでした。
次回はこの辺を参考にしてみようかと思う。
iframeを使用したクロスドメインPOST
指定したidのiframeのdocumentを取得する関数
function getIframeDoc(iframeId){ var iframe = document.getElementById(iframeId); if (document.all) { return iframe.contentWindow.document; } else { return iframe.contentDocument; } }
こんな感じで適当なdivを作って適当なiframeを放り込んで、body作ってDOM操作できるようにしてやる。
var div = document.createElement('div'); div.id = 'iframeContainer'; document.body.appendChild(div); var iframe = document.createElement('iframe'); iframe.id = 'iframe'; document.getElementById('iframeContainer').appendChild(iframe); var iframedoc = getIframeDoc('iframe'); iframedoc.writeln('<body></body>'); iframedoc.close();
iframe経由でPOSTしてやる関数
まあ見たまんま
function submit(iframedoc,action,params){ var form = iframedoc.createElement('form'); form.method = 'post'; form.action = action; iframedoc.body.appendChild(form); for(var paramName in params){ var paramValue = params[paramName]; var input = iframedoc.createElement('input'); input.type = 'text'; input.name = paramName; input.value = paramValue; form.appendChild(input); } form.submit(); }
空iframeを使った場合は基本的にparamsはUTF-8でURLエンコードされてPOSTされるけど、
documentのinputEncodingプロパティが他のエンコーディング(EUC-JPとかSJISとか)になってるページを
読み込ませたiframeだったら、そのエンコーディングでURLエンコードされてPOSTされるよ。
(↑クロスドメインの時はダメだよ)
クロスドメインじゃなければ↓みたいな感じでレスポンスも取れるけど、↑と併用しないとそんなにうれしくないね。
getIframeDoc('iframe').body.innerHTML;
ずっとFirebugで弄ってたんでFirefox以外での動作には自信ないです。
ちゃっちゃとIEコンポーネントブラウザでの動作も確認して、
クロスドメインでPOSTする&レスポンス情報は別になくても困らない系の用途で
GM_xmlhttpRequestを使っているグリモンをSeaHorseに移植したい。