1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
content / browser / font_unique_name_lookup / font_unique_name_lookup_android.h [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_FONT_UNIQUE_NAME_LOOKUP_FONT_UNIQUE_NAME_LOOKUP_ANDROID_H_
#define CONTENT_BROWSER_FONT_UNIQUE_NAME_LOOKUP_FONT_UNIQUE_NAME_LOOKUP_ANDROID_H_
#include <string>
#include <utility>
#include "base/files/file_path.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/sequenced_task_runner.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/mojom/font_unique_name_lookup/font_unique_name_lookup.mojom.h"
static_assert(BUILDFLAG(IS_ANDROID), "This implementation only works safely "
"on Android due to the way it assumes font files to be "
"read-only and unmodifiable.");
namespace content {
// Scans a set of font files for the full font name and postscript name
// information in the name table and builds a Protobuf lookup structure from
// it. The protobuf can be persisted to disk to the Android cache directory, and
// it can be read from disk as well. Provides the lookup structure as a
// ReadOnlySharedMemoryRegion. Performing lookup on it is done through
// FontTableMatcher.
class CONTENT_EXPORT FontUniqueNameLookup {
public:
FontUniqueNameLookup() = delete;
// Retrieve an instance of FontUniqueNameLookup. On the first call to
// GetInstance() this that will start a task reading the lookup table from
// cache if there was a cached one, updating the lookup table if needed
// (i.e. if there was an Android firmware update or no cached one existed)
// from the standard Android font directories, and writing the updated lookup
// table back to file.
static FontUniqueNameLookup& GetInstance();
// Construct a FontUniqueNameLookup given a cache directory path
// |cache_directory| to persist the internal lookup table, a
// FontFilesCollector to enumerate font files and a BuildFingerprintProvider
// to access the Android build fingerprint.
FontUniqueNameLookup(const base::FilePath& cache_directory);
~FontUniqueNameLookup();
// Return a ReadOnlySharedMemoryRegion to access the serialized form of the
// current lookup table. To be used with FontTableMatcher.
base::ReadOnlySharedMemoryRegion DuplicateMemoryRegion();
void QueueShareMemoryRegionWhenReady(
scoped_refptr<base::SequencedTaskRunner> task_runner,
blink::mojom::FontUniqueNameLookup::GetUniqueNameLookupTableCallback
callback);
// Returns true if an up-to-date, consistent font table is present.
bool IsValid();
// If an Android firmware update was detected by checking
// BuildFingerprintProvider, call UpdateTable(). Do not use this method.
// Instead, call GetInstance() to get an initialized instance. Publicly
// exposed for testing.
bool UpdateTableIfNeeded();
// Rescan the files returned by the FontFilesCollector and rebuild the lookup
// table by indexing them. Do not use this method. Instead, call GetInstance()
// to get an initialized instance. Returns true if instance is valid after
// updating, returns false if an error occured in acquiring memory or
// serializing the scanned files to the shared memory region. Publicly exposed
// for testing.
bool UpdateTable();
// Try to find a serialized lookup table in the directory specified at
// construction and load it into memory. Do not use this method. Instead, call
// GetInstance() to get an initialized instance. Publicly exposed for testing.
bool LoadFromFile();
// Serialize the current lookup table into a file in the the cache directory
// specified at construction time. If an up to date table is present and
// persisting fails, discard the internal table, as it might be that we were
// not able to update the file the previous time. Do not use this
// method. Instead, call GetInstance() to get an initialized
// instance. Publicly exposed for testing.
bool PersistToFile();
// Override the internal font files enumeration with an explicit set of fonts
// to be scanned in |font_file_paths|. Only used for testing.
void SetFontFilePathsForTesting(std::vector<base::FilePath> font_file_paths) {
font_file_paths_for_testing_ = std::move(font_file_paths);
}
// Override the Android build fingerprint for testing.
void SetAndroidBuildFingerprintForTesting(
const std::string& build_fingerprint_override) {
android_build_fingerprint_for_testing_ = build_fingerprint_override;
}
// Returns the storage location of the table cache protobuf file.
base::FilePath TableCacheFilePathForTesting() { return TableCacheFilePath(); }
protected:
void ScheduleLoadOrUpdateTable();
private:
// If an Android build fingerprint override is set through
// SetAndroidBuildFingerprint() return that, otherwise return the actual
// platform's Android build fingerprint.
std::string GetAndroidBuildFingerprint() const;
// If an override is set through SetFontFilePathsForTesting() return those
// fonts, otherwise enumerate font files in the the Android platform font
// directories.
std::vector<base::FilePath> GetFontFilePaths() const;
base::FilePath TableCacheFilePath();
void PostCallbacks();
// We have a asynchronous update tasks which need write access to the
// proto_storage_ MappedReadOnlyRegion after reading the index file from disk,
// or after scanning and indexing metadata from font files. At the same time,
// we may receive incoming Mojo requests to tell whether the proto_storage_
// storage area is already ready early for sync access by the
// renderers. Synchronize the information on whether the proto_storage_ is
// ready by means of a WaitableEvent.
base::WaitableEvent proto_storage_ready_;
base::MappedReadOnlyRegion proto_storage_;
base::FilePath cache_directory_;
std::string android_build_fingerprint_for_testing_;
std::vector<base::FilePath> font_file_paths_for_testing_ =
std::vector<base::FilePath>();
struct CallbackOnTaskRunner {
CallbackOnTaskRunner(
scoped_refptr<base::SequencedTaskRunner>,
blink::mojom::FontUniqueNameLookup::GetUniqueNameLookupTableCallback);
CallbackOnTaskRunner(CallbackOnTaskRunner&&);
~CallbackOnTaskRunner();
scoped_refptr<base::SequencedTaskRunner> task_runner;
blink::mojom::FontUniqueNameLookup::GetUniqueNameLookupTableCallback
mojo_callback;
};
std::vector<CallbackOnTaskRunner> pending_callbacks_;
};
} // namespace content
#endif // CONTENT_BROWSER_FONT_UNIQUE_NAME_LOOKUP_FONT_UNIQUE_NAME_LOOKUP_ANDROID_H_