Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Life of a Feature | |
| 2 | |
| 3 In the years since the Chromium browser was first open-sourced, the `//net` | |
| 4 directory has expanded from being the basis of loading web content in the | |
| 5 Chromium browser to accomodating a wide variety of networking needs, | |
|
xunjieli
2017/02/16 21:11:25
nit: s/accomodating/accommodating
| |
| 6 both in the Chromium browser and in other Google and third-party products | |
| 7 and projects. | |
| 8 | |
| 9 This brings with it many new opportunities, such as the ability to | |
| 10 introduce new protocols rapidly or push Web security forward, as well as | |
| 11 new challenges, such as how to balance the needs of various `//net` | |
| 12 consumers effectively. | |
| 13 | |
| 14 To make it easier to contribute new features or to change existing | |
| 15 behaviours in `//net`, this document tries to capture the life of a | |
| 16 feature in `//net`, from initial design to the eventual possibility of | |
| 17 deprecation and removal. | |
| 18 | |
| 19 ## Supported Projects | |
| 20 | |
| 21 When considering the introduction of a new `//net` feature or changing | |
| 22 a `//net` behaviour, it's first necessary to understand where `//net` | |
|
xunjieli
2017/02/16 21:11:25
optional nit: s/behaviour/behavior assuming there
| |
| 23 is used, how it is used, and what the various constraints and limits are. | |
| 24 | |
| 25 To understand a more comprehensive matrix of the supported platforms and | |
| 26 constraints, see [Supported Projects](supported-projects.md). When | |
| 27 examining a new feature request, or a change in behaviour, it's necessary | |
| 28 to consider dimensions such as: | |
| 29 | |
| 30 * Does this feature apply to all supported projects, or is this something | |
| 31 like a Browser-only feature? | |
| 32 * Does this feature apply to all supported platforms, or is this something | |
| 33 specific to a particular subset? | |
| 34 * Is the feature a basic networking library feature, or is it specific to | |
| 35 something in the Web Platform? | |
| 36 * Will some projects wish to strip the feature in order to meet targets | |
| 37 such as memory usage (RAM) or binary size? | |
| 38 * Does it depend on Google services or Google-specific behaviours or | |
| 39 features? | |
| 40 * How will this feature be tested / experimented with? For example, | |
| 41 __Field Trials (Finch)__ and __User Metrics (UMA)__ may not be available | |
| 42 on a number of platforms. | |
| 43 * How risky is the feature towards compatibility/stability? How will it | |
| 44 be undone if there is a bug? | |
| 45 * Are the power/memory/CPU/bandwidth requirements appropriate for the | |
| 46 targetted projects and/or platforms? | |
|
xunjieli
2017/02/16 21:11:25
optional nit: s/targetted/targeted if there is a g
| |
| 47 | |
| 48 ## Design and Layering | |
| 49 | |
| 50 Once the supported platforms and constraints are identified, it's necessary | |
| 51 to determine how to actually design the feature to meet those constraints, | |
| 52 in hopefully the easiest way possible both for implementation and consumption. | |
| 53 | |
| 54 ### Designing for multiple platforms | |
| 55 | |
| 56 In general, `//net` features try to support all platforms with a common | |
| 57 interface, and generally eschew OS-specific interfaces from being exposed as | |
| 58 part of `//net`. | |
| 59 | |
| 60 Cross-platform code is generally done via declaring an interface named | |
| 61 `foo.h`, which is common for all platforms, and then using the build-system to | |
| 62 do compile-time switching between implementations in `foo_win.cc`, `foo_mac.cc`, | |
| 63 `foo_android.cc`, etc. | |
| 64 | |
| 65 The goal is to ensure that consumers generally don't have to think about | |
| 66 OS-specific considerations, and can instead code to the interface. | |
| 67 | |
| 68 ### Designing for multiple products | |
| 69 | |
| 70 While premature abstraction can significantly harm readability, if it is | |
| 71 anticipated that different products will have different implementation needs, | |
| 72 or may wish to selectively disable the feature, it's often necessary to | |
| 73 abstract that interface sufficiently in `//net` to allow for dependency | |
| 74 injection. | |
|
Randy Smith (Not in Mondays)
2017/02/16 21:07:23
I think an abstract example or two would be useful
Ryan Sleevi
2017/02/16 23:29:33
I'm going to leave this for you to fill in, as I'm
Randy Smith (Not in Mondays)
2017/02/17 18:01:09
That's fine; happy to do that in a follow-on CL.
Ryan Sleevi
2017/02/17 18:07:17
Do you feel like those examples belong in this doc
Randy Smith (Not in Mondays)
2017/02/17 18:27:25
In general, what I want in this doc is to have eno
Ryan Sleevi
2017/02/17 22:44:54
I see. I think I had a very different mental image
| |
| 75 | |
| 76 This is true whether discussing concrete classes and interfaces or something | |
| 77 as simple a boolean configuration flag that different consumers wish to set | |
| 78 differently. | |
| 79 | |
| 80 The two most common approaches in `//net` are injection and delegation. | |
| 81 | |
| 82 #### Injection | |
| 83 | |
| 84 Injection refers to the pattern of defining the interface or concrete | |
| 85 configuration parameter (such as a boolean), along with the concrete | |
| 86 implementation, but requiring the `//net` embedder to supply it (perhaps | |
|
Randy Smith (Not in Mondays)
2017/02/16 21:07:23
Suggestion: "it" -> "an instantiation of the imple
| |
| 87 optionally). | |
| 88 | |
| 89 Examples of this pattern include things such as the `ProxyConfigService`, | |
| 90 which has concrete implementations in `//net` for a variety of platforms' | |
| 91 configuration of proxies, but which requires it be supplied as part of the | |
| 92 `URLRequestContextGetter` building, if proxies are going to be supported. | |
| 93 | |
| 94 An example of injecting configuration flags can be seen in the | |
| 95 `HttpNetworkSession::Params` structure, which is used to provide much of | |
| 96 the initialization parameters for the HTTP layer. | |
| 97 | |
| 98 While the ideal form of injection is to pass ownership of the injected | |
| 99 object, such as via a `std::unique_ptr<Foo>`, there are a number of places | |
| 100 in `//net` in which ownership is shared / left to the embedder, and the | |
| 101 injected object is passed around as a naked/raw pointer. | |
|
Randy Smith (Not in Mondays)
2017/02/16 21:07:23
Hmmm. I'd imagine we'd want to move away from thi
| |
| 102 | |
| 103 #### Delegation | |
| 104 | |
| 105 Delegation refers to forcing the `//net` embedder to respond to specific | |
| 106 delegated calls via a Delegate interface that it implements. In general, | |
| 107 when using the delegated pattern, ownership of the delegate should be | |
|
xunjieli
2017/02/16 21:11:25
nit: should it be "delegate pattern"/"delegation p
| |
| 108 transferred, so that the lifetime and threading semantics are clear and | |
| 109 unambiguous. | |
| 110 | |
| 111 That is, for a given class `Foo`, which has a `Foo::Delegate` interface | |
| 112 defined to allow embedders to alter behaviour, prefer a constructor that | |
| 113 is | |
| 114 ``` | |
| 115 explicit Foo(std::unique_ptr<Delegate> delegate); | |
| 116 ``` | |
| 117 so that it is clear that the lifetime of `delegate` is determined by | |
| 118 `Foo`. | |
| 119 | |
| 120 The most notable example of the delegate pattern is `URLRequest::Delegate`. | |
|
Randy Smith (Not in Mondays)
2017/02/16 21:07:23
The most notable example violates the "ownership i
Ryan Sleevi
2017/02/16 23:29:33
I'm not sure I agree. Does the expansion about "le
Randy Smith (Not in Mondays)
2017/02/17 18:01:09
Can you give me a more direct pointer to the legac
Ryan Sleevi
2017/02/17 18:07:17
I see the point of confusion. It's in the bit imme
Randy Smith (Not in Mondays)
2017/02/17 18:27:25
I'm torn here, just because in the process of this
Ryan Sleevi
2017/02/17 22:44:54
I actually don't, but I also recognize how signifi
| |
| 121 | |
| 122 While the use of a `base::Callback` can also be considered a form of | |
| 123 delegation, the `//net` layer tries to eschew any callbacks that can be | |
| 124 called more than once, and instead favors defining class interfaces | |
| 125 with concrete behavioural requirements in order to ensure the correct | |
| 126 lifetimes of objects and to adjust over time. When `//net` takes a | |
| 127 callback (e.g. `net::CompletionCallback`), the intended pattern is to | |
| 128 signal the asynchronous completion of a single method, invoking that | |
| 129 callback at most once before deallocating it. For more discussion | |
| 130 of these patterns, see [Code Patterns](code-patterns.md). | |
| 131 | |
| 132 ### Understanding the Layering | |
| 133 | |
| 134 A significant challenge many feature proposals face is understanding the | |
| 135 layering in `//net` and what different portions of `//net` are allowed to | |
| 136 know. | |
| 137 | |
| 138 #### Socket Pools | |
| 139 | |
| 140 The most common challenge feature proposals encounter is the awareness | |
| 141 that the act of associating an actual request to make with a socket is | |
| 142 done lazily, referred to as "late-binding". | |
| 143 | |
| 144 With late-bound sockets, a given `URLRequest` will not be assigned an actual | |
| 145 transport connection until the request is ready to be sent. This allows for | |
| 146 reprioritizing requests as they come in, to ensure that higher priority requests | |
| 147 get preferential treatment, but it also means that features or data associated | |
| 148 with a `URLRequest` generally don't participate in socket establishment or | |
| 149 maintenance. | |
| 150 | |
| 151 For example, a feature that wanted to associate the low-level network socket | |
|
xunjieli
2017/02/16 21:11:25
nit: s/wanted/wants since the rest of the paragrap
| |
| 152 with a `URLRequest` during connection establishment is not something that the | |
| 153 `//net` design supports, since the `URLRequest` is kept unaware of how sockets | |
| 154 are established by virtue of the socket pools and late binding. This allows for | |
| 155 more flexibility when working to improve performance, such as the ability to | |
| 156 coalesce multiple logical 'sockets' over a single HTTP/2 or QUIC stream, which | |
| 157 may only have a single physical network socket involved. | |
| 158 | |
| 159 #### Making Additional Requests | |
| 160 | |
| 161 From time to time, `//net` feature proposals will involve needing to load | |
| 162 a secondary resource as part of processing. For example, SDCH involves loading | |
| 163 additional dictionaries that are advertised in a header, and other feature | |
| 164 proposals have involved fetching a `/.well-known/` URI or reporting errors to | |
| 165 a particular URL. | |
| 166 | |
| 167 This is particularly challenging, because often, these features are implemented | |
| 168 deeper in the network stack, such as [`//net/cert`](../cert), [`//net/http`](../ http), | |
| 169 or [`//net/filter`](../filter), which [`//net/url_request`](../url_request) depe nds | |
| 170 on. Because `//net/url_request` depends on these low-level directories, it would | |
| 171 be a circular dependency to have these directories depend on `//net/url_request` , | |
| 172 and circular dependencies are forbidden. | |
| 173 | |
| 174 The recommended solution to address this is to adopt the delegation or injection | |
| 175 patterns. The lower-level directory will define some interface that represents t he | |
| 176 "I need this URL" request, and then elsewhere, in a directory allowed to depend | |
| 177 on `//net/url_request`, an implementation of that interface/delegate that uses | |
| 178 `//net/url_request` is implemented. | |
|
Randy Smith (Not in Mondays)
2017/02/16 21:07:22
I feel like this needs to be fleshed out some; thi
Ryan Sleevi
2017/02/16 23:29:33
I'm not sure I really understand this feedback, or
Randy Smith (Not in Mondays)
2017/02/17 18:01:09
Let's talk about this in our VC today. Not blocki
| |
| 179 | |
| 180 ### Understanding the Lifetimes | |
| 181 | |
| 182 Understanding the object lifetime and dependency graph can be one of the largest | |
| 183 challenges to contributing and maintaining `//net`. As a consequence, features | |
| 184 which require introducing more complexity to the lifetimes of objects generally | |
| 185 have a greater challenge to acceptance. | |
| 186 | |
| 187 When designing features, features which model object lifetimes as a hierarchal | |
|
xunjieli
2017/02/16 21:11:25
nit: consider revising the subject of this sentenc
xunjieli
2017/02/16 21:11:25
I slightly prefer "hierachical" over "hierarchal."
| |
| 188 DAG are much more likely to be reviewed and accepted than features which rely on | |
| 189 the use of either reference counting or weak pointers to maintain ownership. | |
|
Randy Smith (Not in Mondays)
2017/02/16 21:07:23
I think that we need to writeup, somewhere, a just
Ryan Sleevi
2017/02/16 23:29:33
I'm also not sure how to interpret this comment, a
Randy Smith (Not in Mondays)
2017/02/17 18:01:09
Not a blocker. This document is already solidly i
| |
| 190 | |
| 191 In addition to preferring explicit lifetimes, such as through judicious use of | |
| 192 `std::unique_ptr<>` to indicate ownership transfer of dependencies, many | |
| 193 features in `//net` also expect that if a `base::Callback` is involved (which | |
| 194 includes `net::CompletionCallback`), then it's possible that invoking the | |
| 195 callback may result in the deletion of the current (calling) object. As | |
| 196 further expanded upon in [Code Patterns](code-patterns.md), features and | |
| 197 changes should be designed such that any callback invocation is the last | |
| 198 bit of code executed, and that the callback is accessed via the stack (such | |
| 199 as through the use of either `base::ResetAndReturn(callback_).Run()` or | |
| 200 `std::move(callback_).Run()`. | |
| 201 | |
| 202 ### Specs: What Are They Good For | |
| 203 | |
| 204 As `//net` is used as the basis for a number of browsers, it's an important part | |
| 205 of the design philosophy to ensure behaviours are well-specified, and that the | |
| 206 implementation conforms to those specifications. This may be seen as burdensome | |
| 207 when it's unclear whether or not a feature will 'take off,' but it's equally | |
| 208 critical to ensure that the Chromium projects do not fork the Web Platform. | |
| 209 | |
| 210 #### Incubation Is Required | |
| 211 | |
| 212 `//net` respects Chromium's overall position of [incubation first](https://group s.google.com/a/chromium.org/d/msg/blink-dev/PJ_E04kcFb8/baiLN3DTBgAJ) standards development. | |
| 213 | |
| 214 With an incubation first approach, before introducing any new features that | |
| 215 might be exposed over the wire to servers, whether they be explicit behaviours | |
| 216 such as adding new headers to implicit behaviours such as | |
|
xunjieli
2017/02/16 21:11:25
nit: s/to/or
whether explicit behaviors [or] impl
| |
| 217 [Happy Eyeballs](https://tools.ietf.org/html/rfc6555), should have some form | |
| 218 of specification written. That specification should at least be on an | |
| 219 incubation track, and the expectation is that the specification should have a | |
| 220 direct path to an appropriate standards track. Features which don't adhere to | |
| 221 this pattern, or which are not making progress towars a standards track, will | |
|
xunjieli
2017/02/16 21:11:25
nit: s/towars/towards
| |
| 222 require a high-level approvals, to ensure that the Platform doesn't fragment. | |
|
xunjieli
2017/02/16 21:11:25
nit: remove 'a'
| |
| 223 | |
| 224 #### Introducing New Headers | |
| 225 | |
| 226 A common form of feature request is the introduction of new headers, either via | |
| 227 the `//net` implementation directly, or through consuming `//net` interfaces | |
| 228 and modifying headers on the fly. | |
| 229 | |
| 230 The introduction of any additional headers SHOULD have an incubated spec attache d, | |
| 231 ideally with cross-vendor interest. Particularly, headers which only apply to | |
| 232 Google or Google services are very likely to be rejected outright. | |
| 233 | |
| 234 #### Making Additional Requests | |
| 235 | |
| 236 While it's necessary to provide abstraction around `//net/url_request` for | |
| 237 any lower-level components that may need to make additional requests, for most | |
| 238 features, that's not all that is necessary. Because `//net/url_request` only | |
| 239 provides a basic HTTP fetching mechanism, it's insufficient for any Web Platform | |
| 240 feature, because it doesn't consider the broader platform concerns such as | |
| 241 interactions with CORS, Service Workers, cookie and authentication policies, or | |
| 242 even basic interactions with optional features like Extensions or SafeBrowsing. | |
| 243 | |
| 244 To account for all of these things, any resource fetching that is to support | |
| 245 a feature of the Web Platform, whether because the resource will be directly | |
| 246 exposed to web content (for example, an image load or prefetch) or because it | |
| 247 is in response to invoking a Web Platform API (for example, invoking the | |
| 248 credential management API), the feature's resource fetching should be | |
| 249 explainable in terms of the [Fetch Living Standard](https://fetch.spec.whatwg.o rg/). | |
| 250 The Fetch standard defines a JavaScript API for fetching resources, but more | |
| 251 importantly, defines a common set of infrastructure and terminology that | |
| 252 tries to define how all resource loads in the Web Platform happen - whether | |
| 253 it be through the JavaScript API, through `XMLHttpRequest`, or the `src` | |
| 254 attribute in HTML tags, for example. | |
| 255 | |
| 256 This also includes any resource fetching that wishes to use the same socket | |
| 257 pools or caches as the Web Platform, to ensure that every resource that is | |
| 258 web exposed (directly or indirectly) was fetched in a consistent and | |
|
xunjieli
2017/02/16 21:11:25
nit: s/was/is
| |
| 259 well-documented way, thus minimizing platform fragmentation and security | |
| 260 issues. | |
| 261 | |
| 262 There are exceptions to this, however, but they're generally few and far | |
| 263 between. In general, any feature that needs to define an abstraction to | |
| 264 allow it to "fetch resources," likely needs to also be "explained in terms | |
| 265 of Fetch". | |
|
Randy Smith (Not in Mondays)
2017/02/16 21:07:22
I think this needs to have some implementation bac
Ryan Sleevi
2017/02/16 23:29:33
While I agree, I think that belongs in something l
Randy Smith (Not in Mondays)
2017/02/17 18:01:09
Yep, I'm completely with you. We need to flesh th
| |
| 266 | |
| 267 ## Implementation | |
| 268 | |
| 269 In general, prior to implementing, try to get a review on net-dev@chromium.org | |
| 270 for the general feedback and design review. | |
| 271 | |
| 272 In addition to the net-dev@chromium.org early review, `//net` requires that any | |
| 273 browser-exposed behaviour should also adhere to the | |
| 274 [Blink Process](https://www.chromium.org/blink#new-features), which includes an | |
| 275 "Intent to Implement" message to blink-dev@chromium.org | |
| 276 | |
| 277 For features that are unclear about their future, such as experiments or trials, | |
| 278 it's also expected that the design planning will also account for how features | |
| 279 will be removed cleanly. For features that radically affect the architecture of | |
| 280 `//net`, expect a high bar of justification, since reversing those changes if | |
| 281 it fails to pan out can cause significant disruption to productivity and | |
|
xunjieli
2017/02/16 21:11:25
nit: they fail to pan out
assuming "it" means "tho
| |
| 282 stability. | |
| 283 | |
| 284 ## Deprecation | |
| 285 | |
| 286 Plan for obsolence, hope for success. Similar to implementation, features that | |
| 287 are to be removed should also go through the | |
| 288 [Blink Process](https://www.chromium.org/blink#TOC-Web-Platform-Changes:-Process ) | |
| 289 for removing features. | |
| 290 | |
| 291 Note that due to the diversity of [Supported Projects](supported-projects.md), | |
| 292 removing a feature while minimizing disruption can be just as complex as adding | |
| 293 a feature. For example, relying solely on __User Metrics (UMA)__ to signal the | |
| 294 safety of removing a feature may not consider all projects, and relying on | |
| 295 __Field Trials (Finch)__ to assess risk or restore the 'legacy' behaviour may no t | |
| 296 work on all projects either. | |
| 297 | |
| 298 It's precisely because of these challenges that there's such a high bar for | |
| 299 adding features, because they may represent multi-year committments to support, | |
|
xunjieli
2017/02/16 21:11:25
nit: s/committments/commitments
| |
| 300 even when the feature itself is deprecated or targetted for removal. | |
| OLD | NEW |