1// Copyright 2018 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#ifndef CONTENT_PUBLIC_BROWSER_BROWSER_TASK_TRAITS_H_
6#define CONTENT_PUBLIC_BROWSER_BROWSER_TASK_TRAITS_H_
7
8#include "base/task/task_traits.h"
9#include "base/task/task_traits_extension.h"
10#include "content/common/content_export.h"
11#include "content/public/browser/browser_thread.h"
12
13namespace content {
14
15// Tasks with this trait will not be executed inside a nested RunLoop.
16//
17// Note: This should rarely be required. Drivers of nested loops should instead
18// make sure to be reentrant when allowing nested application tasks (also rare).
19//
20// TODO(https://crbug.com/876272): Investigate removing this trait -- and any
21// logic for deferred tasks in MessageLoop.
22struct NonNestable {};
23
24// Semantic annotations which tell the scheduler what type of task it's dealing
25// with. This will be used by the scheduler for dynamic prioritization and for
26// attribution in traces, etc...
27// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content_public.browser
28enum class BrowserTaskType {
29 // A catch all tasks that don't fit the types below.
30 kDefault,
31
32 // Critical startup tasks.
33 kBootstrap,
34
35 // Navigation related tasks.
36 kNavigation,
37
38 // A subset of network tasks related to preconnection.
39 kPreconnect,
40
41 // Used to validate values in Java
42 kBrowserTaskType_Last
43};
44
45// TaskTraits for running tasks on the browser threads.
46//
47// These traits enable the use of the //base/task/post_task.h APIs to post tasks
48// to a BrowserThread.
49//
50// To post a task to the UI thread (analogous for IO thread):
51// base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, task);
52//
53// To obtain a TaskRunner for the UI thread (analogous for the IO thread):
54// base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
55//
56// Tasks posted to the same BrowserThread with the same traits will be executed
57// in the order they were posted, regardless of the TaskRunners they were
58// posted via.
59//
60// See //base/task/post_task.h for more detailed documentation.
61//
62// Posting to a BrowserThread must only be done after it was initialized (ref.
63// BrowserMainLoop::CreateThreads() phase).
64class CONTENT_EXPORT BrowserTaskTraitsExtension {
65 public:
66 static constexpr uint8_t kExtensionId =
67 base::TaskTraitsExtensionStorage::kFirstEmbedderExtensionId;
68
69 struct ValidTrait : public base::TaskTraits::ValidTrait {
70 using base::TaskTraits::ValidTrait::ValidTrait;
71
72 ValidTrait(BrowserThread::ID);
73 ValidTrait(BrowserTaskType);
74 ValidTrait(NonNestable);
75 };
76
77 template <
78 class... ArgTypes,
79 class CheckArgumentsAreValid = std::enable_if_t<
80 base::trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
81 constexpr BrowserTaskTraitsExtension(ArgTypes... args)
82 : browser_thread_(
83 base::trait_helpers::GetEnum<BrowserThread::ID>(args...)),
84 task_type_(
85 base::trait_helpers::GetEnum<BrowserTaskType,
86 BrowserTaskType::kDefault>(args...)),
87 nestable_(!base::trait_helpers::HasTrait<NonNestable>(args...)) {}
88
89 // Keep in sync with UiThreadTaskTraits.java
90 constexpr base::TaskTraitsExtensionStorage Serialize() const {
91 static_assert(12 == sizeof(BrowserTaskTraitsExtension),
92 "Update Serialize() and Parse() when changing "
93 "BrowserTaskTraitsExtension");
94 return {
95 kExtensionId,
96 {static_cast<uint8_t>(browser_thread_),
97 static_cast<uint8_t>(task_type_), static_cast<uint8_t>(nestable_)}};
98 }
99
100 static const BrowserTaskTraitsExtension Parse(
101 const base::TaskTraitsExtensionStorage& extension) {
102 return BrowserTaskTraitsExtension(
103 static_cast<BrowserThread::ID>(extension.data[0]),
104 static_cast<BrowserTaskType>(extension.data[1]),
105 static_cast<bool>(extension.data[2]));
106 }
107
108 constexpr BrowserThread::ID browser_thread() const { return browser_thread_; }
109 constexpr BrowserTaskType task_type() const { return task_type_; }
110
111 // Returns true if tasks with these traits may run in a nested RunLoop.
112 constexpr bool nestable() const { return nestable_; }
113
114 private:
115 BrowserTaskTraitsExtension(BrowserThread::ID browser_thread,
116 BrowserTaskType task_type,
117 bool nestable)
118 : browser_thread_(browser_thread),
119 task_type_(task_type),
120 nestable_(nestable) {}
121
122 BrowserThread::ID browser_thread_;
123 BrowserTaskType task_type_;
124 bool nestable_;
125};
126
127template <class... ArgTypes,
128 class = std::enable_if_t<base::trait_helpers::AreValidTraits<
129 BrowserTaskTraitsExtension::ValidTrait,
130 ArgTypes...>::value>>
131constexpr base::TaskTraitsExtensionStorage MakeTaskTraitsExtension(
132 ArgTypes&&... args) {
133 return BrowserTaskTraitsExtension(std::forward<ArgTypes>(args)...)
134 .Serialize();
135}
136
137} // namespace content
138
139#endif // CONTENT_PUBLIC_BROWSER_BROWSER_TASK_TRAITS_H_
140