Chrome Plugin Development – Automated Scripting (3)
Import/Export Scripts
Using sheet. Js js-xlsX library can be very convenient to implement import and export functions.
- Export function
In order to facilitate the recording of different personnel can share the script to achieve this function, but also for the later batch import script. The exported file format is as follows:
Multiple custom fields can be set in the script. For convenience and not conflict with fixed fields, try to use Chinese names.
Custom field
Only in theset-input-value
Event to be set toSetting field Key
ExportScript () {// create a workBook let workBook = xlsx.utils.book_new () // create a workBook let workBook = xlsx.utils.book_new () // create a workBook let workBook = xlsx.utils.book_new ( => {// Create sheet object let sheetData = [] let headers = json.parse (json.stringify (fixedHeader)) // Extract the column that defines the field name in the eventList input event item.eventList .filter(event => event.type === 'set-input-value' && event.key && ! headers.includes(event.key)) .forEach(event => { item[event.key] = event.value headers.unshift(event.key) }) let caseRow = {... item, eventList: JSON.stringify(item.eventList) } if (Array.isArray(item.responseConfig)) { caseRow.responseConfig = JSON.stringify(item.responseConfig) } sheetData.push(caseRow) let sheet = XLSX.utils.json_to_sheet(sheetData, {header: Xlsx.utils.book_append_sheet (workBook, sheet, item.name)}); // openDownloadDialog(workbookBlob, 'automation script.xlsx ')}Copy the code
- The import function
Scripts may need to be executed repeatedly in some scenarios. If you do not import them in batches, you need to modify them each timeCustom field
If you have a lot of Settings it can be very difficult to change. We can edit it in an XLSX file and import it directly, like this
Devtool after import:
Parsing XLSX code
importScript (file) { readWorkbookFromLocalFile(file, wb => { /** * workBook => caseList:[] * 1. First loop sheets to know how many scripts there are * 2. Then loop lines in each sheet to know how many use cases there are in each script * 3. Let caseList = [] wb.sheetnames. forEach(sheetName => {let xlsxData = XLSX.utils.sheet_to_json(wb.Sheets[sheetName]) let allKeyList = getHeaderKeyList(wb.Sheets[sheetName]) let customKeyList = allKeyList.filter(key => ! fixedHeader.includes(key)) let baseCaseDetail = {} let baseEventList = [] xlsxData.forEach((data, If (index === 0) {baseCaseDetail = {name: data.name, urlPath: data.urlPath, width: data.width, height: data.height } if (data.responseConfig && data.responseConfig.length > 5) { baseCaseDetail.responseConfig = JSON.parse(data.responseConfig) } try { baseEventList = JSON.parse(data.eventList) || [] } catch (e) { Console. error(' failed to parse eventList ', ForEach (event => {if (event.type === 'set-input-value' &&) {if (event.type === 'set-input-value' &&) {if (event.type === 'set-input-value' && customKeyList.includes(event.key)) { event.value = data[event.key] } eventList.push(event) }) caseList.push({ ... baseCaseDetail, name: baseCaseDetail.name + '-' + index, eventList: JSON.parse(JSON.stringify(eventList)) }) }) }) this.$store.commit('setCaseList', caseList) this.importFlag = true }) return false }Copy the code
Single script – run different variables multiple times
Usage scenario: each website form automatically input submission, the above import function has included this function
A script that calls a third-party web site
The biggest function of this optimization is this, which can have a lot of space for imagination. Since our company is engaged in human resources outsourcing, the handling personnel always need to perform frequent operations such as entry, transfer, sealing and unsealing of the operators of the government social security website. So I want to do this function to save staff’s workload and improve efficiency.
Step 1 Configurationmanifest.json
The externally_connectable field defines sites that can use the Chrome.* API directly. Some wildcard configurations are not supported, so the domain name needs to be precise.
"externally_connectable": {
"matches": ["http://localhost:63342/*"]
}
Copy the code
The second step in the web page informs the third party website which script to execute
Here we need to know how to notify the third party website. First, the third party website needs to open devTool before we can execute the script.
You can then use the Chrome.* API to send messages to background.js from the configuration page
<! DOCTYPE HTML > < HTML lang="en"> <head> <meta charset="UTF-8"> <title> < span > tabId < / span > < input id = "tabId" value = "759" / > < / div > < div > < span > script name < / span > < input id = "name" value = "nuggets search" / > < / div > <div> <span> <input ID ="key" value=" ha ha "/> </div> <button ID ="button-1"> <span> <span> <pre ID ="response"></pre> </div> <script SRC ="autoScript/js/jquery-1.8.3.js"></script> <script> $('#button-1').on('click', sendMessage) function sendMessage () { let editorExtensionId = 'odfckenjjgjokihccfabfoecjclggmka' let tabId = $('#tabId')[0].value let name = $('#name')[0].value let key = $('#key')[0].value chrome.runtime.sendMessage( EditorExtensionId, {tabId: tabId, data: {type: 'run-case', name: name, customKey: {' search keyword ': key}}}, (response) => { $('#response').text(JSON.stringify(response, null, 2)) console.log(response.success) } ) } </script> </body> </html>Copy the code
The third step, background.js, distributes the request
This part is relatively simple and does not use the long link postMessage because it cannot be called back, so it is not very convenient to notify the result of the original web request.
/ / to monitor externally_connectable configuration of normal web messages sent chrome. Runtime. OnMessageExternal. AddListener (function (request, the sender, SendResponse) {if (request.tabid in connections) {// Do not send messages using long connections because callback cannot be set // connections[request.tabId].postMessage(request.data) chrome.runtime.sendMessage(request, Response => {sendResponse(response)}) return true} else {sendResponse({error: 'onMessageExternal Tab not found in connection list.'}) } })Copy the code
Step 4 Devtool of a third-party web page listens for message execution and returns
Main. Vue / * * * long connection without sendResponse callback, so use this way callback * / chrome. Runtime. OnMessage. AddListener ((MSG, sender, sendResponse) => { let message = msg.data console.log('devtool chrome.runtime.onMessage', msg) if (+msg.tabId === +chrome.devtools.inspectedWindow.tabId && message) { switch (message.type) { case 'run-case': / / 1. Let index = this.caselist.findIndex (item => item.name === message.name) if (index < 0) {return} let newCase = JSON.parse(JSON.stringify(this.caseList[index])) newCase.eventList = newCase.eventList.map(event => { if (event.type === 'set-input-value' && event.key in message.customKey) { event.value = message.customKey[event.key] } return event }) Vue.set(this.caseList, index, newCase) this.$EventBus.$emit('run-case', {index, SendResponse}) // Send to the actual executing page return true}}})Copy the code
home.vue
this.$EventBus.$on('run-case', async ({index, sendResponse}) => {
await this.runCase(index)
sendResponse(this.result[this.caseList[index].name])
})
Copy the code
At this point, we are ready to call the scripts that have been recorded on other pages on our own page.
Complete demo
Import/Export demo
Invoke third-party site scripts to demonstrate