diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/globalscope.rs | 54 | ||||
-rw-r--r-- | components/script/dom/htmlcanvaselement.rs | 30 | ||||
-rw-r--r-- | components/script/dom/window.rs | 17 |
3 files changed, 62 insertions, 39 deletions
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 77d1ee37c03..b3345b90fc0 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -2422,7 +2422,8 @@ impl GlobalScope { headers: &Option<Serde<HeaderMap>>, ) -> Option<CspList> { // TODO: Implement step 1 (local scheme special case) - let mut csp = headers.as_ref()?.get_all("content-security-policy").iter(); + let headers = headers.as_ref()?; + let mut csp = headers.get_all("content-security-policy").iter(); // This silently ignores the CSP if it contains invalid Unicode. // We should probably report an error somewhere. let c = csp.next().and_then(|c| c.to_str().ok())?; @@ -2435,6 +2436,19 @@ impl GlobalScope { PolicyDisposition::Enforce, )); } + let csp_report = headers + .get_all("content-security-policy-report-only") + .iter(); + // This silently ignores the CSP if it contains invalid Unicode. + // We should probably report an error somewhere. + for c in csp_report { + let c = c.to_str().ok()?; + csp_list.append(CspList::parse( + c, + PolicySource::Header, + PolicyDisposition::Report, + )); + } Some(csp_list) } @@ -2822,36 +2836,16 @@ impl GlobalScope { })) } - #[allow(unsafe_code)] - pub(crate) fn is_js_evaluation_allowed(&self, cx: SafeJSContext) -> bool { + pub(crate) fn is_js_evaluation_allowed(&self, source: &str) -> bool { let Some(csp_list) = self.get_csp_list() else { return true; }; - let scripted_caller = unsafe { describe_scripted_caller(*cx) }.unwrap_or_default(); - let is_js_evaluation_allowed = csp_list.is_js_evaluation_allowed() == CheckResult::Allowed; - - if !is_js_evaluation_allowed { - // FIXME: Don't fire event if `script-src` and `default-src` - // were not passed. - for policy in csp_list.0 { - let report = CSPViolationReportBuilder::default() - .resource("eval".to_owned()) - .effective_directive("script-src".to_owned()) - .report_only(policy.disposition == PolicyDisposition::Report) - .source_file(scripted_caller.filename.clone()) - .line_number(scripted_caller.line) - .column_number(scripted_caller.col) - .build(self); - let task = CSPViolationReportTask::new(self, report); + let (is_js_evaluation_allowed, violations) = csp_list.is_js_evaluation_allowed(source); - self.task_manager() - .dom_manipulation_task_source() - .queue(task); - } - } + self.report_csp_violations(violations); - is_js_evaluation_allowed + is_js_evaluation_allowed == CheckResult::Allowed } pub(crate) fn create_image_bitmap( @@ -3464,10 +3458,13 @@ impl GlobalScope { unreachable!(); } + #[allow(unsafe_code)] pub(crate) fn report_csp_violations(&self, violations: Vec<Violation>) { + let scripted_caller = + unsafe { describe_scripted_caller(*GlobalScope::get_cx()) }.unwrap_or_default(); for violation in violations { let (sample, resource) = match violation.resource { - ViolationResource::Inline { .. } => (None, "inline".to_owned()), + ViolationResource::Inline { sample } => (sample, "inline".to_owned()), ViolationResource::Url(url) => (None, url.into()), ViolationResource::TrustedTypePolicy { sample } => { (Some(sample), "trusted-types-policy".to_owned()) @@ -3475,6 +3472,8 @@ impl GlobalScope { ViolationResource::TrustedTypeSink { sample } => { (Some(sample), "trusted-types-sink".to_owned()) }, + ViolationResource::Eval { sample } => (sample, "eval".to_owned()), + ViolationResource::WasmEval => (None, "wasm-eval".to_owned()), }; let report = CSPViolationReportBuilder::default() .resource(resource) @@ -3482,6 +3481,9 @@ impl GlobalScope { .effective_directive(violation.directive.name) .original_policy(violation.policy.to_string()) .report_only(violation.policy.disposition == PolicyDisposition::Report) + .source_file(scripted_caller.filename.clone()) + .line_number(scripted_caller.line) + .column_number(scripted_caller.col + 1) .build(self); let task = CSPViolationReportTask::new(self, report); self.task_manager() diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 303c781c8b3..bb27d28cea8 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -407,15 +407,23 @@ impl HTMLCanvasElement { &self, image_type: &EncodedImageType, quality: Option<f64>, - bytes: &[u8], + snapshot: &Snapshot, encoder: &mut W, ) { + // We can't use self.Width() or self.Height() here, since the size of the canvas + // may have changed since the snapshot was created. Truncating the dimensions to a + // u32 can't panic, since the data comes from a canvas which is always smaller than + // u32::MAX. + let canvas_data = snapshot.data(); + let width = snapshot.size().width as u32; + let height = snapshot.size().height as u32; + match image_type { EncodedImageType::Png => { // FIXME(nox): https://github.com/image-rs/image-png/issues/86 // FIXME(nox): https://github.com/image-rs/image-png/issues/87 PngEncoder::new(encoder) - .write_image(bytes, self.Width(), self.Height(), ColorType::Rgba8) + .write_image(canvas_data, width, height, ColorType::Rgba8) .unwrap(); }, EncodedImageType::Jpeg => { @@ -435,14 +443,14 @@ impl HTMLCanvasElement { }; jpeg_encoder - .write_image(bytes, self.Width(), self.Height(), ColorType::Rgba8) + .write_image(canvas_data, width, height, ColorType::Rgba8) .unwrap(); }, EncodedImageType::Webp => { // No quality support because of https://github.com/image-rs/image/issues/1984 WebPEncoder::new_lossless(encoder) - .write_image(bytes, self.Width(), self.Height(), ColorType::Rgba8) + .write_image(canvas_data, width, height, ColorType::Rgba8) .unwrap(); }, } @@ -567,7 +575,7 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement { self.encode_for_mime_type( &image_type, Self::maybe_quality(quality), - snapshot.data(), + &snapshot, &mut encoder, ); encoder.into_inner(); @@ -589,8 +597,8 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement { return Err(Error::Security); } - // Step 2. and 3. - // If this canvas element's bitmap has pixels (i.e., neither its horizontal dimension + // Step 2. Let result be null. + // Step 3. If this canvas element's bitmap has pixels (i.e., neither its horizontal dimension // nor its vertical dimension is zero), // then set result to a copy of this canvas element's bitmap. let result = if self.Width() == 0 || self.Height() == 0 { @@ -627,12 +635,12 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement { // type and quality if given. let mut encoded: Vec<u8> = vec![]; - this.encode_for_mime_type(&image_type, quality, snapshot.data(), &mut encoded); + this.encode_for_mime_type(&image_type, quality, &snapshot, &mut encoded); let blob_impl = BlobImpl::new_from_bytes(encoded, image_type.as_mime_type()); - // Step 4.2.1 & 4.2.2 - // Set result to a new Blob object, created in the relevant realm of this canvas element - // Invoke callback with « result » and "report". + // Step 4.2.1 Set result to a new Blob object, created in the relevant realm of this canvas element let blob = Blob::new(&this.global(), blob_impl, CanGc::note()); + + // Step 4.2.2 Invoke callback with « result » and "report". let _ = callback.Call__(Some(&blob), ExceptionHandling::Report, CanGc::note()); } else { let _ = callback.Call__(None, ExceptionHandling::Report, CanGc::note()); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 418c737acd4..e210476a5df 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1389,7 +1389,17 @@ impl WindowMethods<crate::DomTypeHolder> for Window { // https://drafts.csswg.org/cssom-view/#dom-window-resizeto fn ResizeTo(&self, width: i32, height: i32) { // Step 1 - //TODO determine if this operation is allowed + let window_proxy = match self.window_proxy.get() { + Some(proxy) => proxy, + None => return, + }; + + // If target is not an auxiliary browsing context that was created by a script + // (as opposed to by an action of the user), then return. + if !window_proxy.is_auxiliary() { + return; + } + let dpr = self.device_pixel_ratio(); let size = Size2D::new(width, height).to_f32() * dpr; self.send_to_embedder(EmbedderMsg::ResizeTo(self.webview_id(), size.to_i32())); @@ -2392,7 +2402,10 @@ impl Window { return (None, Rect::zero()); } - let response = self.layout.borrow().query_offset_parent(node.to_opaque()); + let response = self + .layout + .borrow() + .query_offset_parent(node.to_trusted_node_address()); let element = response.node_address.and_then(|parent_node_address| { let node = unsafe { from_untrusted_node_address(parent_node_address) }; DomRoot::downcast(node) |