热门标签 | 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扩展程序



推荐阅读
  • POJ 2482 星空中的星星:利用线段树与扫描线算法解决
    在《POJ 2482 星空中的星星》问题中,通过运用线段树和扫描线算法,可以高效地解决星星在窗口内的计数问题。该方法不仅能够快速处理大规模数据,还能确保时间复杂度的最优性,适用于各种复杂的星空模拟场景。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 本文详细探讨了使用纯JavaScript开发经典贪吃蛇游戏的技术细节和实现方法。通过具体的代码示例,深入解析了游戏逻辑、动画效果及用户交互的实现过程,为开发者提供了宝贵的参考和实践经验。 ... [详细]
  • 技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告
    技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • 自定义滚动条美化页面内容
    当页面内容超出显示范围时,为了提升用户体验和页面美观,通常会添加滚动条。如果默认的浏览器滚动条无法满足设计需求,我们可以自定义一个符合要求的滚动条。本文将详细介绍自定义滚动条的实现过程。 ... [详细]
  • Ext JS MVC系列一:环境搭建与框架概览
    本文主要介绍了如何在项目中使用Ext JS 4作为前端框架,并详细讲解了Ext JS 4的MVC开发模式。文章将从项目目录结构、相关CSS和JS文件的引用以及MVC框架的整体认识三个方面进行总结。 ... [详细]
  • Framework7:构建跨平台移动应用的高效框架
    Framework7 是一个开源免费的框架,适用于开发混合移动应用(原生与HTML混合)或iOS&Android风格的Web应用。此外,它还可以作为原型开发工具,帮助开发者快速创建应用原型。 ... [详细]
  • 在使用Eclipse进行调试时,如果遇到未解析的断点(unresolved breakpoint)并显示“未加载符号表,请使用‘file’命令加载目标文件以进行调试”的错误提示,这通常是因为调试器未能正确加载符号表。解决此问题的方法是通过GDB的`file`命令手动加载目标文件,以便调试器能够识别和解析断点。具体操作为在GDB命令行中输入 `(gdb) file `。这一步骤确保了调试环境能够正确访问和解析程序中的符号信息,从而实现有效的调试。 ... [详细]
  • 装饰者模式(Decorator):一种灵活的对象结构设计模式
    装饰者模式(Decorator)是一种灵活的对象结构设计模式,旨在为单个对象动态地添加功能,而无需修改原有类的结构。通过封装对象并提供额外的行为,装饰者模式比传统的继承方式更加灵活和可扩展。例如,可以在运行时为特定对象添加边框或滚动条等特性,而不会影响其他对象。这种模式特别适用于需要在不同情况下动态组合功能的场景。 ... [详细]
  • 在处理大规模数据数组时,优化分页组件对于提高页面加载速度和用户体验至关重要。本文探讨了如何通过高效的分页策略,减少数据渲染的负担,提升应用性能。具体方法包括懒加载、虚拟滚动和数据预取等技术,这些技术能够显著降低内存占用和提升响应速度。通过实际案例分析,展示了这些优化措施的有效性和可行性。 ... [详细]
  • 在Eclipse中提升开发效率,推荐使用Google V8插件以增强Node.js的调试体验。安装方法有两种:一是通过Eclipse Marketplace搜索并安装;二是通过“Help”菜单中的“Install New Software”,在名称栏输入“googleV8”。此插件能够显著改善调试过程中的性能和响应速度,提高开发者的生产力。 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 本文详细介绍了如何利用CSS技术对链接下划线进行个性化定制和美化,涵盖了多种实用技巧和方法。通过对CSS属性的灵活运用,可以实现不同风格的下划线效果,提升网页的视觉体验。文中不仅提供了基础的代码示例,还结合实际案例进行了深入解析,帮助读者更好地理解和应用这些技巧。此外,文章还引用了《CSS2.0中文手册》中的相关内容,增加了技术的权威性和实用性。 ... [详细]
  • 本文全面解析了JavaScript中的DOM操作,并提供了详细的实践指南。DOM节点(Node)通常代表一个标签、文本或HTML属性,每个节点都具有一个nodeType属性,用于标识其类型。文章深入探讨了DOM节点的创建、查询、修改和删除等操作,结合实际案例,帮助读者更好地理解和掌握DOM编程技术。 ... [详细]
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社区 版权所有