Chrome 浏览器插件之监控网页地址

浏览器插件开发手册:http://open.chrome.360.cn/extension_dev/overview.html
浏览器插件demo,请先参考博客:https://www.cnblogs.com/liuxianan/p/chrome-plugin-develop.html
注意事项,由于js和C++的差异性,导致踩了不少坑:

1.js如果提及默认值,请填写null。
坑:chrome.tabs.getAllInWindow(integer windowId, function callback)
windowId  默认为当前窗口 然后给了一个连接值:chrome.windows.WINDOW_ID_NONE,此时发现获取不到数据。如果参数给null就对了

2.js函数执行顺序是异步的,并不会等待,所以需要使用回调,返回值不一定是正确的。如下通过函数返回值判断标签是否存在的方式是错误的:
错误方式:
function isExistTab()
{
	//block1
	var bExist = false;
	chrome.tabs.getAllInWindow(null, function(tabs)
	{
		//block2
		for ( var i = 0; i <tabs.length; i++)
		{
			url = tabs[i].url;
			if(url.indexOf("pan.bitqiu.com") != -1)
			{
				bexist = true;
				break;
			}
		}
	});
	//block3
	return bExist ;
}

调试你会发现,代码执行顺序是block1=》block3=》block2 ,并不是顺序执行

3.js中的try catch 只会抓当前代码块的异常,并不会捕获代码块里面的函数的异常
function test()
{
	try
	{
		....
		....
		//这段function代码的异常不会被捕获
		function()
		{
			try{}
			catch(e){}
		}
	}
	catch(e)
	{
	}
}

首先我们需要学习参考手册,了解基本的插件包格式和对象接口。监控浏览器网页地址可以参考浏览器插件demo学习里面的使用方法。

开发思考?
  1. 如何需要监控浏览器请求发生变化?
  2. 如何打开标签页,判断标签页是否存在?

问题1:如何需要监控浏览器请求发生变化?
答:首先监控浏览器请求那么生命周期必须和浏览器共存,才能在整体上监控浏览器请求变化。
那么首先可以排除popup里面处理js,所以我们把目标转移到content.js 和 background.js, 但是根据手册我们:

下面是content scipt可以做的一些事情范例:

从页面中找到没有写成超链接形式的url,并将它们转成超链接。
放大页面字体使文字更清晰
找到并处理DOM中的microformat
当然,content scripts也有一些限制,它们不能做的事情包括 :

不能使用除了chrome.extension之外的chrome.* 的接口
不能访问它所在扩展中定义的函数和变量
不能访问web页面或其它content script中定义的函数和变量
不能做cross-site XMLHttpRequests
这些限制其实并不像看上去那么糟糕。Content scripts 可以使用messages机制与它所在的扩展通信,来间接使用chrome.*接口,或访问扩展数据。Content scripts还可以通过共享的DOM来与web页面通信。更多功能参见执行环境。

所以我们在content.js里面没有办法处理和标签页相关的事物。但是可以使用messages机制和其他扩展通讯。message 需要json格式字符串

document.addEventListener('DOMContentLoaded', function()
{
	try
	{
		//alert(JSON.stringify(document));
		//按照匹配规则匹配
		//if(location.href == 'https://www.baidu.com/')
		//发送消息,有backgrand处理
		chrome.runtime.sendMessage({greeting:location.href}, function(response) {
		});
	}
	catch(e)
	{
		alert(e);
	}
	
});

问题1:如何打开标签页?
答:通过问题1我们可以知道如果处理messge的话,最好的方式就是在background.js里面处理message,因为background.js可以很轻松的和标签页交互,并且处理标签页的事务。

// 监听来自content-script的消息


chrome.runtime.onMessage.addListener(function(request, sender, sendResponse)
{
	//{greeting:url}
	try
	{
		var url = request.greeting;
		//url.match()
		isExistTab(bExist =>{
			if(bExist)
			{
				//alert(url);
			}
			else
			{
				//如果不存在打开新的标签页
				openUrlNewTab("https://pan.bitqiu.com/");
			}
		});
	}
	catch(e)
	{
		alert(e);
	}
	
	sendResponse('ans:ok');
});

// 获取当前选项卡ID
function getCurrentTabId(callback)
{
	chrome.tabs.query({active: true, currentWindow: true}, function(tabs)
	{
		if(callback) callback(tabs.length ? tabs[0].id: null);
	});
}

// 当前标签打开某个链接
function openUrlCurrentTab(url)
{
	getCurrentTabId(tabId => {
		chrome.tabs.update(tabId, {url: url});
	})
}

// 新标签打开某个链接
function openUrlNewTab(url)
{
	chrome.tabs.create({url: url});
}

//判断某个标签页是否存在
function isExistTab(callback)
{
	chrome.tabs.getAllInWindow(null, function(tabs)
	{
		bexist = false;
		for ( var i = 0; i <tabs.length; i++)
		{
			url = tabs[i].url;
			if(url.indexOf("pan.bitqiu.com") != -1)
			{
				bexist = true;
				break;
			}
		}
		
		if(callback) callback(bexist)
	});
}

现在就是配置插件manifest.json

{
  "manifest_version": 2,
  
  "name": "watch_url_redirect",
  
  "description": "watch url address if is match role and open a new tab ",
  
  "version": "1.0.2",
  
  "icons":
	{
		"16": "img/icon.png",
		"48": "img/icon.png",
		"128": "img/icon.png"
	},
  
  "background":
	{
		"scripts": ["js/background.js"]
	},
	
  "browser_action": 
	{
		"default_icon": "img/icon.png",
		"default_title": "stwatch",
		"default_popup": "popup.html"
	},
	
	// 需要直接注入页面的JS
	"content_scripts": 
	[
		{
			// "<all_urls>" 表示匹配所有地址
			"matches": ["<all_urls>"],
			// 多个JS按顺序注入
			"js": ["js/content-script.js"],
			// 代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle
			"run_at": "document_start"
		}
	],
	
	// 权限申请
	"permissions":
	[
		"contextMenus", // 右键菜单
		"tabs", // 标签
		"notifications", // 通知
		"webRequest", // web请求
		"webRequestBlocking", // 阻塞式web请求
		"storage", // 插件本地存储
		"http://*/*", // 可以通过executeScript或者insertCSS访问的网站
		"https://*/*" // 可以通过executeScript或者insertCSS访问的网站
	]
	
}

此时整个插件完成请求监控。

思考:
其实在写background.js的时候我发现事实我们可以监控:chrome.webRequest.onBeforeRequest.addListener,但是不知道为什么这个接口没有被触发,所以使用了message机制来实现。等后面有时间研究在来解决这个问题.

猜你喜欢

转载自blog.csdn.net/CAir2/article/details/83143656