热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

chrome扩展程序_Chrome扩展程序:弥合各层之间的差距

chrome扩展程序构建Chrome扩展程序很容易,而且从很多方面来说都是如此。该文档确实做得很好,并且包含大量示例。另外,检查已安装的任

chrome扩展程序

构建Chrome扩展程序很容易,而且从很多方面来说都是如此。 该文档确实做得很好,并且包含大量示例。 另外,检查已安装的任何组件以查看其背后的魔力很容易。 另一个很大的优点是,它全都是Javascript,CSS和HTML,并带有Chrome API的额外奖励,可让您额外获得一点点魔术。

最近,我不得不为我的公司开发一个工具栏,该工具栏必须阅读当前查看的页面,显示一些SEO信息,进行一些AJAX调用等。 并不是很困难,但是我确实发现了一个没有得到充分记录的问题(如果有的话)。

在继续进行之前,如果您对Chrome扩展程序的开发不完全了解,建议您阅读本概述 。 您将了解有关架构多层之间的复杂性的更多信息。

问题

我决定通过在每个网页中注入iframe来加载扩展程序的UI元素(如工具栏和其他弹出窗口)。 考虑到这一点,在多个iframe ,当前DOM,Chrome后台Javascript文件和Chrome提供的其他层之间进行通信并不是一件容易的事。

实际上,问题出在使用iframe上 。 我必须通过JSON对象从Background层向任何iframe发送大量数据,反之亦然。 由于跨域限制,无法通过页面中插入的内容脚本来操纵iframe

例如,当前查看的页面URL是

http://www.example.com

并且注入的iframe URL是

chrome-extensions:// uniqueidmadeoutoflotsandlotsofletters

两者之间的通信是不可能的,因为跨域通信是一个很大的问题。

那么为什么要使用iframe?

好吧, iframe是(当前)隔离大量Javascript,CSS和HTML的唯一方法,而不受当前网页样式和行为的影响。

另外,我很固执,以为可能存在一种以优雅的方式在所有层之间进行通信的方法。 即使我在Google或StackOverflow上找不到答案。

有什么解决办法?

使用Chrome API方法chrome.tabs.sendMessage从“背景”层发送消息时,该消息将发送到所有帧,而不仅仅是发送了ContentScript的消息。

我不知道为什么我没有想到这一点!

由于它的ContentScript内喷射的内部框架 ,而且能获得到Chrome API。

因此, iframe可以使用默认的DOM方法window.parent.postMessage与其父ContentScript进行对话,并通过chrome.extension.sendRequest与Background层进行对话,并且还可以使用chrome.extension.onMessage来监听Background层消息。 addListener方法

如何实现?

这个想法很简单:我创建了一组接待员 ,负责处理从一层到另一层的所有消息传输。

当前,这是我设置各层角色的方式:

背景(请参阅background.js)

可以从ContentScript接收消息,然后将它们重定向到适当的iframe或处理消息。

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

原价$ 11.95 您的完全免费

可以将消息发送到所有框架(ContentScript和iframe )。

ContentScript(请参阅inject.js)

可以同时从Background层和iframe接收消息。

当来自iframe时 (通过默认的window.postMessage方法),它将消息重定向到Background(如果指定)。 如果未指定,它将处理该消息。

只能将消息发送到后台。

iframe(请参阅iframe.js)

可以从唯一的Background层接收消息,然后检查它是否适合他,然后处理该消息。

可以使用window.parent.postMessage将消息发送到ContentScript。

换句话说:

–背景与ContentScript和iframe对话,但仅收听ContentScript。

– ContentScript侦听Background和iframe ,但仅侦听Background。

iframe与ContentScript对话并收听背景。

旁注:我知道Background也可以侦听iframe消息,但是在我的示例中,由于没有必要,因此我跳过了这个概念。

区分iframe

每个iframe都有一个唯一的ID(在下面的示例中称为View ),因此很容易将消息重定向到特定的iframe 。 一种简单的方法是在加载iframe时在URL中添加一个属性,如下所示:

chrome.extension.getURL('html/iframe/comment.html?view=comment’);

讯息设定

传递的消息是包含两个属性的简单对象:

- 信息

–数据

每层(背景,ContentScript和IFrame)都有一个tell方法,该方法发送带有两个属性的消息。

tell(‘tell-something’, {attribute1:’a’, attribute2:’b’});

iframe发送消息时,当前iframe 视图ID也会作为data中属性发送

tell(‘tell-parent-something’, {source:’comment’});

当需要将消息发送到特定的iframe时 ,将在数据中添加带有正确视图IDview属性。

tell(‘tell-to-an-iframe’, {
view:’comment’,
title:’hello world!’
});

如果需要将邮件发送到所有iframe ,则可以使用“ *”通配符。

tell(‘tell-to-all-iframes’, {view:’*’, title:’foo bar’});

如果未指定视图,则应由ContentScript / Background处理消息。

现在,这个例子(最后)!

我为喜欢我称为iHeart的页面创建了一个简单的扩展名(您可以在github上找到源代码)。

例

这是一个简单的按钮,在屏幕左侧有一个心形。 单击后,用户可以添加评论并保存。 保存的页面将在扩展弹出按钮中列出:

心形按钮

坚韧的细节

每层都有自己的告诉监听方法:

背景

_this.tell = function (message, data){
var data = data || {};
chrome.tabs.getSelected(null, function (tab){
if (!tab) return;
chrome.tabs.sendMessage(tab.id, {
message   : message,
data : data
});
});
};

倾听

function onPostMessage (request, sender, sendResponse){
if (!request.message) return;
if (request.data.view){
_this.tell(request.message, request.data);
return;
}
processMessage(request);
};

内容脚本

function tell (message, data){
var data = data || {};
// send a message to "background.js"
chrome.extension.sendRequest({
message : message,
data : data
});
};

倾听

// messages coming from iframes and the current webpage
function dom_onMessage (event){
if (!event.data.message) return;
// tell another iframe a message
if (event.data.view){
tell(event.data);
}else{
processMessage(event.data);
}
};
// messages coming from "background.js"
function background_onMessage (request, sender, sendResponse){
if (request.data.view) return;
processMessage(request);
};

iframe

_this.tell = function (message, data){
var data = data || {};
data.source = _view;
window.parent.postMessage({
message   : message,
data : data
}, '*');
};

倾听

function background_onMessage (request, sender, sendResponse){
// make sure the message was for this view (you can use the "*" wildcard to target all views)
if (
!request.message ||
!request.data.view ||
(request.data.view != _view && request.data.view != '*')
) return;
// call the listener callback
if (_listener) _listener(request);
};

通信过程非常简单。 当您访问网页并看到所看到的内容时(它可以是任何东西,这是您想要的,我不会判断),然后单击iHeart按钮。 然后,该按钮指示打开评论iframe。

js / iframe / heart.js

function heart_onClick (event){
$('.heart').addClass('active');
_iframe.tell('heart-clicked');
};

然后,它在ContentScript中处理消息并打开注释弹出窗口。

js / inspect.js

function processMessage (request){
if (!request.message) return;
switch (request.message){
case 'iframe-loaded':
message_onIframeLoaded(request.data);
break;
case 'heart-clicked':
message_onHeartClicked(request.data);
break;
case 'save-iheart':
message_onSaved(request.data);
break;
}
};
...
function message_onHeartClicked (data){
var comment = getView('comment');
comment.iframe.show();
tell('open-comment', {
view:'comment',
url:window.location.href,
title:document.title
});
};

出现注释弹出窗口,并在注释框下方显示当前网页标题。

js / iframe / comment.js

function onMessage (request){
switch (request.message){
case 'open-comment':
message_onOpenComment(request.data);
break;
case 'website-is-hearted':
message_onIsHearted(request.data);
break;
}
};
...
function message_onOpenComment (data){
$('.page-title').html(data.title);
};

按下保存按钮后,注释iframe会将信息发送回ContentScript。

js / iframe / comment.js

function save_onClick (event){
var comment = $('#comment').val() || '';
_iframe.tell('save-iheart', {
comment   : comment
});
};

ContentScript隐藏注释iframe,并告诉Background保存整个内容。

js / inject.js

function message_onSaved (data){
var comment = getView('comment');
comment.iframe.hide();
tell('save-iheart', {
url:window.location.href,
title:document.title,
comment:data.comment
});
};

最后,Background通过将网站保存为数组来最终确定所有细节。

js / background.js

function onPostMessage (request, sender, sendResponse){
if (!request.message) return;
if (request.data.view){
_this.tell(request.message, request.data);
return;
}
switch (request.message){
case 'save-iheart':
message_onSaved(request.data);
break;
case 'all-iframes-loaded':
message_allIframesLoaded(request.data);
break;
}
};

function message_onSaved (data){
_websites.push({
url           : data.url,
title         : data.title,
comment       : data.comment
});
};

……接待员做了他们的工作

就是这样。 那是我解决多种类型的层之间的通信问题的解决方案,这并不难……

现在,如果我可以轻松解决个人关系中的沟通问题,那就太好了,谢谢:P

通过处理数据验证,将喜欢的网页保存在数据库中,动态调整iframe内容的大小,为扩展添加一些动画以使其使用更加有趣,可以进一步处理该示例。 所有这些都很棒,并且已经可以实现,但这超出了本文的范围。

翻译自: https://www.sitepoint.com/chrome-extensions-bridging-the-gap-between-layers/

chrome扩展程序



推荐阅读
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • Python自动化测试入门:Selenium环境搭建
    本文详细介绍如何在Python环境中安装和配置Selenium,包括开发工具PyCharm的安装、Python环境的设置以及Selenium包的安装方法。此外,还提供了编写和运行第一个自动化测试脚本的步骤。 ... [详细]
  • 本文探讨了2019年前端技术的发展趋势,包括工具化、配置化和泛前端化等方面,并提供了详细的学习路线和职业规划建议。 ... [详细]
  • 理解文档对象模型(DOM)
    本文介绍了文档对象模型(DOM)的基本概念,包括其作为HTML文档的节点树结构,以及如何通过JavaScript操作DOM来实现网页的动态交互。 ... [详细]
  • EasyMock实战指南
    本文介绍了如何使用EasyMock进行单元测试,特别是当测试对象的合作者依赖于外部资源或尚未实现时。通过具体的示例,展示了EasyMock在模拟对象行为方面的强大功能。 ... [详细]
  • 本文深入探讨了JavaScript中实现继承的四种常见方法,包括原型链继承、构造函数继承、组合继承和寄生组合继承。对于正在学习或从事Web前端开发的技术人员来说,理解这些继承模式对于提高代码质量和维护性至关重要。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 本文介绍如何通过Windows批处理脚本定期检查并重启Java应用程序,确保其持续稳定运行。脚本每30分钟检查一次,并在需要时重启Java程序。同时,它会将任务结果发送到Redis。 ... [详细]
  • 本文详细介绍了浏览器的同源策略及其重要性,并探讨了多种实现跨域访问的方法。同源策略是浏览器的一项核心安全机制,确保不同源的客户端脚本无法在未经授权的情况下读取或修改其他来源的资源。例如,a.com下的JavaScript代码通过AJAX请求获取b.com的数据将被阻止。 ... [详细]
  • 配置PHPStudy环境并使用DVWA进行Web安全测试
    本文详细介绍了如何在PHPStudy环境下配置DVWA( Damn Vulnerable Web Application ),并利用该平台进行SQL注入和XSS攻击的练习。通过此过程,读者可以熟悉常见的Web漏洞及其利用方法。 ... [详细]
  • 一个登陆界面
    预览截图html部分123456789101112用户登入1314邮箱名称邮箱为空15密码密码为空16登 ... [详细]
  • 本文探讨了如何通过WebBrowser控件在用户点击输入框时自动显示图片验证码。该过程可能涉及JavaScript事件的触发与响应。 ... [详细]
  • 深入解析ES6至ES8的新特性与应用
    本文详细介绍了自2015年发布的ECMAScript 6.0(简称ES6)以来,JavaScript语言的多项重要更新,旨在帮助开发者更好地理解和利用这些新特性进行复杂应用的开发。 ... [详细]
  • ServletContext接口在Java Web开发中扮演着重要角色,它提供了一种方式来获取关于整个Web应用程序的信息。通过ServletContext,开发者可以访问初始化参数、共享数据以及应用资源。 ... [详细]
  • 2015款Chromebook Pixel评测:高端Chrome OS笔记本体验
    在笔记本电脑领域,Chromebook Pixel凭借其精致的铝合金外壳、细腻的显示屏和舒适的键盘,成为了外观设计的佼佼者。然而,尽管外观出众,它是否值得购买仍需考量。 ... [详细]
author-avatar
RAL-1314921
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有