在WebExtension background.js中运行多个脚本

Run multiple scripts in WebExtension background.js

本文关键字:脚本 运行 WebExtension background js      更新时间:2023-09-26

我正在构建我的第一个Firefox Web扩展,并且我正在使用OAuth集成API。

当用户单击工具栏中的图标时,它会给他们一个身份验证号码,以便进入网页。然后他们这样做,授权我的应用程序,它存储一个访问令牌。

我被卡住的地方是目前我的代码依赖于弹出窗口保持打开从响应API的响应轮询。我假设我需要在后台文件中运行民意调查,但我不确定我将如何做到这一点。

我popup.js

// Set Vars
var successComp = 0;
// Poll to check for authentication
function pollAccessToken(device_code, interval) {
    var request = new XMLHttpRequest();
    request.open('POST', 'https://private-anon-535ecb43fa-trakt.apiary-mock.com/oauth/device/token');
    request.setRequestHeader('Content-Type', 'application/json');
    request.onreadystatechange = function () {
        if (this.readyState === 4) {
            switch (this.status) {
                case 200:
                    // Get Response and put in array
                    var response = JSON.parse(this.responseText);
                    // Save Access Token and Refresh Token to storage
                    chrome.storage.local.set({"access_token": response.access_token, "refresh_token": response.refresh_token});
                    // Set success notification
                    chrome.runtime.sendMessage({"title": "Trakt for IMDb Authentication Success", "content": "Awesome, you've authenticated your Trakt account! Enjoy using Trakt for IMDb."});
                    // Set successComp to 1 so clearTimeout doesn't trigger
                    successComp = 1;
                    break;
                case 400:
                    // Request still pending
                    setTimeout(pollAccessToken.bind(null, device_code).bind(null, interval), interval * 1000);
                    break;
                case 404:
                    // Display Request not found/invalid error
                    chrome.runtime.sendMessage({"title": "Trakt for IMDb Authentication Error", "content": "Whoops, looks like there was an error authenticating your Trakt account. Please try again."});
                    break;
                case 409:
                    // Code already used
                    chrome.runtime.sendMessage({"title": "Trakt for IMDb already approved", "content": "Whoops, looks like you've already approved this code. If you continue to have issues, please try again."});
                    break;
                case 410:
                    // Code Expired
                    chrome.runtime.sendMessage({"title": "Trakt for IMDb Authentication Token Error", "content": "Whoops, looks like your token expired and there was an error authenticating your Trakt account. Please try again"});
                    break;
                case 418:
                    // Code Denied
                    chrome.runtime.sendMessage({"title": "Trakt for IMDb Authentication Denied", "content": "Oh no, it looks like you denied us access to your account! If you didn't mean to do this, please try again."});
                    break;
                case 429:
                    // Slow down polling
                    setTimeout(pollAccessToken.bind(null, device_code).bind(null, interval), interval * 1100);
                    break;
                default:
                    // Request still pending
                    setTimeout(pollAccessToken.bind(null, device_code).bind(null, interval), interval * 1000);
                    break;
            }
        }
    };
    var body = {
        'code': device_code,
        'client_id': APP_KEY,
        'client_secret': APP_SEC
    };
    request.send(JSON.stringify(body));
}
// Get and display authentication
function outputAuth() {
    var request = new XMLHttpRequest();
    request.open('POST', 'https://private-anon-535ecb43fa-trakt.apiary-mock.com/oauth/device/code');
    request.setRequestHeader('Content-Type', 'application/json');
    request.onreadystatechange = function () {
        if (this.readyState === 4) {
            // Get Response and put in array
            var response = JSON.parse(this.responseText);
            // Output authentication data
            document.body.innerHTML = '<section id="traktLogo"><img src="../icons/trakt-logo.png" width="100px" height="100px" alt="Trakt" /></section><h1>Trakt Authentication</h1><h2>Enter the following code into the activation page.</h2><code>' + response.user_code + '</code><a href="' + response.verification_url + '" id="activation" target="_newtab">Activation Page</a>';
            var pollAccess = pollAccessToken(response.device_code, response.interval);
            setTimeout(stopPolling, response.expires_in * 1000);
        }
    };
    var body = {
        'client_id': APP_KEY
    };
    request.send(JSON.stringify(body));
}
// Stop Polling Function
function stopPolling() {
    if (successComp === 0) {
        // Response polling expired
        clearTimeout(pollAccess);
        chrome.runtime.sendMessage({"title": "Trakt for IMDb Authentication Timed Out", "content": "Whoops, looks like you took too long in authenticating your Trakt account. Please try again."});
    }
}
// Check if Access Token Exists
chrome.storage.local.get("access_token", function (result) {
    if (result.access_token && typeof result.access_token !== undefined) {
        // Output Profile Page
        document.body.innerHTML = '<p>Profile Page</p>';
    } else {  
        // Output Authenctication Page
        outputAuth();
    }
});
我background.js

// Display a Notification
function notify(message) {
    chrome.notifications.create({
        "type": "basic",
        "title": message.title,
        "message": message.content,
        "iconUrl": chrome.extension.getURL("icons/icon-256.png")
    });
}
/*
Assign `notify()` as a listener to messages from the content script.
*/
chrome.runtime.onMessage.addListener(notify);

我很高兴把投票代码发送到后台。js文件,我只是不太确定我将如何触发它。这也是非常重要的,我有代码,将停止pollAccessToken函数运行x分钟后,由API文档指定。

完整的源代码可以在Github上预览Trakt for IMDb

轮询API文档可以在Trakt中找到。tv API on Apiary

我想我已经得到了它与以下脚本的工作。如果有人能告诉我为什么下面的东西不能像我想的那样工作,我将非常感激:)

popup.js

// Get and display authentication
function outputAuth() {
    var request = new XMLHttpRequest();
    request.open('POST', 'https://private-anon-535ecb43fa-trakt.apiary-mock.com/oauth/device/code');
    request.setRequestHeader('Content-Type', 'application/json');
    request.onreadystatechange = function () {
        if (this.readyState === 4) {
            // Get Response and put in array
            var response = JSON.parse(this.responseText);
            // Output authentication data
            document.body.innerHTML = '<section id="traktLogo"><img src="../icons/trakt-logo.png" width="100px" height="100px" alt="Trakt" /></section><h1>Trakt Authentication</h1><h2>Enter the following code into the activation page.</h2><code>' + response.user_code + '</code><a href="' + response.verification_url + '" id="activation" target="_newtab">Activation Page</a>';
            chrome.runtime.sendMessage({"type": "pollRequest", "device_code": response.device_code, "interval": response.interval, "expires_in": response.expires_in});
        }
    };
    var body = {
        'client_id': APP_KEY
    };
    request.send(JSON.stringify(body));
}
// Check if Access Token Exists
chrome.storage.local.get("access_token", function (result) {
    if (result.access_token && typeof result.access_token !== undefined) {
        // Output Profile Page
        document.body.innerHTML = '<p>Profile Page</p>';
    } else {  
        // Output Authenctication Page
        outputAuth();
    }
});

background.js

// key.js - Trakt for IMDb by dpDesignz
var APP_KEY = '';
var APP_SEC = '';
// Display a Notification
function notify(message) {
    chrome.notifications.create({
        "type": "basic",
        "title": message.title,
        "message": message.content,
        "iconUrl": chrome.extension.getURL("icons/icon-256.png")
    });
}
// Set Vars
var successComp = 0;
// Poll to check for authentication
function pollAccessToken(device_code, interval) {
    var request = new XMLHttpRequest();
    request.open('POST', 'https://private-anon-535ecb43fa-trakt.apiary-mock.com/oauth/device/token');
    request.setRequestHeader('Content-Type', 'application/json');
    request.onreadystatechange = function () {
        if (this.readyState === 4) {
            switch (this.status) {
                case 200:
                    // Get Response and put in array
                    var response = JSON.parse(this.responseText);
                    // Save Access Token and Refresh Token to storage
                    chrome.storage.local.set({"access_token": response.access_token, "refresh_token": response.refresh_token});
                    // Set success notification
                    notify({"title": "Trakt for IMDb Authentication Success", "content": "Awesome, you've authenticated your Trakt account! Enjoy using Trakt for IMDb."});
                    // Set successComp to 1 so clearTimeout doesn't trigger
                    successComp = 1;
                    break;
                case 400:
                    // Request still pending
                    setTimeout(pollAccessToken.bind(null, device_code).bind(null, interval), interval * 1000);
                    break;
                case 404:
                    // Display Request not found/invalid error
                    notify({"title": "Trakt for IMDb Authentication Error", "content": "Whoops, looks like there was an error authenticating your Trakt account. Please try again."});
                    break;
                case 409:
                    // Code already used
                    notify({"title": "Trakt for IMDb already approved", "content": "Whoops, looks like you've already approved this code. If you continue to have issues, please try again."});
                    break;
                case 410:
                    // Code Expired
                    notify({"title": "Trakt for IMDb Authentication Token Error", "content": "Whoops, looks like your token expired and there was an error authenticating your Trakt account. Please try again"});
                    break;
                case 418:
                    // Code Denied
                    notify({"title": "Trakt for IMDb Authentication Denied", "content": "Oh no, it looks like you denied us access to your account! If you didn't mean to do this, please try again."});
                    break;
                case 429:
                    // Slow down polling
                    setTimeout(pollAccessToken.bind(null, device_code).bind(null, interval), interval * 1100);
                    break;
                default:
                    // Request still pending
                    setTimeout(pollAccessToken.bind(null, device_code).bind(null, interval), interval * 1000);
                    break;
            }
        }
    };
    var body = {
        'code': device_code,
        'client_id': APP_KEY,
        'client_secret': APP_SEC
    };
    request.send(JSON.stringify(body));
}
// Stop Polling Function
function stopPolling() {
    if (successComp === 0) {
        // Response polling expired
        clearTimeout(pollAccess);
        notify({"title": "Trakt for IMDb Authentication Timed Out", "content": "Whoops, looks like you took too long in authenticating your Trakt account. Please try again."});
    }
}
// Assign functions based on type
chrome.runtime.onMessage.addListener(function(data) {
    switch (data.type) {
        case "notification":
            notify(data);
            break;
        case "pollRequest":
            var pollAccess = pollAccessToken(data.device_code, data.interval);
            setTimeout(stopPolling, data.expires_in * 1000);
            break;
    }
});