如何编写google浏览器插件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何编写google浏览器插件相关的知识,希望对你有一定的参考价值。

  方法如下:

  1、创建一个单独的文件夹,比如说为百度贴吧开发一个插件,就叫TiebaAddion。之后在这个文件夹里创建一个名字为“manifest.json”的文件,在里面写上如下的样子。

  
"name": "TiebaAddin",
"version": "1.0",
"description": "An addin for Tieba.",
"browser_action": "default_icon": "icon.png",
"permissions": [http://*/*]
  

  2、现在需要找一个图标,放在这个目录下,名字叫icon.png,当然,这个名字只要和上面的配置文件里default_icon的属性一致就好。

  3、现在只要点击Chrome工具条的菜单按钮选择里面的工具(Tools)>> 扩展(Extensions)就好。菜单按钮如右图。

  4、选择开发者模式,选择加载未打包的插件,然后,选择第一步中的那个文件夹即可。

  5、在地址栏的右侧出现了图标,但是点击图标却什么也没做,因为我们还什么代码没有写。现在在那个目录下,建立一个html文件,并且名字为popup.html,同时在配置文件里“browser_action”下加上一条:"popup": "popup.html"。

  示范:


"name": "TiebaAddin",
"version": "1.0",
"description": "An addin for Tieba.",
"browser_action": "default_icon": "icon.png","popup": "popup.html",
"permissions": [http://*/*]

      此处注意,每一对大括号里的最后一项后面都没有逗号,其余的每项之间必须用逗号间隔!哪怕是browser_action这样复合的项目,在他的大括号后也要有逗号。

  6、在Popup.html里写上一些html代码,比如简单的输出HelloWorld也好,这个Popup.html和普通的html文件按没有任何差别。

  7、这就是基本的插件制作方法。

参考技术A 首先启谷歌浏览器发者工具浏览器右角选项点击拉菜单选工具——发者工具快捷键CTRL+shift+I

打发者工具浏览器现调试面板左侧网页HTML调试查看右侧CSS代码调试些JS资源折叠起

谷歌浏览器调试处实现元素定位鼠标放指定元素浏览器面视图加灰突显示所应元素

右侧CSS代码调试错工具仅查看应标签代码同实更改代码值并浏览器视图显现变化

CSS调试盒模型形象视图右侧折叠面板打实现margin,padding等定位计算本回答被提问者采纳

使用CSharp编写Google Protobuf插件

什么是 Google Protocol Buffer?

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 多种语言的API,包括C++、 C# 、GO、 JAVA、 PYTHON

如果你并不了解Protobuf能做什么,建议结合google搜索关键字,看一下入门级别的文章,或者看一下官方文档中的,或者中文的 .官方的文档中有各种语言相关的示例,可以结合代码看一下实际的用法。

很多人说为什么不用json(或者xml), 答案很简单,Protobuf更小,更简洁,而且序列化和反序列化更快!

谷歌最新开源的框架就是默认使用Protobuf作为数据传输格式和服务描述文件。对于gRpc 就不做详细介绍了,有兴趣的可以看一下官网。

言归正传,在实际使用Protobuf过程中,我发现Protobuf不但可以编写描述消息(Message)的内容,同时可以表述其他方法(类似Rpc中的方法),主要是gRpc中看到的。同时在Protobuf 代码生成工具的包中,有一个这样的目录,一致以来都没搞明白是做什么用的,如下图:

在目录中存在大量已经定义好的proto文件,其实这些文件是Protobuf的描述文件,类似元数据。用本身的语法描述本身,同时通过这些文件生成对应的语言的元数据类等代码,比如在C#版本的Google.Protobuf中就能看到上述描述文件生成的类,如下图所示

而这些描述文件中最重要的文件 就是descriptor.proto 这个文件,这个文件是整个proto语法的描述类,描述了实际Protobuf各层次语法的结构,来一起看一下这个文件的一些代码, 上面这个代码描述了proto文件定义的语法定义,如前面两个字段意思是可选的name,可选的package字段,中间是描述可多个message_type(Message),service(Rpc Service) ,enum_type(枚举)等定义,然后一层层分解下去。 基本上就可以了解Protobuf语法的全貌和扩展点了

message FileDescriptorProto {
  optional string name = 1;       // file name, relative to root of source tree
  optional string package = 2;    // e.g. "foo", "foo.bar", etc.

  // Names of files imported by this file.
  repeated string dependency = 3;  // Indexes of the public imported files in the dependency list above.
  repeated int32 public_dependency = 10;  // Indexes of the weak imported files in the dependency list.
  // For Google-internal migration only. Do not use.
  repeated int32 weak_dependency = 11;  // All top-level definitions in this file.
  repeated DescriptorProto message_type = 4;
  repeated EnumDescriptorProto enum_type = 5;
  repeated ServiceDescriptorProto service = 6;
  repeated FieldDescriptorProto extension = 7;

  optional FileOptions options = 8;  // This field contains optional information about the original source code.
  // You may safely remove this entire field without harming runtime
  // functionality of the descriptors -- the information is needed only by
  // development tools.
  optional SourceCodeInfo source_code_info = 9;  // The syntax of the proto file.
  // The supported values are "proto2" and "proto3".
  optional string syntax = 12;
}

同时在compiler目录下 还有一个plugin的目录,其中的plugin.proto文件很耐人寻味,先来看下这个文件中的内容

syntax = "proto3";package google.protobuf.compiler;option java_package = "com.google.protobuf.compiler";option java_outer_classname = "PluginProtos";option csharp_namespace = "Google.Protobuf.Compiler";option go_package = "plugin_go";import "google/protobuf/descriptor.proto";message CodeGeneratorRequest {  repeated string file_to_generate = 1;  string parameter = 2;  repeated FileDescriptorProto proto_file = 15;
}message CodeGeneratorResponse {  
  string error = 1; 
  message File {    
    string name = 1;    string insertion_point = 2;    string content = 15;
  }  repeated File file = 15;
}

删除了非必要的注释后,我们可以看到这个文件里面其实只定义了两个类型,一个是代码生成请求,一个是代码生成响应,而在CodeGeneratorRequest中又有之前我们在descriptor.proto中看到的FileDescriptorProto 这个类的信息,用大腿都可以想到这里应该就是代码生成插件获取元数据的入口了,那么怎么做呢?

从gRpc 的代码生成示例中 我们可以看到 其实Protobuf是支持自定义生成代码插件的,如下所示:

%PROTOC% -I../../protos --csharp_out Greeter  ../../protos/helloworld.proto --grpc_out Greeter --plugin=protoc-gen-grpc=%PLUGIN%

按理我们可以实现自己的插件来生成我们需要的任意格式,包括各种代码,甚至是文档。但是这个资料却非常少,几乎没有多少相关的文章,后来终于找到一片关于plugin的文章 ,大家有兴趣的可以看看,不过文章的重点是这句:

The core part is the interface code to read a request from the stdin, traverse the AST and write the response on the stdout.

原来插件的接口代码其实是从标准输入中读取流,然后再把你要生成的内容输出到标准输出中。这些终于知道怎么用了。。

撩起袖子开始干,通过protoc命令行生成plugin.proto的代码

protoc-I../../protos --csharp_out test  ../../protos/plugin.proto

新建一个控制台项目,把代码copy 到项目中,并在Program.cs代码中添加测试的代码

using Google.Protobuf;using Google.Protobuf.Compiler;using System;namespace DotBPE.ProtobufPlugin{    class Program
    {        static void Main(string[] args)        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;            var response = new CodeGeneratorResponse();            try
            {
                CodeGeneratorRequest request;                using (var inStream = Console.OpenStandardInput())
                {
                    request = CodeGeneratorRequest.Parser.ParseFrom(inStream);
                }
                ParseCode(request, response);
            }            catch (Exception e)
            {
                response.Error += e.ToString();
            }            using (var output = Console.OpenStandardOutput())
            {
                response.WriteTo(output);
                output.Flush();

            }
        }        private static void ParseCode(CodeGeneratorRequest request, CodeGeneratorResponse response)        {
           DotbpeGen.Generate(request,response);
        }
    }
}

哈哈 开始编译,然而编译不通过!,坑爹啊! 原来C#版本中 Google.Protobuf已经生成好的类 都是internal访问权限,不能从外部引用。。。但是Google.Protobuf是开源的。。而且我需要用的类 我也可以通过protoc命令自己生成到同一个项目中,或者设置成public访问权限。。方便起见,我直接copy了Google.Protobuf的源码到我们的项目中,这次再次编译 ,代码就完美运行了,接下来的工作 不过是填充DotbpeGen.Generate 的代码了,这不过是体力活。

至于CodeGeneratorRequest和CodeGeneratorResponse 到底有什么方法,其实看proto文件就能知道。然后我们编写一个proto文件测试以下

//benchmark.proto
syntax = "proto3";
package dotbpe; option csharp_namespace = "DotBPE.IntegrationTesting";

import public "dotbpe_option.proto"; option optimize_for = SPEED;//Benchmark测试服务service BenchmarkTest{    option (service_id)= 50000 ;//设定服务ID    //测试发送Echo消息    rpc Echo (BenchmarkMessage) returns (BenchmarkMessage){        option (message_id)= 1 ;//设定消息ID    };//Echo尾部的注释    // 测试发送退出消息    rpc Quit (Void) returns (Void){        option (message_id)= 10000 ;//设定消息ID    };//Quit尾部的注释}//我是void消息message Void { }//我是BenchmarkMessage消息message BenchmarkMessage {  //字段前的注释  string field1 = 1; //字段后的注释  //字段前的注释 多行  //字段前的字数多行  int32 field2 = 2; //字段后的注释  /**  * 字段前注释特殊格式  * 字段前注释特殊格式多行  */  int32 field3 = 3;  
string field4 = 4;  repeated fixed64 field5 = 5;
 string field9 = 9;
  string field18 = 18;
   bool field80 = 80;
  bool field81 = 81;
  int32 field280 = 280 ;
  int32 field6 = 6;
  int64 field22 = 22 ;
  bool field59 = 59 ;
  string field7 = 7;
  int32 field16 = 16 ;
  int32 field130 = 130 ;  
  bool field12 = 12 ;
  bool field17 = 17;
  bool field13 = 13;
  bool field14 = 14;
  int32 field104 = 104 ;
 int32 field100 = 100 ;
  int32 field101 = 101 ;
   string field102 = 102;
  string field103 = 103;
  int32 field29 = 29 ;
  bool field30 = 30 ;
  int32 field60 = 60 ;
  int32 field271 = 271 ;
  int32 field272 = 272;  
  int32 field150 = 150;  
   int32 field23 = 23;  
  bool field24 = 24;  
  int32 field25 = 25 ;
  bool field78 = 78 ;  
  int32 field67 = 67;
  int32 field68 = 68 ;
  int32 field128 = 128 ;
  string field129 = 129 ;
  int32 field131 = 131 ; }
// dotbpe_option.proto// [START declaration]syntax = "proto3";package dotbpe;// [END declaration]// [START csharp_declaration]option csharp_namespace = "DotBPE.ProtoBuf";// [END csharp_declaration]import "google/protobuf/descriptor.proto";//扩展服务extend google.protobuf.ServiceOptions {  int32 service_id = 51001;  bool disable_generic_service_client = 51003; //是否生成客户端代码
  bool disable_generic_service_server = 51004; //是否生成服务端代码}
extend google.protobuf.MethodOptions {  int32 message_id = 51002;
}

extend google.protobuf.FileOptions {  bool disable_generic_services_client = 51003; //是否生成客户端代码
  bool disable_generic_services_server = 51004; //是否生成服务端代码
  bool generic_markdown_doc = 51005; //是否生成文档}

上面的dotbpe_option.proto 我们proto文件进行了自定义的扩展,添加一些自己需要的额外信息,其实所有扩展都是对descriptor.proto中消息的扩展。

然后我们通过命令来生成一下,这里有个特殊的约定,一定要注意当我们设置

protoc-gen-dotbpe=../../tool/ampplugin/dotbpe_amp.exe 插件的名称protoc-gen-dotbpe时,那么输出的目录一定要写成--dotbpe_out ,两个名字一点要匹配哦

set -excd $(dirname $0)/../../test/IntegrationTesting/

PROTOC=protoc
PLUGIN=protoc-gen-dotbpe=../../tool/ampplugin/dotbpe_amp.exe
IntegrationTesting_DIR=./DotBPE.IntegrationTesting/$PROTOC  -I=./protos --csharp_out=$IntegrationTesting_DIR --dotbpe_out=$IntegrationTesting_DIR \
    ./protos/benchmark.proto  --plugin=$PLUGIN

差不多就结束了,相关的代码可以在 查看到,这是我最近在写的一个C#的rpc框架,现在完成了基本的功能,还需要进一步完善,有机会再介绍把。

descriptor.proto信息挖掘

我们注意到在descriptor.proto文件中包含有这样的一个message: SourceCodeInfo, 这个消息体里有如下字段

 optional string leading_comments = 3; optional string trailing_comments = 4;
 repeated string leading_detached_comments = 6;

这是非常有意思的定义,意思是可以在运行时获取到proto文件中的注释。这可以帮助我们生成 文档或者代码注释,但是读取逻辑比较复杂,其内部有一个通过Path和Span来定位元素的逻辑。因为在实际的情况中,一般都是要获取Service和Message上的注释,那么就来专门讨论一下如何获取这两个类型的注释吧。

下面是 SourceCodeInfo.Location 中我们需要用到Path示例

 * [4, m] - Message的注释
 * [4, m, 2, f] - Message 中 字段(field)的注释
 * [6, s] - Service的注释
 * [6, s, 2, r] - ServiceRpc方法的注释

where:

  • m - proto文件中Message的索引(就是第几个定义的Message), 从0开始

  • f - Message中Field字段的索引(就是第几个字段), 从0开始

  • s - proto文件中Service的索引, 从0开始

  • r - Service中Rpc方法的索引, 从0开始

like this:

// [4, 0] 就是这里的注释 message MyMessage {  // [4, 0, 2, 0] 在这里
  int32 field1 = 1; // [4, 0, 2, 0] 也在这里}// [4, 0] 就是这里的注释 // [6, 0] 在这里!service MyService {  // [6, 0, 2, 0] 在这里!
  rpc (MyMessage) returns (MyMessage);
}

想要了解全部内容可以去看下descriptor.proto中的注释内容 吧


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

以上是关于如何编写google浏览器插件的主要内容,如果未能解决你的问题,请参考以下文章

如何更新google chrome浏览器插件

google浏览器怎么安装本地插件

如何在谷歌浏览器增加插件

3分钟搞定chrome google浏览器和google账号,让您的电脑和手机书签同步

Google Chrome插件分享

Chrome浏览器如何查看插件列表