Chromium资源解耦

对Chromium代码的修改,经常会涉及到资源文件的修改,比如图片、HTML文件、字符串等等。如果直接在grd文件里修改,长久的开发过程中,势必会把自己的修改跟Chromium的修改混在一起,导致了代码日后难以维护,因此需要对此做一些恰当的解耦。

字符串资源解耦

对应chrome/app目录下的字符串资源文件,我们在gclxry/chrome/app目录下面存放自己的字符串资源。 首先我们在gclxry/chrome/app目录下面创建一个gn工程文件BUILD.gn,其内容如下:

# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//tools/grit/grit_rule.gni")

group("strings") {
  public_deps = [
    ":gclxry_strings",
  ]
}

grit("gclxry_strings") {
  source = "gclxry_strings.grd"
  use_qualified_include = true
  output_dir = "$root_gen_dir/chrome"
  outputs = [
    "grit/gclxry_strings.h",
    "gclxry_strings_am.pak",
    "gclxry_strings_ar.pak",
    "gclxry_strings_bg.pak",
    "gclxry_strings_bn.pak",
    "gclxry_strings_ca.pak",
    "gclxry_strings_cs.pak",
    "gclxry_strings_da.pak",
    "gclxry_strings_de.pak",
    "gclxry_strings_el.pak",
    "gclxry_strings_en-GB.pak",
    "gclxry_strings_en-US.pak",
    "gclxry_strings_es.pak",
    "gclxry_strings_es-419.pak",
    "gclxry_strings_et.pak",
    "gclxry_strings_fa.pak",
    "gclxry_strings_fake-bidi.pak",
    "gclxry_strings_fi.pak",
    "gclxry_strings_fil.pak",
    "gclxry_strings_fr.pak",
    "gclxry_strings_gu.pak",
    "gclxry_strings_he.pak",
    "gclxry_strings_hi.pak",
    "gclxry_strings_hr.pak",
    "gclxry_strings_hu.pak",
    "gclxry_strings_id.pak",
    "gclxry_strings_it.pak",
    "gclxry_strings_ja.pak",
    "gclxry_strings_kn.pak",
    "gclxry_strings_ko.pak",
    "gclxry_strings_lt.pak",
    "gclxry_strings_lv.pak",
    "gclxry_strings_ml.pak",
    "gclxry_strings_mr.pak",
    "gclxry_strings_ms.pak",
    "gclxry_strings_nl.pak",
    "gclxry_strings_nb.pak",
    "gclxry_strings_pl.pak",
    "gclxry_strings_pt-BR.pak",
    "gclxry_strings_pt-PT.pak",
    "gclxry_strings_ro.pak",
    "gclxry_strings_ru.pak",
    "gclxry_strings_sk.pak",
    "gclxry_strings_sl.pak",
    "gclxry_strings_sr.pak",
    "gclxry_strings_sv.pak",
    "gclxry_strings_sw.pak",
    "gclxry_strings_ta.pak",
    "gclxry_strings_te.pak",
    "gclxry_strings_th.pak",
    "gclxry_strings_tr.pak",
    "gclxry_strings_uk.pak",
    "gclxry_strings_vi.pak",
    "gclxry_strings_zh-CN.pak",
    "gclxry_strings_zh-TW.pak",
  ]
}

如上,我们生成的资源头文件是grit/gclxry_strings.h,稍后我们可以在代码里使用这个头文件。

然后我们添加自己的字符串资源文件gclxry_strings.grd,其内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<grit base_dir="." latest_public_release="0" current_release="1"
      output_all_resource_defines="false" source_lang_id="en" enc_check="möl">
  <outputs>
    <!-- TODO add each of your output files.  Modify the three below, and add
    your own for your various languages.  See the user's guide
    (https://www.chromium.org/developers/tools-we-use-in-chromium/grit/grit-users-guide)
    for more details.
    Note that all output references are relative to the output directory
    which is specified at build time. -->
    <output filename="grit/gclxry_strings.h" type="rc_header">
      <emit emit_type='prepend'></emit>
    </output>
    <output filename="gclxry_strings_am.pak" type="data_package" lang="am" />
    <output filename="gclxry_strings_ar.pak" type="data_package" lang="ar" />
    <output filename="gclxry_strings_bg.pak" type="data_package" lang="bg" />
    <output filename="gclxry_strings_bn.pak" type="data_package" lang="bn" />
    <output filename="gclxry_strings_ca.pak" type="data_package" lang="ca" />
    <output filename="gclxry_strings_cs.pak" type="data_package" lang="cs" />
    <output filename="gclxry_strings_da.pak" type="data_package" lang="da" />
    <output filename="gclxry_strings_de.pak" type="data_package" lang="de" />
    <output filename="gclxry_strings_el.pak" type="data_package" lang="el" />
    <output filename="gclxry_strings_en-GB.pak" type="data_package" lang="en-GB" />
    <output filename="gclxry_strings_en-US.pak" type="data_package" lang="en" />
    <output filename="gclxry_strings_es.pak" type="data_package" lang="es" />
    <output filename="gclxry_strings_es-419.pak" type="data_package" lang="es-419" />
    <output filename="gclxry_strings_et.pak" type="data_package" lang="et" />
    <output filename="gclxry_strings_fa.pak" type="data_package" lang="fa" />
    <output filename="gclxry_strings_fake-bidi.pak" type="data_package" lang="fake-bidi" />
    <output filename="gclxry_strings_fi.pak" type="data_package" lang="fi" />
    <output filename="gclxry_strings_fil.pak" type="data_package" lang="fil" />
    <output filename="gclxry_strings_fr.pak" type="data_package" lang="fr" />
    <output filename="gclxry_strings_gu.pak" type="data_package" lang="gu" />
    <output filename="gclxry_strings_he.pak" type="data_package" lang="he" />
    <output filename="gclxry_strings_hi.pak" type="data_package" lang="hi" />
    <output filename="gclxry_strings_hr.pak" type="data_package" lang="hr" />
    <output filename="gclxry_strings_hu.pak" type="data_package" lang="hu" />
    <output filename="gclxry_strings_id.pak" type="data_package" lang="id" />
    <output filename="gclxry_strings_it.pak" type="data_package" lang="it" />
    <output filename="gclxry_strings_ja.pak" type="data_package" lang="ja" />
    <output filename="gclxry_strings_kn.pak" type="data_package" lang="kn" />
    <output filename="gclxry_strings_ko.pak" type="data_package" lang="ko" />
    <output filename="gclxry_strings_lt.pak" type="data_package" lang="lt" />
    <output filename="gclxry_strings_lv.pak" type="data_package" lang="lv" />
    <output filename="gclxry_strings_ml.pak" type="data_package" lang="ml" />
    <output filename="gclxry_strings_mr.pak" type="data_package" lang="mr" />
    <output filename="gclxry_strings_ms.pak" type="data_package" lang="ms" />
    <output filename="gclxry_strings_nl.pak" type="data_package" lang="nl" />
    <!-- The translation console uses 'no' for Norwegian Bokmål. It should
         be 'nb'. -->
    <output filename="gclxry_strings_nb.pak" type="data_package" lang="no" />
    <output filename="gclxry_strings_pl.pak" type="data_package" lang="pl" />
    <output filename="gclxry_strings_pt-BR.pak" type="data_package" lang="pt-BR" />
    <output filename="gclxry_strings_pt-PT.pak" type="data_package" lang="pt-PT" />
    <output filename="gclxry_strings_ro.pak" type="data_package" lang="ro" />
    <output filename="gclxry_strings_ru.pak" type="data_package" lang="ru" />
    <output filename="gclxry_strings_sk.pak" type="data_package" lang="sk" />
    <output filename="gclxry_strings_sl.pak" type="data_package" lang="sl" />
    <output filename="gclxry_strings_sr.pak" type="data_package" lang="sr" />
    <output filename="gclxry_strings_sv.pak" type="data_package" lang="sv" />
    <output filename="gclxry_strings_sw.pak" type="data_package" lang="sw" />
    <output filename="gclxry_strings_ta.pak" type="data_package" lang="ta" />
    <output filename="gclxry_strings_te.pak" type="data_package" lang="te" />
    <output filename="gclxry_strings_th.pak" type="data_package" lang="th" />
    <output filename="gclxry_strings_tr.pak" type="data_package" lang="tr" />
    <output filename="gclxry_strings_uk.pak" type="data_package" lang="uk" />
    <output filename="gclxry_strings_vi.pak" type="data_package" lang="vi" />
    <output filename="gclxry_strings_zh-CN.pak" type="data_package" lang="zh-CN" />
    <output filename="gclxry_strings_zh-TW.pak" type="data_package" lang="zh-TW" />
  </outputs>
  <translations>
    <file path="translations/gclxry_strings_zh-CN.xtb" lang="zh-CN" />
  </translations>
  <release seq="1" allow_pseudo="false">
    <messages fallback_to_english="true">
      <message name="IDS_HELLO_WORLD" desc="IDS_HELLO_WORLD" meaning="IDS_HELLO_WORLD">Hello World</message>
    </messages> 
  </release>
</grit

我们只关心中文版,所以translations里面只加了translations/gclxry_strings_zh-CN.xtb。

最后是把我们的字符串资源关联到Chromium系统中。在chrome/chrome_repack_locales.gni的恰当位置加上:

source_patterns += [
  "${root_gen_dir}/chrome/gclxry_strings_",
]

deps += [
  "//gclxry/chrome/app:gclxry_strings",
]

然后在tools/gritsettings/resource_ids里面加上我们的资源ID范围:

"gclxry/chrome/app/gclxry_strings.grd": {
  "messages": [50000],
},

非字符串资源解耦

非字符串资源跟字符串资源有些不同。对应chrome/browser目录下的资源,我们创建一个自己的gclxry/chrome/browser目录,在这个目录下面创建一个BUILD.gn文件,其内容如下:

import("//chrome/common/features.gni")
import("//tools/grit/grit_rule.gni")

grit("gclxry_browser_resources") {
  source = "gclxry_browser_resources.grd"
  defines = chrome_grit_defines
  outputs = [
    "grit/gclxry_browser_resources.h",
    "gclxry_browser_resources.pak",
  ]
  output_dir = "$root_gen_dir/chrome"
}

从上面可以看到,以后我们代码可以通过grit/gclxry_browser_resources.h头文件来使用非字符串资源文件了。 然后创建一个gclxry_browser_resources.grd文件,其内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<grit latest_public_release="0" current_release="1">
  <outputs>
    <output filename="grit/gclxry_browser_resources.h" type="rc_header">
      <emit emit_type='prepend'></emit>
    </output>
    <output filename="gclxry_browser_resources.pak" type="data_package" />
  </outputs>
  <release seq="1">
    <includes>
      <include name="IDR_CLOSE_BUTTON_NORMAL_PNG" file="resources\close_button_normal.png" type="BINDATA" />
    </includes>
  </release>
</grit>

同样的,最后是把我们的非字符串资源关联到Chromium系统中。在chrome/chrome_paks.gni的恰当位置加上:

sources += [
  "$root_gen_dir/chrome/gclxry_browser_resources.pak",
]

deps += [
  "//gclxry/chrome/browser:gclxry_browser_resources",
]

然后在tools/gritsettings/resource_ids里面加上我们的资源ID范围:

 "gclxry/chrome/browser/gclxry_browser_resources.grd": {
   "includes": [55000],
 },