preface

Before I always wanted to know some knowledge about the Google plug-in, through the Google plug-in can better realize the Google debugging tools, and then just before the recent need to share, this two weeks to learn and understand the Google plug-in, and then wrote this article, I know and write down some thinking. At the same time, I also want to use Google plug-in to write some small tools, not only learn new things, but also have a certain interest. Of course, because of time reasons, if the author of this piece of understanding is wrong, welcome to correct ~

What is a Google Plugin

Google Plugin, full name Google Browser extension. So what is the Google Chrome Extension, officially explained below

Extensions allow you to add features to Chrome without delving into native code. You can create new extensions for Chrome using the core technologies you are already familiar with in web development (HTML, CSS, and JavaScript).

The students who have doubts will ask why people are still called Google plug-in, which is just like what Lu Xun said: there is no way in the world, and when more people walk, there will be a way. Google Chrome extension originally is not Google plug-in, Google plug-in should be the bottom of the browser things, but too many people, so this article also uses the Google plug-in to collectively refer to Google Chrome extension.

The basic use

The following is a brief introduction of the main components of Google Plug-in. At present, the popular version of Google Plug-in is version 2.0. All the following instructions are based on version 2.0, version 3.0 is easier than version 2.0.

The configuration file

The core file of the Google plugin is the manifest.json (manifest) file. The manifest.json file has the following basic API:

{"name": "Chrome Extension ", "version": "1.0.0"," Manifest_version ": 2, "description": "A litlle chrome extension demo" }Copy the code

It contains the name, version, and related description of the written Google plug-in, where manifest_version represents the manifest file version. Manifest.json is the core part of Google plug-in. The author believes that this file is equivalent to an entry configuration file for the plug-in. The development only needs to configure the corresponding JS file in this file and call the Api provided by Google Browser to achieve the purpose of improving the plug-in.

Basic Usage Api

There are many more apis in the listing file, but here are just a few that I think are important to get a sense of how Google plug-ins are developed.

  • browser_action
{... "browser_action": { "default_icon": { "16": "images/get_started16.png", "32": "Images /get_started32.png"}, "default_title":" Google stroking translation ", "default_popup": "popup.html"},... }Copy the code

Browser_action sets the name of the icon in the upper right corner of the browser. Default_popup allows you to configure a small window that appears when you click the icon, where you can do some temporary things

  • permissions
{... "permissions": [ "activeTab", "storage", "tabs", "contextMenus" ], ... }Copy the code

Permissions can be configured with Google Plugins such as contextMenus, Tabs, and storage.

  • content_scripts
{... "content_scripts": { "matches": ["<all_urls>"], "css": ["content/content_script.css"], "js": ["content/content_script.js"] }, ... }Copy the code

Content-scripts, which is a form of Google plugin that injects scripts to pages (even though it is called Script, it can also include CSS), makes it easy to configure javascript and CSS to a given page

  • background
{... "background" : {" scripts ": [" background. Js]", "persistent" : false},...}Copy the code

Background is a resident page that has the longest life cycle of any type of page in the plug-in. It opens with the browser and closes with the browser, so it usually places global code that needs to be run all the time, run on startup, in the background

I have also drawn a distribution of the scripts mentioned above in the browser

Above, after introducing the basic and important Api of Google Plugin manifest file, interested students can start to write a few simple tools to realize their lofty ambitions and ideals, and sublimate their noble soul. Accordingly, THE author also shares an interesting Google plug-in tool implementation process, through the development of this tool can also deepen the understanding of Google plug-in.

precondition

Because some students do not quite know how to develop Google plug-in, or to say the preconditions. First you need to open the administrative extension and open developer mode. Click the “load decompressed program” button to load the local Google plug-in. If the code is updated during development, you need to refresh the loaded plug-in. Click “close” and then open it again without refreshing the development page.

Google word translation plugin

The most frequently used Google plug-in is the translation tool. For the English words or sentences I don’t understand on the web page, I can directly select them with the mouse and translate them into Chinese easily and quickly. So how does the Google Chrome translation tool work?

thinking

How to do a dash word translation plug-in, the first thing to consider are the following:

  • How to achieve translation effect
  • How do we select the elements we need
  • How do I display the cross word translation panel after selecting the element
  • All browser tabs need to support translation effects

After thinking about the above points, with these doubts, THE author in the following one answer, but also listed some points encountered.

Delimit word translation panel

Regardless of the function of the plugin, write the style of the panel for the translation of the underlined words first, and achieve the following effect

The HTML code is as follows

<span class="close">X</span></header> <main> <div class="source"> <div class="title">英文</div> <div class="content">test</div> </div> <div class="result"> <div class="content">... </div> </div> </main> </div>Copy the code

Once you’ve done the simple styling above, start thinking about how to display the cross word translation panel on the current page of your browser. For Google Chrome, the interaction on a web page is content_scripts, which introduces the JAVASCRIPT or CSS required for the cross word translation panel to generate the current panel

Second, configure content_scripts in the configuration file, introduce JS files, and dynamically generate DOM elements. The general idea is to generate a translation panel by listening to the release of the mouse, add opacity style on top of the generated elements, and use Google’s free translation Api for translation. The code is shown below

// manifest.json { ... "content_scripts": { "matches": ["<all_urls>"], "css": ["content_script.css"], "js": ["content_script.js"] }, "permissions": [ "activeTab" ], ... } // content_script.js class TranslatePanel { createPanel = () => { let wrapper = document.createElement('div') Wrapper. InnerHTML = '<header> Google delimit translation plugin <span class="close">X</span></header> <main> <div class="source"> <div Class ="title"> English </div> <div class="content">test</div> </div> <div class="result"> <div class="title"> Simplified Chinese </div> <div class="content">... </div> </div> </main> ` wrapper.classList.add('translate-panel') wrapper.querySelector('.close').onclick = () => { this.wrapper.classList.remove('show') } document.body.appendChild(wrapper) this.wrapper = wrapper } showPanel = () => { this.wrapper.classList.add('show') } translateSelect = (content) => { const source = this.wrapper.querySelector('.source  .content') const result = this.wrapper.querySelector('.result .content') source.innerHTML = content result.innerHTML = 'In translation... ' fetch(`https://translate.google.cn/translate_a/single?client=at&sl=en&tl=zh-CN&dt=t&q=${content}`) .then(res => res.json()) .then(res => { result.innerHTML = res[0][0][0] }) } locationPanel = (target) => { this.wrapper.style.top = target.y + 'px' this.wrapper.style.left = target.x + 'px' ### } } let panel = new TranslatePanel() panel.createPanel() Window.onmouseup = (target) => {// Get the selected content const Content = window.getSelection().toString().trim() if (! content) return panel.locationPanel({ x: target.pageX, y: target.pageY }) panel.translateSelect(content) panel.showPanel() }Copy the code

In the above process, the author used Google’s free translation excuse, but this interface still has some problems according to the current use, we temporarily put aside. So now, the slide word translation panel has been basically written.

Script communication

Every time a word is selected, it will trigger the word translation function. At this time, there is an urgent need for a switch to control the translation function. This switch can be placed on the popup script. The implementation of the specific style will not be introduced, but mainly look at the HTML structure

The basic effect is as follows

<div class="switch-wrapper"> <div class="switch-desc"> Whether to enable delimit translation </div> <input type="checkbox" class="switch" /> </div>Copy the code

In the meantime, now that we have panels and underline translation panels, let’s think about how to communicate between popup scripts and content_script scripts. First of all, in the popup script, we need to check whether there is a storage state for cross word translation when opening the window, and we need to store it when the state changes, and then send the request under the current TAB.

// popup.js
let switchWrapp = document.querySelector('.switch')

chrome.storage.sync.get(['checked'], (target) => {
    if (target) {
        switchWrapp.checked = target.checked
    }
})

switchWrapp.onclick = (e) => {
    chrome.storage.sync.set({ checked: e.target.checked })

    chrome.tabs.query( {active: true, currentWindow: true }, (tabs) => {
        chrome.tabs.sendMessage(tabs[0].id, { checked: e.target.checked })
    })
}
Copy the code

Chrome.storage in the code above can be used to store data and track data. Storage. Sync allows users to synchronize data between different tabs without storing data in the background. Storage also has a number of apis, such as onChanged, to monitor changes in storage data. I’m not going to go through them. Content_script.js needs to add a listening event after sending the status to enable or disable strobe translation

Content_script.js let checked = false window.onmouseup = (target) => {··· if (! content || ! Checked) return ···} Chrome.storage.sync.get (['checked'], (target) => { if (target) checked = target.checked }) chrome.runtime.onMessage.addListener((target) => { if (target) { checked = target.checked } })Copy the code

In the development process, it is possible to perform this operation on the current TAB, but when multiple tabs are opened, it will appear that the translation can not display the translation panel. After thinking about the above, I should store the checked in this case, and should not put it in the content_script script

Content_script.js let panel = new TranslatePanel() panel.createpanel () window.onmouseup = (target) => {// Get the selected content const content = window.getSelection().toString().trim() if (! content) return window.chrome.storage.sync.get(['checked'], (result) => { if (result.checked) { panel.locationPanel({ x: target.pageX, y: target.pageY }) panel.translateSelect(content) panel.showPanel() } }) } chrome.runtime.onMessage.addListener((target) =>  { if (target.type == 'CHECKED') { chrome.storage.sync.set({ checked: target.checked }) } })Copy the code

The popup script communicates with the content_script script, and the translation plugin can turn the translation function on or off using the popup button. In the same way, other modules can communicate with each other in this way, except that other scripts communicate with content_script by using tabs and looking up the current TAB to send the request.

Right click to the translation page

When turning off delimit translation, you can no longer directly translate the selected content is not very friendly, this time can be right click when the translation menu item. Because this part of the content needs to be there all the time and it needs to be in the background.

/ / backgrond. Js / / when extension first installation, update to the new version or Chrome update to new version produced in Chrome. Runtime. OnInstalled. AddListener (() = > { Chrome. ContextMenus. Create ({" id ":" SELECT_TRANSLATE ", "title" : "% s" translation, "contexts" : ["selection"] }) }) chrome.contextMenus.onClicked.addListener((target) => { if (target.menuItemId == 'SELECT_TRANSLATE')  { chrome.tabs.create({url: `https://translate.google.cn/?sl=en&tl=zh-CN&text=${target.selectionText}&op=translate`}) } })Copy the code

Cross-domain problem

In the development process, some students also see a problem, such as Google this translation Api needs the same origin in order to call the interface normally, and then can only use delimit word translation in The Google translation page, the scene was very awkward…… So, normally speaking, this cross word translation is also very unreasonable. Next, we need to solve this cross-domain problem.

At that time, the author tried to use JSONP, that is, to use embedded scripts to cross domains. However, there were still some problems, mainly because the interface of Google translation does not support callback functions. Meanwhile, I also checked some materials and found that background can be notified in content_script. Background calls Google Translate Api to avoid this situation, mainly because background has very high permissions, almost all Chrome extension APIS can be called, and it can be unlimited cross-domain, that is, cross-domain access to any website without requiring the other party to set CORS. The added code is as follows

// content_script.js translateSelect = (content) => { const source = this.wrapper.querySelector('.source .content') Const result = this. Wrapper. QuerySelector ('. The result. The content ') source. The innerHTML = the content result. The innerHTML = 'translation... ' chrome.runtime.sendMessage({ type: 'QUERY_TRANSLATE', queryContent: content }, (res) => { result.innerHTML = res[0][0][0] }) } // background.js chrome.runtime.onMessage.addListener((request, sender, callBack) => { if (request.type == 'QUERY_TRANSLATE') { fetch(`https://translate.google.cn/translate_a/single?client=at&sl=en&tl=zh-CN&dt=t&q=${request.queryContent}`) .then(res => res.json()) .then(res => { callBack(res) }) return true } })Copy the code

Listening events that send messages in background return true to keep the message channel open with content_script and send requests asynchronously.

Now think about it, if you use the background of the plug-in, you can ask for some excuses across domains. If it is not properly used, it still feels very dangerous. You can get some information from other websites.

Points to be improved

  • Support translation of other languages

    The Google Translate interface has two apis, SL (the language before the text is translated) and TL (the language into which the text needs to be translated), which support the translation of other languages by changing the corresponding values

  • Perfect style, to achieve the first selected icon in translation

    Adding an extra step feels more interactive without having to switch on and off

The code structure

After introducing the React Developer plugin, I originally planned to share another development tool about Google DevTool, which is similar to React Developer Tools. However, due to the lack of time, there are a lot of points involved. At the same time, access to a lot of data for this piece of introduction is shallow, so decided to focus on introduce cross word translation, from the development of the cross word translation can make readers more quickly realize that Google plug-in, some of the Google browser, extrapolate, if for devtool tools plug-in development interested students can also go to look at. In addition, some students may think that the current development efficiency is a little low. At present, The development of Google plug-in can also be developed based on React + ANTD, which can achieve the effect of efficient and fast development of a plug-in.

At the end

When learning the Google plug-in, THE author encountered some problems, such as less documents, official documents are in English and often 404, but fortunately, Google Browser provides a lot of Api, the author also felt a lot of fun when writing the plug-in. This article is still written more easy to understand, if there is something wrong or unclear place, welcome to raise your hand to speak

More and more

  • The official document: developer.chrome.com/docs/extens…
  • React + ANTD scaffolding: github.com/jhen0409/re…
  • Full code: github.com/ting0130/ch…