Chrome扩展程序:在内容脚本中访问localStorage

189

我有一个选项页面,在那里用户可以定义某些选项,并将其保存在localStorage中:options.html

现在,我还有一个内容脚本需要获取在options.html页面中定义的选项,但是当我尝试从内容脚本访问localStorage时,它不返回来自选项页面的值。

我如何让我的内容脚本从localStorage获取值,无论是来自选项页面还是后台页面?


2
相关:https://dev59.com/1XA75IYBdhLWcg3w6Nr8 - Shay Erlichmen
1
相关:https://dev59.com/flLTa4cB1Zd3GeqPWgQI - Jason
1
相关链接:http://stackoverflow.com/questions/39768005/single-data-store-offline-locally-for-both-a-web-site-and-an-extension-in-chrome?noredirect=1#comment66832892_39768005 - super1ha1
4个回答

275

更新 2016:

谷歌浏览器发布了存储 API:https://developer.chrome.com/docs/extensions/reference/storage/

它与其他 Chrome API 一样易于使用,您可以在 Chrome 的任何页面上下文中使用它。

    // Save it using the Chrome extension storage API.
    chrome.storage.sync.set({'foo': 'hello', 'bar': 'hi'}, function() {
      console.log('Settings saved');
    });

    // Read it using the storage API
    chrome.storage.sync.get(['foo', 'bar'], function(items) {
      message('Settings retrieved', items);
    });
要使用它,请确保在清单文件中定义:
    "permissions": [
      "storage"
    ],

有一些方法可以“删除”、“清除”、“获取使用的字节数”,以及一个事件监听器来监听存储变化“onChanged”。

使用本地localStorage(2011年的旧回复

内容脚本在网页的上下文中运行,而不是扩展页面。因此,如果您从内容脚本访问localStorage,它将是该网页的存储,而不是扩展页面的存储。

现在,要让您的内容脚本读取您的扩展存储(您从选项页面设置的存储),您需要使用扩展消息传递

首先,您需要告诉内容脚本向您的扩展发送请求来获取一些数据,而这个数据可以是您的扩展localStorage:

contentscript.js

chrome.runtime.sendMessage({method: "getStatus"}, function(response) {
  console.log(response.status);
});

background.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getStatus")
      sendResponse({status: localStorage['status']});
    else
      sendResponse({}); // snub them.
});
你可以围绕此功能编写API,以获取通用的localStorage数据到你的内容脚本中,或者获取整个localStorage数组。

我希望这能解决你的问题。

为了更加高端和通用...

contentscript.js

chrome.runtime.sendMessage({method: "getLocalStorage", key: "status"}, function(response) {
  console.log(response.data);
});

background.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getLocalStorage")
      sendResponse({data: localStorage[request.key]});
    else
      sendResponse({}); // snub them.
});

1
显然,请求也可以是{method:'getStorage',key:'status'},监听器将响应相应的数据。 - J.C. Inacio
8
背景页和选项页属于同一扩展上下文,因此您不需要使用内容脚本或消息传递。您可以直接从选项页调用 localStorage 或者在选项页中使用 chrome.extension.getBackgroundPage - Mohamed Mansour
1
这很奇怪。我在选项页面设置了一些选项,并在后台页面根据这些选项创建上下文菜单。问题是,如果我从选项页面在localStorage中设置一个变量,它不会立即反映到后台页面(即没有新的上下文菜单),除非我禁用并重新启用扩展程序。你能想到任何原因吗? - Bibhas Debnath
我相信Chrome已经改变了扩展程序的设计,所以应该使用background.js,而不是options,因为options页面只在激活时存在并在关闭时销毁。 - Mohamed Mansour
感谢 @OrangeTux,哇,我写下这个回答已经两年了 :) 我刚刚将其更新到新的 API,谢谢。 - Mohamed Mansour
显示剩余7条评论

53
有时候使用 chrome.storage API 比 localStorage 更好,因为你可以:
  • 在不需要内容脚本和扩展之间传递消息的情况下从内容脚本中存储信息;
  • 将数据作为 JavaScript 对象存储,而不需要将其序列化为 JSON(localStorage 只能存储字符串)。
这里有一个简单的代码演示了如何使用 chrome.storage。内容脚本获取已访问页面的 URL 和时间戳,并将其存储,popup.js 从存储区域获取它。

content_script.js

(function () {
    var visited = window.location.href;
    var time = +new Date();
    chrome.storage.sync.set({'visitedPages':{pageUrl:visited,time:time}}, function () {
        console.log("Just visited",visited)
    });
})();

弹出窗口.js

(function () {
    chrome.storage.onChanged.addListener(function (changes,areaName) {
        console.log("New item in storage",changes.visitedPages.newValue);
    })
})();

"Changes" 这里是一个包含给定键的旧值和新值的对象。 "AreaName" 参数指的是存储区域的名称,可以是 'local'、'sync' 或 'managed'。

记得在 manifest.json 中声明存储权限。

manifest.json

...
"permissions": [
    "storage"
 ],
...

1
onChanged事件已经在changes对象中提供了数据。此外,特别注意onChanged事件的namespace。如果您使用chrome.storage.local.set存储某些内容,则会触发onChanged事件,但是使用chrome.storage.sync.get读取则没有太大意义。 - Rob W
没错,您说得对,我已经编辑了我的答案。显然,在其他情况下您可以使用chrome.storage.sync.get,但在这里它确实是多余的。 - Pawel Miech
1
针对您答案的第5个修订版本:如果未更改visitedPages,则changes.visitedPages将为未定义。在该行中加入if (changes.visitedPages) { ... }即可解决此问题。 - Rob W
如果我在某个auth.js和content_script中设置了Google Auth,那么当我获取用户详细信息时,我应该如何管理这两个文件之间的消息传递? - Sudhir Kaushik
如果我在某个auth.js和content_script中设置了Google Auth,当我获取用户详细信息时,我应该如何管理这两个文件之间的消息传递? - undefined

8

@Jason,全有或全无的事务怎么样? - Pacerier

6
< p >【适用于清单v3】< /p > < p >您可以执行一个从网页返回本地存储项的脚本。该脚本可以从弹出窗口或后台服务工作者中执行。

< p >在manifest.json文件中添加以下行:

< p >"permissions": ["scripting"]


 let [tab] = await chrome.tabs.query({ active: true, currentWindow: true })

 // Execute script in the current tab
  const fromPageLocalStore = await chrome.scripting.executeScript({
    target: { tabId: tabId },
    func: () => {
      return JSON.stringify(localStorage)
    }
  })

  const localStorageItems = JSON.parse(fromPageLocalStore[0].result)

我寻找了几个小时才找到这个解决方案,原来如此简单,谢谢。 - James Pog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接