对于我创建的附加组件的即将推出的版本,我想检测在哪个选项卡(如果有)中在新选项卡或窗口中打开了链接。
我的附加组件是缩放附加组件,如果用户在新选项卡或窗口中打开链接,我希望能够复制原始选项卡的缩放级别。
我已经弄清楚如何在使用内容 JavaScript 中的 window.open()
打开链接时检测开启器(这相当简单),但是我不知道如何实现确定是否从上下文菜单(在新选项卡/新窗口中打开链接)或 Ctrl/⌘/Shift打开了新选项卡/窗口kbd>+单击。
为了检测它是否是从 content-Javascript 打开的,我使用:
const Cc = Components.classes;
const Ci = Components.interfaces;
let windowTracker = {
observe: function( subject, topic, data ) {
if( 'chrome-document-global-created' == topic && subject instanceof Ci.nsIDOMWindow ) {
// here I can use subject.opener
}
}
}
let observerService = Cc[ '@mozilla.org/observer-service;1' ].getService( Ci.nsIObserverService );
observerService.addObserver( this, 'chrome-document-global-created', false );
为了检测任何可能的非内容 JavaScript 开场白,我在 observe()
中尝试过:
let windowTracker = {
observe: function( subject, topic, data ) {
if( 'chrome-document-global-created' == topic && subject instanceof Ci.nsIDOMWindow ) {
let topWindow = subject.QueryInterface( Ci.nsIInterfaceRequestor )
.getInterface( Ci.nsIWebNavigation )
.QueryInterface( Ci.nsIDocShellTreeItem )
.rootTreeItem
.QueryInterface( Ci.nsIInterfaceRequestor )
.getInterface( Ci.nsIDOMWindow );
// here I tried topWindow.opener, with mixed results
}
}
}
...但结果好坏参半。
当我使用上下文菜单或 Ctrl/⌘/Shift+单击在新选项卡或窗口中打开链接时,topWindow.opener
等于 null
,但如果我使用 Ctrl+Shift+ 打开附加组件管理器A,topWindow.opener
将是 ChromeWindow
的实例。
所以,看来我走在正确的轨道上,但并不完全正确,因为我只对用户在新选项卡或窗口中发起的内容链接打开感兴趣。
我所追求的目标可行吗?
在检查 Firefox 的源代码时,我注意到可能有一种方法(除非我误解了其目的)可以给我我想要的东西:getOpener()
在 nsIDocShell
。但是,该方法并未在脚本 API 中公开。
我可以利用类似的东西吗?
最佳答案
我成功地通过拦截 ChromeWindow.openLinkIn()
让它工作与 Proxy
对象:
// window is a top level ChromeWindow
window.openLinkIn = new Proxy( window.openLinkIn, {
apply: function( target, thisArg, argumentsList ) {
let url = argumentsList[ 0 ];
let where = argumentsList[ 1 ];
let params = argumentsList.length > 2 ? argumentsList[ 2 ] : {};
// links opened through the context menu or Ctrl/⌘/Shift+click
// don't have params.fromChrome = true
if( !url || !where || params.fromChrome ) {
return target.apply( thisArg, argumentsList );
}
switch( where ) {
case 'tab':
// break intentionally omitted
case 'tabshifted':
let tabBrowser = window.gBrowser;
tabBrowser.tabContainer.addEventListener( 'TabOpen', function onTabOpen( event ) {
tabBrowser.tabContainer.removeEventListener( 'TabOpen', onTabOpen, true );
let tab = event.target;
// do something with the new tab
}, true );
break;
case 'window':
let windowTracker = {
init: function() {
observerService.addObserver( this, 'toplevel-window-ready', false );
},
destroy: function() {
observerService.removeObserver( this, 'toplevel-window-ready' );
},
observe: function( subject, topic, data ) {
let self = this;
let chromeWindow = subject;
if( 'toplevel-window-ready' == topic && chromeWindow instanceof Ci.nsIDOMWindow ) {
chromeWindow.addEventListener( 'DOMContentLoaded', function onChromeWindowDOMContentLoaded( event ) {
this.removeEventListener( 'DOMContentLoaded', onChromeWindowDOMContentLoaded, true );
if( 'navigator:browser' == this.document.documentElement.getAttribute( 'windowtype' ) ) {
// do something with the new chromeWindow
// destroy the windowTracker
self.destroy();
}
}, true );
}
}
}
windowTracker.init();
break;
}
return target.apply( thisArg, argumentsList );
}
} );
PS.:当然,当您的扩展程序被禁用时,请务必清理并重新安装原始功能。你可以用这样的东西来做到这一点:
let originalOpenLinkIn = window.openLinkIn;
window.openLinkIn = new Proxy( window.openLinkIn, {
apply: /* implementation from above */
} );
// then when cleaning up:
window.openLinkIn = originalOpenLinkIn;
关于javascript - 检测打开新选项卡/窗口的原始选项卡(如果有),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28550228/