Javascript 如何在Firefox的一个选项卡中更改用户代理?

Javascript 如何在Firefox的一个选项卡中更改用户代理?,javascript,firefox-addon,user-agent,Javascript,Firefox Addon,User Agent,我正在开发一个Firefox扩展,我需要更改单个选项卡的用户代理。我使用了诸如User Agent Switcher之类的扩展,但它只允许我在整个浏览器中更改User Agent。你知道这是否可能吗?我在哪里可以阅读 非常感谢, 这是一个有趣的插件。我想做一个插件,它只在一个选项卡中启用代理,我想这会帮助你很快让我做到这一点 复制粘贴代码。它将在选项卡1中加载的所有内容中欺骗用户代理。在所有其他选项卡中,它将让负载通过。然而,如果没有loadContext,您将无法分辨它来自哪个选项卡,所以可能

我正在开发一个Firefox扩展,我需要更改单个选项卡的用户代理。我使用了诸如User Agent Switcher之类的扩展,但它只允许我在整个浏览器中更改User Agent。你知道这是否可能吗?我在哪里可以阅读

非常感谢,
这是一个有趣的插件。我想做一个插件,它只在一个选项卡中启用代理,我想这会帮助你很快让我做到这一点

复制粘贴代码。它将在选项卡1中加载的所有内容中欺骗用户代理。在所有其他选项卡中,它将让负载通过。然而,如果没有loadContext,您将无法分辨它来自哪个选项卡,所以可能只是忽略它,让它走

我们需要比我更有经验的ppl的建议。在什么情况下我们会得到一个空的loadContext? 复制粘贴代码

const {classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu, results: Cr, manager: Cm} = Components;
Cu.import('resource://gre/modules/Services.jsm');

var myTabToSpoofIn = Services.wm.getMostRecentBrowser('navigator:browser').gBrowser.tabContainer[0]; //will spoof in the first tab of your browser

var httpRequestObserver = {
    observe: function (subject, topic, data) {
        var httpChannel, requestURL;

        if (topic == "http-on-modify-request") {
            httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
            var goodies = loadContextGoodies(httpChannel)
            if (goodies) {
              if (goodies.aTab == myTabToSpoofIn) {
                httpChannel.setRequestHeader('User-Agent', 'user agent spoofeddddd', false);
              } else {
                //we arent spoofing in this tab so ignore it
              }
            } else {
                //no goodies so we dont know what tab its from, im not sure when we dont have a loadContext we need to ask other ppl
                //no goodies for this channel, so dont know what tab its in so probably just load this, your decision though, make it option to user, if cannot find associated load context ask user if they want the data to be loaded with default user agent or just not load it at all
                //httpChannel.cancel(Cr.NS_BINDING_ABORTED); //uncomment this to abort it
            }
        }
    }
};

Services.obs.addObserver(httpRequestObserver, "http-on-modify-request", false);
//Services.obs.removeObserver(httpRequestObserver, "http-on-modify-request", false); //run this on shudown of your addon otherwise the observer stags registerd







//this function gets the contentWindow and other good stuff from loadContext of httpChannel
function loadContextGoodies(httpChannel) {
    //httpChannel must be the subject of http-on-modify-request QI'ed to nsiHTTPChannel as is done on line 8 "httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);"
    //start loadContext stuff
    var loadContext;
    try {
        var interfaceRequestor = httpChannel.notificationCallbacks.QueryInterface(Ci.nsIInterfaceRequestor);
        //var DOMWindow = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow); //not to be done anymore because: https://developer.mozilla.org/en-US/docs/Updating_extensions_for_Firefox_3.5#Getting_a_load_context_from_a_request //instead do the loadContext stuff below
        try {
            loadContext = interfaceRequestor.getInterface(Ci.nsILoadContext);
        } catch (ex) {
            try {
                loadContext = subject.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
            } catch (ex2) {}
        }
    } catch (ex0) {}

    if (!loadContext) {
        //no load context so dont do anything although you can run this, which is your old code
        //this probably means that its loading an ajax call or like a google ad thing
        return null;
    } else {
        var contentWindow = loadContext.associatedWindow;
        if (!contentWindow) {
            //this channel does not have a window, its probably loading a resource
            //this probably means that its loading an ajax call or like a google ad thing
            return null;
        } else {
            var aDOMWindow = contentWindow.top.QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIWebNavigation)
                .QueryInterface(Ci.nsIDocShellTreeItem)
                .rootTreeItem
                .QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIDOMWindow);
            var gBrowser = aDOMWindow.gBrowser;
            var aTab = gBrowser._getTabForContentWindow(contentWindow.top); //this is the clickable tab xul element, the one found in the tab strip of the firefox window, aTab.linkedBrowser is same as browser var above //can stylize tab like aTab.style.backgroundColor = 'blue'; //can stylize the tab like aTab.style.fontColor = 'red';
            var browser = aTab.linkedBrowser; //this is the browser within the tab //this is where the example in the previous section ends
            return {
                aDOMWindow: aDOMWindow,
                gBrowser: gBrowser,
                aTab: aTab,
                browser: browser,
                contentWindow: contentWindow
            };
        }
    }
    //end loadContext stuff
}

还有一张便条。由于要更改用户请求,请确保在
httpChannel.setRequestHeader('MyCustomRequestHeader','hiiii',false)中将第三个参数设置为false
否则,它会将预先存在的用户代理与您提供的新用户代理合并

当后台进程(例如,来自加载项)发出与任何特定浏览器选项卡无关的http请求时,您将获得空上下文。所以,是的,在这种情况下忽略它是最明智的方法。非常感谢你的回答,我急切地等待有人来帮助我们,但什么情况下没有标签?只是插件在执行调用,对吗?在tab中加载的任何资源文件都将始终具有tab权限?不,这将产生严重的隐私影响,因为上下文用于跟踪给定请求是否是私有浏览会话的一部分。当然,可能会有Firefox bug或一些插件以这种方式运行,并以某种方式通过了Mozilla的审查过程,但这是非常不可能的。完美!我希望标签上的所有内容都有上下文。谢谢你的验证。我有其他扩展的例外情况,是的,如果没有上下文忽略是一个好方法。