从浏览器动作弹出窗口:打开一个新标签并填写输入字段 [英] From a browser action popup: open a new tab and fill input fields

查看:117
本文介绍了从浏览器动作弹出窗口:打开一个新标签并填写输入字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建基本的Chrome扩展程序,该扩展程序通过浏览器操作弹出窗口在新标签中打开网站,并填写登录凭据。我可以让Chrome扩展程序打开新页面,但似乎无法将它输入到输入字段中。



Manifest.json


$ manifest $ {
manifest_version:2,

name: Vena,
description:此扩展程序将允许用户登录vena帐户,
version:1.0,

browser_action:{
default_icon:images / icon.png,
default_popup:popup.html
},
权限:[
activeTab
]
}

popup.html

 <!doctype html> 
< html>
< head>
< title>自动登录< / title>
< script src =popup.js>< / script>
< / head>
< body>
< h1>登入< / h1>
< button id =checkPage>登入!< / button>
< / body>
< / html>

popup.js

  document.addEventListener('DOMContentLoaded',function(){
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('点击',function(){

var newURL =https://vena.io/;
chrome.tabs.create({url:newURL});

var loginField = document.getElementsByClassName('js-email form-control input-lg');
var passwordField = document.getElementsByClassName('js-password form-control input-lg');

loginField.value ='gsand';
passwordField.value ='123';

$ b},false);
},false );

如何在新标签的输入区域填写信息?

$另一次,您可能想要使用弹出式窗口以外的其他功能(例如,只是一个简单的浏览器动作按钮或面板)来测试您的功能。由于弹出窗口在许多条件下都会消失,所以调试弹出窗口之外的东西更容易。一旦你调试了基本的功能,你可以将它移动到弹出窗口中,并处理使用弹出窗口的具体问题。


您需要使用内容脚本与网页互动:

主要问题是您必须使用内容脚本进行互动与网页一样,如操作DOM,就像你想做的那样。内容脚本必须注入到网页中。这可以通过 manifest.json 中的 content_scripts 条目或 chrome.tabs.executeScript() 脚本,事件脚本,弹出窗口,面板,包含附加组件页面的选项卡等)。对于你正在做的事情, chrome.tabs.executeScript()就是要走的路。

其他问题:


  1. chrome.tabs.create() 是异步的。您需要等待回调才能执行,以便存在该选项卡以注入内容脚本。您不能将脚本注入到尚不存在的选项卡中。注意:您可以使用其他更复杂的方法来确定何时注入内容脚本,但回调 chrome.tabs.create()是一种很好的方法在这种情况下。

  2. 创建新选项卡后,您需要注入脚本。这不是活动标签,因此您需要将https://vena.io/*添加到 permissions manifest.json

  3. 内容脚本运行时的页面。你需要等到它们可用。我刚刚使用了 setTimeout 循环轮询,直到元素可用。我选择了250毫秒的间隔轮询,最多100次(25秒)。元素在第一次延迟后每次都有。
  4. document.getElementsByClassName() 返回一个 HTMLCollection ,而不是一个元素。
  5. 激活另一个选项卡时弹出窗口关闭。弹出窗口关闭/销毁后,您无法在弹出窗口的代码中进行更多处理。为了解决这个问题:


    1. chrome.tabs.create() code> active:false 以防止新标签立即变为活动状态。

    2. 调用 chrome.tabs.update() chrome.tabs.executeScript()在注入内容脚本后即可激活该选项卡(即完成弹窗中要执行的所有处理)。




    代码



    在您的 manifest.json popup.js 中需要。
    $ b

    manifest.json

      {
    manifest_version:2,

    name:Vena,
    description:此扩展程序将允许用户登录vena帐户,
    版本:1.0,

    browser_action: {
    default_icon:icon.png,
    default_popup:popup.html
    },
    权限:[
    activeTab ,//这是不需要的,因为你从不与活动标签交互
    https://vena.io/*
    ]
    }

    popup.js

     var checkPageButton = document.getElementById('checkPage'); 
    checkPageButton.addEventListener('click',function(){
    var newURL =https://vena.io/;
    //不能使选项卡激活或弹出将被销毁,阻止任何
    //进一步处理。
    chrome.tabs.create({url:newURL,active:false},function(tab){
    console.log('Attempting to注入脚本到tab:',tab);
    chrome.tabs.executeScript(tab.id,{code:`
    (function(){
    var count = 100; //只尝试100次
    函数changeLoginWhenExists(){
    var loginField = document.getElementsByClassName('js-email form-control input-lg')[0];
    var passwordField = document.getElementsByClassName(' js-password form-control input-lg')[0];
    // loginField和passwordField都是HTMLCollection
    if(loginField&& passwordField){
    loginFie ld.value ='gsand';
    passwordField.value ='123';
    } else {
    if(count-> 0){
    //我们需要的元素还不存在,请稍等一会再试。
    //这可能更适合作为MutationObserver
    setTimeout(changeLoginWhenExists,250);
    }
    }
    }
    changeLoginWhenExists();
    })();
    `},函数(结果){
    //现在我们完成了处理,使选项卡激活。这将
    //关闭/销毁弹出窗口。
    chrome.tabs.update(tab.id,{active:true});
    });
    });
    },false);
    },false);



    可能需要使用 document.execCommand('insertText',false,text); < h2>

    根据页面的不同,您可能需要/希望使用:

      document.execCommand('insertText',false,textValue); 

    如果您这样做,您需要先选择/聚焦所需的元素。这将不是设置 .value 属性。你使用哪个取决于你实际做了什么以及你正在改变的页面的组成。对于问题中的具体示例,设置元素的 .value 属性起作用。对于插入文本,使用`document.execCommand('insertText')更普遍适用。



    可能需要一个 MutationObserver



    在上面的代码中,我使用 setTimeout() 循环,直到所需的元素存在。虽然在上述情况下可行,但根据您的使用情况,使用 MutationObserver 可能更合适。很大程度上,使用哪种方法将取决于您需要立即响应所添加的期望元素以及通过查找元素将哪些类型的负载放在页面上。有关观看DOM更改的更多信息,请参阅:是否有JavaScript / jQuery DOM更改侦听器?



    用户界面注释



    目前您的弹出窗口只有一个按钮:登录。从用户交互的角度来看,使用普通的浏览器动作按钮可能会更好。如果您打算为弹出窗口添加功能,请继续并保留弹出窗口。如果您不打算添加功能,则强制用户点击两次(点击:打开弹出窗口,然后点击:登录),但点击一次时没有太大意义。



    使用实际的密码管理器



    如果这是你想要的功能,而不仅仅是你放置的东西一起学习,你应该使用一个真正的密码管理器。安全地存储密码并在网站中适当地插入它们的功能是非常重要的。您可以轻松地犯错,导致安全性受到影响。我强烈建议您调查各种可用选项,并选择适合您需求的选项。基本上,我所见过的所有功能都可以轻松为您提供目前的功能:打开弹出窗口;选择该网站;去网站并填写用户名和密码。密码管理员是一个非常重要的项目。这是 不是 项目可以轻易采取,或者对于在安全问题方面没有经验的人。


    I'm trying to build a basic Chrome extension that, from a browser action popup, opens a website in a new tab, and fills in the login credentials. I can get the Chrome extension to open the new page but can't seem to get it to input text into the input fields.

    Manifest.json

    {
      "manifest_version": 2,
    
      "name": "Vena",
      "description": "This extension will allow users to login to vena accounts",
      "version": "1.0",
    
      "browser_action": {
       "default_icon": "images/icon.png",
       "default_popup": "popup.html"
      },
      "permissions": [
       "activeTab"
       ]
    }
    

    popup.html

    <!doctype html>
    <html>
      <head>
        <title>Auto-Login</title>
        <script src="popup.js"></script>
      </head>
      <body>
        <h1>Login</h1>
        <button id="checkPage">Login!</button>
      </body>
    </html>
    

    popup.js

    document.addEventListener('DOMContentLoaded', function() {
      var checkPageButton = document.getElementById('checkPage');
      checkPageButton.addEventListener('click', function() {
    
        var newURL = "https://vena.io/";
        chrome.tabs.create({ url: newURL });
    
        var loginField = document.getElementsByClassName('js-email form-control input-lg');
        var passwordField = document.getElementsByClassName('js-password form-control input-lg');
    
        loginField.value = 'gsand';
        passwordField.value = '123';
    
    
      }, false);
    }, false);
    

    How do I fill in the information in the input areas of the new tab?

    解决方案

    Another time, you may want to use something other than a popup (e.g. just a plain browser action button, or a panel) to test out your functionality. It is easier to debug things other than a popup due to the fact that the popup will disappear under so many conditions. Once you have the basic functionality debugged, you can move it into a popup and deal with the issues specific to using a popup.

    Issues

    You need to use a content script to interact with web pages:
    The primary issue is that you have to use a content script to interact with a web page, such as manipulating the DOM, as you desire to do. Content scripts have to be injected into the web page. This can be done with a content_scripts entry in your manifest.json, or with chrome.tabs.executeScript() from JavaScript that is in the background context (background scripts, event scripts, popups, panels, tabs containing pages from your add-on, etc.). For what you are doing, chrome.tabs.executeScript() is the way to go.

    Additional issues:

    1. chrome.tabs.create() is asynchronous. You need to wait for the callback to execute so the tab exists in order to inject a content script. You can not inject scripts into a tab that does not yet exist. Note: You could use other, more complex, methods of determining when to inject the content script, but the callback for chrome.tabs.create() is a good way to do it in this case.
    2. Once you create the new tab, you want to inject a script. This is not the "active tab", so you need to add "https://vena.io/*" to your permissions in your manifest.json.
    3. The elements you desire to interact with are not immediately available on the page when the content script is run. You need to wait until they are available. I just used a setTimeout loop to poll until the elements are available. I chose to poll on 250ms intervals a maximum of 100 times (25 seconds). The elements were there each time after the first delay.
    4. document.getElementsByClassName() returns an HTMLCollection, not a single element.
    5. Popups close when you activate a different tab. Once the popup is closed/destroyed, you can not do any more processing within the code for the popup. In order to get around that:

      1. In your chrome.tabs.create(), include active:false to prevent the new tab from becoming active immediately.
      2. Call chrome.tabs.update() in the callback for chrome.tabs.executeScript() to active the tab once the content script has been injected (i.e. when you are done with all the processing you are going to do in the popup).

    Code

    Changes were only needed in your manifest.json and popup.js.

    manifest.json

    {
      "manifest_version": 2,
    
      "name": "Vena",
      "description": "This extension will allow users to login to vena accounts",
      "version": "1.0",
    
      "browser_action": {
         "default_icon": "icon.png",
         "default_popup": "popup.html"
      },
      "permissions": [
        "activeTab", //This is not needed as you never interact with the active tab
        "https://vena.io/*"
      ]
    }
    

    popup.js

    document.addEventListener('DOMContentLoaded', function() {
      var checkPageButton = document.getElementById('checkPage');
      checkPageButton.addEventListener('click', function() {
        var newURL = "https://vena.io/";
        //Must not make the tab active, or the popup will be destroyed preventing any
        //  further processing.
        chrome.tabs.create({ url: newURL,active:false }, function(tab){
            console.log('Attempting to inject script into tab:',tab);
            chrome.tabs.executeScript(tab.id,{code:`
                (function(){
                    var count = 100; //Only try 100 times
                    function changeLoginWhenExists(){
                        var loginField = document.getElementsByClassName('js-email form-control input-lg')[0];
                        var passwordField = document.getElementsByClassName('js-password form-control input-lg')[0];
                        //loginField and passwordField are each an HTMLCollection
                        if( loginField && passwordField ){
                            loginField.value = 'gsand';
                            passwordField.value = '123';
                        } else {
                            if(count-- > 0 ){
                                //The elements we need don't exist yet, wait a bit to try again.
                                //This could more appropriately be a MutationObserver
                                setTimeout(changeLoginWhenExists,250);
                            }
                        }
                    }
                    changeLoginWhenExists();
                })();
            `},function(results){
                //Now that we are done with processing, make the tab active. This will
                //  close/destroy the popup.
                chrome.tabs.update(tab.id,{active:true});
            });
        });
      }, false);
    }, false);
    

    May need use document.execCommand('insertText', false, text);

    Depending on the page, you may need/want to use:

    document.execCommand('insertText', false, textValue);
    

    If you do so, you will need to first select/focus the desired element. This would be instead of setting the .value property. Which you use will depend on what you are actually doing and the composition of the page you are altering. For the specific example in the question, setting the element's .value property works. For inserting text, using `document.execCommand('insertText') is more generally applicable.

    May need a MutationObserver

    In the above code I use a setTimeout() loop to delay until the desired elements exist. While that works in the above case, depending on your use case, it may be more appropriate for you to use a MutationObserver. Largely, which to use will depend on how immediately you need to respond to the desired elements being added and what type of load you are putting on the page by looking for the elements. For more information about watching for DOM changes see: Is there a JavaScript/jQuery DOM change listener?

    UI comment

    Currently you have a popup that has a single button: "Login". From a user interaction point of view, it would probably be better to just use a plain browser action button. If you are intending to add functionality to your popup, then go ahead and keep the popup. If you are not going to add functionality, it does not make a lot of sense to force your user to click twice (click: open popup, then click: login) when they could have just clicked once.

    Use an actual Password Manager

    If this is functionality that you desire, rather than just something you are putting together just to learn, you should use an actual Password Manager. The functionality of securely storing passwords and inserting them appropriately in websites is non-trivial. You can easily make mistakes that result in compromising your security. I strongly recommend that you investigate the various ones available and choose one which fits your needs. Basically, all the ones that I have seen would easily provide you with the functionality you have at this time: open a popup; select the site; go to the site and fill in the user name and password. A password manager is a very significant project. It is not a project to be taken on lightly, or for someone who is not experienced in security issues.

    这篇关于从浏览器动作弹出窗口:打开一个新标签并填写输入字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆