[M108 Migration] Encrypt password field in AutoFill DB
[platform/framework/web/chromium-efl.git] / gin / v8_platform.cc
1 // Copyright 2014 The Chromium Authors
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 "gin/public/v8_platform.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/bit_cast.h"
11 #include "base/check_op.h"
12 #include "base/debug/stack_trace.h"
13 #include "base/location.h"
14 #include "base/memory/nonscannable_memory.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/rand_util.h"
17 #include "base/system/sys_info.h"
18 #include "base/task/post_job.h"
19 #include "base/task/task_traits.h"
20 #include "base/task/thread_pool.h"
21 #include "base/task/thread_pool/thread_pool_instance.h"
22 #include "base/trace_event/trace_event.h"
23 #include "base/tracing_buildflags.h"
24 #include "build/build_config.h"
25 #include "gin/per_isolate_data.h"
26 #include "v8_platform_page_allocator.h"
27
28 namespace gin {
29
30 namespace {
31
32 base::LazyInstance<V8Platform>::Leaky g_v8_platform = LAZY_INSTANCE_INITIALIZER;
33
34 constexpr base::TaskTraits kLowPriorityTaskTraits = {
35     base::TaskPriority::BEST_EFFORT};
36
37 constexpr base::TaskTraits kDefaultTaskTraits = {
38     base::TaskPriority::USER_VISIBLE};
39
40 constexpr base::TaskTraits kBlockingTaskTraits = {
41     base::TaskPriority::USER_BLOCKING};
42
43 void PrintStackTrace() {
44   base::debug::StackTrace trace;
45   trace.Print();
46 }
47
48 class ConvertableToTraceFormatWrapper final
49     : public base::trace_event::ConvertableToTraceFormat {
50  public:
51   explicit ConvertableToTraceFormatWrapper(
52       std::unique_ptr<v8::ConvertableToTraceFormat> inner)
53       : inner_(std::move(inner)) {}
54   ConvertableToTraceFormatWrapper(const ConvertableToTraceFormatWrapper&) =
55       delete;
56   ConvertableToTraceFormatWrapper& operator=(
57       const ConvertableToTraceFormatWrapper&) = delete;
58   ~ConvertableToTraceFormatWrapper() override = default;
59   void AppendAsTraceFormat(std::string* out) const final {
60     inner_->AppendAsTraceFormat(out);
61   }
62
63  private:
64   std::unique_ptr<v8::ConvertableToTraceFormat> inner_;
65 };
66
67 class EnabledStateObserverImpl final
68     : public base::trace_event::TraceLog::EnabledStateObserver {
69  public:
70   EnabledStateObserverImpl() {
71     base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
72   }
73
74   EnabledStateObserverImpl(const EnabledStateObserverImpl&) = delete;
75
76   EnabledStateObserverImpl& operator=(const EnabledStateObserverImpl&) = delete;
77
78   ~EnabledStateObserverImpl() override {
79     base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(
80         this);
81   }
82
83   void OnTraceLogEnabled() final {
84     base::AutoLock lock(mutex_);
85     for (auto* o : observers_) {
86       o->OnTraceEnabled();
87     }
88   }
89
90   void OnTraceLogDisabled() final {
91     base::AutoLock lock(mutex_);
92     for (auto* o : observers_) {
93       o->OnTraceDisabled();
94     }
95   }
96
97   void AddObserver(v8::TracingController::TraceStateObserver* observer) {
98     {
99       base::AutoLock lock(mutex_);
100       DCHECK(!observers_.count(observer));
101       observers_.insert(observer);
102     }
103
104     // Fire the observer if recording is already in progress.
105     if (base::trace_event::TraceLog::GetInstance()->IsEnabled())
106       observer->OnTraceEnabled();
107   }
108
109   void RemoveObserver(v8::TracingController::TraceStateObserver* observer) {
110     base::AutoLock lock(mutex_);
111     DCHECK(observers_.count(observer) == 1);
112     observers_.erase(observer);
113   }
114
115  private:
116   base::Lock mutex_;
117   std::unordered_set<v8::TracingController::TraceStateObserver*> observers_;
118 };
119
120 base::LazyInstance<EnabledStateObserverImpl>::Leaky g_trace_state_dispatcher =
121     LAZY_INSTANCE_INITIALIZER;
122
123 // TODO(skyostil): Deduplicate this with the clamper in Blink.
124 class TimeClamper {
125  public:
126 // As site isolation is enabled on desktop platforms, we can safely provide
127 // more timing resolution. Jittering is still enabled everywhere.
128 #if BUILDFLAG(IS_ANDROID)
129   static constexpr double kResolutionSeconds = 100e-6;
130 #else
131   static constexpr double kResolutionSeconds = 5e-6;
132 #endif
133
134   TimeClamper() : secret_(base::RandUint64()) {}
135   TimeClamper(const TimeClamper&) = delete;
136   TimeClamper& operator=(const TimeClamper&) = delete;
137
138   double ClampTimeResolution(double time_seconds) const {
139     bool was_negative = false;
140     if (time_seconds < 0) {
141       was_negative = true;
142       time_seconds = -time_seconds;
143     }
144     // For each clamped time interval, compute a pseudorandom transition
145     // threshold. The reported time will either be the start of that interval or
146     // the next one depending on which side of the threshold |time_seconds| is.
147     double interval = floor(time_seconds / kResolutionSeconds);
148     double clamped_time = interval * kResolutionSeconds;
149     double tick_threshold = ThresholdFor(clamped_time);
150
151     if (time_seconds >= tick_threshold)
152       clamped_time = (interval + 1) * kResolutionSeconds;
153     if (was_negative)
154       clamped_time = -clamped_time;
155     return clamped_time;
156   }
157
158  private:
159   inline double ThresholdFor(double clamped_time) const {
160     uint64_t time_hash =
161         MurmurHash3(base::bit_cast<int64_t>(clamped_time) ^ secret_);
162     return clamped_time + kResolutionSeconds * ToDouble(time_hash);
163   }
164
165   static inline double ToDouble(uint64_t value) {
166     // Exponent for double values for [1.0 .. 2.0]
167     static const uint64_t kExponentBits = uint64_t{0x3FF0000000000000};
168     static const uint64_t kMantissaMask = uint64_t{0x000FFFFFFFFFFFFF};
169     uint64_t random = (value & kMantissaMask) | kExponentBits;
170     return base::bit_cast<double>(random) - 1;
171   }
172
173   static inline uint64_t MurmurHash3(uint64_t value) {
174     value ^= value >> 33;
175     value *= uint64_t{0xFF51AFD7ED558CCD};
176     value ^= value >> 33;
177     value *= uint64_t{0xC4CEB9FE1A85EC53};
178     value ^= value >> 33;
179     return value;
180   }
181
182   const uint64_t secret_;
183 };
184
185 base::LazyInstance<TimeClamper>::Leaky g_time_clamper =
186     LAZY_INSTANCE_INITIALIZER;
187
188 #if BUILDFLAG(USE_PARTITION_ALLOC)
189
190 base::LazyInstance<gin::PageAllocator>::Leaky g_page_allocator =
191     LAZY_INSTANCE_INITIALIZER;
192
193 #endif  // BUILDFLAG(USE_PARTITION_ALLOC)
194
195 class JobDelegateImpl : public v8::JobDelegate {
196  public:
197   explicit JobDelegateImpl(base::JobDelegate* delegate) : delegate_(delegate) {}
198   JobDelegateImpl() = default;
199
200   JobDelegateImpl(const JobDelegateImpl&) = delete;
201   JobDelegateImpl& operator=(const JobDelegateImpl&) = delete;
202
203   // v8::JobDelegate:
204   bool ShouldYield() override { return delegate_->ShouldYield(); }
205   void NotifyConcurrencyIncrease() override {
206     delegate_->NotifyConcurrencyIncrease();
207   }
208   uint8_t GetTaskId() override { return delegate_->GetTaskId(); }
209   bool IsJoiningThread() const override { return delegate_->IsJoiningThread(); }
210
211  private:
212   raw_ptr<base::JobDelegate> delegate_;
213 };
214
215 class JobHandleImpl : public v8::JobHandle {
216  public:
217   explicit JobHandleImpl(base::JobHandle handle) : handle_(std::move(handle)) {}
218   ~JobHandleImpl() override = default;
219
220   JobHandleImpl(const JobHandleImpl&) = delete;
221   JobHandleImpl& operator=(const JobHandleImpl&) = delete;
222
223   // v8::JobHandle:
224   void NotifyConcurrencyIncrease() override {
225     handle_.NotifyConcurrencyIncrease();
226   }
227   bool UpdatePriorityEnabled() const override { return true; }
228   void UpdatePriority(v8::TaskPriority new_priority) override {
229     handle_.UpdatePriority(ToBaseTaskPriority(new_priority));
230   }
231   void Join() override { handle_.Join(); }
232   void Cancel() override { handle_.Cancel(); }
233   void CancelAndDetach() override { handle_.CancelAndDetach(); }
234   bool IsActive() override { return handle_.IsActive(); }
235   bool IsValid() override { return !!handle_; }
236
237  private:
238   static base::TaskPriority ToBaseTaskPriority(v8::TaskPriority priority) {
239     switch (priority) {
240       case v8::TaskPriority::kBestEffort:
241         return base::TaskPriority::BEST_EFFORT;
242       case v8::TaskPriority::kUserVisible:
243         return base::TaskPriority::USER_VISIBLE;
244       case v8::TaskPriority::kUserBlocking:
245         return base::TaskPriority::USER_BLOCKING;
246     }
247   }
248
249   base::JobHandle handle_;
250 };
251
252 }  // namespace
253
254 }  // namespace gin
255
256 namespace base {
257 namespace trace_event {
258
259 // Allow std::unique_ptr<v8::ConvertableToTraceFormat> to be a valid
260 // initialization value for trace macros.
261 template <>
262 struct base::trace_event::TraceValue::Helper<
263     std::unique_ptr<v8::ConvertableToTraceFormat>> {
264   static constexpr unsigned char kType = TRACE_VALUE_TYPE_CONVERTABLE;
265   static inline void SetValue(
266       TraceValue* v,
267       std::unique_ptr<v8::ConvertableToTraceFormat> value) {
268     // NOTE: |as_convertable| is an owning pointer, so using new here
269     // is acceptable.
270     v->as_convertable =
271         new gin::ConvertableToTraceFormatWrapper(std::move(value));
272   }
273 };
274
275 }  // namespace trace_event
276 }  // namespace base
277
278 namespace gin {
279
280 class V8Platform::TracingControllerImpl : public v8::TracingController {
281  public:
282   TracingControllerImpl() = default;
283   TracingControllerImpl(const TracingControllerImpl&) = delete;
284   TracingControllerImpl& operator=(const TracingControllerImpl&) = delete;
285   ~TracingControllerImpl() override = default;
286
287   // TracingController implementation.
288 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
289   const uint8_t* GetCategoryGroupEnabled(const char* name) override {
290     return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name);
291   }
292   uint64_t AddTraceEvent(
293       char phase,
294       const uint8_t* category_enabled_flag,
295       const char* name,
296       const char* scope,
297       uint64_t id,
298       uint64_t bind_id,
299       int32_t num_args,
300       const char** arg_names,
301       const uint8_t* arg_types,
302       const uint64_t* arg_values,
303       std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
304       unsigned int flags) override {
305     base::trace_event::TraceArguments args(
306         num_args, arg_names, arg_types,
307         reinterpret_cast<const unsigned long long*>(arg_values),
308         arg_convertables);
309     DCHECK_LE(num_args, 2);
310     base::trace_event::TraceEventHandle handle =
311         TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID(
312             phase, category_enabled_flag, name, scope, id, bind_id, &args,
313             flags);
314     uint64_t result;
315     memcpy(&result, &handle, sizeof(result));
316     return result;
317   }
318   uint64_t AddTraceEventWithTimestamp(
319       char phase,
320       const uint8_t* category_enabled_flag,
321       const char* name,
322       const char* scope,
323       uint64_t id,
324       uint64_t bind_id,
325       int32_t num_args,
326       const char** arg_names,
327       const uint8_t* arg_types,
328       const uint64_t* arg_values,
329       std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
330       unsigned int flags,
331       int64_t timestampMicroseconds) override {
332     base::trace_event::TraceArguments args(
333         num_args, arg_names, arg_types,
334         reinterpret_cast<const unsigned long long*>(arg_values),
335         arg_convertables);
336     DCHECK_LE(num_args, 2);
337     base::TimeTicks timestamp =
338         base::TimeTicks() + base::Microseconds(timestampMicroseconds);
339     base::trace_event::TraceEventHandle handle =
340         TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
341             phase, category_enabled_flag, name, scope, id, bind_id,
342             TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, &args, flags);
343     uint64_t result;
344     memcpy(&result, &handle, sizeof(result));
345     return result;
346   }
347   void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
348                                 const char* name,
349                                 uint64_t handle) override {
350     base::trace_event::TraceEventHandle traceEventHandle;
351     memcpy(&traceEventHandle, &handle, sizeof(handle));
352     TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_enabled_flag, name,
353                                                 traceEventHandle);
354   }
355 #endif  // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
356   void AddTraceStateObserver(TraceStateObserver* observer) override {
357     g_trace_state_dispatcher.Get().AddObserver(observer);
358   }
359   void RemoveTraceStateObserver(TraceStateObserver* observer) override {
360     g_trace_state_dispatcher.Get().RemoveObserver(observer);
361   }
362 };
363
364 // static
365 V8Platform* V8Platform::Get() { return g_v8_platform.Pointer(); }
366
367 V8Platform::V8Platform() : tracing_controller_(new TracingControllerImpl) {}
368
369 V8Platform::~V8Platform() = default;
370
371 #if BUILDFLAG(USE_PARTITION_ALLOC)
372 PageAllocator* V8Platform::GetPageAllocator() {
373   return g_page_allocator.Pointer();
374 }
375
376 void V8Platform::OnCriticalMemoryPressure() {
377 // We only have a reservation on 32-bit Windows systems.
378 // TODO(bbudge) Make the #if's in BlinkInitializer match.
379 #if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_32_BITS)
380   partition_alloc::ReleaseReservation();
381 #endif
382 }
383
384 v8::ZoneBackingAllocator* V8Platform::GetZoneBackingAllocator() {
385   static struct Allocator final : v8::ZoneBackingAllocator {
386     MallocFn GetMallocFn() const override {
387       return &base::AllocNonQuarantinable;
388     }
389     FreeFn GetFreeFn() const override { return &base::FreeNonQuarantinable; }
390   } allocator;
391   return &allocator;
392 }
393 #endif  // BUILDFLAG(USE_PARTITION_ALLOC)
394
395 std::shared_ptr<v8::TaskRunner> V8Platform::GetForegroundTaskRunner(
396     v8::Isolate* isolate) {
397   PerIsolateData* data = PerIsolateData::From(isolate);
398   return data->task_runner();
399 }
400
401 int V8Platform::NumberOfWorkerThreads() {
402   // V8Platform assumes the scheduler uses the same set of workers for default
403   // and user blocking tasks.
404   const size_t num_foreground_workers =
405       base::ThreadPoolInstance::Get()
406           ->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
407               kDefaultTaskTraits);
408   DCHECK_EQ(num_foreground_workers,
409             base::ThreadPoolInstance::Get()
410                 ->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
411                     kBlockingTaskTraits));
412   return std::max(1, static_cast<int>(num_foreground_workers));
413 }
414
415 void V8Platform::CallOnWorkerThread(std::unique_ptr<v8::Task> task) {
416   base::ThreadPool::PostTask(FROM_HERE, kDefaultTaskTraits,
417                              base::BindOnce(&v8::Task::Run, std::move(task)));
418 }
419
420 void V8Platform::CallBlockingTaskOnWorkerThread(
421     std::unique_ptr<v8::Task> task) {
422   base::ThreadPool::PostTask(FROM_HERE, kBlockingTaskTraits,
423                              base::BindOnce(&v8::Task::Run, std::move(task)));
424 }
425
426 void V8Platform::CallLowPriorityTaskOnWorkerThread(
427     std::unique_ptr<v8::Task> task) {
428   base::ThreadPool::PostTask(FROM_HERE, kLowPriorityTaskTraits,
429                              base::BindOnce(&v8::Task::Run, std::move(task)));
430 }
431
432 void V8Platform::CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task,
433                                            double delay_in_seconds) {
434   base::ThreadPool::PostDelayedTask(
435       FROM_HERE, kDefaultTaskTraits,
436       base::BindOnce(&v8::Task::Run, std::move(task)),
437       base::Seconds(delay_in_seconds));
438 }
439
440 std::unique_ptr<v8::JobHandle> V8Platform::CreateJob(
441     v8::TaskPriority priority,
442     std::unique_ptr<v8::JobTask> job_task) {
443   base::TaskTraits task_traits;
444   switch (priority) {
445     case v8::TaskPriority::kBestEffort:
446       task_traits = kLowPriorityTaskTraits;
447       break;
448     case v8::TaskPriority::kUserVisible:
449       task_traits = kDefaultTaskTraits;
450       break;
451     case v8::TaskPriority::kUserBlocking:
452       task_traits = kBlockingTaskTraits;
453       break;
454   }
455   // Ownership of |job_task| is assumed by |worker_task|, while
456   // |max_concurrency_callback| uses an unretained pointer.
457   auto* job_task_ptr = job_task.get();
458   auto handle =
459       base::CreateJob(FROM_HERE, task_traits,
460                       base::BindRepeating(
461                           [](const std::unique_ptr<v8::JobTask>& job_task,
462                              base::JobDelegate* delegate) {
463                             JobDelegateImpl delegate_impl(delegate);
464                             job_task->Run(&delegate_impl);
465                           },
466                           std::move(job_task)),
467                       base::BindRepeating(
468                           [](v8::JobTask* job_task, size_t worker_count) {
469                             return job_task->GetMaxConcurrency(worker_count);
470                           },
471                           base::Unretained(job_task_ptr)));
472
473   return std::make_unique<JobHandleImpl>(std::move(handle));
474 }
475
476 bool V8Platform::IdleTasksEnabled(v8::Isolate* isolate) {
477   return PerIsolateData::From(isolate)->task_runner()->IdleTasksEnabled();
478 }
479
480 double V8Platform::MonotonicallyIncreasingTime() {
481   return base::TimeTicks::Now().ToInternalValue() /
482       static_cast<double>(base::Time::kMicrosecondsPerSecond);
483 }
484
485 double V8Platform::CurrentClockTimeMillis() {
486   double now_seconds = base::Time::Now().ToJsTime() / 1000;
487   return g_time_clamper.Get().ClampTimeResolution(now_seconds) * 1000;
488 }
489
490 v8::TracingController* V8Platform::GetTracingController() {
491   return tracing_controller_.get();
492 }
493
494 v8::Platform::StackTracePrinter V8Platform::GetStackTracePrinter() {
495   return PrintStackTrace;
496 }
497
498 }  // namespace gin