Spotify Chrome Extension: Music Controller | Phase 6
Tags: programming, javascript, webdev, react
Published: 2020-12-24 16:35:34

### <center>Spotify Chrome Extension - Merging the Front-end & Back-end</center>

------------

### <center>This is Phase Six of a multi-phase project where we build a Spotify Chrome Extension powered by ReactJS that allows us to control the user's Spotify session</center>

### <center>Phase One can be found [here](https://dev.to/anobjectisa/spotify-chrome-extension-music-controller-phase-1-iki "here").</center>

------------

#### <center>This tutorial assumes you know how Google Chrome Extensions work. Learn more [here](https://anobjectisa.com/?p=11 "here").</center>

------------

![React-Chrome Spotify Controller](https://user-images.githubusercontent.com/58220766/103039828-ced12000-453f-11eb-9784-329d602f6500.png)

### Like any Chrome Extension, we need to inject the foreground page into the User's browser.

##### We, of course, inject from our **Background.js** script.

```
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    if (changeInfo.status === 'complete' && tab.url.includes('http')) {
        active_tabId = tabId;

        chrome.tabs.executeScript(tabId, { file: './inject_script.js' }, function () {
            chrome.tabs.executeScript(tabId, { file: './foreground.bundle.js' }, function () {
                console.log("INJECTED AND EXECUTED");
            });
        });
    }
});

chrome.tabs.onActivated.addListener(activeInfo => {
    chrome.tabs.get(activeInfo.tabId, function (tab) {
        if (tab.url.includes('http')) active_tabId = activeInfo.tabId;
    });
});
```

#### Now that we've done that, let create GET and SET state functions for our entire App.

##### Staying in our Background.js file, we'll create those two functions...

```
function get_state() {
    return new Promise((resolve, reject) => {
        chrome.storage.local.get('chrome-ext-Spotify-controller', item => {
            if (chrome.runtime.lastError) {
                reject('fail');
            } else {
                const state = item['chrome-ext-Spotify-controller'] ? item['chrome-ext-Spotify-controller'] : "{}";

                resolve(JSON.parse(state));
            }
        });
    });
}

function set_state(_state) {
    return new Promise((resolve, reject) => {
        get_state()
            .then(res => {
                const updated_state = {
                    ...res,
                    ..._state
                }

                chrome.storage.local.set({ 'chrome-ext-Spotify-controller': JSON.stringify(updated_state) }, () => {
                    if (chrome.runtime.lastError) {
                        reject('fail');
                    } else {
                        resolve('success');
                    }
                });
            });
    });
}
```

--------------------

### All that's left to do is pair our Spotify API logic in the Background script to the function calls in our Foreground script.

**We won't go into every function pairing here, we'll show you one.
See the video tutorial for a detailed walk-through.**

In the **Foreground.js** component we have our **start_pause** function message our **Background.js** script.

```
start_pause = () => {
    chrome.runtime.sendMessage({ message: this.state.isPlaying ? 'pause' : 'play', payload: { isPlaying: !this.state.isPlaying } }, response => {
        if (response.message === 'success') {
            this.setState(_state => {
                return {
                    isPlaying: !_state.isPlaying,
                    current_track: response.current_track
                }
            });
        }
    });
}
```

In our **Background.js** script, we catch that message, call the Spotify API, and send back a response to the **Foreground.js** component.

```
...
if (request.message === 'play') {
    player.play()
        .then(res => set_state(request.payload))
        .then(res => player.current())
        .then(res => sendResponse({ message: 'success', current_track: res.current_track }))
        .catch(err => sendResponse({ message: 'fail' }));

    return true;
} else if (request.message === 'pause') {
    player.pause()
        .then(res => set_state(request.payload))
        .then(res => player.current())
        .then(res => sendResponse({ message: 'success', current_track: res.current_track }))
        .catch(err => sendResponse({ message: 'fail' }));

    return true;
...
```

--------------------------

### After merging our Background and Foreground, we handle the Login System.

If you want to see how that's done see the **video tutorial below**.

You can find the **final** source files for this project [here](https://github.com/an-object-is-a/project-1-spotify-controller-phase6 "here").

------------

#### <center>If you want a more in-depth guide, check out my full video tutorial on YouTube, **[An Object Is A](https://www.youtube.com/c/anobjectisa "An Object Is A")**.</center>

### <center>Build a Cyberpunk 2077-inspired Spotify Controller - Phase 6</center>

{% youtube WXlOeeHhvqs %}