如何从扩展程序中检测Google Chrome中的页面标题更改? [英] How to detect page title change in Google Chrome from an extension?

查看:115
本文介绍了如何从扩展程序中检测Google Chrome中的页面标题更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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





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



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

  { 
manifest_version:2,

name:检测页面标题变化,
description:Blah,
version: 1.0,

browser_action:{
default_icon:icon.png,
default_popup:background.html
},
权限:[
标签
]
}

然而,我对其余的事情一无所知。我搜索了 1 2 code> ,并尝试了类似堆栈溢出线程的解决方案,例如这一个我但找不到符合我要求的任何内容。



你有什么建议吗?请包括一个例子,如果可能的话。

解决方案

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



我的方法基于SO的答案,而不是轮询驱动(以固定的时间间隔检查条件)是事件驱动的(通知可能的条件变化)。

优点包括即时检测到变化(否则在下次调查之前不会被检测到),并且在条件没有改变时不浪费轮询资源。无可否认,第二个参数在这里几乎不适用,但第一个参数仍然存在。






架构一览:


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

  2. 分析标题的初始状态,并通过 sendMessage 报告到后台页面。 注册一个处理程序title change事件。
  3. 每当事件触发并调用处理程序时,分析标题的新状态,通过 sendMessage







1有一个问题。普通内容脚本注入机制在内容脚本在清单中定义时,会在导航到与URL匹配的页面时将其注入到页面中。

 content_scripts:[
{
matches:[
*://theoldreader.com/*

js:[observer.js],
run_at:document_idle
}
]

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

  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 或类似的请求都会失败。因此,建议在尝试与父扩展进行通信时始终检查异常,如果失败,则自行终止(通过删除处理程序):

 尝试{
chrome.runtime.sendMessage({'count':count});
} catch(e){//当父扩展不再可用或重载时发生
console.warn(无法与父扩展进行通信,注销观察者);
observer.disconnect();






第二步也有虽然这取决于您正在观看的服务的具体情况。内容脚本范围内的某些页面不会显示未读项目的数量,但并不表示没有新消息。



观察网络服务工作,我的结论是,如果标题改变为没有导航的东西,可以安全地假设新值如果正确,但是对于初始标题不应该有新项目应该被忽略为不可靠。



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

 函数notify标题,已更改){
// ...
var match = /^\((\d+)\)/.exec(title);
var match_zero = / ^ Old Reader $ /。exec(title);

if(match&& match [1]){
count = match [1];
} else if(match_zero&& changed){
count = 0;
}
//否则,请考虑我们不知道计数
// ...
}

用初始标题和改变 = false 步骤3和步骤2。 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 已设置,请参阅原始答案



请注意, notify 会在改变 = true 时调用,所以从(1)旧阅读器到旧阅读器没有导航,被认为是真正的改变,以零未读的消息。


I'm creating a Google Chrome extension and I need to detect when a page's title changes. The page's title is changed like in Twitter: (num) Twitter (see the screenshot below) - when a new tweet is posted, the number increments. Example:

I'm trying to detect the title changes of a URL that's loaded in one of my tabs and play a beep sound whenever there's a difference. This check is to be done in a repeated interval and I think that can be accomplished using setTimeOut() function.

I've created a manifest.json as follows:

{
  "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"
  ]
}

However, I'm clueless about the rest. I've searched through the docs 1 2 and tried the solutions on similar Stack Overflow threads such as this one I but couldn't find anything that suits my requirements.

Do you have any suggestions? Please include an example, if possible.

解决方案

Instead of arguing in comments that a certain approach is better, let me be more constructive and add an answer by showing a particular implementation I co-wrote myself, and explain some gotchas you may run into. Code snippets refer to a service different from Twitter, but the goal was the same. In fact, this code's goal is to report the exact number of unread messages, so yours might be simpler.

My approach is based on an answer here on SO, and instead of being polling-driven (check condition at fixed intervals) is event-driven (be notified of potential changes in condition).

Advantages include immediate detection of a change (which would otherwise not be detected until the next poll) and not wasting resources on polls while the condition does not change. Admittedly, the second argument hardly applies here, but the first one still stands.


Architecture at a glance:

  1. Inject a content script into the page in question.

  2. Analyze initial state of the title, report to background page via sendMessage.

  3. Register a handler for a title change event.

  4. Whenever the event fires and the handler is called, analyze the new state of the title, report to background page via sendMessage.


Already step 1 has a gotcha to it. Normal content script injection mechanism, when the content script is defined in the manifest, will inject it in pages upon navigation to a page that matches the URL.

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

This works pretty well, until your extension is reloaded. This can happen in development as you're applying changes you've made, or in deployed instances as it is auto-updated. What happens then is that content scripts are not re-injected in existing open pages (until navigation happens, like a reload). Therefore, if you rely on manifest-based injection, you should also consider including programmatic injection into already-open tabs when extension initializes:

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

On the other end, content script instances that were active at the time of extension reload are not terminated, but are orphaned: any sendMessage or similar request will fail. It is, therefore, recommended to always check for exceptions when trying to communicate with the parent extension, and self-terminate (by removing handlers) if it fails:

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();
}


Step 2 also has a gotcha to it, though it depends on the specifics of the service you're watching. Some pages inside the scope of the content script will not show the number of unread items, but it does not mean that there are no new messages.

After observing how the web service works, I concluded that if the title changes to something without navigation, it's safe to assume the new value if correct, but for the initial title "no new items" should be ignored as unreliable.

So, the analysis code accounts for whether it's the initial reading or handling an update:

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
  //...
}

It is called with the initial title and changed = false in step 2.


Steps 3 & 4 are the main answer to "how to watch for title changes" (in an event-driven way).

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 });

For specifics as to why certain options of observer.observe are set, see the original answer.

Note that notify is called with changed = true, so going from "(1) The Old Reader" to "The Old Reader" without navigation is considered to be a "true" change to zero unread messages.

这篇关于如何从扩展程序中检测Google Chrome中的页面标题更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆