ポップアップウィンドウで異なるドメインのページを開き、元のページと通信するユーザースクリプトのサンプル。
Tampermonkeyで上記のユーザースクリプトをインストールし、
テスト用ページ
にアクセス。
ポップアップウィンドウを開き、一定時間通信した後、閉じる。
※ログはデベロッパーツールのコンソールを参照。
ポップアップウィンドウで異なるドメインのページを開き、元のページと通信するユーザースクリプトのサンプル。
Tampermonkeyで上記のユーザースクリプトをインストールし、
テスト用ページ
にアクセス。
ポップアップウィンドウを開き、一定時間通信した後、閉じる。
※ログはデベロッパーツールのコンソールを参照。
// ==UserScript== | |
// @name test-postMessage | |
// @namespace http://furyu.hatenablog.com/ | |
// @author furyu | |
// @version 0.1 | |
// @include https://twitter.com/furyutei/status/2688944309 | |
// @include https://nazo.furyutei.work/test/postMessage | |
// @description test-postMessage | |
// ==/UserScript== | |
( function () { | |
var POPUP_NAME = 'test-postMessage', | |
POPUP_URL = 'https://nazo.furyutei.work/test/postMessage'; | |
function get_popup_info() { | |
if ( ( ! window.opener ) || ( ! window.name ) || ( ! window.name.match( /^([^.]+)\.(.*)$/ ) ) ) { | |
return null; | |
} | |
else { | |
var popup_info = { | |
name : RegExp.$1, | |
parent_origin : RegExp.$2 | |
}; | |
if ( popup_info.name != POPUP_NAME ) { | |
return null; | |
} | |
return popup_info; | |
} | |
} // end of get_popup_info() | |
function get_origin( url ) { | |
return new URL( url ).origin; | |
} // end of get_origin() | |
function message_handler( event ) { | |
} // end of message_handler() | |
function parent_main() { | |
var parent_origin = get_origin( location.href ), | |
popup_origin = get_origin( POPUP_URL ), | |
popup_window = window.open( POPUP_URL, POPUP_NAME + '.' + parent_origin, 'width=640,height=480,top=' + ( window.screenY + 64 ) + ',left=' + (window.screenX + 48 ) + ',toolbar=0,scrollbars=1,status=1,resizable=1,location=1,menuBar=0' ), | |
timeout_timer_id = setTimeout( function () { | |
console.error( new Date().toISOString(), 'connection timeout' ); | |
finish(); | |
}, 30000 ), | |
healthcheck_timer_id = null, | |
healthcheck_counter = 0, | |
last_healthcheck_counter = 0, | |
message_handler = function ( event ) { | |
if ( event.origin != popup_origin ) { | |
console.error( new Date().toISOString(), 'origin error:', event.origin ); | |
return; | |
} | |
var message = event.data; | |
switch ( message.status ) { | |
case 'START' : | |
if ( ! timeout_timer_id ) { | |
break; | |
} | |
clearTimeout( timeout_timer_id ); | |
timeout_timer_id = null; | |
healthcheck_timer_id = setInterval( function () { | |
console.log( new Date().toISOString(), 'healthcheck_counter=', healthcheck_counter, last_healthcheck_counter ); | |
try { | |
console.log( 'popup_window.closed =', popup_window.closed ); | |
} | |
catch ( error ) { | |
} | |
if ( healthcheck_counter == last_healthcheck_counter ) { | |
console.error( new Date().toISOString(), 'healthcheck timeout' ); | |
finish(); | |
return; | |
} | |
last_healthcheck_counter = healthcheck_counter; | |
}, 3000 ); | |
break; | |
case 'ALIVE' : | |
healthcheck_counter ++; | |
break; | |
case 'END' : | |
console.log( new Date().toISOString(), 'send close request' ); | |
popup_window.postMessage( { | |
command : 'CLOSE_REQUEST' | |
}, popup_origin ); | |
finish(); | |
break; | |
default : | |
console.error( new Date().toISOString(), 'message error:', message ); | |
return; | |
} | |
console.log( new Date().toISOString(), 'popup status:', message.status, healthcheck_counter, message ); | |
}, | |
finish = function () { | |
if ( healthcheck_timer_id ) { | |
clearTimeout( healthcheck_timer_id ); | |
} | |
window.removeEventListener( 'message', message_handler ); | |
}; | |
window.addEventListener( 'message', message_handler ); | |
console.log( new Date().toISOString(), 'ready' ); | |
} // end of parent_main() | |
function popup_main( popup_info ) { | |
var parent_window = window.opener, | |
parent_origin = popup_info.parent_origin, | |
healthcheck_counter = 0, | |
healthcheck_timer_id = setInterval( function () { | |
healthcheck_counter ++; | |
console.log( new Date().toISOString(), 'alive', healthcheck_counter ); | |
parent_window.postMessage( { | |
status : 'ALIVE', | |
counter : healthcheck_counter | |
}, parent_origin ); | |
}, 500 ), | |
end_timer_id = setTimeout( function () { | |
console.log( new Date().toISOString(), 'end' ); | |
parent_window.postMessage( { | |
status : 'END' | |
}, parent_origin ); | |
}, 10000 ); | |
window.addEventListener( 'message', function ( event ) { | |
if ( event.origin != parent_origin ) { | |
console.error( new Date().toISOString(), 'origin error:', event.origin ); | |
return; | |
} | |
var message = event.data; | |
switch ( message.command ) { | |
case 'CLOSE_REQUEST' : | |
window.open( '', '_self', '' ); | |
window.close(); | |
break; | |
default : | |
console.error( new Date().toISOString(), 'message error:', message ); | |
return; | |
} | |
console.log( new Date().toISOString(), 'parent command:', message.command, message ); | |
} ); | |
console.log( new Date().toISOString(), 'start' ); | |
parent_window.postMessage( { | |
status : 'START' | |
}, parent_origin ); | |
} // end of popup_main() | |
var popup_info = get_popup_info(); | |
if ( popup_info ) { | |
popup_main( popup_info ); | |
} | |
else { | |
parent_main(); | |
} | |
} )(); |
覚え書き
ポップアップウィンドウで異なるドメインのページを開き、元のページと通信するユーザースクリプトのサンプル。
元ページは、一定時間メッセージが来ない場合、タイムアウトとみなす
テスト方法
Tampermonkeyで上記のユーザースクリプトをインストールし、
https://twitter.com/furyutei/status/2688944309
にアクセス。
ポップアップウィンドウを開き、一定時間通信した後、閉じる。
※ログはデベロッパーツールのコンソールを参照。