Files
palemoon27/security/manager/ssl/nsSecureBrowserUIImpl.cpp
T
roytam1 c7dc12e90f import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1251253 - prevent null pointer dereference of |aContext| in CacheStorageService::DoomStorageEntries. r=mayhemer (35b449c612)
- Bug 1260498 - Make test_rel_preconnect work in e10s mode. r=mcmanus (e6823ce4c4)
- Bug 1016628 - Add prefetch abilities to the predictor. r=mayhemer (53ab180c97)
- Bug 1258482 - FileList should contain only Files, not Directories, r=smaug (ff78125454)
- Bug 1258694 - Implement Directory::GetFiles(), r=smaug (305784524e)
- Bug 1263992 - patch 1 - Remove DirectoryType enum, r=smaug (89e1a59041)
- Bug 1263992 - patch 2 - Support the creation of directories from FileSystemTasks, r=smaug (c569092cef)
- Bug 1243586 - Implement Upgrade-Insecure-Requests HTTP Request Header Field. r=rbarnes (4b8a84c656)
- Bug 1262572 - http 0.9 telemetry. r=hurley (6006881336)
- Bug 587177 - Update all comments before SetOriginalURI to reflect reality, r=mcmanus (b2fedb0728)
- Bug 1261632 - Assert that OnStopRequest is called only once. r=michal (c35b1922b9)
- Bug 1232422 - Convert 5 tests within netwerk/test to use AsyncOpen2 (r=mcmanus) (4af8d43814)
- Bug 831450 - No Range Requests against weak Etag r=mayhemer (9b4a159e1e)
- Bug 1214277 - Avoid bypassing opening a cache entry for possibly intercepted channels; r=mcmanus (c5b0de6990)
- partial apply Bug 1234369 - Convert 25 tests within netwerk/test to use AsyncOpen2 (1b81d5a303)
- Bug 299031 - heuristic cache rule for 410 should be longer r=mayhemer (848834fc31)
- Bug 1121447 - trust cache less for error codes r=mayhemer (0424fec819)
- Bug 1125916 - Check whether loadInfo and loadContext match. r=sicking, r=jduell (6740850922)
- Bug 1258778 - Purge the skia glyph cache when receiving a low memory notice. r=erahm (633c60b0c6)
- Bug 1125916 - Add SEC_FORCE_PRIVATE_BROWSING to LoadInfo. r=sicking, r=jduell (10b5a1cacb)
- Bug 1105556 - test fixes. r=sicking, ckerschb (845d0dbd65)
- Bug 1258481 - Use RegionBuilder for nsRegion IPC. r=jrmuizel (616c279297)
- Bug 1014691 - Fix an include-what-you-use error in TestCompositor.cpp. r=kats (2797f83f1d)
- Bug 1256408 - Add graphics microbenchmarking. r=mstange (49b11b051b)
- Bug 1258481 - Add a RegionBuilder for accumulating rects. r=jrmuizel (acd79192db)
- Track whether or not remote layers have acknowledged compositor changes. (bug 1256517 part 1, r=mattwoodrow) (e3cc77ed41)
- Move compositable field out of individual compositable ops. (bug 1256517 part 2, r=mattwoodrow) (1d4a063df3)
- Bug 1241058: Assure several operations properly operate on the current group target. r=jrmuizel (6119e2b4db)
- Bug 1247700: Avoid crash from invalid fonts. r=bas (c4c2799b94)
- Bug 1242421 - remove useless null check. r=roc@ocallahan.org (44faf6556d)
- Add instrumentation for when content processes fail to acquire D3D11 devices. (bug 1247539, r=milan) (bd9265d78e)
- Make access to gfxWindowsPlatform D3D11 devices thread-safe. (bug 1258174, r=bas) (032e74b163)
- Disable device access on textures created against stale layers. (bug 1256517 part 3, r=nical) (ffcebbdee6)
- Block compositable updates from stale layers. (bug 1256517 part 4, r=mattwoodrow,nical) (fc83339f2d)
- Fix build bustage for bug 1256517 r=broken tree (3952871373)
- Bug 1256678 - Replace DrawTargetCairo::FillGlyphs crashes with other crashes - r=bobowen (b7245ba436)
- Bug 1120485. Log CloseHandle error reason during MessageChannel shutdown failure. r=milan (2f81d9c2aa)
- Bug 1242448 - Ensure the tile pool does not hold textures during shutdown. r=edwin (d31c304258)
- Bug 1258851 - Propagate the isScrollbarContainer layer flag to the compositor. r=mattwoodrow (b9906d7557)
- Bug 1260391: Transfer |CompositableOperation| in |AsyncChildMessageData|, r=dvander (1def34c5f8)
- Bug 1252324 - add DrawTarget API for 3D transforms for use in layers. r=jrmuizel (bc80529422)
- Bug 1255342 - implement DrawTargetCairo::LockBits for Cairo Win32 surfaces. r=sotaro (6f5661691b)
- Bug 1263480 - Don't let cairo go into an error state when DrawSurface is called with an empty destination rectangle. r=lsalzman (4300940101)
- Bug 1251241 - return from DrawTargetCairo::FillGlyphs if |aFont| is ullptr. r=roc (bb92f95ccd)
- Bug 1255320 - Create DrawTarget with DIB as similar DrawTarget r=jrmuizel (03f1da030d)
- Bug 1215265 - Put shutting down gfx ipdl protocols for child processes behind a pref. r=sotaro (aa781b37f9)
- Bug 1262898: Keep the GeckoChildProcessHost alive for the lifetime of the CompositorBridge and ImageBridge parent actors. r=jimm r=nical (dcca3b54e1)
- Bug 1251619: Remove unused gfxPlatform::CreateDrawTargetForUpdateSurface r=mchang (b29565995e)
- Bug 1255973 - Remove redundant overrides from gfxPlatform subclasses. r=jfkthame (d45f8a6640)
- Bug 1259466. Rename layers.offmainthreadcomposition.enabled. r=milan We would rather people not use this pref. (f362da1bd3)
- Bug 881609: Call InitLayersAccelerationPrefs only once. r=nrc (faed10a0d4)
- Bug 1209780. Mark some DrawResult's as unused in layout/svg. r=seth (48192d6b34)
- Bug 1251115 - Fix incorrect rendering result while mask path is not resolvable; r=mstange (a52b478fdf)
- Bug 1228354 - Part1 - Support luminance mask mode. r=mstange r=bas (b03abbe8a6)
- Bug 1228354 - Part2. Add test case for mask-mode. r=heycam (6bea36a70c)
- Bug 1259802: Add type replacement annotations to simplify rust binding generation for nsStyleStruct.h, r=bholley (48c13e62f2)
- Bug 1261754 - Part 1: Improve static assertions for style struct bits. r=dholbert (2ce6d994a5)
- Bug 1261552 - Reimplement default placement-new for style structs. r=heycam (db9d7782e2)
- Bug 1261552 - Introduce StaticPresData and hoist some shared functionality into it. r=heycam (adf2e16b4d)
- Bug 1226627 - Truncate the result in ZoomText/UnZoomText rather than rounding it for better performance. r=roc (f1d1084ba1)
- Bug 1247777 - Part1: parse and compute -webkit-text-fill-color property. r=heycam (fc4161355c)
- Bug 1247777 - Part2: implement -webkit-text-fill-color rendering. r=jfkthame (0f30da9c5b)
- Bug 1247777 - Part3: reftests for -webkit-text-fill-color. r=jfkthame Add this test into web-platform-tests. (02e41db8cc)
- Bug 1043461 - Followup to ensure we still test custom property position when the UA style sheet doesn't have custom properties in it. r=dholbert (48df73d684)
- Bug 1247777 - Part4.1: replace windows-style line endings with unix-style line endings. r=bz (be8ba60960)
- Bug 1247777 - Part4.2: add compatible webkit prefixed properties in CSS properties ordering check test. r=bz (7b78825e14)
- Bug 1261552 - Introduce StyleStructContext, and make all style struct constructors take it. r=heycam (65b3966841)
- Bug 1258017 - Use an nsCOMPtr to hold onto the nsIStyleRule. r=dbaron (e88d7e368f)
- Bug 1258017 - Use a RefPtr to hold onto the parent style context. r=dbaron (6a7289ca43)
- Bug 1258017 - Redesign and simplify rule tree GC. r=dbaron (3bf60a9b04)
- Bug 1253149 - Remove the #ifdef __cplusplus bits from ServoBindings.h. r=SimonSapin (bf2b18a470)
- Bug 1251496 - Forward stylesheet management to RawServoStyleSet. r=heycam (0a3aa90b2d)
- Bug 1260310 - Generalize nsStyleContext to support resolving styles from either nsRuleNode or ServoComputedValues. r=heycam (82b6d5d008)
- Bug 1258017 - Cleanup fixes for trunk. r=me (674a65815a)
- Bug 1236400 part 1: Add internal enum values to represent "display: -webkit-box" & "display: -webkit-inline-box". r=mats (509c94da15)
- Bug 1236400 part 2: Extend NeedsAnonFlexOrGridItem() & related code to wrap all inline-level -webkit-box children in an anonymous flex item. r=mats (dc11b9b09f)
- Bug 1236400 part 3: If webkit prefix support is enabled, skip CSS Parser code that converts "display: -webkit-box" directly to "display: flex". r=mats (e09b459124)
- Bug 1236400 part 4: Add reftests to test how non-block-level content gets wrapped inside a -webkit-box. (no review) (46e4d8cb07)
- Bug 1261754 - Part 2: Make quotes computed values shareable between different structs. r=dholbert (a78e43b706)
- Bug 1261754 - Part 3: Move quotes from nsStyleQuotes to nsStyleList and delete nsStyleQuotes. r=dholbert (fdcd9aaa3f)
- Bug 1209273 - Part 1: Support for adjust-color CSS property. r=dbaron (818a7fe0ff)
- Bug 1209273 - Part 2: Force printing background if color-adjust: exact. r=dbaron (ffd52c0dbc)
- Bug 1261754 - Part 4: Move image-rendering from nsStyleSVG to nsStyleVisibility. r=dholbert (ee8372fb94)
- Bug 1261754 - Part 5: Move text-rendering from nsStyleSVG to nsStyleText. r=dholbert (c13a11313d)
- Bug 1261754 - Part 6: Move vertical-align from nsStyleTextReset to nsStyleDisplay. r=dholbert (d374b3700b)
- Bug 1261754 - Part 7: Move pointer-events from nsStyleVisibility to nsStyleUserInterface. r=dholbert (8693251243)
- Bug 1261754 - Part 8: Move box-shadow from nsStyleBorder to a new nsStyleEffects struct. r=dholbert (8263476827)
- Bug 1261754 - Part 9: Move clip from nsStyleDisplay to nsStyleEffects. r=dholbert (5418597309)
- Bug 1261754 - Part 10: Move mix-blend-mode from nsStyleDisplay to nsStyleEffects. r=dholbert (ebae613929)
- Bug 1261754 - Part 11: Move opacity from nsStyleDisplay to nsStyleEffects. r=dholbert (589292af44)
- Bug 1187851 patch 6 - Make dynamic changes to filter change fixed position containing block for descendants. r=roc (003a3aa6ce)
- Bug 1261754 - Part 12: Move filter from nsStyleSVGReset to nsStyleEffects. r=dholbert (78d87914f9)
- Bug 1259513: Make gfxContext constructor private, use a utility function that can return nullptr. r=bas,lsalzman (43df6e429f)
- Bug 1259785: Do a proper flush when taking a snapshot so our dependent targets and command lists get appropriately cleared. r=jrmuizel (9f7372cce1)
- Bug 1251431 - Part 1: Allow usage of an A8 source pattern to MaskSurface for D2D 1.1 Moz2D backend. r=jwatt (632eb6d2da)
- Bug 1251431 - Part 2: Do not apply the device transform when drawing to an already intermediate surface. r=jwatt (3a24f4a5c6)
- Bug 1251431 - GCC compilation fixup. (2356f0a58c)
- Bug 1238328: Purge stored command lists by calling EndDraw/BeginDraw on a regular basis when they're used. r=jrmuizel (33f47b281f)
- Bug 1246641: Also execute an occasional EndDraw for CommandLists used by non-operator OVER drawing. r=jrmuizel (b3e03ad111)
- Bug 1258168: Push ClearType compatible clipping layers when the last pushed layer was marked as opaque. r=jrmuizel (bd069ad7b6)
- Bug 1264736: Crash sooner if we can't get a valid command list, at least in nightly/aurora. r=bas (fb4bb56815)
- Bug 1255438 - create nsI{Mutable,}Array directly; r=keeler (1b802b23b7)
- Bug 1255438 - fix OS X warning bustage and reopen this CLOSED TREE; r=me (07a05910a6)
- bug 1197314: Remove PR_snprintf calls in security/manager/ssl/ r=keeler (f2271aad87)
- Bug 1258298 - Switch more Scoped.h templates in PSM to UniquePtr equivalents. r=keeler (2ee1a85d8e)
- Bug 1191414 - gather telemetry on usage of <keygen>. r=keeler,r=vladan (150bad38a1)
- Bug 1260644 - Use UniquePLArenaPool to manage PLArenaPools in PSM. r=keeler (9e8ad9c0d4)
- Bug 1247250 - Enable TLS 1.3 anti-downgrade on non-secure fallback. r=keeler (7a950b427a)
- Bug 1215796 - Remove the static fallback whitelist. r=keeler (fa55b5920b)
- bug 1254667 - change certificate verification SHA1 policy to "allow or locally-installed roots" r=jcj (5d0bb9e8b1)
- bug 1245280 - add policy mechanism to optionally enforce BRs for falling back to subject CN r=Cykesiopka,mgoodwin (ecd4f2180a)
- Bug 1254653 - Add telemetry to measure how often we encounter EV certificates r=keeler (9da287b490)
- Bug 1259909 - Obviate char PORT_Free() calls in PSM. r=keeler (b7ba2a47da)
- Bug 1252882 - Add a Content Signature Service r=keeler,r=franziskus,r=Cykesiopka (8b806022a0)
- Bug 1255784 - u2f tests should use SpecialPowers.pushPrefEnv, r=jjones (839a58476f)
- Bug 1244960 - Complete FIDO u2f NSSToken (Part 1). r=keeler, r=baku (3d64aa2b7c)
- Bug 1244960 - FIDO u2f NSSToken (Part 2): Use Attestation Certificates. r=keeler (aee3ffc830)
- Bug 1244960 - FIDO u2f NSSToken (Part 3): Review updates. r=keeler (b2f81c2b72)
- Bug 1244960 - FIDO u2f NSSToken (Part 4): Correct FacetID base algorithm. r=keeler (9e70506580)
- Bug 1244960 - FIDO u2f NSSToken (Part 5): Review updates. r=keeler (62a28f2502)
- Bug 1231643 - Part 1. Create skia-A8-surface for mask composition when backendtype of the source DrawTarget is CG; r=mstange (dd03d86f55)
- Bug 1244598 - Move resource files of w3c-css/masking into ./support subdir. r=dbaron (4c9e789191)
- Bug 1243675 - Part 1. Add mask-image property reftest. r=dbaron (18e5dfa90b)
- Bug 1243675 - Part 2. Add mask-clip property reftest. r=dbaron (ddf834d408)
- Bug 1243675 - Part 3. Add mask-position property reftest. r=dbaron (68cae7c7e6)
- Bug 1243675 - Part 4. Add mask-repeat property reftest. r=dbaron (0a3ed45377)
- Bug 1243675 - Part 5. Add mask-origin property reftest. r=dbaron (f5785145a7)
- Bug 1243675 - Part 6. Add mask-size property reftest. r=dbaron (1ab2040973)
- Bug 1231643 - Part 2. Enable mask-composite reftest; r=dbaron (8c3b863d97)
- Bug 1263622 - Fixed nsNSSComponent.cpp compilation on mingw. r=dkeeler,ted (0e651c0211)
- Bug 1266249 - Remove mHasCachedOutline. r=dbaron (c46459acf2)
- Bug 1235634 - Construct nsNSSShutdownList::singleton lazily on first use r=keeler (1b53753c2e)
- Bug 1262645 - Address misc issues with nsGetUserCertChoice(). r=keeler (ec675be29a)
- Bug 1238001 - Allow TLS info to be updated on renegotiation, r=keeler (a2ec0c8a07)
- Bug 1201437 - Add new WebProgress state flag for user-overridden cert. r=keeler (0b9edbc8d8)
- Bug 1201437 - Make cert override tests check for STATE_CERT_USER_OVERRIDDEN. r=keeler (5246515084)
- bug 1261936 - stop using the subject common name in certificate verification error messages r=Cykesiopka (982cf43a11)
- bug 1230234 - fix a leak in client auth certificate handling r=Cykesiopka (6e83f81218)
- Bug 1260643 - Convert most uses of ScopedCERTCertificate in PSM to UniqueCERTCertificate. r=keeler (806b895c41)
- Bug 1207137 - Set a security state flag when weak crypto override is needed. r=keeler Bug 1254306 - Do not check the fallback limit version for the RC4 fallback. r=keeler (8b5cb7101f)
- Bug 1253010 - part 3 - create all nsIDateTimeFormat instances directly; r=smontagu (c1aa5d1d62)
- Bug 1260310 - Create servo style contexts from ServoStyleSet. r=heycam (05f876eb13)
- Bug 759568 - Part 1. Parse background-clip:text; r=dholbert r=heycam (d013b8fd84)
- Bug 1251995 part 6 - Use struct to pass params for nsTextFrame::PainText* functions. r=jfkthame (3b9c163eab)
- Bug 759568 - Part 2. Render background-clip:text; r=jfkthame (e534e048bf)
- Bug 759568 - Part 4. mochitest for background-clip:text; r=heycom (3e548ebf99)
- Bug 759568 - Part 5. reftest for background-clip:text; r=dbaron (43d2915305)
- Bug 759568 - Part 6. Remove unused nsDisplayList::mVisibleRect; r=jfkthame (960a85de40)
- Bug 1264910 - Simplify pref callback register/unregister in nsLayoutUtils. r=dholbert (f50219f117)
- Bug 1097499 part 1 - Control support of 'text-combine-upright: digits' via a separate pref. r=heycam (37df36e815)
- Bug 1261062 - When constraining the displayport by the max texture size, maintain the relative distribution of the margins. r=dvander (9a9423bdf1)
- Bug 1246290 - Add a pref to allow disabling APZ on documents which have scroll-linked effects. r=botond (781b63c578)
- Bug 1263347 - When checking if displayport changes should schedule a paint, make sure to use the proper displayport. r=mstange (998f59843e)
- Bug 1097499 part 15 - Add reftests for text-combine-upright. r=jfkthame (843bea00bc)
- Bug 1097499 followup - Fix metadata of tests submitted to w3c. DONTBUILD (e671b5b38b)
- Bug 1097499 followup 2 - Fix metadata of tests submitted to w3c. DONTBUILD (abf0895450)
- Bug 1097499 part 2 - Add a macro to simplify usage of nsStyleContext::GetUniqueStyleData. r=heycam (10486f1f24)
- Bug 1097499 part 3 - Add a separate anonbox for text nodes. r=heycam (7dd4347215)
- Bug 1097499 part 4 - Adjust computed value of writing-mode on text frames when text-combine-upright is used. r=heycam (c193f14b27)
- Bug 1097499 part 5 - Layout text combine upright. r=jfkthame (c21422930b)
- Bug 1097499 part 6 - Inherit move direction from parent for horizontal-in-vertical text. r=jfkthame (cf436b8494)
- Bug 1097499 part 7 - Add reverse function of GetFullWidth. r=emk (32d02e7437)
- Bug 1097499 part 8 - Move CountGraphemeClusters to mozilla::unicode. r=emk (e2b8942e53)
- Bug 1156588 - Add crashtest. (237adb0604)
- Bug 1234622. Tweak how nsDocumentViewer::FindContainerView finds the parent presshell. r=bz (d1e76ae2e9)
- Bug 1245978 part 1: Make nsDocumentViewer::CreateStyleSet directly return the thing it creates. r=heycam (ede16260a4)
- Bug 1245978 part 2: Drop redundant 'virtual' keyword from NS_DECL_NSIDOCUMENTVIEWERPRINT macro (which already includes 'override' keyword). r=heycam (42b8962e4f)
- Bug 1183879 - Soften "non-subdocument frame" warning to also allow dummy nsFrames, which exist while subdocument is loading. r=dholbert (6ebcb53421)
- Bug 1259246. Move nsIPresShell::GetRealPrimaryFrameFor to nsLayoutUtils::GetRealPrimaryFrameFor. r=dholbert (d3efd2f03a)
- Bug 645647 part 1 - Don't let empty bullet frames block suppressing white-space in intrinsic size calculations. r=dholbert (2ce0a86bfb)
- Bug 645647 part 2 - Reftests. (496e491990)
- Bug 645647 part 3 - Remove unused trailingTextFrame member. r=dholbert (bd26ea25e6)
- Bug 645647 part 4 - Add an 'm' prefix to some members to follow our naming conventions. r=dholbert (fe3c5240c9)
- Bug 1097499 part 9 - Transform full-width characters to non-full-width correspondents for combined text. r=jfkthame (5b1eafe2a7)
- Bug 1097499 part 10 - Add fwid/hwid/twid/qwid font feature support to gfx. r=jfkthame (682698dd38)
- Bug 1097499 part 11 - Set width variant for text-combined frame. r=jfkthame (937f61e0e9)
- Bug 1097499 part 12 - Handle spacing sensibly for text-combine-upright. r=jfkthame (9ae1ab2941)
- Bug 1220438 - Correct baseline offset computation of text decoration for vertical-rl. r=jfkthame (10ad32d702)
- Bug 1258636 part 1 - Use structs to pass params for decoration-related functions in nsCSSRendering. r=jfkthame (deef7071f1)
- Bug 1258636 part 2 - Use struct to pass params for nsTextFrame::PaintDecorationLine. r=jfkthame (df5bde2547)
- Bug 1229743 part 1 - Simplify text decoration handling code with lambda function and range-based for loop. r=jfkthame (51cd3ea4ca)
- Bug 1229743 part 2 - Fix up decoration rect computation for vertical-rl and sideways-lr. r=jfkthame (0113279f53)
- Bug 1251995 part 7 - Use struct to pass params for nsTextFrame::Paint*Shadow functions. r=jfkthame (e81ba231aa)
- Bug 759568 - Part 3. Render text-selection beneath background image; r=jfkthame (e6757762ff)
- Bug 1097499 part 13 - Draw decoration line properly for text-combine-upright. r=jfkthame (8f4be7f987)
- Bug 1264120. Remove usage of nsAutoPtr from gfx/src. r=jfkthame (6831454d8c)
- Bug 1119619 - Allow font-selection to fall back to an alternative face within the same family if the first-found face was not Regular, to handle cases where some styled faces have a reduced character set. r=m_kato (d8851b2877)
- Bug 1243226 - relax the limit on fontconfig generics. r=heycam, a=me (05df737d0e)
- Bug 1245811 - part 1 (based on patch by Andrew Comminos) - Replace gfxPlatformFontList::FindFamily with FindAndAddFamilies to allow for the possibility of the implementation returning multiple font families (e.g. when fontconfig has 'prefer' aliases). r=karlt (2bef9fafb0)
- Bug 1245811 - part 2 (based on patch by Andrew Comminos) - Let gfxFcPlatformFontList return multiple families for a given name once fontconfig substitutions have been applied. r=karlt (1ffb425a0e)
- Bug 1265452 - Remove use of nsAutoPtr from gfx/thebes. r=jrmuizel (d02c913ad5)
- Bug 1265459 - Replace uses of nsAutoPtr<gfxTextRun> with UniquePtr, and let MakeTextRun and similar methods return a UniquePtr. r=jrmuizel (da32e376b7)
- Bug 1097499 part 14 - Draw emphasis marks properly for text-combine-upright. r=jfkthame (c9115615c6)
- Bug 1097499 part 16 - Enable text-combine-upright by default. r=jfkthame (b616987f95)
- Bug 1261699 - preserve user fontconfig autohint settings in Cairo glyph rendering options. r=jfkthame (3e46dff5ff)
- Bug 1216001 - Fix a typo that eliminated a possible paint optimization. r=xidorn (6a350cadb7)
- Bug 1261568 - part1: take -webkit-text-fill-color into consideration while (d49cf427ab)
- Bug 1261568 - part2.1: update manifest before adding test. r=jgraham Bug 1261568 - part2.2: add reftest. r=jfkthame (ef3c22cfb4)
2024-04-22 16:19:21 +08:00

1350 lines
44 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nspr.h"
#include "mozilla/Logging.h"
#include "nsISecureBrowserUI.h"
#include "nsSecureBrowserUIImpl.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsCURILoader.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocument.h"
#include "nsIDOMElement.h"
#include "nsPIDOMWindow.h"
#include "nsIWebProgress.h"
#include "nsIWebProgressListener.h"
#include "nsIChannel.h"
#include "nsIHttpChannel.h"
#include "nsIFileChannel.h"
#include "nsIWyciwygChannel.h"
#include "nsIFTPChannel.h"
#include "nsITransportSecurityInfo.h"
#include "nsISSLStatus.h"
#include "nsIURI.h"
#include "nsISecurityEventSink.h"
#include "nsISecurityInfoProvider.h"
#include "imgIRequest.h"
#include "nsThreadUtils.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsCRT.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIProtocolHandler.h"
using namespace mozilla;
//
// Log module for nsSecureBrowserUI logging...
//
// To enable logging (see prlog.h for full details):
//
// set NSPR_LOG_MODULES=nsSecureBrowserUI:5
// set NSPR_LOG_FILE=nspr.log
//
// this enables LogLevel::Debug level information and places all output in
// the file nspr.log
//
LazyLogModule gSecureDocLog("nsSecureBrowserUI");
struct RequestHashEntry : PLDHashEntryHdr {
void *r;
};
static bool
RequestMapMatchEntry(const PLDHashEntryHdr *hdr, const void *key)
{
const RequestHashEntry *entry = static_cast<const RequestHashEntry*>(hdr);
return entry->r == key;
}
static void
RequestMapInitEntry(PLDHashEntryHdr *hdr, const void *key)
{
RequestHashEntry *entry = static_cast<RequestHashEntry*>(hdr);
entry->r = (void*)key;
}
static const PLDHashTableOps gMapOps = {
PLDHashTable::HashVoidPtrKeyStub,
RequestMapMatchEntry,
PLDHashTable::MoveEntryStub,
PLDHashTable::ClearEntryStub,
RequestMapInitEntry
};
#ifdef DEBUG
class nsAutoAtomic {
public:
explicit nsAutoAtomic(Atomic<int32_t> &i)
:mI(i) {
mI++;
}
~nsAutoAtomic() {
mI--;
}
protected:
Atomic<int32_t> &mI;
private:
nsAutoAtomic(); // not accessible
};
#endif
nsSecureBrowserUIImpl::nsSecureBrowserUIImpl()
: mNotifiedSecurityState(lis_no_security)
, mNotifiedToplevelIsEV(false)
, mNewToplevelSecurityState(STATE_IS_INSECURE)
, mNewToplevelIsEV(false)
, mNewToplevelSecurityStateKnown(true)
, mIsViewSource(false)
, mSubRequestsBrokenSecurity(0)
, mSubRequestsNoSecurity(0)
, mCertUserOverridden(false)
, mRestoreSubrequests(false)
, mOnLocationChangeSeen(false)
#ifdef DEBUG
, mOnStateLocationChangeReentranceDetection(0)
#endif
, mTransferringRequests(&gMapOps, sizeof(RequestHashEntry))
{
MOZ_ASSERT(NS_IsMainThread());
ResetStateTracking();
}
NS_IMPL_ISUPPORTS(nsSecureBrowserUIImpl,
nsISecureBrowserUI,
nsIWebProgressListener,
nsISupportsWeakReference,
nsISSLStatusProvider)
NS_IMETHODIMP
nsSecureBrowserUIImpl::Init(nsIDOMWindow* aWindow)
{
MOZ_ASSERT(NS_IsMainThread());
if (MOZ_LOG_TEST(gSecureDocLog, LogLevel::Debug)) {
nsCOMPtr<nsIDOMWindow> window(do_QueryReferent(mWindow));
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: Init: mWindow: %p, aWindow: %p\n", this,
window.get(), aWindow));
}
if (!aWindow) {
NS_WARNING("Null window passed to nsSecureBrowserUIImpl::Init()");
return NS_ERROR_INVALID_ARG;
}
if (mWindow) {
NS_WARNING("Trying to init an nsSecureBrowserUIImpl twice");
return NS_ERROR_ALREADY_INITIALIZED;
}
nsCOMPtr<nsPIDOMWindow> pwin(do_QueryInterface(aWindow));
if (pwin->IsInnerWindow()) {
pwin = pwin->GetOuterWindow();
}
nsresult rv;
mWindow = do_GetWeakReference(pwin, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsPIDOMWindow> piwindow(do_QueryInterface(aWindow));
if (!piwindow) return NS_ERROR_FAILURE;
nsIDocShell *docShell = piwindow->GetDocShell();
// The Docshell will own the SecureBrowserUI object
if (!docShell)
return NS_ERROR_FAILURE;
docShell->SetSecurityUI(this);
/* GetWebProgress(mWindow) */
// hook up to the webprogress notifications.
nsCOMPtr<nsIWebProgress> wp(do_GetInterface(docShell));
if (!wp) return NS_ERROR_FAILURE;
/* end GetWebProgress */
wp->AddProgressListener(static_cast<nsIWebProgressListener*>(this),
nsIWebProgress::NOTIFY_STATE_ALL |
nsIWebProgress::NOTIFY_LOCATION |
nsIWebProgress::NOTIFY_SECURITY);
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::GetState(uint32_t* aState)
{
MOZ_ASSERT(NS_IsMainThread());
return MapInternalToExternalState(aState, mNotifiedSecurityState,
mNotifiedToplevelIsEV);
}
// static
already_AddRefed<nsISupports>
nsSecureBrowserUIImpl::ExtractSecurityInfo(nsIRequest* aRequest)
{
nsCOMPtr<nsISupports> retval;
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
if (channel)
channel->GetSecurityInfo(getter_AddRefs(retval));
if (!retval) {
nsCOMPtr<nsISecurityInfoProvider> provider(do_QueryInterface(aRequest));
if (provider)
provider->GetSecurityInfo(getter_AddRefs(retval));
}
return retval.forget();
}
nsresult
nsSecureBrowserUIImpl::MapInternalToExternalState(uint32_t* aState, lockIconState lock, bool ev)
{
NS_ENSURE_ARG(aState);
switch (lock)
{
case lis_broken_security:
*aState = STATE_IS_BROKEN;
break;
case lis_mixed_security:
*aState = STATE_IS_BROKEN;
break;
case lis_high_security:
*aState = STATE_IS_SECURE | STATE_SECURE_HIGH;
break;
default:
case lis_no_security:
*aState = STATE_IS_INSECURE;
break;
}
if (ev && (*aState & STATE_IS_SECURE))
*aState |= nsIWebProgressListener::STATE_IDENTITY_EV_TOPLEVEL;
if (mCertUserOverridden && (*aState & STATE_IS_SECURE)) {
*aState |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
}
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
if (!docShell)
return NS_OK;
// For content docShell's, the mixed content security state is set on the root docShell.
if (docShell->ItemType() == nsIDocShellTreeItem::typeContent) {
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem(do_QueryInterface(docShell));
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
docShell = do_QueryInterface(sameTypeRoot);
if (!docShell)
return NS_OK;
}
// Has a Mixed Content Load initiated in nsMixedContentBlocker?
// * If not, the state should not be broken because no actual mixed-content
// load has occurred, overriding the previous state if it was flagged as mixed.
if (lock == lis_mixed_security &&
!docShell->GetHasMixedActiveContentLoaded() &&
!docShell->GetHasMixedDisplayContentLoaded() &&
!docShell->GetHasMixedActiveContentBlocked() &&
!docShell->GetHasMixedDisplayContentBlocked()) {
*aState = STATE_IS_SECURE | STATE_SECURE_HIGH;
if (ev) {
*aState |= nsIWebProgressListener::STATE_IDENTITY_EV_TOPLEVEL;
}
if (mCertUserOverridden) {
*aState |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
}
}
// * If so, the state should be broken or insecure; overriding the previous
// state set by the lock parameter.
uint32_t tempState = STATE_IS_BROKEN;
if (lock == lis_no_security) {
// this is to ensure that http: pages with mixed content in nested
// iframes don't get marked as broken instead of insecure
tempState = STATE_IS_INSECURE;
}
if (docShell->GetHasMixedActiveContentLoaded() &&
docShell->GetHasMixedDisplayContentLoaded()) {
*aState = tempState |
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT |
nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
} else if (docShell->GetHasMixedActiveContentLoaded()) {
*aState = tempState |
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
} else if (docShell->GetHasMixedDisplayContentLoaded()) {
*aState = tempState |
nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT;
}
// Has Mixed Content Been Blocked in nsMixedContentBlocker?
if (docShell->GetHasMixedActiveContentBlocked())
*aState |= nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT;
if (docShell->GetHasMixedDisplayContentBlocked())
*aState |= nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT;
// Has Tracking Content been Blocked?
if (docShell->GetHasTrackingContentBlocked())
*aState |= nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT;
if (docShell->GetHasTrackingContentLoaded())
*aState |= nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT;
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::SetDocShell(nsIDocShell* aDocShell)
{
MOZ_ASSERT(NS_IsMainThread());
nsresult rv;
mDocShell = do_GetWeakReference(aDocShell, &rv);
return rv;
}
static uint32_t GetSecurityStateFromSecurityInfoAndRequest(nsISupports* info,
nsIRequest* request)
{
nsresult res;
uint32_t securityState;
nsCOMPtr<nsITransportSecurityInfo> psmInfo(do_QueryInterface(info));
if (!psmInfo) {
MOZ_LOG(gSecureDocLog, LogLevel::Debug, ("SecureUI: GetSecurityState: - no nsITransportSecurityInfo for %p\n",
(nsISupports *)info));
return nsIWebProgressListener::STATE_IS_INSECURE;
}
MOZ_LOG(gSecureDocLog, LogLevel::Debug, ("SecureUI: GetSecurityState: - info is %p\n",
(nsISupports *)info));
res = psmInfo->GetSecurityState(&securityState);
if (NS_FAILED(res)) {
MOZ_LOG(gSecureDocLog, LogLevel::Debug, ("SecureUI: GetSecurityState: - GetSecurityState failed: %d\n",
res));
securityState = nsIWebProgressListener::STATE_IS_BROKEN;
}
if (securityState != nsIWebProgressListener::STATE_IS_INSECURE) {
// A secure connection does not yield a secure per-uri channel if the
// scheme is plain http.
nsCOMPtr<nsIURI> uri;
nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
if (channel) {
channel->GetURI(getter_AddRefs(uri));
} else {
nsCOMPtr<imgIRequest> imgRequest(do_QueryInterface(request));
if (imgRequest) {
imgRequest->GetURI(getter_AddRefs(uri));
}
}
if (uri) {
bool isHttp, isFtp;
if ((NS_SUCCEEDED(uri->SchemeIs("http", &isHttp)) && isHttp) ||
(NS_SUCCEEDED(uri->SchemeIs("ftp", &isFtp)) && isFtp)) {
MOZ_LOG(gSecureDocLog, LogLevel::Debug, ("SecureUI: GetSecurityState: - "
"channel scheme is insecure.\n"));
securityState = nsIWebProgressListener::STATE_IS_INSECURE;
}
}
}
MOZ_LOG(gSecureDocLog, LogLevel::Debug, ("SecureUI: GetSecurityState: - Returning %d\n",
securityState));
return securityState;
}
// nsIWebProgressListener
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnProgressChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
void
nsSecureBrowserUIImpl::ResetStateTracking()
{
mDocumentRequestsInProgress = 0;
mTransferringRequests.Clear();
}
void
nsSecureBrowserUIImpl::EvaluateAndUpdateSecurityState(nsIRequest* aRequest,
nsISupports* info,
bool withNewLocation,
bool withNewSink)
{
mNewToplevelIsEV = false;
bool updateStatus = false;
nsCOMPtr<nsISSLStatus> temp_SSLStatus;
mNewToplevelSecurityState =
GetSecurityStateFromSecurityInfoAndRequest(info, aRequest);
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: remember mNewToplevelSecurityState => %x\n",
this, mNewToplevelSecurityState));
nsCOMPtr<nsISSLStatusProvider> sp(do_QueryInterface(info));
if (sp) {
// Ignore result
updateStatus = true;
(void) sp->GetSSLStatus(getter_AddRefs(temp_SSLStatus));
if (temp_SSLStatus) {
bool aTemp;
if (NS_SUCCEEDED(temp_SSLStatus->GetIsExtendedValidation(&aTemp))) {
mNewToplevelIsEV = aTemp;
}
}
}
mNewToplevelSecurityStateKnown = true;
if (updateStatus) {
mSSLStatus = temp_SSLStatus;
}
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: remember securityInfo %p\n", this,
info));
nsCOMPtr<nsIAssociatedContentSecurity> associatedContentSecurityFromRequest(
do_QueryInterface(aRequest));
if (associatedContentSecurityFromRequest) {
mCurrentToplevelSecurityInfo = aRequest;
} else {
mCurrentToplevelSecurityInfo = info;
}
// The subrequest counters are now in sync with mCurrentToplevelSecurityInfo,
// don't restore after top level document load finishes.
mRestoreSubrequests = false;
UpdateSecurityState(aRequest, withNewLocation, withNewSink || updateStatus);
}
void
nsSecureBrowserUIImpl::UpdateSubrequestMembers(nsISupports* securityInfo,
nsIRequest* request)
{
// For wyciwyg channels in subdocuments we only update our
// subrequest state members.
uint32_t reqState = GetSecurityStateFromSecurityInfoAndRequest(securityInfo,
request);
if (reqState & STATE_IS_SECURE) {
// do nothing
} else if (reqState & STATE_IS_BROKEN) {
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: subreq BROKEN\n", this));
++mSubRequestsBrokenSecurity;
} else {
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: subreq INSECURE\n", this));
++mSubRequestsNoSecurity;
}
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aProgressStateFlags,
nsresult aStatus)
{
MOZ_ASSERT(NS_IsMainThread());
#ifdef DEBUG
nsAutoAtomic atomic(mOnStateLocationChangeReentranceDetection);
NS_ASSERTION(mOnStateLocationChangeReentranceDetection == 1,
"unexpected parallel nsIWebProgress OnStateChange and/or OnLocationChange notification");
#endif
/*
All discussion, unless otherwise mentioned, only refers to
http, https, file or wyciwig requests.
Redirects are evil, well, some of them.
There are multiple forms of redirects.
Redirects caused by http refresh content are ok, because experiments show,
with those redirects, the old page contents and their requests will come to STOP
completely, before any progress from new refreshed page content is reported.
So we can safely treat them as separate page loading transactions.
Evil are redirects at the http protocol level, like code 302.
If the toplevel documents gets replaced, i.e. redirected with 302, we do not care for the
security state of the initial transaction, which has now been redirected,
we only care for the new page load.
For the implementation of the security UI, we make an assumption, that is hopefully true.
Imagine, the received page that was delivered with the 302 redirection answer,
also delivered html content.
What happens if the parser starts to analyze the content and tries to load contained sub objects?
In that case we would see start and stop requests for subdocuments, some for the previous document,
some for the new target document. And only those for the new toplevel document may be
taken into consideration, when deciding about the security state of the next toplevel document.
Because security state is being looked at, when loading stops for (sub)documents, this
could cause real confusion, because we have to decide, whether an incoming progress
belongs to the new toplevel page, or the previous, already redirected page.
Can we simplify here?
If a redirect at the http protocol level is seen, can we safely assume, its html content
will not be parsed, anylzed, and no embedded objects will get loaded (css, js, images),
because the redirect is already happening?
If we can assume that, this really simplify things. Because we will never see notification
for sub requests that need to get ignored.
I would like to make this assumption for now, but please let me (kaie) know if I'm wrong.
Excurse:
If my assumption is wrong, then we would require more tracking information.
We need to keep lists of all pointers to request object that had been seen since the
last toplevel start event.
If the start for a redirected page is seen, the list of releveant object must be cleared,
and only progress for requests which start after it must be analyzed.
All other events must be ignored, as they belong to now irrelevant previous top level documents.
Frames are also evil.
First we need a decision.
kaie thinks:
Only if the toplevel frame is secure, we should try to display secure lock icons.
If some of the inner contents are insecure, we display mixed mode.
But if the top level frame is not secure, why indicate a mixed lock icon at all?
I think we should always display an open lock icon, if the top level frameset is insecure.
That's the way Netscape Communicator behaves, and I think we should do the same.
The user will not know which parts are secure and which are not,
and any certificate information, displayed in the tooltip or in the "page info"
will only be relevant for some subframe(s), and the user will not know which ones,
so we shouldn't display it as a general attribute of the displayed page.
Why are frames evil?
Because the progress for the toplevel frame document is not easily distinguishable
from subframes. The same STATE bits are reported.
While at first sight, when a new page load happens,
the toplevel frameset document has also the STATE_IS_NETWORK bit in it.
But this can't really be used. Because in case that document causes a http 302 redirect,
the real top level frameset will no longer have that bit.
But we need some way to distinguish top level frames from inner frames.
I saw that the web progress we get delivered has a reference to the toplevel DOM window.
I suggest, we look at all incoming requests.
If a request is NOT for the toplevel DOM window, we will always treat it as a subdocument request,
regardless of whether the load flags indicate a top level document.
*/
nsCOMPtr<nsIDOMWindow> windowForProgress;
aWebProgress->GetDOMWindow(getter_AddRefs(windowForProgress));
nsCOMPtr<nsIDOMWindow> window(do_QueryReferent(mWindow));
NS_ASSERTION(window, "Window has gone away?!");
if (!mIOService) {
mIOService = do_GetService(NS_IOSERVICE_CONTRACTID);
}
bool isNoContentResponse = false;
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
if (httpChannel)
{
uint32_t response;
isNoContentResponse = NS_SUCCEEDED(httpChannel->GetResponseStatus(&response)) &&
(response == 204 || response == 205);
}
const bool isToplevelProgress = (windowForProgress.get() == window.get()) && !isNoContentResponse;
if (windowForProgress)
{
if (isToplevelProgress)
{
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: progress: for toplevel\n", this));
}
else
{
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: progress: for something else\n", this));
}
}
else
{
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: progress: no window known\n", this));
}
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange\n", this));
if (mIsViewSource) {
return NS_OK;
}
if (!aRequest)
{
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange with null request\n", this));
return NS_ERROR_NULL_POINTER;
}
if (MOZ_LOG_TEST(gSecureDocLog, LogLevel::Debug)) {
nsXPIDLCString reqname;
aRequest->GetName(reqname);
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: %p %p OnStateChange %x %s\n", this, aWebProgress,
aRequest, aProgressStateFlags, reqname.get()));
}
nsCOMPtr<nsISupports> securityInfo(ExtractSecurityInfo(aRequest));
nsCOMPtr<nsIURI> uri;
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
if (channel) {
channel->GetURI(getter_AddRefs(uri));
}
nsCOMPtr<imgIRequest> imgRequest(do_QueryInterface(aRequest));
if (imgRequest) {
NS_ASSERTION(!channel, "How did that happen, exactly?");
// for image requests, we get the URI from here
imgRequest->GetURI(getter_AddRefs(uri));
}
if (uri) {
bool vs;
if (NS_SUCCEEDED(uri->SchemeIs("javascript", &vs)) && vs) {
// We ignore the progress events for javascript URLs.
// If a document loading gets triggered, we will see more events.
return NS_OK;
}
}
uint32_t loadFlags = 0;
aRequest->GetLoadFlags(&loadFlags);
if (aProgressStateFlags & STATE_START
&&
aProgressStateFlags & STATE_IS_REQUEST
&&
isToplevelProgress
&&
loadFlags & nsIChannel::LOAD_DOCUMENT_URI)
{
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: SOMETHING STARTS FOR TOPMOST DOCUMENT\n", this));
}
if (aProgressStateFlags & STATE_STOP
&&
aProgressStateFlags & STATE_IS_REQUEST
&&
isToplevelProgress
&&
loadFlags & nsIChannel::LOAD_DOCUMENT_URI)
{
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: SOMETHING STOPS FOR TOPMOST DOCUMENT\n", this));
}
bool isSubDocumentRelevant = true;
// We are only interested in requests that load in the browser window...
if (!imgRequest) { // is not imgRequest
nsCOMPtr<nsIHttpChannel> httpRequest(do_QueryInterface(aRequest));
if (!httpRequest) {
nsCOMPtr<nsIFileChannel> fileRequest(do_QueryInterface(aRequest));
if (!fileRequest) {
nsCOMPtr<nsIWyciwygChannel> wyciwygRequest(do_QueryInterface(aRequest));
if (!wyciwygRequest) {
nsCOMPtr<nsIFTPChannel> ftpRequest(do_QueryInterface(aRequest));
if (!ftpRequest) {
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: not relevant for sub content\n", this));
isSubDocumentRelevant = false;
}
}
}
}
}
// This will ignore all resource, chrome, data, file, moz-icon, and anno
// protocols. Local resources are treated as trusted.
if (uri && mIOService) {
bool hasFlag;
nsresult rv =
mIOService->URIChainHasFlags(uri,
nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
&hasFlag);
if (NS_SUCCEEDED(rv) && hasFlag) {
isSubDocumentRelevant = false;
}
}
#if defined(DEBUG)
nsCString info2;
uint32_t testFlags = loadFlags;
if (testFlags & nsIChannel::LOAD_DOCUMENT_URI)
{
testFlags -= nsIChannel::LOAD_DOCUMENT_URI;
info2.AppendLiteral("LOAD_DOCUMENT_URI ");
}
if (testFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI)
{
testFlags -= nsIChannel::LOAD_RETARGETED_DOCUMENT_URI;
info2.AppendLiteral("LOAD_RETARGETED_DOCUMENT_URI ");
}
if (testFlags & nsIChannel::LOAD_REPLACE)
{
testFlags -= nsIChannel::LOAD_REPLACE;
info2.AppendLiteral("LOAD_REPLACE ");
}
const char *_status = NS_SUCCEEDED(aStatus) ? "1" : "0";
nsCString info;
uint32_t f = aProgressStateFlags;
if (f & nsIWebProgressListener::STATE_START)
{
f -= nsIWebProgressListener::STATE_START;
info.AppendLiteral("START ");
}
if (f & nsIWebProgressListener::STATE_REDIRECTING)
{
f -= nsIWebProgressListener::STATE_REDIRECTING;
info.AppendLiteral("REDIRECTING ");
}
if (f & nsIWebProgressListener::STATE_TRANSFERRING)
{
f -= nsIWebProgressListener::STATE_TRANSFERRING;
info.AppendLiteral("TRANSFERRING ");
}
if (f & nsIWebProgressListener::STATE_NEGOTIATING)
{
f -= nsIWebProgressListener::STATE_NEGOTIATING;
info.AppendLiteral("NEGOTIATING ");
}
if (f & nsIWebProgressListener::STATE_STOP)
{
f -= nsIWebProgressListener::STATE_STOP;
info.AppendLiteral("STOP ");
}
if (f & nsIWebProgressListener::STATE_IS_REQUEST)
{
f -= nsIWebProgressListener::STATE_IS_REQUEST;
info.AppendLiteral("IS_REQUEST ");
}
if (f & nsIWebProgressListener::STATE_IS_DOCUMENT)
{
f -= nsIWebProgressListener::STATE_IS_DOCUMENT;
info.AppendLiteral("IS_DOCUMENT ");
}
if (f & nsIWebProgressListener::STATE_IS_NETWORK)
{
f -= nsIWebProgressListener::STATE_IS_NETWORK;
info.AppendLiteral("IS_NETWORK ");
}
if (f & nsIWebProgressListener::STATE_IS_WINDOW)
{
f -= nsIWebProgressListener::STATE_IS_WINDOW;
info.AppendLiteral("IS_WINDOW ");
}
if (f & nsIWebProgressListener::STATE_IS_INSECURE)
{
f -= nsIWebProgressListener::STATE_IS_INSECURE;
info.AppendLiteral("IS_INSECURE ");
}
if (f & nsIWebProgressListener::STATE_IS_BROKEN)
{
f -= nsIWebProgressListener::STATE_IS_BROKEN;
info.AppendLiteral("IS_BROKEN ");
}
if (f & nsIWebProgressListener::STATE_IS_SECURE)
{
f -= nsIWebProgressListener::STATE_IS_SECURE;
info.AppendLiteral("IS_SECURE ");
}
if (f & nsIWebProgressListener::STATE_SECURE_HIGH)
{
f -= nsIWebProgressListener::STATE_SECURE_HIGH;
info.AppendLiteral("SECURE_HIGH ");
}
if (f & nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN)
{
f -= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
info.AppendLiteral("STATE_CERT_USER_OVERRIDDEN ");
}
if (f & nsIWebProgressListener::STATE_RESTORING)
{
f -= nsIWebProgressListener::STATE_RESTORING;
info.AppendLiteral("STATE_RESTORING ");
}
if (f > 0)
{
info.AppendLiteral("f contains unknown flag!");
}
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: %s %s -- %s\n", this, _status,
info.get(), info2.get()));
if (aProgressStateFlags & STATE_STOP
&&
channel)
{
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: seeing STOP with security state: %d\n", this,
GetSecurityStateFromSecurityInfoAndRequest(securityInfo, aRequest)
));
}
#endif
if (aProgressStateFlags & STATE_TRANSFERRING
&&
aProgressStateFlags & STATE_IS_REQUEST)
{
// The listing of a request in mTransferringRequests
// means, there has already been data transfered.
mTransferringRequests.Add(aRequest, fallible);
return NS_OK;
}
bool requestHasTransferedData = false;
if (aProgressStateFlags & STATE_STOP
&&
aProgressStateFlags & STATE_IS_REQUEST)
{
PLDHashEntryHdr* entry = mTransferringRequests.Search(aRequest);
if (entry) {
mTransferringRequests.RemoveEntry(entry);
requestHasTransferedData = true;
}
if (!requestHasTransferedData) {
// Because image loads doesn't support any TRANSFERRING notifications but
// only START and STOP we must ask them directly whether content was
// transferred. See bug 432685 for details.
nsCOMPtr<nsISecurityInfoProvider> securityInfoProvider =
do_QueryInterface(aRequest);
// Guess true in all failure cases to be safe. But if we're not
// an nsISecurityInfoProvider, then we just haven't transferred
// any data.
bool hasTransferred;
requestHasTransferedData =
securityInfoProvider &&
(NS_FAILED(securityInfoProvider->GetHasTransferredData(&hasTransferred)) ||
hasTransferred);
}
}
bool allowSecurityStateChange = true;
if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI)
{
// The original consumer (this) is no longer the target of the load.
// Ignore any events with this flag, do not allow them to update
// our secure UI state.
allowSecurityStateChange = false;
}
if (aProgressStateFlags & STATE_START
&&
aProgressStateFlags & STATE_IS_REQUEST
&&
isToplevelProgress
&&
loadFlags & nsIChannel::LOAD_DOCUMENT_URI)
{
int32_t saveSubBroken;
int32_t saveSubNo;
nsCOMPtr<nsIAssociatedContentSecurity> prevContentSecurity;
int32_t newSubBroken = 0;
int32_t newSubNo = 0;
bool inProgress = (mDocumentRequestsInProgress != 0);
if (allowSecurityStateChange && !inProgress) {
saveSubBroken = mSubRequestsBrokenSecurity;
saveSubNo = mSubRequestsNoSecurity;
prevContentSecurity = do_QueryInterface(mCurrentToplevelSecurityInfo);
}
if (allowSecurityStateChange && !inProgress)
{
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: start for toplevel document\n", this
));
if (prevContentSecurity)
{
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: start, saving current sub state\n", this
));
// before resetting our state, let's save information about
// sub element loads, so we can restore it later
prevContentSecurity->SetCountSubRequestsBrokenSecurity(saveSubBroken);
prevContentSecurity->SetCountSubRequestsNoSecurity(saveSubNo);
prevContentSecurity->Flush();
MOZ_LOG(gSecureDocLog, LogLevel::Debug, ("SecureUI:%p: Saving subs in START to %p as %d,%d\n",
this, prevContentSecurity.get(), saveSubBroken, saveSubNo));
}
bool retrieveAssociatedState = false;
if (securityInfo &&
(aProgressStateFlags & nsIWebProgressListener::STATE_RESTORING) != 0) {
retrieveAssociatedState = true;
} else {
nsCOMPtr<nsIWyciwygChannel> wyciwygRequest(do_QueryInterface(aRequest));
if (wyciwygRequest) {
retrieveAssociatedState = true;
}
}
if (retrieveAssociatedState)
{
// When restoring from bfcache, we will not get events for the
// page's sub elements, so let's load the state of sub elements
// from the cache.
nsCOMPtr<nsIAssociatedContentSecurity>
newContentSecurity(do_QueryInterface(securityInfo));
if (newContentSecurity)
{
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: start, loading old sub state\n", this
));
newContentSecurity->GetCountSubRequestsBrokenSecurity(&newSubBroken);
newContentSecurity->GetCountSubRequestsNoSecurity(&newSubNo);
MOZ_LOG(gSecureDocLog, LogLevel::Debug, ("SecureUI:%p: Restoring subs in START from %p to %d,%d\n",
this, newContentSecurity.get(), newSubBroken, newSubNo));
}
}
else
{
// If we don't get OnLocationChange for this top level load later,
// it didn't get rendered. But we reset the state to unknown and
// mSubRequests* to zeros. If we would have left these values after
// this top level load stoped, we would override the original top level
// load with all zeros and break mixed content state on back and forward.
mRestoreSubrequests = true;
}
}
if (allowSecurityStateChange && !inProgress) {
ResetStateTracking();
mSubRequestsBrokenSecurity = newSubBroken;
mSubRequestsNoSecurity = newSubNo;
mNewToplevelSecurityStateKnown = false;
}
// By using a counter, this code also works when the toplevel
// document get's redirected, but the STOP request for the
// previous toplevel document has not yet have been received.
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: ++mDocumentRequestsInProgress\n", this
));
++mDocumentRequestsInProgress;
return NS_OK;
}
if (aProgressStateFlags & STATE_STOP
&&
aProgressStateFlags & STATE_IS_REQUEST
&&
isToplevelProgress
&&
loadFlags & nsIChannel::LOAD_DOCUMENT_URI)
{
nsCOMPtr<nsISecurityEventSink> temp_ToplevelEventSink;
if (allowSecurityStateChange) {
temp_ToplevelEventSink = mToplevelEventSink;
}
if (mDocumentRequestsInProgress <= 0) {
// Ignore stop requests unless a document load is in progress
// Unfortunately on application start, see some stops without having seen any starts...
return NS_OK;
}
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnStateChange: --mDocumentRequestsInProgress\n", this
));
if (!temp_ToplevelEventSink && channel)
{
if (allowSecurityStateChange)
{
ObtainEventSink(channel, temp_ToplevelEventSink);
}
}
bool sinkChanged = false;
bool inProgress;
if (allowSecurityStateChange) {
sinkChanged = (mToplevelEventSink != temp_ToplevelEventSink);
mToplevelEventSink = temp_ToplevelEventSink;
}
--mDocumentRequestsInProgress;
inProgress = mDocumentRequestsInProgress > 0;
if (allowSecurityStateChange && requestHasTransferedData) {
// Data has been transferred for the single toplevel
// request. Evaluate the security state.
// Do this only when the sink has changed. We update and notify
// the state from OnLacationChange, this is actually redundant.
// But when the target sink changes between OnLocationChange and
// OnStateChange, we have to fire the notification here (again).
if (sinkChanged || mOnLocationChangeSeen) {
EvaluateAndUpdateSecurityState(aRequest, securityInfo, false,
sinkChanged);
return NS_OK;
}
}
mOnLocationChangeSeen = false;
if (mRestoreSubrequests && !inProgress)
{
// We get here when there were no OnLocationChange between
// OnStateChange(START) and OnStateChange(STOP). Then the load has not
// been rendered but has been retargeted in some other way then by external
// app handler. Restore mSubRequests* members to what the current security
// state info holds (it was reset to all zero in OnStateChange(START)
// before).
nsCOMPtr<nsIAssociatedContentSecurity> currentContentSecurity(
do_QueryInterface(mCurrentToplevelSecurityInfo));
// Drop this indication flag, the restore operation is just being done.
mRestoreSubrequests = false;
// We can do this since the state didn't actually change.
mNewToplevelSecurityStateKnown = true;
int32_t subBroken = 0;
int32_t subNo = 0;
if (currentContentSecurity)
{
currentContentSecurity->GetCountSubRequestsBrokenSecurity(&subBroken);
currentContentSecurity->GetCountSubRequestsNoSecurity(&subNo);
MOZ_LOG(gSecureDocLog, LogLevel::Debug, ("SecureUI:%p: Restoring subs in STOP from %p to %d,%d\n",
this, currentContentSecurity.get(), subBroken, subNo));
}
mSubRequestsBrokenSecurity = subBroken;
mSubRequestsNoSecurity = subNo;
}
return NS_OK;
}
if (aProgressStateFlags & STATE_STOP
&&
aProgressStateFlags & STATE_IS_REQUEST)
{
if (!isSubDocumentRelevant)
return NS_OK;
// if we arrive here, LOAD_DOCUMENT_URI is not set
// We only care for the security state of sub requests which have actually transfered data.
if (allowSecurityStateChange && requestHasTransferedData)
{
UpdateSubrequestMembers(securityInfo, aRequest);
// Care for the following scenario:
// A new top level document load might have already started,
// but the security state of the new top level document might not yet been known.
//
// At this point, we are learning about the security state of a sub-document.
// We must not update the security state based on the sub content,
// if the new top level state is not yet known.
//
// We skip updating the security state in this case.
if (mNewToplevelSecurityStateKnown) {
UpdateSecurityState(aRequest, false, false);
}
}
return NS_OK;
}
return NS_OK;
}
// I'm keeping this as a separate function, in order to simplify the review
// for bug 412456. We should inline this in a follow up patch.
void nsSecureBrowserUIImpl::ObtainEventSink(nsIChannel *channel,
nsCOMPtr<nsISecurityEventSink> &sink)
{
if (!sink)
NS_QueryNotificationCallbacks(channel, sink);
}
void
nsSecureBrowserUIImpl::UpdateSecurityState(nsIRequest* aRequest,
bool withNewLocation,
bool withUpdateStatus)
{
lockIconState newSecurityState = lis_no_security;
if (mNewToplevelSecurityState & STATE_IS_SECURE) {
// If a subresoure/request was insecure, then we have mixed security.
if (mSubRequestsBrokenSecurity || mSubRequestsNoSecurity) {
newSecurityState = lis_mixed_security;
} else {
newSecurityState = lis_high_security;
}
}
if (mNewToplevelSecurityState & STATE_IS_BROKEN) {
newSecurityState = lis_broken_security;
}
mCertUserOverridden =
mNewToplevelSecurityState & STATE_CERT_USER_OVERRIDDEN;
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: UpdateSecurityState: old-new %d - %d\n", this,
mNotifiedSecurityState, newSecurityState));
bool flagsChanged = false;
if (mNotifiedSecurityState != newSecurityState) {
// Something changed since the last time.
flagsChanged = true;
mNotifiedSecurityState = newSecurityState;
// If we have no security, we also shouldn't have any SSL status.
if (newSecurityState == lis_no_security) {
mSSLStatus = nullptr;
}
}
if (mNotifiedToplevelIsEV != mNewToplevelIsEV) {
flagsChanged = true;
mNotifiedToplevelIsEV = mNewToplevelIsEV;
}
if (flagsChanged || withNewLocation || withUpdateStatus) {
TellTheWorld(aRequest);
}
}
void
nsSecureBrowserUIImpl::TellTheWorld(nsIRequest* aRequest)
{
uint32_t state = STATE_IS_INSECURE;
GetState(&state);
if (mToplevelEventSink) {
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: UpdateSecurityState: calling OnSecurityChange\n",
this));
mToplevelEventSink->OnSecurityChange(aRequest, state);
} else {
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: UpdateSecurityState: NO mToplevelEventSink!\n",
this));
}
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsIURI* aLocation,
uint32_t aFlags)
{
MOZ_ASSERT(NS_IsMainThread());
#ifdef DEBUG
nsAutoAtomic atomic(mOnStateLocationChangeReentranceDetection);
NS_ASSERTION(mOnStateLocationChangeReentranceDetection == 1,
"unexpected parallel nsIWebProgress OnStateChange and/or OnLocationChange notification");
#endif
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnLocationChange\n", this));
bool updateIsViewSource = false;
bool temp_IsViewSource = false;
nsCOMPtr<nsIDOMWindow> window;
if (aLocation)
{
bool vs;
nsresult rv = aLocation->SchemeIs("view-source", &vs);
NS_ENSURE_SUCCESS(rv, rv);
if (vs) {
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnLocationChange: view-source\n", this));
}
updateIsViewSource = true;
temp_IsViewSource = vs;
}
if (updateIsViewSource) {
mIsViewSource = temp_IsViewSource;
}
mCurrentURI = aLocation;
window = do_QueryReferent(mWindow);
NS_ASSERTION(window, "Window has gone away?!");
// When |aRequest| is null, basically we don't trust that document. But if
// docshell insists that the document has not changed at all, we will reuse
// the previous security state, no matter what |aRequest| may be.
if (aFlags & LOCATION_CHANGE_SAME_DOCUMENT)
return NS_OK;
// The location bar has changed, so we must update the security state. The
// only concern with doing this here is that a page may transition from being
// reported as completely secure to being reported as partially secure
// (mixed). This may be confusing for users, and it may bother users who
// like seeing security dialogs. However, it seems prudent given that page
// loading may never end in some edge cases (perhaps by a site with malicious
// intent).
nsCOMPtr<nsIDOMWindow> windowForProgress;
aWebProgress->GetDOMWindow(getter_AddRefs(windowForProgress));
nsCOMPtr<nsISupports> securityInfo(ExtractSecurityInfo(aRequest));
if (windowForProgress.get() == window.get()) {
// For toplevel channels, update the security state right away.
mOnLocationChangeSeen = true;
EvaluateAndUpdateSecurityState(aRequest, securityInfo, true, false);
return NS_OK;
}
// For channels in subdocuments we only update our subrequest state members.
UpdateSubrequestMembers(securityInfo, aRequest);
// Care for the following scenario:
// A new toplevel document load might have already started, but the security
// state of the new toplevel document might not yet be known.
//
// At this point, we are learning about the security state of a sub-document.
// We must not update the security state based on the sub content, if the new
// top level state is not yet known.
//
// We skip updating the security state in this case.
if (mNewToplevelSecurityStateKnown) {
UpdateSecurityState(aRequest, true, false);
}
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsresult aStatus,
const char16_t* aMessage)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
nsresult
nsSecureBrowserUIImpl::OnSecurityChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t state)
{
MOZ_ASSERT(NS_IsMainThread());
#if defined(DEBUG)
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
if (!channel)
return NS_OK;
nsCOMPtr<nsIURI> aURI;
channel->GetURI(getter_AddRefs(aURI));
if (aURI) {
nsAutoCString temp;
aURI->GetSpec(temp);
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: OnSecurityChange: (%x) %s\n", this,
state, temp.get()));
}
#endif
return NS_OK;
}
// nsISSLStatusProvider methods
NS_IMETHODIMP
nsSecureBrowserUIImpl::GetSSLStatus(nsISSLStatus** _result)
{
NS_ENSURE_ARG_POINTER(_result);
MOZ_ASSERT(NS_IsMainThread());
switch (mNotifiedSecurityState)
{
case lis_broken_security:
case lis_mixed_security:
case lis_high_security:
break;
default:
MOZ_FALLTHROUGH_ASSERT("if this is reached you must add more entries to the switch");
case lis_no_security:
*_result = nullptr;
return NS_OK;
}
*_result = mSSLStatus;
NS_IF_ADDREF(*_result);
return NS_OK;
}