···11+--- original
22++++ modified
33+@@ -4,6 +4,7 @@
44+55+ use std::collections::HashSet;
66+ use std::iter::FromIterator;
77++use std::path::PathBuf;
88+ use std::sync::Arc as StdArc;
99+ use std::time::{Duration, SystemTime, UNIX_EPOCH};
1010+1111+@@ -15,7 +16,7 @@
1212+ };
1313+ use embedder_traits::{AuthenticationResponse, GenericEmbedderProxy};
1414+ use futures::{TryFutureExt, TryStreamExt, future};
1515+-use headers::authorization::Basic;
1616++use headers::authorization::{Basic, Bearer};
1717+ use headers::{
1818+ AccessControlAllowCredentials, AccessControlAllowHeaders, AccessControlAllowMethods,
1919+ AccessControlMaxAge, AccessControlRequestMethod, Authorization, CacheControl, ContentLength,
2020+@@ -56,9 +57,10 @@
2121+ CacheState, HttpsState, RedirectTaint, Response, ResponseBody, ResponseType,
2222+ };
2323+ use net_traits::{
2424+- CookieSource, DOCUMENT_ACCEPT_HEADER_VALUE, DebugVec, FetchMetadata, NetworkError,
2525+- RedirectEndValue, RedirectStartValue, ReferrerPolicy, ResourceAttribute, ResourceFetchTiming,
2626+- ResourceTimeValue, TlsSecurityInfo, TlsSecurityState,
2727++ AtProtoSessionState, AuthCacheEntry, BasicAuthCacheEntry, BearerAuthCacheEntry, CookieSource,
2828++ DOCUMENT_ACCEPT_HEADER_VALUE, DebugVec, FetchMetadata, NetworkError, RedirectEndValue,
2929++ RedirectStartValue, ReferrerPolicy, ResourceAttribute, ResourceFetchTiming, ResourceTimeValue,
3030++ TlsSecurityInfo, TlsSecurityState,
3131+ };
3232+ use parking_lot::{Mutex, RwLock};
3333+ use profile_traits::mem::{Report, ReportKind};
3434+@@ -91,7 +93,7 @@
3535+ use crate::http_cache::{
3636+ CacheKey, CachedResourcesOrGuard, HttpCache, construct_response, invalidate, refresh,
3737+ };
3838+-use crate::resource_thread::{AuthCache, AuthCacheEntry};
3939++use crate::resource_thread::AuthCache;
4040+ use crate::websocket_loader::start_websocket;
4141+4242+ /// The various states an entry of the HttpCache can be in.
4343+@@ -106,6 +108,7 @@
4444+ }
4545+4646+ pub struct HttpState {
4747++ pub config_dir: Option<PathBuf>,
4848+ pub hsts_list: RwLock<HstsList>,
4949+ pub cookie_jar: RwLock<CookieStorage>,
5050+ pub http_cache: HttpCache,
5151+@@ -114,9 +117,40 @@
5252+ pub client: ServoClient,
5353+ pub override_manager: CertificateErrorOverrideManager,
5454+ pub embedder_proxy: GenericEmbedderProxy<NetToEmbedderMsg>,
5555++ pub atproto_session: RwLock<Option<AtProtoSessionState>>,
5656+ }
5757+5858+ impl HttpState {
5959++ pub(crate) fn update_atproto_session(&self, session: Option<AtProtoSessionState>) {
6060++ let mut atproto_session = self.atproto_session.write();
6161++ let current_endpoint = atproto_session.clone().map(|s| s.endpoint);
6262++ *atproto_session = session.clone();
6363++ if let Some(ref session) = session {
6464++ if let Some(config_dir) = &self.config_dir {
6565++ session.save(config_dir);
6666++ }
6767++ } else if let Some(config_dir) = &self.config_dir {
6868++ AtProtoSessionState::reset(config_dir);
6969++ }
7070++
7171++ if let Some(session) = session {
7272++ let mut auth_cache = self.auth_cache.write();
7373++ let origin = session.endpoint.origin().ascii_serialization();
7474++ auth_cache.entries.insert(
7575++ origin,
7676++ AuthCacheEntry::Bearer(BearerAuthCacheEntry {
7777++ token: session.access_jwt.clone(),
7878++ }),
7979++ );
8080++ } else if let Some(endpoint) = current_endpoint {
8181++ let mut auth_cache = self.auth_cache.write();
8282++ let origin = endpoint.origin().ascii_serialization();
8383++ auth_cache.entries.remove(&origin);
8484++ } else {
8585++ error!("Failed to remove Bearer auth entry");
8686++ }
8787++ }
8888++
8989+ pub(crate) fn memory_reports(&self, suffix: &str, ops: &mut MallocSizeOfOps) -> Vec<Report> {
9090+ vec![
9191+ Report {
9292+@@ -577,14 +611,40 @@
9393+ }
9494+ }
9595+9696++enum AuthCredential {
9797++ Basic(Authorization<Basic>),
9898++ Bearer(Authorization<Bearer>),
9999++}
100100++
101101++impl AuthCredential {
102102++ fn update_headers(self, headers: &mut HeaderMap) {
103103++ match self {
104104++ Self::Basic(auth) => headers.typed_insert(auth),
105105++ Self::Bearer(auth) => headers.typed_insert(auth),
106106++ }
107107++ }
108108++}
109109++
110110+ fn auth_from_cache(
111111+ auth_cache: &RwLock<AuthCache>,
112112+ origin: &ImmutableOrigin,
113113+-) -> Option<Authorization<Basic>> {
114114++) -> Option<AuthCredential> {
115115+ if let Some(auth_entry) = auth_cache.read().entries.get(&origin.ascii_serialization()) {
116116+- let user_name = &auth_entry.user_name;
117117+- let password = &auth_entry.password;
118118+- Some(Authorization::basic(user_name, password))
119119++ match auth_entry {
120120++ AuthCacheEntry::Basic(auth_entry) => {
121121++ let user_name = &auth_entry.user_name;
122122++ let password = &auth_entry.password;
123123++ Some(AuthCredential::Basic(Authorization::basic(
124124++ user_name, password,
125125++ )))
126126++ },
127127++ AuthCacheEntry::Bearer(auth_entry) => {
128128++ let token = &auth_entry.token;
129129++ Some(AuthCredential::Bearer(
130130++ Authorization::bearer(token).unwrap(),
131131++ ))
132132++ },
133133++ }
134134+ } else {
135135+ None
136136+ }
137137+@@ -1645,15 +1705,15 @@
138138+ authorization_value.is_none() &&
139139+ has_credentials(¤t_url)
140140+ {
141141+- authorization_value = Some(Authorization::basic(
142142++ authorization_value = Some(AuthCredential::Basic(Authorization::basic(
143143+ current_url.username(),
144144+ current_url.password().unwrap_or(""),
145145+- ));
146146++ )));
147147+ }
148148+149149+ // Substep 6
150150+ if let Some(basic) = authorization_value {
151151+- http_request.headers.typed_insert(basic);
152152++ basic.update_headers(&mut http_request.headers);
153153+ }
154154+ }
155155+ }
156156+@@ -1858,7 +1918,7 @@
157157+ };
158158+159159+ // Store the credentials as a proxy-authentication entry.
160160+- let entry = AuthCacheEntry {
161161++ let entry = BasicAuthCacheEntry {
162162+ user_name: credentials.username,
163163+ password: credentials.password,
164164+ };
165165+@@ -1865,7 +1925,7 @@
166166+ {
167167+ let mut auth_cache = context.state.auth_cache.write();
168168+ let key = request.current_url().origin().ascii_serialization();
169169+- auth_cache.entries.insert(key, entry);
170170++ auth_cache.entries.insert(key, AuthCacheEntry::Basic(entry));
171171+ }
172172+173173+ // Make sure this is set to None,
+14
patches/components/net/lib.rs.patch
···11+--- original
22++++ modified
33+@@ -24,6 +24,11 @@
44+ #[cfg(feature = "test-util")]
55+ pub mod test_util;
66+ mod websocket_loader;
77++pub mod atproto {
88++ pub mod pds;
99++ pub mod session;
1010++ pub mod xrpc;
1111++}
1212+1313+ /// An implementation of the [Fetch specification](https://fetch.spec.whatwg.org/)
1414+ pub mod fetch {
···11+--- original
22++++ modified
33+@@ -0,0 +1,48 @@
44++# A proposal for a new trust model on the Web
55++
66++The current security model of the Web sits mostly on what is known as the Same Origin Policy (SOP): this ties cross-page capabilities to a domain name, delegating trust to the CA infrastructure.
77++
88++This means that the mechanisms defining the trust relationship from a page to another are shared by the service providers (who can decide which domains they use) and the User Agent (UA) in charge of implementing proper isolation according to the SOP. Of course this has been abused by service providers who ended up using the same domain to share data among different apps by scoping them with url paths.
99++
1010++On the other hand, end users have no say on how two or more pages could trust each other. This is a very top down, rigid model. Instead, what about giving users ways to create their own "trust zones" that can include content from different sources?
1111++
1212++A trust zone establishes its own origin, so trusted urls are of the form:
1313++trusted://<zoneID>.<userID>/<zone specific path>
1414++
1515++User IDs are used to fetch a zone description resource that lists the set of valid zones for that user and describes how to interpret the path component of the trusted url. A user ID can be:
1616++
1717++- a DID for that user. The zone description resource url needs to be set in the DID document.
1818++- a web domain controlled by the user. The zone description resource will then be fetched at the `.well-known/trusted-zones.json` relative url.
1919++
2020++TODO: integrity checks of the zone resource.
2121++
2222++# Trusted url example:
2323++
2424++Let's consider that the resource at https://webbeef.org/.well-known/trusted-zones.json is:
2525++
2626++```json
2727++{
2828++ "zones": [
2929++ {
3030++ "name": "demo",
3131++ "mappings": [
3232++ {
3333++ "path": "port8000",
3434++ "source": "https://localhost:8000/"
3535++ },
3636++ {
3737++ "path": "port8080",
3838++ "source": "https://localhost:8080/"
3939++ }
4040++ ]
4141++ }
4242++ ]
4343++}
4444++```
4545++
4646++That will make these 2 urls same-origin, and would let them share eg. BroadcastChannel messages.
4747++
4848++trusted://demo.webbeef.org/port8000/index.html
4949++trusted://demo.webbeef.org/port8080/messages/send.html
5050++
5151++
···11+--- original
22++++ modified
33+@@ -0,0 +1,29 @@
44++/* This Source Code Form is subject to the terms of the Mozilla Public
55++ * License, v. 2.0. If a copy of the MPL was not distributed with this
66++ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
77++
88++// TODO: expose some methods only to internal pages, and figure out the privacy story.
99++
1010++dictionary AtProtoSession {
1111++ required USVString did;
1212++ required USVString handle;
1313++};
1414++
1515++[Exposed=Window,
1616++Func="Embedder::is_allowed_to_embed"]
1717++interface AtProto {
1818++ // Tries to login with the submitted credentials.
1919++ // Resolves with the new session if successful, rejects otherwise.
2020++ Promise<AtProtoSession> login(USVString handle, USVString password);
2121++
2222++ // Revokes the current session if it exists.
2323++ Promise<undefined> logout();
2424++
2525++ // Resolves with the logged in user DID if any, rejects otherwise.
2626++ Promise<AtProtoSession> current();
2727++};
2828++
2929++partial interface Navigator {
3030++ [Func="Embedder::is_allowed_to_embed"]
3131++ readonly attribute AtProto atproto;
3232++};
+39-7
patches/components/servo/servo.rs.patch
···11--- original
22+++ modified
33-@@ -63,7 +63,7 @@
33+@@ -4,6 +4,7 @@
44+55+ use std::cell::{Cell, Ref, RefCell, RefMut};
66+ use std::cmp::max;
77++use std::path::PathBuf;
88+ use std::rc::{Rc, Weak};
99+ use std::sync::Arc;
1010+ use std::time::Duration;
1111+@@ -63,7 +64,7 @@
412 use servo_bluetooth_traits::BluetoothRequest;
513 use servo_config::opts::Opts;
614 use servo_config::prefs::{PrefValue, Preferences};
···917 use servo_geometry::{
1018 DeviceIndependentIntRect, convert_rect_to_css_pixel, convert_size_to_css_pixel,
1119 };
1212-@@ -229,9 +229,7 @@
2020+@@ -229,9 +230,7 @@
1321 }
14221523 if self.constellation_proxy.disconnected() {
···2028 }
21292230 self.paint.borrow_mut().perform_updates();
2323-@@ -283,10 +281,39 @@
3131+@@ -283,10 +282,39 @@
24322533 fn handle_delegate_errors(&self) {
2634 while let Some(error) = self.servo_errors.try_recv() {
···6169 fn clean_up_destroyed_webview_handles(&self) {
6270 // Remove any webview handles that have been destroyed and would not be upgradable.
6371 // Note that `retain` is O(capacity) because it visits empty buckets, so it may be worth
6464-@@ -444,6 +471,11 @@
7272+@@ -444,6 +472,11 @@
6573 webview.request_create_new(response_sender);
6674 }
6775 },
···7381 EmbedderMsg::WebViewClosed(webview_id) => {
7482 if let Some(webview) = self.get_webview_handle(webview_id) {
7583 webview.delegate().notify_closed(webview);
7676-@@ -597,10 +629,7 @@
8484+@@ -597,10 +630,7 @@
7785 .delegate
7886 .borrow()
7987 .notify_devtools_server_started(port, token),
···8593 },
8694 EmbedderMsg::RequestDevtoolsConnection(response_sender) => {
8795 self.delegate
8888-@@ -725,6 +754,47 @@
9696+@@ -725,6 +755,47 @@
8997 .notify_accessibility_tree_update(webview, tree_update);
9098 }
9199 },
···133141 }
134142 }
135143 }
136136-@@ -959,6 +1029,14 @@
144144+@@ -863,6 +934,7 @@
145145+ async_runtime,
146146+ public_storage_threads.clone(),
147147+ private_storage_threads.clone(),
148148++ opts.config_dir.clone(),
149149+ );
150150+151151+ if opts::get().multiprocess {
152152+@@ -959,6 +1031,14 @@
137153 self.0.site_data_manager.borrow()
138154 }
139155···148164 pub(crate) fn paint<'a>(&'a self) -> Ref<'a, Paint> {
149165 self.0.paint.borrow()
150166 }
167167+@@ -1060,6 +1140,7 @@
168168+ async_runtime: Box<dyn net_traits::AsyncRuntime>,
169169+ public_storage_threads: StorageThreads,
170170+ private_storage_threads: StorageThreads,
171171++ config_dir: Option<PathBuf>,
172172+ ) {
173173+ // Global configuration options, parsed from the command line.
174174+ let opts = opts::get();
175175+@@ -1101,6 +1182,7 @@
176176+ wgpu_image_map: paint.webgpu_image_map(),
177177+ async_runtime,
178178+ privileged_urls,
179179++ config_dir,
180180+ };
181181+182182+ let layout_factory = Arc::new(LayoutFactoryImpl());