1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/component_updater/soda_ja_jp_component_installer.h"
6 
7 #include "base/bind.h"
8 #include "base/files/file_util.h"
9 #include "build/build_config.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/component_updater/soda_component_installer.h"
12 #include "chrome/common/pref_names.h"
13 #include "components/component_updater/component_updater_service.h"
14 #include "components/crx_file/id_util.h"
15 #include "components/soda/constants.h"
16 #include "components/update_client/update_client_errors.h"
17 #include "content/public/browser/browser_task_traits.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "crypto/sha2.h"
20 #include "media/base/media_switches.h"
21 
22 using content::BrowserThread;
23 
24 namespace component_updater {
25 
26 namespace {
27 
28 // The SHA256 of the SubjectPublicKeyInfo used to sign the component.
29 // The component id is: onhpjgkfgajmkkeniaoflicgokpaebfa
30 constexpr uint8_t kSodaJaJpPublicKeySHA256[32] = {
31     0xed, 0x7f, 0x96, 0xa5, 0x60, 0x9c, 0xaa, 0x4d, 0x80, 0xe5, 0xb8,
32     0x26, 0xea, 0xf0, 0x41, 0x50, 0x09, 0x52, 0xa4, 0xb3, 0x1e, 0x6a,
33     0x8e, 0x24, 0x99, 0xde, 0x51, 0x14, 0xc4, 0x3c, 0xfa, 0x48};
34 
35 static_assert(base::size(kSodaJaJpPublicKeySHA256) == crypto::kSHA256Length,
36               "Wrong hash length");
37 
38 constexpr char kSodaJaJpManifestName[] = "SODA ja-JP Models";
39 
40 }  // namespace
41 
SodaJaJpComponentInstallerPolicy(OnSodaJaJpComponentReadyCallback callback)42 SodaJaJpComponentInstallerPolicy::SodaJaJpComponentInstallerPolicy(
43     OnSodaJaJpComponentReadyCallback callback)
44     : on_component_ready_callback_(callback) {}
45 
46 SodaJaJpComponentInstallerPolicy::~SodaJaJpComponentInstallerPolicy() = default;
47 
GetExtensionId()48 const std::string SodaJaJpComponentInstallerPolicy::GetExtensionId() {
49   return crx_file::id_util::GenerateIdFromHash(
50       kSodaJaJpPublicKeySHA256, sizeof(kSodaJaJpPublicKeySHA256));
51 }
52 
UpdateSodaJaJpComponentOnDemand()53 void SodaJaJpComponentInstallerPolicy::UpdateSodaJaJpComponentOnDemand() {
54   const std::string crx_id =
55       component_updater::SodaJaJpComponentInstallerPolicy::GetExtensionId();
56   g_browser_process->component_updater()->GetOnDemandUpdater().OnDemandUpdate(
57       crx_id, component_updater::OnDemandUpdater::Priority::FOREGROUND,
58       base::BindOnce([](update_client::Error error) {
59         if (error != update_client::Error::NONE &&
60             error != update_client::Error::UPDATE_IN_PROGRESS)
61           LOG(ERROR) << "On demand update of the SODA ja-JP component failed "
62                         "with error: "
63                      << static_cast<int>(error);
64       }));
65 }
66 
VerifyInstallation(const base::DictionaryValue & manifest,const base::FilePath & install_dir) const67 bool SodaJaJpComponentInstallerPolicy::VerifyInstallation(
68     const base::DictionaryValue& manifest,
69     const base::FilePath& install_dir) const {
70   return base::PathExists(
71       install_dir.Append(speech::kSodaLanguagePackDirectoryRelativePath));
72 }
73 
74 bool SodaJaJpComponentInstallerPolicy::
SupportsGroupPolicyEnabledComponentUpdates() const75     SupportsGroupPolicyEnabledComponentUpdates() const {
76   return true;
77 }
78 
RequiresNetworkEncryption() const79 bool SodaJaJpComponentInstallerPolicy::RequiresNetworkEncryption() const {
80   return true;
81 }
82 
83 update_client::CrxInstaller::Result
OnCustomInstall(const base::DictionaryValue & manifest,const base::FilePath & install_dir)84 SodaJaJpComponentInstallerPolicy::OnCustomInstall(
85     const base::DictionaryValue& manifest,
86     const base::FilePath& install_dir) {
87   return SODAComponentInstallerPolicy::SetComponentDirectoryPermission(
88       install_dir);
89 }
90 
OnCustomUninstall()91 void SodaJaJpComponentInstallerPolicy::OnCustomUninstall() {}
92 
ComponentReady(const base::Version & version,const base::FilePath & install_dir,std::unique_ptr<base::DictionaryValue> manifest)93 void SodaJaJpComponentInstallerPolicy::ComponentReady(
94     const base::Version& version,
95     const base::FilePath& install_dir,
96     std::unique_ptr<base::DictionaryValue> manifest) {
97   VLOG(1) << "Component ready, version " << version.GetString() << " in "
98           << install_dir.value();
99 
100   on_component_ready_callback_.Run(install_dir);
101 }
102 
GetRelativeInstallDir() const103 base::FilePath SodaJaJpComponentInstallerPolicy::GetRelativeInstallDir() const {
104   return base::FilePath(speech::kSodaJaJpInstallationRelativePath);
105 }
106 
GetHash(std::vector<uint8_t> * hash) const107 void SodaJaJpComponentInstallerPolicy::GetHash(
108     std::vector<uint8_t>* hash) const {
109   hash->assign(kSodaJaJpPublicKeySHA256,
110                kSodaJaJpPublicKeySHA256 + base::size(kSodaJaJpPublicKeySHA256));
111 }
112 
GetName() const113 std::string SodaJaJpComponentInstallerPolicy::GetName() const {
114   return kSodaJaJpManifestName;
115 }
116 
117 update_client::InstallerAttributes
GetInstallerAttributes() const118 SodaJaJpComponentInstallerPolicy::GetInstallerAttributes() const {
119   return update_client::InstallerAttributes();
120 }
121 
GetMimeTypes() const122 std::vector<std::string> SodaJaJpComponentInstallerPolicy::GetMimeTypes()
123     const {
124   return std::vector<std::string>();
125 }
126 
UpdateSodaJaJpInstallDirPref(PrefService * prefs,const base::FilePath & install_dir)127 void UpdateSodaJaJpInstallDirPref(PrefService* prefs,
128                                   const base::FilePath& install_dir) {
129 #if !defined(OS_ANDROID)
130   prefs->SetFilePath(
131       prefs::kSodaJaJpConfigPath,
132       install_dir.Append(speech::kSodaLanguagePackDirectoryRelativePath));
133 #endif
134 }
135 
RegisterSodaJaJpComponent(ComponentUpdateService * cus,PrefService * prefs,base::OnceClosure callback)136 void RegisterSodaJaJpComponent(ComponentUpdateService* cus,
137                                PrefService* prefs,
138                                base::OnceClosure callback) {
139   DCHECK_CURRENTLY_ON(BrowserThread::UI);
140     auto installer = base::MakeRefCounted<ComponentInstaller>(
141         std::make_unique<SodaJaJpComponentInstallerPolicy>(base::BindRepeating(
142             [](ComponentUpdateService* cus, PrefService* prefs,
143                const base::FilePath& install_dir) {
144               content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
145                   ->PostTask(FROM_HERE,
146                              base::BindOnce(&UpdateSodaJaJpInstallDirPref,
147                                             prefs, install_dir));
148             },
149             cus, prefs)));
150 
151     installer->Register(cus, std::move(callback));
152 }
153 
154 }  // namespace component_updater
155