Retrieve a random URL from the bookmarks in Chrome and open it in a new tab

Currently, I am in the process of developing a unique chrome extension that randomly loads URLs from your bookmarks bar whenever a new tab is opened.

In my app.js file, you will find the following code snippet:

var bookmarksArray = [];

// This function traverses the bookmarks tree and saves URLs in the bookmarksArray
function process_bookmark(bookmarks) {
  for (var i =0; i < bookmarks.length; i++) {
    var bookmark = bookmarks[i];
    if (bookmark.url) {
        bookmarksArray.push(bookmark.url);
    }

    if (bookmark.children) {
        process_bookmark(bookmark.children);
    }
  }
}

// Processes all user bookmarks
 function createbookmarksArray(){
    chrome.bookmarks.getTree(process_bookmark);
}

// Retrieves a random bookmark URL from the array and loads it
 function getBookmark(){
    window.location.href = bookmarksArray[Math.floor(Math.random()*bookmarksArray.length)];
}

// All necessary functions to be called upon Page Load
function onLoadFunctions(){
    createbookmarksArray();
    getBookmark();
 }

// Function executed on page load
 document.addEventListener("DOMContentLoaded", function(event) {
onLoadFunctions();
});

Additionally, my manifest.json requests permissions for newtab and bookmarks. The newtab is linked to index.html which then calls ap.js.

Upon running this extension, an error message "Your file was not found. It may have been moved or deleted.ERR_FILE_NOT_FOUND" appears.

Interestingly, running

window.location.href = bookmarksArray[Math.floor(Math.random()*bookmarksArray.length)];
in the console works flawlessly.

Could it be that I am incorrectly calling the functions?

Answer №1

When working with Chrome API functions, callbacks are essential. For instance, calling createbookmarksArray initiates the process of fetching bookmarks but immediately calls getBookmark with an empty array.

chrome.bookmarks.getTree operates asynchronously - triggering the process when called and executing the callback after completion. Inline code takes precedence in JavaScript, ensuring that all current functions finish before the callback fires, regardless of how quickly Chrome retrieves bookmarks.

To circumvent this issue, utilizing async and await is recommended. While not directly supported by the Chrome API, you can integrate a library like chrome-extension-async to incorporate these features.

Below is an example of how your code can be structured:

// Function executed on page load
document.addEventListener("DOMContentLoaded", async event => {
    try {
        // Using await ensures JS continues after the callback fires
        const bookmarkTree = await chrome.bookmarks.getTree();

        // Flatten the collection and select a random bookmark
        const bookmarksArray = process_bookmark(bookmarkTree);
        const randomIndex = Math.floor(Math.random()*bookmarksArray.length);
        const randomBookmark = bookmarksArray[randomIndex];

        // Open a new tab with the selected URL
        await chrome.tabs.create({ url: randomBookmark });
    }
    catch(err){
         // Error handling for the callbacks goes here
    }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A guide on using AJAX to update an HTML table and other data simultaneously from within a single script

I'm reaching out for your assistance. In my javascript code, I currently make two separate AJAX calls - one to create a map using openstreetmap and another to refresh an HTML table. Both PHP pages involved in these calls utilize the same MySQL reques ...

Is there a way for me to connect to my Firebase Realtime Database using my Firebase Cloud Function?

My current challenge involves retrieving the list of users in my database when a specific field is updated. I aim to modify the scores of players based on the structure outlined below: The Realtime Database Schema: { "users": { &quo ...

JavaScript code must be tailored to reference a JS file based on the specific environment, whether it be Production, Development, or staging

I need to determine which .js file to refer based on the URL of Prod, Dev, and QA environments. For Production URLs (domain.com and www.domain.com), I should refer to prod.js file. For Dev and QA URLs (dev.domain.com and staging.com), I should refer to s ...

Tips for storing STL geometry in a cache outside of the STLLoader event listener

I am attempting to read and cache a geometry from an STL file using Three.js STLLoader. I am utilizing an event loop callback to retrieve the data (similar to the STLLoader example). My intention is to store it in an external variable called "cgeom". Howev ...

What is the best way to empty input, select, and textarea fields after performing a clone operation

I am currently working on creating a form to display items and need a fresh text field when the user clicks the ADD button. function addNewItem() { //ADD ROW AND CLONE var table = document.getElementById('tbl'); var tbody = document.create ...

One of the challenges faced with using AngularJS is that it can often

I have a piece of code that is functioning correctly: angular.module('foo', []).config( function($locationProvider) { $locationProvider.html5Mode(true); } ); However, when the code is minified, it gets compressed and looks like this: a ...

Having trouble sending the welcome message?

Upon someone's entry, an error message Cannot read properties of undefined (reading 'send') is popping up in the console. I have ensured that all the necessary intents are selected for a proper welcome system or message display. Even when I ...

Is there a way to encircle text around a three-dimensional sphere?

Currently seeking a solution to wrap text around a sphere in either Babylon or Three.js. I am willing to explore different JavaScript technologies for this task. ...

Exploring the conundrum of dropdown links in Bootstrap4

I have a little issue with my dropdown menu. The "Documents" link is not redirecting to the correct page. <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="./docs/index.html" data-target="./docs/index.html" target="_bla ...

What is the best method to eliminate an invalid element from the DOM?

Below is the code snippet showing the xpaths where the value of $value can be found. We have noticed an abnormal tag td1 in the given URL (visible in the image) which is missing a closing tag. It seems like the developers intentionally placed it there, as ...

The dot operator cannot be used to access Json objects

Utilizing a4j jsFunction to transmit data to the server and receive JSON in return <a4j:jsFunction name="submitData" action="#{imageRetriveBean.saveData}" data="#{responseNodesPathsBean}" oncomplete="processData(event.data)"> <a4j:param name= ...

When attempting to start a new React Native project using npx, I encountered an error stating "react-native: command not found"

After running 'npx react-native init MyProject' for the first time, it prompted that react-native would be downloaded, but I mistakenly terminated the process. Now, when I try again, it shows an error saying 'react-native: command not found& ...

Concealing UI elements within the primary stack during navigation to a nested stack in React navigation

Is there a way to hide the user interface in my main stack when I switch to the nested drawer stack? I am currently facing an issue where the header from my main stack appears above the header in my nested stack when I navigate to a screen using: navigat ...

Assign an identifier to the bootbox textarea

To initiate the bootbox with a textarea, use the following code snippet: bootbox.prompt({ title: "This is the title", inputType: 'textarea', placeholder: 'Feedback', callback: function (result) { console.log(result); } }); You ...

How can you simply hide Bootstrap alerts instead of deleting them when closing?

I am utilizing the power of Bootstrap 4 Alerts to showcase error messages, just like in their demo: <div class="alert alert-warning alert-dismissible fade show" role="alert"> <strong>Holy guacamole!</strong> You shou ...

Ways to remove or modify all characters in a string except for the first one

Greetings everyone! I am seeking some advice on regex as I continue to learn more about it. My query is this: In JavaScript, how can I replace or delete all characters except for the first one in a string? For example, let's say I have the string "ap ...

Looking to decrease Cumulative Layout Shift (CLS) on the NextJS website for enhanced performance

I have chosen to use NextJS with Mantine for my website development. Utilizing createStyles, I have added custom stylings and incorporated various mantine components into the design. After deploying the site on Vercel, I discovered that all performance me ...

Unable to back out of side navigation

My side navigation menu is giving me some trouble. It opens up just fine when I click the button, but it won't close back up when I click it again. The button is supposed to toggle between opening and closing the side navigation. I've looked at ...

ng-html-bind for a label with a checkbox

Currently, I have a view that uses the standard bootstrap layout for checkboxes. In this layout, the input is located within the label tag. <div class="checkbox"> <label ng-bind-html="vm.trustedHtml"> <input type="checkbox" ng- ...

Using a gogocartojs map in your JavaScript project

I have created a new project and am attempting to integrate gogocartoJs into it. While the project itself is functioning properly, I am experiencing issues with the map not displaying as expected. Although I have followed the provided guides, there seems ...