javascript - 如何从扩展程序检测 Google Chrome 中的页面标题更改?

标签 javascript google-chrome google-chrome-extension

我正在创建一个 Google Chrome 扩展程序,我需要检测页面标题何时更改。页面标题的更改类似于 Twitter:(num) Twitter(请参见下面的屏幕截图) - 当发布新推文时,数字会增加。示例:

enter image description here

我正在尝试检测在我的一个选项卡中加载的 URL 的标题更改,并在出现差异时播放蜂鸣声。此检查将在重复的时间间隔内完成,我认为可以使用 setTimeOut() 函数来完成。

我创建了一个manifest.json,如下所示:

{
  "manifest_version": 2,

  "name": "Detect Page Title Changes",
  "description": "Blah",
  "version": "1.0",

  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "background.html"
  },
  "permissions": [
    "tabs"
  ]
}

但是,我对其余的一无所知。我搜索过文档 1 2 并在类似的 Stack Overflow 线程上尝试了解决方案,例如 this one但我找不到任何适合我要求的东西。

你有什么建议吗?如果可能,请提供一个示例。

最佳答案

与其在评论中争论某种方法更好,不如让我更有建设性并通过显示 particular implementation 来添加答案。我自己共同撰写,并解释了您可能遇到的一些问题代码片段指的是与 Twitter 不同的服务,但目标是相同的。事实上,此代码的目标是报告未读消息的确切数量,因此您的代码片段可能会更简单。

我的方法基于 an answer这里关于SO,而不是轮询驱动(以固定时间间隔检查条件)是事件驱动(通知条件的潜在变化)。

优点包括立即检测到更改(否则直到下一次轮询才会检测到),并且在条件未更改时不会在轮询上浪费资源。诚然,第二个论点在这里几乎不适用,但第一个论点仍然成立。

<小时/>

架构概览:

  1. 将内容脚本插入相关页面。

  2. 分析标题的初始状态,通过sendMessage报告给后台页面。

  3. 注册标题更改事件的处理程序。

  4. 每当事件触发并调用处理程序时,分析标题的新状态,通过 sendMessage 向后台页面报告。

<小时/>

第 1 步已经有一个问题了。正常的内容脚本注入(inject)机制,当在 list 中定义内容脚本时,会在导航到与 URL 匹配的页面时将其注入(inject)到页面中。

"content_scripts": [
  {
    "matches": [
      "*://theoldreader.com/*"
    ],
    "js": ["observer.js"],
    "run_at": "document_idle"
  }
]

这工作得很好,直到您的扩展程序重新加载。当您应用所做的更改时,这可能会在开发中发生,或者在自动更新的部署实例中发生。然后会发生的情况是,内容脚本不会重新注入(inject)现有的打开页面中(直到发生导航,例如重新加载)。因此,如果您依赖基于 list 的注入(inject),您还应该考虑在扩展初始化时将编程注入(inject)到已打开的选项卡中:

function startupInject() {
  chrome.tabs.query(
    {url: "*://theoldreader.com/*"},
    function (tabs) {
      for (var i in tabs) {
        chrome.tabs.executeScript(tabs[i].id, {file: "observer.js"});
      }
    }
  );
}

另一方面,扩展程序重新加载时处于事件状态的内容脚本实例不会终止,而是孤立的:任何 sendMessage 或类似请求都将失败。因此,建议在尝试与父扩展通信时始终检查异常,并在失败时自行终止(通过删除处理程序):

try {
  chrome.runtime.sendMessage({'count' : count});
} catch(e) { // Happens when parent extension is no longer available or was reloaded
  console.warn("Could not communicate with parent extension, deregistering observer");
  observer.disconnect();
}
<小时/>

第 2 步也有一个问题,不过这取决于您正在观看的服务的具体情况。内容脚本范围内的某些页面不会显示未读邮件的数量,但这并不意味着没有新邮件。

在观察网络服务的工作原理后,我得出的结论是,如果标题在没有导航的情况下更改为某些内容,则可以安全地假设新值(如果正确),但对于初始标题“无新项目”应因不可靠而被忽略。

因此,分析代码会考虑是初始读取还是处理更新:

function notify(title, changed) {
  // ...
  var match = /^\((\d+)\)/.exec(title);
  var match_zero = /^The Old Reader$/.exec(title);

  if (match && match[1]) {
    count = match[1];
  } else if (match_zero && changed) {
    count = 0;
  }
  // else, consider that we don't know the count
  //...
}

它是用初始标题调用的,并且在第 2 步中 changed = false

<小时/>

步骤 3 和 4 是“如何监视标题更改”(以事件驱动的方式)的主要答案。

var target = document.querySelector('head > title');

var observer = new window.MutationObserver(
  function(mutations) {
    mutations.forEach(
      function(mutation){
        notify(mutation.target.textContent, true);
      }
    );
  }
);

observer.observe(target, { subtree: true, characterData: true, childList: true });

有关设置 observer.observe 某些选项的具体原因,请参阅 original answer .

请注意,notify 是通过 changed = true 调用的,因此从“(1) The Old Reader”变为“The Old Reader” "没有导航被认为是零未读消息的“真正”更改。

关于javascript - 如何从扩展程序检测 Google Chrome 中的页面标题更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39879733/

相关文章:

javascript - 调试 react 。确定更改了哪个 Prop

css - Chrome : Text blurry when skew back : skew(-10deg) -> skew(10deg)

javascript - 尝试将消息传递到background.js时收到错误:

javascript - 如何获取正在运行 content.js 的选项卡的选项卡 ID?

google-chrome-extension - 如何触发点击按钮

javascript - PouchDB IE11 使用文件 ://

Javascript 操作顺序问题

html - 自动完成 = "new password"不工作, "use password for"下拉列表仍然显示

html - 登录后 Odoo 8 界面未全高显示

javascript - jQuery/JS : How to create a SEO-friendly link