zoukankan      html  css  js  c++  java
  • chromium如何新增extension API以及添加内部扩展

      写chromium扩展、写webui,还有一点便是如何增加extension API,下边所描述涉及两种添加extension api的方法,第一种较为麻烦,但有利于完整理解。全文参考chromium官方文档
    一、通过json文件添加扩展API
    1、增加导出接口权限限制:chrome/common/extensions/api/_permission_features.json。api的名称为“myapi”,如果加上"location": "component"表示只有内部程序可以使用该api,这样子外界插件使用就会出现提示:“ 'myapi' is not allowed for specified install location.”
      "myapi": {
        "channel": "stable",
        "extension_types": ["extension", "packaged_app","platform_app","hosted_app"]
      },
    2、创建myapi.json文件,注意到文件名要以unix的方式命名,文件里的namespace值要相对应。文件名为“src\chrome\common\extensions\api\myapi.json”,内容如下:
    [{
        "namespace": "myapi",
        "functions": [
        {
            "name": "helloWorld",
            "type": "function",
            "description": "Hello world by cswuyg",
            "parameters": [{
                "name": "data",
                "type": "string",
                "description": "data is hello world by cswuyg"
            },
            {
                "name": "callback",
                "type": "function",
                "parameters": [{
                    "name": "result",
                    "type": "string",
                    "description": "result of hello world by cswuyg."
                }]
            }]
        }]
    }]
    3、添加myapi.json到chrome/common/extensions/api/api.gyp,因为我用sln编译的,所以还需要自己手动把myapi.json添加到api.sln。代码片段:
     'variables': {  
          ......
         'management.json',
         'myapi.json',    
         ......

    api.sln编译通过之后,产生的C++接口文件在src\build\Debug\obj\global_intermediate\chrome\common\extensions\api下。

    4、添加myapi.json文件扩展资源定义chrome/common/extensions_api_resources.grd文件。定一个ID值IDR_EXTENSION_API_JSON_MYAPI。代码片段
             ......
            <include name="IDR_EXTENSION_API_JSON_METRICSPRIVATE" file="extensions\api\metrics_private.json" type="BINDATA" />
            <include name="IDR_EXTENSION_API_JSON_MYAPI" file="extensions\api\myapi.json" type="BINDATA" />    
            ......
    5、在chrome/common/extensions/api/extension_api.cc的ExtensionAPI::InitDefaultConfiguration函数中通过IDR_EXTENSION_API_JSON_MYAPI ID值加载myapi.json文件。
    void ExtensionAPI::InitDefaultConfiguration() {
           ...... 
          RegisterSchema("myapi", ReadFromResource(
          IDR_EXTENSION_API_JSON_MYAPI));
          ......
    }

    6、在src\chrome\browser\extensions\api\myapi文件夹下完成扩展的C++响应。

    //myapi_api.h
    #pragma once
    #include "chrome/browser/extensions/extension_function.h" namespace extensions { class HelloWorldFunction : public AsyncExtensionFunction{ public: HelloWorldFunction(); //ExtensionFunction: virtual bool RunImpl() OVERRIDE; protected: virtual ~HelloWorldFunction(){}; private: DECLARE_EXTENSION_FUNCTION_NAME("myapi.helloWorld") }; }
    //myapi_api.cpp
    #include "myapi_api.h"
    #include "chrome/common/extensions/api/myapi.h"
    
    namespace extensions{
        namespace myapi = api::myapi;
        HelloWorldFunction::HelloWorldFunction() {}
    
        bool HelloWorldFunction::RunImpl() 
        {
            scoped_ptr<::extensions::myapi::HelloWorld::Params> params(
                ::extensions::myapi::HelloWorld::Params::Create(*args_));
            results_ = myapi::HelloWorld::Results::Create(params->data + "helloWorldResult!!");
            SendResponse(true);
            return true;
        }
    
    }
    把增加的文件,添加到src/chrome/chrome_browser_extensions.gypi文件下,下次用runhooks的时候sln里内容就不会丢失修改。
    7、在chrome/browser/extensions/extension_function_registry.cc下的ExtensionFunctionRegistry::ResetFunctions()函数中注册扩展函数的响应。
    void ExtensionFunctionRegistry::ResetFunctions() {
    #if defined(ENABLE_EXTENSIONS)
    ......
      RegisterFunction<extensions::HelloWorldFunction>();
    ......
    #endif  // defined(ENABLE_EXTENSIONS)
    }
    8、在src\chrome\common\extensions\permissions\api_permission.cc的RegisterAllPermissions函数中添加新扩展api类型的permission。这里的字符串跟扩展的manifest.json里的permissions键的值、*.json接口脚本namespace值相对应。
     { APIPermission::Kmyapi, "myapi", kFlagNone,
          IDS_EXTENSION_PROMPT_WARNING_MYAPI,
          PermissionMessage::kmyapi }, 
     
    到这里就可以实现一个导出接口了,步骤略微繁琐,这是不推荐的遗留方式,下边介绍一种简洁的、推荐的方式。
     
    二、通过IDL文件添加扩展API
    1、增加导出接口权限限制:chrome/common/extensions/api/_permission_features.json。api的名称为“myIdl”。
      "myIdl": {
        "channel": "stable",
        "extension_types": ["extension", "packaged_app","platform_app","hosted_app"]
      },
    2、创建my_idl.idl文件,把它加入到api.gyp 中,使用runhooks重新生成解决方案,或者修改api.sln工程里的api_rules.mk文件的属性。
    my_idl.idl文件:
    [permissions=myIdl]
    namespace myIdl {
      callback HelloWorld2Callback = void (DOMString result);
      interface Functions {
        static void HelloWorld2(DOMString input, HelloWorld2Callback callback);
      };
    };

    api.gyp:

              'media_galleries.idl',
              'media_galleries_private.idl',
              'my_idl.idl',
        编译之后产生my_idl.h、my_idl.cpp文件
    3、 在src\chrome\common\extensions\permissions\api_permission.cc的RegisterAllPermissions函数中添加新扩展api类型的permission。这里的字符串跟扩展的manifest.json里的permissions键的值相对应,跟idl文件里的namespace值对应。
     { APIPermission::KmyIdl, "myIdl", kFlagNone,
          IDS_EXTENSION_PROMPT_WARNING_MYAPI,
          PermissionMessage::kmyIdl },

    4、添加实现文件在\src\chrome\browser\extensions\api\下,需要注意DECLARE_EXTENSION_FUNCTION_NAME定义的函数名要跟idl里定义的接口名一样,否则会在output中提示不存在该函数。而类名,则要跟自动生成的src\build\Debug\obj\global_intermediate\chrome\common\extensions\api\generated_api.h里注册的名称一致。

    my_idl.h文件:

    #pragma once
    
    #include "chrome/browser/extensions/extension_function.h"
    
    namespace extensions {
        class MyIdlHelloWorld2Function : public AsyncExtensionFunction{
        public:
            MyIdlHelloWorld2Function();
            //ExtensionFunction:
            virtual bool RunImpl() OVERRIDE;
        protected:
            virtual ~MyIdlHelloWorld2Function(){};
    
        private:
            DECLARE_EXTENSION_FUNCTION_NAME("myIdl.HelloWorld2")
        };
    }

    my_idl.cc文件:

    #include "my_idl_api.h"
    #include "chrome/common/extensions/api/my_idl.h"
    
    namespace extensions{
        namespace myIdl = api::my_idl;
        MyIdlHelloWorld2Function::MyIdlHelloWorld2Function() {}
    
        bool MyIdlHelloWorld2Function::RunImpl() 
        {
            scoped_ptr<::extensions::myIdl::HelloWorld2::Params> params(
                ::extensions::myIdl::HelloWorld2::Params::Create(*args_));
            results_ = myIdl::HelloWorld2::Results::Create(params->input + " result by cswuyg");
            SendResponse(true);
            return true;
        }
    }

       到这里就可以了,步骤明显比legacy方式简单多了。  

    三、实现一个内置扩展
        如果需要做一个内部的扩展功能,但是又不希望这个扩展是可选的,也就是说这是浏览器自带的一个默认扩展, 就像chrome://bookmarks,该怎么做呢?
    1、创建扩展的web资源文件,在src\chrome\browser\resources\myapi文件夹下,其中manifest.json文件的“key”的来源:通过载入一个自定义的crx插件然后在chromium的appdata下找到该插件的key,该key可能被用于计算extension-id,如果扩展无法调用接口,有可能是key不对,在src\base\base64.cc的Base64Decode函数处做检查。
    manifest.json:
    {
        "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi4h7GFx0NvfD3EhvKNf7bAp2/U+0Be92WDRgkkOG8l+73weIDb7/UpZ831JSFxnjtOoKj7PLTYk//tYd3ZYhIdnZfPap6M6s0v8nzibCkvqCbsChg7EbuJ6Cf3l4upU+0QTPHYKswcDBkMg6oNrRj3vhWeKUEBPktBu99/S2MKwIDAQAB",
        "name": "myapi_cswuyg",
        "version": "1.0",
        "manifest_version": 2,
        "description": "myapi",
        "permissions": ["myapi"],
        "chrome_url_overrides": {
            "cswuyg": "popup.html"
        },
        "content_security_policy": "object-src 'self'; script-src chrome://resources 'self'"
    }

    popup.html:

    <html>
    <body>
        <p>Hello World</p>
        <script type="text/javascript" src="test.js">
        </script>
    </body>
    </html>

    test.js:

    function myapi() {
        var input = {};
        input.data = 'helloworld';
        input.name = 'cswuyg';
        var strInput = JSON.stringify(input);
        chrome.myapi.helloWorld((strInput), function(data){
            alert('result = ' + data);
        });        
    }
    chrome.browserAction.onClicked.addListener(myapi);
    myapi();
    2、把web资源添加到src\chrome\browser\resources\component_extension_resources.grd文件中,用于资源打包,必须把除了mainfest.json文件之外的其他独立文件都加进来。
      <include name="IDR_MYAPI_MAIN" file="myapi/popup.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
      <include name="IDR_MYAPI_COMMON_JS" file="myapi/test.js" type="BINDATA" />
    3、添加ID跟扩展资源的对应关系。在:src\chrome\browser\browser_resources.grd 文件下,定义一个ID IDR_MYAPI_MANIFEST跟扩展mainfest.json的关联。
          <include name="IDR_MYAPI_MANIFEST" file="resources\myapi\manifest.json" type="BINDATA" />
    4、添加IDR_MYAPI_MANIFEST对应的扩展的加载放到 src\chrome\browser\extensions\component_loader.cc文件下,AddDefaultComponentExtensions()函数中
      Add(IDR_CLOUDPRINT_MANIFEST, FilePath(FILE_PATH_LITERAL("cloud_print")));
      Add(IDR_MYAPI_MANIFEST, FilePath(FILE_PATH_LITERAL("myapi")));
    5、在src\chrome\common\extensions\extension.cc文件的LoadChromeURLOverrides函数下增加被扩展函数的override逻辑。
        // Restrict override pages to a list of supported URLs.
        bool is_override = (page != chrome::kChromeUINewTabHost &&
                            page != chrome::kChromeUIBookmarksHost &&
                            page != chrome::kChromeUIHistoryHost &&
                            page != "cswuyg"
                            );
        这样子就可以使用chrome:\\cswuyg打开页面了,该页面使用的是扩展的API,同时它打包在resource.pak里。
        特别注意,manifest.json中的chrome_url_overrides的键必须跟LoadChromeURLOverrides里添加的Host名称一致。如果要修改chrome://...的hostname名称需要修改两个地方,一个是manifest.json的chrome_url_overrides的子键,一个是extension.cc文件LoadChromeURLOverride函数里“Restrict override pages to a list of supported URLs.”处的Host名称。
        使用*.json添加扩展API,可以参考top_site.json的实现。
        使用*.idl添加扩展API,可以参考downloads.idl的实现。
        添加内置扩展,可以参考chrome://bookmarks的实现。
     
  • 相关阅读:
    Linux环境下入侵工具Knark的分析及防范 java程序员
    六个步骤即可防范ARP地址欺骗类病毒 java程序员
    巧用命令行 揪出ARP欺骗病毒母机方法 java程序员
    poj3264Balanced Lineup(线段树RMQ)
    有了1A的把握再去提交
    poj2828Buy Tickets(线段树 单点更新+区间求和+区间第K值)
    poj2513Colored Sticks(无向图判欧拉路、回路+trie树)
    ACM数学(转)
    sdut2381Broken Keyboard
    sdut2383Decode the Strings(循环节)
  • 原文地址:https://www.cnblogs.com/cswuyg/p/2956863.html
Copyright © 2011-2022 走看看