OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | |
5 /** | 4 /** |
6 * @constructor | |
7 * @extends {WebInspector.PanelWithSidebar} | |
8 * @implements {WebInspector.TargetManager.Observer} | 5 * @implements {WebInspector.TargetManager.Observer} |
| 6 * @unrestricted |
9 */ | 7 */ |
10 WebInspector.SecurityPanel = function() | 8 WebInspector.SecurityPanel = class extends WebInspector.PanelWithSidebar { |
11 { | 9 constructor() { |
12 WebInspector.PanelWithSidebar.call(this, "security"); | 10 super('security'); |
13 | 11 |
14 this._mainView = new WebInspector.SecurityMainView(this); | 12 this._mainView = new WebInspector.SecurityMainView(this); |
15 | 13 |
16 this._sidebarMainViewElement = new WebInspector.SecurityPanelSidebarTreeElem
ent(WebInspector.UIString("Overview"), this._setVisibleView.bind(this, this._mai
nView), "security-main-view-sidebar-tree-item", "lock-icon"); | 14 this._sidebarMainViewElement = new WebInspector.SecurityPanelSidebarTreeElem
ent( |
17 this._sidebarTree = new WebInspector.SecurityPanelSidebarTree(this._sidebarM
ainViewElement, this.showOrigin.bind(this)); | 15 WebInspector.UIString('Overview'), this._setVisibleView.bind(this, this.
_mainView), |
| 16 'security-main-view-sidebar-tree-item', 'lock-icon'); |
| 17 this._sidebarTree = |
| 18 new WebInspector.SecurityPanelSidebarTree(this._sidebarMainViewElement,
this.showOrigin.bind(this)); |
18 this.panelSidebarElement().appendChild(this._sidebarTree.element); | 19 this.panelSidebarElement().appendChild(this._sidebarTree.element); |
19 | 20 |
20 /** @type {!Map<!NetworkAgent.LoaderId, !WebInspector.NetworkRequest>} */ | 21 /** @type {!Map<!NetworkAgent.LoaderId, !WebInspector.NetworkRequest>} */ |
21 this._lastResponseReceivedForLoaderId = new Map(); | 22 this._lastResponseReceivedForLoaderId = new Map(); |
22 | 23 |
23 /** @type {!Map<!WebInspector.SecurityPanel.Origin, !WebInspector.SecurityPa
nel.OriginState>} */ | 24 /** @type {!Map<!WebInspector.SecurityPanel.Origin, !WebInspector.SecurityPa
nel.OriginState>} */ |
24 this._origins = new Map(); | 25 this._origins = new Map(); |
25 | 26 |
26 /** @type {!Map<!WebInspector.NetworkLogView.MixedContentFilterValues, numbe
r>} */ | 27 /** @type {!Map<!WebInspector.NetworkLogView.MixedContentFilterValues, numbe
r>} */ |
27 this._filterRequestCounts = new Map(); | 28 this._filterRequestCounts = new Map(); |
28 | 29 |
29 /** @type {!Map<!WebInspector.Target, !Array<!WebInspector.EventTarget.Event
Descriptor>>}*/ | 30 /** @type {!Map<!WebInspector.Target, !Array<!WebInspector.EventTarget.Event
Descriptor>>}*/ |
30 this._eventListeners = new Map(); | 31 this._eventListeners = new Map(); |
31 WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capabili
ty.Network); | 32 WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capabili
ty.Network); |
| 33 } |
| 34 |
| 35 /** |
| 36 * @return {!WebInspector.SecurityPanel} |
| 37 */ |
| 38 static _instance() { |
| 39 return /** @type {!WebInspector.SecurityPanel} */ (self.runtime.sharedInstan
ce(WebInspector.SecurityPanel)); |
| 40 } |
| 41 |
| 42 /** |
| 43 * @param {string} text |
| 44 * @param {!WebInspector.SecurityPanel} panel |
| 45 * @return {!Element} |
| 46 */ |
| 47 static createCertificateViewerButton(text, panel) { |
| 48 /** |
| 49 * @param {!Event} e |
| 50 */ |
| 51 function showCertificateViewer(e) { |
| 52 e.consume(); |
| 53 panel.showCertificateViewer(); |
| 54 } |
| 55 |
| 56 return createTextButton(text, showCertificateViewer, 'security-certificate-b
utton'); |
| 57 } |
| 58 |
| 59 /** |
| 60 * @param {string} text |
| 61 * @param {string} origin |
| 62 * @return {!Element} |
| 63 */ |
| 64 static createCertificateViewerButton2(text, origin) { |
| 65 /** |
| 66 * @param {!Event} e |
| 67 */ |
| 68 function showCertificateViewer(e) { |
| 69 function certificateCallback(names) { |
| 70 InspectorFrontendHost.showCertificateViewer(names); |
| 71 } |
| 72 |
| 73 e.consume(); |
| 74 WebInspector.multitargetNetworkManager.getCertificate(origin, certificateC
allback); |
| 75 } |
| 76 |
| 77 return createTextButton(text, showCertificateViewer, 'security-certificate-b
utton'); |
| 78 } |
| 79 |
| 80 /** |
| 81 * @param {!SecurityAgent.SecurityState} securityState |
| 82 */ |
| 83 setRanInsecureContentStyle(securityState) { |
| 84 this._ranInsecureContentStyle = securityState; |
| 85 } |
| 86 |
| 87 /** |
| 88 * @param {!SecurityAgent.SecurityState} securityState |
| 89 */ |
| 90 setDisplayedInsecureContentStyle(securityState) { |
| 91 this._displayedInsecureContentStyle = securityState; |
| 92 } |
| 93 |
| 94 /** |
| 95 * @param {!SecurityAgent.SecurityState} newSecurityState |
| 96 * @param {!Array<!SecurityAgent.SecurityStateExplanation>} explanations |
| 97 * @param {?SecurityAgent.InsecureContentStatus} insecureContentStatus |
| 98 * @param {boolean} schemeIsCryptographic |
| 99 */ |
| 100 _updateSecurityState(newSecurityState, explanations, insecureContentStatus, sc
hemeIsCryptographic) { |
| 101 this._sidebarMainViewElement.setSecurityState(newSecurityState); |
| 102 this._mainView.updateSecurityState(newSecurityState, explanations, insecureC
ontentStatus, schemeIsCryptographic); |
| 103 } |
| 104 |
| 105 /** |
| 106 * @param {!WebInspector.Event} event |
| 107 */ |
| 108 _onSecurityStateChanged(event) { |
| 109 var data = /** @type {!WebInspector.PageSecurityState} */ (event.data); |
| 110 var securityState = /** @type {!SecurityAgent.SecurityState} */ (data.securi
tyState); |
| 111 var explanations = /** @type {!Array<!SecurityAgent.SecurityStateExplanation
>} */ (data.explanations); |
| 112 var insecureContentStatus = /** @type {?SecurityAgent.InsecureContentStatus}
*/ (data.insecureContentStatus); |
| 113 var schemeIsCryptographic = /** @type {boolean} */ (data.schemeIsCryptograph
ic); |
| 114 this._updateSecurityState(securityState, explanations, insecureContentStatus
, schemeIsCryptographic); |
| 115 } |
| 116 |
| 117 selectAndSwitchToMainView() { |
| 118 // The sidebar element will trigger displaying the main view. Rather than ma
king a redundant call to display the main view, we rely on this. |
| 119 this._sidebarMainViewElement.select(); |
| 120 } |
| 121 /** |
| 122 * @param {!WebInspector.SecurityPanel.Origin} origin |
| 123 */ |
| 124 showOrigin(origin) { |
| 125 var originState = this._origins.get(origin); |
| 126 if (!originState.originView) |
| 127 originState.originView = new WebInspector.SecurityOriginView(this, origin,
originState); |
| 128 |
| 129 this._setVisibleView(originState.originView); |
| 130 } |
| 131 |
| 132 /** |
| 133 * @override |
| 134 */ |
| 135 wasShown() { |
| 136 super.wasShown(); |
| 137 if (!this._visibleView) |
| 138 this.selectAndSwitchToMainView(); |
| 139 } |
| 140 |
| 141 /** |
| 142 * @override |
| 143 */ |
| 144 focus() { |
| 145 this._sidebarTree.focus(); |
| 146 } |
| 147 |
| 148 /** |
| 149 * @param {!WebInspector.VBox} view |
| 150 */ |
| 151 _setVisibleView(view) { |
| 152 if (this._visibleView === view) |
| 153 return; |
| 154 |
| 155 if (this._visibleView) |
| 156 this._visibleView.detach(); |
| 157 |
| 158 this._visibleView = view; |
| 159 |
| 160 if (view) |
| 161 this.splitWidget().setMainWidget(view); |
| 162 } |
| 163 |
| 164 /** |
| 165 * @param {!WebInspector.Event} event |
| 166 */ |
| 167 _onResponseReceived(event) { |
| 168 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data); |
| 169 if (request.resourceType() === WebInspector.resourceTypes.Document) |
| 170 this._lastResponseReceivedForLoaderId.set(request.loaderId, request); |
| 171 } |
| 172 |
| 173 /** |
| 174 * @param {!WebInspector.NetworkRequest} request |
| 175 */ |
| 176 _processRequest(request) { |
| 177 var origin = WebInspector.ParsedURL.extractOrigin(request.url); |
| 178 |
| 179 if (!origin) { |
| 180 // We don't handle resources like data: URIs. Most of them don't affect th
e lock icon. |
| 181 return; |
| 182 } |
| 183 |
| 184 var securityState = /** @type {!SecurityAgent.SecurityState} */ (request.sec
urityState()); |
| 185 |
| 186 if (request.mixedContentType === NetworkAgent.RequestMixedContentType.Blocka
ble && this._ranInsecureContentStyle) |
| 187 securityState = this._ranInsecureContentStyle; |
| 188 else if ( |
| 189 request.mixedContentType === NetworkAgent.RequestMixedContentType.Option
allyBlockable && |
| 190 this._displayedInsecureContentStyle) |
| 191 securityState = this._displayedInsecureContentStyle; |
| 192 |
| 193 if (this._origins.has(origin)) { |
| 194 var originState = this._origins.get(origin); |
| 195 var oldSecurityState = originState.securityState; |
| 196 originState.securityState = this._securityStateMin(oldSecurityState, secur
ityState); |
| 197 if (oldSecurityState !== originState.securityState) { |
| 198 this._sidebarTree.updateOrigin(origin, securityState); |
| 199 if (originState.originView) |
| 200 originState.originView.setSecurityState(securityState); |
| 201 } |
| 202 } else { |
| 203 // TODO(lgarron): Store a (deduplicated) list of different security detail
s we have seen. https://crbug.com/503170 |
| 204 var originState = {}; |
| 205 originState.securityState = securityState; |
| 206 |
| 207 var securityDetails = request.securityDetails(); |
| 208 if (securityDetails) { |
| 209 originState.securityDetails = securityDetails; |
| 210 } |
| 211 |
| 212 this._origins.set(origin, originState); |
| 213 |
| 214 this._sidebarTree.addOrigin(origin, securityState); |
| 215 |
| 216 // Don't construct the origin view yet (let it happen lazily). |
| 217 } |
| 218 } |
| 219 |
| 220 /** |
| 221 * @param {!WebInspector.Event} event |
| 222 */ |
| 223 _onRequestFinished(event) { |
| 224 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data); |
| 225 this._updateFilterRequestCounts(request); |
| 226 this._processRequest(request); |
| 227 } |
| 228 |
| 229 /** |
| 230 * @param {!WebInspector.NetworkRequest} request |
| 231 */ |
| 232 _updateFilterRequestCounts(request) { |
| 233 if (request.mixedContentType === NetworkAgent.RequestMixedContentType.None) |
| 234 return; |
| 235 |
| 236 /** @type {!WebInspector.NetworkLogView.MixedContentFilterValues} */ |
| 237 var filterKey = WebInspector.NetworkLogView.MixedContentFilterValues.All; |
| 238 if (request.wasBlocked()) |
| 239 filterKey = WebInspector.NetworkLogView.MixedContentFilterValues.Blocked; |
| 240 else if (request.mixedContentType === NetworkAgent.RequestMixedContentType.B
lockable) |
| 241 filterKey = WebInspector.NetworkLogView.MixedContentFilterValues.BlockOver
ridden; |
| 242 else if (request.mixedContentType === NetworkAgent.RequestMixedContentType.O
ptionallyBlockable) |
| 243 filterKey = WebInspector.NetworkLogView.MixedContentFilterValues.Displayed
; |
| 244 |
| 245 if (!this._filterRequestCounts.has(filterKey)) |
| 246 this._filterRequestCounts.set(filterKey, 1); |
| 247 else |
| 248 this._filterRequestCounts.set(filterKey, this._filterRequestCounts.get(fil
terKey) + 1); |
| 249 |
| 250 this._mainView.refreshExplanations(); |
| 251 } |
| 252 |
| 253 /** |
| 254 * @param {!WebInspector.NetworkLogView.MixedContentFilterValues} filterKey |
| 255 * @return {number} |
| 256 */ |
| 257 filterRequestCount(filterKey) { |
| 258 return this._filterRequestCounts.get(filterKey) || 0; |
| 259 } |
| 260 |
| 261 showCertificateViewer() { |
| 262 var securityModel = WebInspector.SecurityModel.fromTarget(this._target); |
| 263 securityModel.showCertificateViewer(); |
| 264 } |
| 265 |
| 266 /** |
| 267 * @param {!SecurityAgent.SecurityState} stateA |
| 268 * @param {!SecurityAgent.SecurityState} stateB |
| 269 * @return {!SecurityAgent.SecurityState} |
| 270 */ |
| 271 _securityStateMin(stateA, stateB) { |
| 272 return WebInspector.SecurityModel.SecurityStateComparator(stateA, stateB) <
0 ? stateA : stateB; |
| 273 } |
| 274 |
| 275 /** |
| 276 * @override |
| 277 * @param {!WebInspector.Target} target |
| 278 */ |
| 279 targetAdded(target) { |
| 280 if (this._target) |
| 281 return; |
| 282 |
| 283 var listeners = []; |
| 284 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target); |
| 285 if (resourceTreeModel) { |
| 286 listeners = listeners.concat([ |
| 287 resourceTreeModel.addEventListener( |
| 288 WebInspector.ResourceTreeModel.Events.MainFrameNavigated, this._onMa
inFrameNavigated, this), |
| 289 resourceTreeModel.addEventListener( |
| 290 WebInspector.ResourceTreeModel.Events.InterstitialShown, this._onInt
erstitialShown, this), |
| 291 resourceTreeModel.addEventListener( |
| 292 WebInspector.ResourceTreeModel.Events.InterstitialHidden, this._onIn
terstitialHidden, this), |
| 293 ]); |
| 294 } |
| 295 |
| 296 var networkManager = WebInspector.NetworkManager.fromTarget(target); |
| 297 if (networkManager) { |
| 298 listeners = listeners.concat([ |
| 299 networkManager.addEventListener( |
| 300 WebInspector.NetworkManager.Events.ResponseReceived, this._onRespons
eReceived, this), |
| 301 networkManager.addEventListener( |
| 302 WebInspector.NetworkManager.Events.RequestFinished, this._onRequestF
inished, this), |
| 303 ]); |
| 304 } |
| 305 |
| 306 var securityModel = WebInspector.SecurityModel.fromTarget(target); |
| 307 if (securityModel) { |
| 308 listeners = listeners.concat([securityModel.addEventListener( |
| 309 WebInspector.SecurityModel.Events.SecurityStateChanged, this._onSecuri
tyStateChanged, this)]); |
| 310 } |
| 311 |
| 312 this._target = target; |
| 313 this._eventListeners.set(target, listeners); |
| 314 } |
| 315 |
| 316 /** |
| 317 * @override |
| 318 * @param {!WebInspector.Target} target |
| 319 */ |
| 320 targetRemoved(target) { |
| 321 if (this._target !== target) |
| 322 return; |
| 323 |
| 324 delete this._target; |
| 325 |
| 326 WebInspector.EventTarget.removeEventListeners(this._eventListeners.get(targe
t)); |
| 327 this._eventListeners.delete(target); |
| 328 } |
| 329 |
| 330 /** |
| 331 * @param {!WebInspector.Event} event |
| 332 */ |
| 333 _onMainFrameNavigated(event) { |
| 334 var frame = /** type {!PageAgent.Frame}*/ (event.data); |
| 335 var request = this._lastResponseReceivedForLoaderId.get(frame.loaderId); |
| 336 |
| 337 this.selectAndSwitchToMainView(); |
| 338 this._sidebarTree.clearOrigins(); |
| 339 this._origins.clear(); |
| 340 this._lastResponseReceivedForLoaderId.clear(); |
| 341 this._filterRequestCounts.clear(); |
| 342 // After clearing the filtered request counts, refresh the |
| 343 // explanations to reflect the new counts. |
| 344 this._mainView.refreshExplanations(); |
| 345 |
| 346 if (request) { |
| 347 var origin = WebInspector.ParsedURL.extractOrigin(request.url); |
| 348 this._sidebarTree.setMainOrigin(origin); |
| 349 this._processRequest(request); |
| 350 } |
| 351 } |
| 352 |
| 353 _onInterstitialShown() { |
| 354 // The panel might have been displaying the origin view on the |
| 355 // previously loaded page. When showing an interstitial, switch |
| 356 // back to the Overview view. |
| 357 this.selectAndSwitchToMainView(); |
| 358 this._sidebarTree.toggleOriginsList(true /* hidden */); |
| 359 } |
| 360 |
| 361 _onInterstitialHidden() { |
| 362 this._sidebarTree.toggleOriginsList(false /* hidden */); |
| 363 } |
32 }; | 364 }; |
33 | 365 |
34 /** @typedef {string} */ | 366 /** @typedef {string} */ |
35 WebInspector.SecurityPanel.Origin; | 367 WebInspector.SecurityPanel.Origin; |
36 | 368 |
37 /** | 369 /** |
38 * @typedef {Object} | 370 * @typedef {Object} |
39 * @property {!SecurityAgent.SecurityState} securityState - Current security sta
te of the origin. | 371 * @property {!SecurityAgent.SecurityState} securityState - Current security sta
te of the origin. |
40 * @property {?NetworkAgent.SecurityDetails} securityDetails - Security details
of the origin, if available. | 372 * @property {?NetworkAgent.SecurityDetails} securityDetails - Security details
of the origin, if available. |
41 * @property {?Promise<>} certificateDetailsPromise - Certificate details of the
origin. | 373 * @property {?Promise<>} certificateDetailsPromise - Certificate details of the
origin. |
42 * @property {?WebInspector.SecurityOriginView} originView - Current SecurityOri
ginView corresponding to origin. | 374 * @property {?WebInspector.SecurityOriginView} originView - Current SecurityOri
ginView corresponding to origin. |
43 */ | 375 */ |
44 WebInspector.SecurityPanel.OriginState; | 376 WebInspector.SecurityPanel.OriginState; |
45 | 377 |
46 WebInspector.SecurityPanel.prototype = { | |
47 /** | |
48 * @param {!SecurityAgent.SecurityState} securityState | |
49 */ | |
50 setRanInsecureContentStyle: function(securityState) | |
51 { | |
52 this._ranInsecureContentStyle = securityState; | |
53 }, | |
54 | |
55 /** | |
56 * @param {!SecurityAgent.SecurityState} securityState | |
57 */ | |
58 setDisplayedInsecureContentStyle: function(securityState) | |
59 { | |
60 this._displayedInsecureContentStyle = securityState; | |
61 }, | |
62 | |
63 /** | |
64 * @param {!SecurityAgent.SecurityState} newSecurityState | |
65 * @param {!Array<!SecurityAgent.SecurityStateExplanation>} explanations | |
66 * @param {?SecurityAgent.InsecureContentStatus} insecureContentStatus | |
67 * @param {boolean} schemeIsCryptographic | |
68 */ | |
69 _updateSecurityState: function(newSecurityState, explanations, insecureConte
ntStatus, schemeIsCryptographic) | |
70 { | |
71 this._sidebarMainViewElement.setSecurityState(newSecurityState); | |
72 this._mainView.updateSecurityState(newSecurityState, explanations, insec
ureContentStatus, schemeIsCryptographic); | |
73 }, | |
74 | |
75 /** | |
76 * @param {!WebInspector.Event} event | |
77 */ | |
78 _onSecurityStateChanged: function(event) | |
79 { | |
80 var data = /** @type {!WebInspector.PageSecurityState} */ (event.data); | |
81 var securityState = /** @type {!SecurityAgent.SecurityState} */ (data.se
curityState); | |
82 var explanations = /** @type {!Array<!SecurityAgent.SecurityStateExplana
tion>} */ (data.explanations); | |
83 var insecureContentStatus = /** @type {?SecurityAgent.InsecureContentSta
tus} */ (data.insecureContentStatus); | |
84 var schemeIsCryptographic = /** @type {boolean} */ (data.schemeIsCryptog
raphic); | |
85 this._updateSecurityState(securityState, explanations, insecureContentSt
atus, schemeIsCryptographic); | |
86 }, | |
87 | |
88 selectAndSwitchToMainView: function() | |
89 { | |
90 // The sidebar element will trigger displaying the main view. Rather tha
n making a redundant call to display the main view, we rely on this. | |
91 this._sidebarMainViewElement.select(); | |
92 }, | |
93 /** | |
94 * @param {!WebInspector.SecurityPanel.Origin} origin | |
95 */ | |
96 showOrigin: function(origin) | |
97 { | |
98 var originState = this._origins.get(origin); | |
99 if (!originState.originView) | |
100 originState.originView = new WebInspector.SecurityOriginView(this, o
rigin, originState); | |
101 | |
102 this._setVisibleView(originState.originView); | |
103 }, | |
104 | |
105 wasShown: function() | |
106 { | |
107 WebInspector.Panel.prototype.wasShown.call(this); | |
108 if (!this._visibleView) | |
109 this.selectAndSwitchToMainView(); | |
110 }, | |
111 | |
112 /** | |
113 * @override | |
114 */ | |
115 focus: function() | |
116 { | |
117 this._sidebarTree.focus(); | |
118 }, | |
119 | |
120 /** | |
121 * @param {!WebInspector.VBox} view | |
122 */ | |
123 _setVisibleView: function(view) | |
124 { | |
125 if (this._visibleView === view) | |
126 return; | |
127 | |
128 if (this._visibleView) | |
129 this._visibleView.detach(); | |
130 | |
131 this._visibleView = view; | |
132 | |
133 if (view) | |
134 this.splitWidget().setMainWidget(view); | |
135 }, | |
136 | |
137 /** | |
138 * @param {!WebInspector.Event} event | |
139 */ | |
140 _onResponseReceived: function(event) | |
141 { | |
142 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data); | |
143 if (request.resourceType() === WebInspector.resourceTypes.Document) | |
144 this._lastResponseReceivedForLoaderId.set(request.loaderId, request)
; | |
145 }, | |
146 | |
147 /** | |
148 * @param {!WebInspector.NetworkRequest} request | |
149 */ | |
150 _processRequest: function(request) | |
151 { | |
152 var origin = WebInspector.ParsedURL.extractOrigin(request.url); | |
153 | |
154 if (!origin) { | |
155 // We don't handle resources like data: URIs. Most of them don't aff
ect the lock icon. | |
156 return; | |
157 } | |
158 | |
159 var securityState = /** @type {!SecurityAgent.SecurityState} */ (request
.securityState()); | |
160 | |
161 if (request.mixedContentType === NetworkAgent.RequestMixedContentType.Bl
ockable && this._ranInsecureContentStyle) | |
162 securityState = this._ranInsecureContentStyle; | |
163 else if (request.mixedContentType === NetworkAgent.RequestMixedContentTy
pe.OptionallyBlockable && this._displayedInsecureContentStyle) | |
164 securityState = this._displayedInsecureContentStyle; | |
165 | |
166 if (this._origins.has(origin)) { | |
167 var originState = this._origins.get(origin); | |
168 var oldSecurityState = originState.securityState; | |
169 originState.securityState = this._securityStateMin(oldSecurityState,
securityState); | |
170 if (oldSecurityState !== originState.securityState) { | |
171 this._sidebarTree.updateOrigin(origin, securityState); | |
172 if (originState.originView) | |
173 originState.originView.setSecurityState(securityState); | |
174 } | |
175 } else { | |
176 // TODO(lgarron): Store a (deduplicated) list of different security
details we have seen. https://crbug.com/503170 | |
177 var originState = {}; | |
178 originState.securityState = securityState; | |
179 | |
180 var securityDetails = request.securityDetails(); | |
181 if (securityDetails) { | |
182 originState.securityDetails = securityDetails; | |
183 } | |
184 | |
185 this._origins.set(origin, originState); | |
186 | |
187 this._sidebarTree.addOrigin(origin, securityState); | |
188 | |
189 // Don't construct the origin view yet (let it happen lazily). | |
190 } | |
191 }, | |
192 | |
193 /** | |
194 * @param {!WebInspector.Event} event | |
195 */ | |
196 _onRequestFinished: function(event) | |
197 { | |
198 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data); | |
199 this._updateFilterRequestCounts(request); | |
200 this._processRequest(request); | |
201 }, | |
202 | |
203 /** | |
204 * @param {!WebInspector.NetworkRequest} request | |
205 */ | |
206 _updateFilterRequestCounts: function(request) | |
207 { | |
208 if (request.mixedContentType === NetworkAgent.RequestMixedContentType.No
ne) | |
209 return; | |
210 | |
211 /** @type {!WebInspector.NetworkLogView.MixedContentFilterValues} */ | |
212 var filterKey = WebInspector.NetworkLogView.MixedContentFilterValues.All
; | |
213 if (request.wasBlocked()) | |
214 filterKey = WebInspector.NetworkLogView.MixedContentFilterValues.Blo
cked; | |
215 else if (request.mixedContentType === NetworkAgent.RequestMixedContentTy
pe.Blockable) | |
216 filterKey = WebInspector.NetworkLogView.MixedContentFilterValues.Blo
ckOverridden; | |
217 else if (request.mixedContentType === NetworkAgent.RequestMixedContentTy
pe.OptionallyBlockable) | |
218 filterKey = WebInspector.NetworkLogView.MixedContentFilterValues.Dis
played; | |
219 | |
220 if (!this._filterRequestCounts.has(filterKey)) | |
221 this._filterRequestCounts.set(filterKey, 1); | |
222 else | |
223 this._filterRequestCounts.set(filterKey, this._filterRequestCounts.g
et(filterKey) + 1); | |
224 | |
225 this._mainView.refreshExplanations(); | |
226 }, | |
227 | |
228 /** | |
229 * @param {!WebInspector.NetworkLogView.MixedContentFilterValues} filterKey | |
230 * @return {number} | |
231 */ | |
232 filterRequestCount: function(filterKey) | |
233 { | |
234 return this._filterRequestCounts.get(filterKey) || 0; | |
235 }, | |
236 | |
237 showCertificateViewer: function() | |
238 { | |
239 var securityModel = WebInspector.SecurityModel.fromTarget(this._target); | |
240 securityModel.showCertificateViewer(); | |
241 }, | |
242 | |
243 /** | |
244 * @param {!SecurityAgent.SecurityState} stateA | |
245 * @param {!SecurityAgent.SecurityState} stateB | |
246 * @return {!SecurityAgent.SecurityState} | |
247 */ | |
248 _securityStateMin: function(stateA, stateB) | |
249 { | |
250 return WebInspector.SecurityModel.SecurityStateComparator(stateA, stateB
) < 0 ? stateA : stateB; | |
251 }, | |
252 | |
253 /** | |
254 * @override | |
255 * @param {!WebInspector.Target} target | |
256 */ | |
257 targetAdded: function(target) | |
258 { | |
259 if (this._target) | |
260 return; | |
261 | |
262 var listeners = []; | |
263 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target
); | |
264 if (resourceTreeModel) { | |
265 listeners = listeners.concat([ | |
266 resourceTreeModel.addEventListener(WebInspector.ResourceTreeMode
l.Events.MainFrameNavigated, this._onMainFrameNavigated, this), | |
267 resourceTreeModel.addEventListener(WebInspector.ResourceTreeMode
l.Events.InterstitialShown, this._onInterstitialShown, this), | |
268 resourceTreeModel.addEventListener(WebInspector.ResourceTreeMode
l.Events.InterstitialHidden, this._onInterstitialHidden, this), | |
269 ]); | |
270 } | |
271 | |
272 var networkManager = WebInspector.NetworkManager.fromTarget(target); | |
273 if (networkManager) { | |
274 listeners = listeners.concat([ | |
275 networkManager.addEventListener(WebInspector.NetworkManager.Even
ts.ResponseReceived, this._onResponseReceived, this), | |
276 networkManager.addEventListener(WebInspector.NetworkManager.Even
ts.RequestFinished, this._onRequestFinished, this), | |
277 ]); | |
278 } | |
279 | |
280 var securityModel = WebInspector.SecurityModel.fromTarget(target); | |
281 if (securityModel) { | |
282 listeners = listeners.concat([ | |
283 securityModel.addEventListener(WebInspector.SecurityModel.Events
.SecurityStateChanged, this._onSecurityStateChanged, this) | |
284 ]); | |
285 } | |
286 | |
287 this._target = target; | |
288 this._eventListeners.set(target, listeners); | |
289 }, | |
290 | |
291 /** | |
292 * @override | |
293 * @param {!WebInspector.Target} target | |
294 */ | |
295 targetRemoved: function(target) | |
296 { | |
297 if (this._target !== target) | |
298 return; | |
299 | |
300 delete this._target; | |
301 | |
302 WebInspector.EventTarget.removeEventListeners(this._eventListeners.get(t
arget)); | |
303 this._eventListeners.delete(target); | |
304 }, | |
305 | |
306 /** | |
307 * @param {!WebInspector.Event} event | |
308 */ | |
309 _onMainFrameNavigated: function(event) | |
310 { | |
311 var frame = /** type {!PageAgent.Frame}*/ (event.data); | |
312 var request = this._lastResponseReceivedForLoaderId.get(frame.loaderId); | |
313 | |
314 this.selectAndSwitchToMainView(); | |
315 this._sidebarTree.clearOrigins(); | |
316 this._origins.clear(); | |
317 this._lastResponseReceivedForLoaderId.clear(); | |
318 this._filterRequestCounts.clear(); | |
319 // After clearing the filtered request counts, refresh the | |
320 // explanations to reflect the new counts. | |
321 this._mainView.refreshExplanations(); | |
322 | |
323 if (request) { | |
324 var origin = WebInspector.ParsedURL.extractOrigin(request.url); | |
325 this._sidebarTree.setMainOrigin(origin); | |
326 this._processRequest(request); | |
327 } | |
328 }, | |
329 | |
330 _onInterstitialShown: function() | |
331 { | |
332 // The panel might have been displaying the origin view on the | |
333 // previously loaded page. When showing an interstitial, switch | |
334 // back to the Overview view. | |
335 this.selectAndSwitchToMainView(); | |
336 this._sidebarTree.toggleOriginsList(true /* hidden */); | |
337 }, | |
338 | |
339 _onInterstitialHidden: function() | |
340 { | |
341 this._sidebarTree.toggleOriginsList(false /* hidden */); | |
342 }, | |
343 | |
344 __proto__: WebInspector.PanelWithSidebar.prototype | |
345 }; | |
346 | 378 |
347 /** | 379 /** |
348 * @return {!WebInspector.SecurityPanel} | 380 * @unrestricted |
349 */ | 381 */ |
350 WebInspector.SecurityPanel._instance = function() | 382 WebInspector.SecurityPanelSidebarTree = class extends TreeOutlineInShadow { |
351 { | 383 /** |
352 return /** @type {!WebInspector.SecurityPanel} */ (self.runtime.sharedInstan
ce(WebInspector.SecurityPanel)); | 384 * @param {!WebInspector.SecurityPanelSidebarTreeElement} mainViewElement |
353 }; | 385 * @param {function(!WebInspector.SecurityPanel.Origin)} showOriginInPanel |
354 | 386 */ |
355 /** | 387 constructor(mainViewElement, showOriginInPanel) { |
356 * @param {string} text | 388 super(); |
357 * @param {!WebInspector.SecurityPanel} panel | 389 this.registerRequiredCSS('security/sidebar.css'); |
358 * @return {!Element} | 390 this.registerRequiredCSS('security/lockIcon.css'); |
359 */ | |
360 WebInspector.SecurityPanel.createCertificateViewerButton = function(text, panel) | |
361 { | |
362 /** | |
363 * @param {!Event} e | |
364 */ | |
365 function showCertificateViewer(e) | |
366 { | |
367 e.consume(); | |
368 panel.showCertificateViewer(); | |
369 } | |
370 | |
371 return createTextButton(text, showCertificateViewer, "security-certificate-b
utton"); | |
372 }; | |
373 | |
374 /** | |
375 * @param {string} text | |
376 * @param {string} origin | |
377 * @return {!Element} | |
378 */ | |
379 WebInspector.SecurityPanel.createCertificateViewerButton2 = function(text, origi
n) | |
380 { | |
381 /** | |
382 * @param {!Event} e | |
383 */ | |
384 function showCertificateViewer(e) | |
385 { | |
386 function certificateCallback(names) | |
387 { | |
388 InspectorFrontendHost.showCertificateViewer(names); | |
389 } | |
390 | |
391 e.consume(); | |
392 WebInspector.multitargetNetworkManager.getCertificate(origin, certificat
eCallback); | |
393 } | |
394 | |
395 return createTextButton(text, showCertificateViewer, "security-certificate-b
utton"); | |
396 }; | |
397 | |
398 /** | |
399 * @constructor | |
400 * @extends {TreeOutlineInShadow} | |
401 * @param {!WebInspector.SecurityPanelSidebarTreeElement} mainViewElement | |
402 * @param {function(!WebInspector.SecurityPanel.Origin)} showOriginInPanel | |
403 */ | |
404 WebInspector.SecurityPanelSidebarTree = function(mainViewElement, showOriginInPa
nel) | |
405 { | |
406 TreeOutlineInShadow.call(this); | |
407 this.registerRequiredCSS("security/sidebar.css"); | |
408 this.registerRequiredCSS("security/lockIcon.css"); | |
409 this.appendChild(mainViewElement); | 391 this.appendChild(mainViewElement); |
410 | 392 |
411 this._showOriginInPanel = showOriginInPanel; | 393 this._showOriginInPanel = showOriginInPanel; |
412 this._mainOrigin = null; | 394 this._mainOrigin = null; |
413 | 395 |
414 /** @type {!Map<!WebInspector.SecurityPanelSidebarTree.OriginGroupName, !Tre
eElement>} */ | 396 /** @type {!Map<!WebInspector.SecurityPanelSidebarTree.OriginGroupName, !Tre
eElement>} */ |
415 this._originGroups = new Map(); | 397 this._originGroups = new Map(); |
416 | 398 |
417 for (var key in WebInspector.SecurityPanelSidebarTree.OriginGroupName) { | 399 for (var key in WebInspector.SecurityPanelSidebarTree.OriginGroupName) { |
418 var originGroupName = WebInspector.SecurityPanelSidebarTree.OriginGroupN
ame[key]; | 400 var originGroupName = WebInspector.SecurityPanelSidebarTree.OriginGroupNam
e[key]; |
419 var originGroup = new TreeElement(originGroupName, true); | 401 var originGroup = new TreeElement(originGroupName, true); |
420 originGroup.selectable = false; | 402 originGroup.selectable = false; |
421 originGroup.expand(); | 403 originGroup.expand(); |
422 originGroup.listItemElement.classList.add("security-sidebar-origins"); | 404 originGroup.listItemElement.classList.add('security-sidebar-origins'); |
423 this._originGroups.set(originGroupName, originGroup); | 405 this._originGroups.set(originGroupName, originGroup); |
424 this.appendChild(originGroup); | 406 this.appendChild(originGroup); |
425 } | 407 } |
426 this._clearOriginGroups(); | 408 this._clearOriginGroups(); |
427 | 409 |
428 // This message will be removed by clearOrigins() during the first new page
load after the panel was opened. | 410 // This message will be removed by clearOrigins() during the first new page
load after the panel was opened. |
429 var mainViewReloadMessage = new TreeElement(WebInspector.UIString("Reload to
view details")); | 411 var mainViewReloadMessage = new TreeElement(WebInspector.UIString('Reload to
view details')); |
430 mainViewReloadMessage.selectable = false; | 412 mainViewReloadMessage.selectable = false; |
431 mainViewReloadMessage.listItemElement.classList.add("security-main-view-relo
ad-message"); | 413 mainViewReloadMessage.listItemElement.classList.add('security-main-view-relo
ad-message'); |
432 this._originGroups.get(WebInspector.SecurityPanelSidebarTree.OriginGroupName
.MainOrigin).appendChild(mainViewReloadMessage); | 414 this._originGroups.get(WebInspector.SecurityPanelSidebarTree.OriginGroupName
.MainOrigin) |
| 415 .appendChild(mainViewReloadMessage); |
433 | 416 |
434 /** @type {!Map<!WebInspector.SecurityPanel.Origin, !WebInspector.SecurityPa
nelSidebarTreeElement>} */ | 417 /** @type {!Map<!WebInspector.SecurityPanel.Origin, !WebInspector.SecurityPa
nelSidebarTreeElement>} */ |
435 this._elementsByOrigin = new Map(); | 418 this._elementsByOrigin = new Map(); |
| 419 } |
| 420 |
| 421 /** |
| 422 * @param {boolean} hidden |
| 423 */ |
| 424 toggleOriginsList(hidden) { |
| 425 for (var key in WebInspector.SecurityPanelSidebarTree.OriginGroupName) { |
| 426 var originGroupName = WebInspector.SecurityPanelSidebarTree.OriginGroupNam
e[key]; |
| 427 var group = this._originGroups.get(originGroupName); |
| 428 if (group) |
| 429 group.hidden = hidden; |
| 430 } |
| 431 } |
| 432 |
| 433 /** |
| 434 * @param {!WebInspector.SecurityPanel.Origin} origin |
| 435 * @param {!SecurityAgent.SecurityState} securityState |
| 436 */ |
| 437 addOrigin(origin, securityState) { |
| 438 var originElement = new WebInspector.SecurityPanelSidebarTreeElement( |
| 439 origin, this._showOriginInPanel.bind(this, origin), 'security-sidebar-tr
ee-item', 'security-property'); |
| 440 originElement.listItemElement.title = origin; |
| 441 this._elementsByOrigin.set(origin, originElement); |
| 442 this.updateOrigin(origin, securityState); |
| 443 } |
| 444 |
| 445 /** |
| 446 * @param {!WebInspector.SecurityPanel.Origin} origin |
| 447 */ |
| 448 setMainOrigin(origin) { |
| 449 this._mainOrigin = origin; |
| 450 } |
| 451 |
| 452 /** |
| 453 * @param {!WebInspector.SecurityPanel.Origin} origin |
| 454 * @param {!SecurityAgent.SecurityState} securityState |
| 455 */ |
| 456 updateOrigin(origin, securityState) { |
| 457 var originElement = |
| 458 /** @type {!WebInspector.SecurityPanelSidebarTreeElement} */ (this._elem
entsByOrigin.get(origin)); |
| 459 originElement.setSecurityState(securityState); |
| 460 |
| 461 var newParent; |
| 462 if (origin === this._mainOrigin) { |
| 463 newParent = this._originGroups.get(WebInspector.SecurityPanelSidebarTree.O
riginGroupName.MainOrigin); |
| 464 } else { |
| 465 switch (securityState) { |
| 466 case SecurityAgent.SecurityState.Secure: |
| 467 newParent = this._originGroups.get(WebInspector.SecurityPanelSidebarTr
ee.OriginGroupName.Secure); |
| 468 break; |
| 469 case SecurityAgent.SecurityState.Unknown: |
| 470 newParent = this._originGroups.get(WebInspector.SecurityPanelSidebarTr
ee.OriginGroupName.Unknown); |
| 471 break; |
| 472 default: |
| 473 newParent = this._originGroups.get(WebInspector.SecurityPanelSidebarTr
ee.OriginGroupName.NonSecure); |
| 474 break; |
| 475 } |
| 476 } |
| 477 |
| 478 var oldParent = originElement.parent; |
| 479 if (oldParent !== newParent) { |
| 480 if (oldParent) { |
| 481 oldParent.removeChild(originElement); |
| 482 if (oldParent.childCount() === 0) |
| 483 oldParent.hidden = true; |
| 484 } |
| 485 newParent.appendChild(originElement); |
| 486 newParent.hidden = false; |
| 487 } |
| 488 } |
| 489 |
| 490 _clearOriginGroups() { |
| 491 for (var originGroup of this._originGroups.values()) { |
| 492 originGroup.removeChildren(); |
| 493 originGroup.hidden = true; |
| 494 } |
| 495 this._originGroups.get(WebInspector.SecurityPanelSidebarTree.OriginGroupName
.MainOrigin).hidden = false; |
| 496 } |
| 497 |
| 498 clearOrigins() { |
| 499 this._clearOriginGroups(); |
| 500 this._elementsByOrigin.clear(); |
| 501 } |
436 }; | 502 }; |
437 | 503 |
438 WebInspector.SecurityPanelSidebarTree.prototype = { | |
439 /** | |
440 * @param {boolean} hidden | |
441 */ | |
442 toggleOriginsList: function(hidden) | |
443 { | |
444 for (var key in WebInspector.SecurityPanelSidebarTree.OriginGroupName) { | |
445 var originGroupName = WebInspector.SecurityPanelSidebarTree.OriginGr
oupName[key]; | |
446 var group = this._originGroups.get(originGroupName); | |
447 if (group) | |
448 group.hidden = hidden; | |
449 } | |
450 }, | |
451 | |
452 /** | |
453 * @param {!WebInspector.SecurityPanel.Origin} origin | |
454 * @param {!SecurityAgent.SecurityState} securityState | |
455 */ | |
456 addOrigin: function(origin, securityState) | |
457 { | |
458 var originElement = new WebInspector.SecurityPanelSidebarTreeElement(ori
gin, this._showOriginInPanel.bind(this, origin), "security-sidebar-tree-item", "
security-property"); | |
459 originElement.listItemElement.title = origin; | |
460 this._elementsByOrigin.set(origin, originElement); | |
461 this.updateOrigin(origin, securityState); | |
462 }, | |
463 | |
464 /** | |
465 * @param {!WebInspector.SecurityPanel.Origin} origin | |
466 */ | |
467 setMainOrigin: function(origin) | |
468 { | |
469 this._mainOrigin = origin; | |
470 }, | |
471 | |
472 /** | |
473 * @param {!WebInspector.SecurityPanel.Origin} origin | |
474 * @param {!SecurityAgent.SecurityState} securityState | |
475 */ | |
476 updateOrigin: function(origin, securityState) | |
477 { | |
478 var originElement = /** @type {!WebInspector.SecurityPanelSidebarTreeEle
ment} */ (this._elementsByOrigin.get(origin)); | |
479 originElement.setSecurityState(securityState); | |
480 | |
481 var newParent; | |
482 if (origin === this._mainOrigin) { | |
483 newParent = this._originGroups.get(WebInspector.SecurityPanelSidebar
Tree.OriginGroupName.MainOrigin); | |
484 } else { | |
485 switch (securityState) { | |
486 case SecurityAgent.SecurityState.Secure: | |
487 newParent = this._originGroups.get(WebInspector.SecurityPanelSid
ebarTree.OriginGroupName.Secure); | |
488 break; | |
489 case SecurityAgent.SecurityState.Unknown: | |
490 newParent = this._originGroups.get(WebInspector.SecurityPanelSid
ebarTree.OriginGroupName.Unknown); | |
491 break; | |
492 default: | |
493 newParent = this._originGroups.get(WebInspector.SecurityPanelSid
ebarTree.OriginGroupName.NonSecure); | |
494 break; | |
495 } | |
496 } | |
497 | |
498 var oldParent = originElement.parent; | |
499 if (oldParent !== newParent) { | |
500 if (oldParent) { | |
501 oldParent.removeChild(originElement); | |
502 if (oldParent.childCount() === 0) | |
503 oldParent.hidden = true; | |
504 } | |
505 newParent.appendChild(originElement); | |
506 newParent.hidden = false; | |
507 } | |
508 | |
509 }, | |
510 | |
511 _clearOriginGroups: function() | |
512 { | |
513 for (var originGroup of this._originGroups.values()) { | |
514 originGroup.removeChildren(); | |
515 originGroup.hidden = true; | |
516 } | |
517 this._originGroups.get(WebInspector.SecurityPanelSidebarTree.OriginGroup
Name.MainOrigin).hidden = false; | |
518 }, | |
519 | |
520 clearOrigins: function() | |
521 { | |
522 this._clearOriginGroups(); | |
523 this._elementsByOrigin.clear(); | |
524 }, | |
525 | |
526 __proto__: TreeOutlineInShadow.prototype | |
527 }; | |
528 | |
529 | |
530 /** | 504 /** |
531 * A mapping from Javascript key IDs to names (sidebar section titles). | 505 * A mapping from Javascript key IDs to names (sidebar section titles). |
532 * Note: The names are used as keys into a map, so they must be distinct from ea
ch other. | 506 * Note: The names are used as keys into a map, so they must be distinct from ea
ch other. |
533 * @enum {string} | 507 * @enum {string} |
534 */ | 508 */ |
535 WebInspector.SecurityPanelSidebarTree.OriginGroupName = { | 509 WebInspector.SecurityPanelSidebarTree.OriginGroupName = { |
536 MainOrigin: WebInspector.UIString("Main Origin"), | 510 MainOrigin: WebInspector.UIString('Main Origin'), |
537 NonSecure: WebInspector.UIString("Non-Secure Origins"), | 511 NonSecure: WebInspector.UIString('Non-Secure Origins'), |
538 Secure: WebInspector.UIString("Secure Origins"), | 512 Secure: WebInspector.UIString('Secure Origins'), |
539 Unknown: WebInspector.UIString("Unknown / Canceled") | 513 Unknown: WebInspector.UIString('Unknown / Canceled') |
540 }; | 514 }; |
541 | 515 |
542 | |
543 /** | 516 /** |
544 * @constructor | 517 * @unrestricted |
545 * @extends {TreeElement} | |
546 * @param {string} text | |
547 * @param {function()} selectCallback | |
548 * @param {string} className | |
549 * @param {string} cssPrefix | |
550 */ | 518 */ |
551 WebInspector.SecurityPanelSidebarTreeElement = function(text, selectCallback, cl
assName, cssPrefix) | 519 WebInspector.SecurityPanelSidebarTreeElement = class extends TreeElement { |
552 { | 520 /** |
553 TreeElement.call(this, "", false); | 521 * @param {string} text |
| 522 * @param {function()} selectCallback |
| 523 * @param {string} className |
| 524 * @param {string} cssPrefix |
| 525 */ |
| 526 constructor(text, selectCallback, className, cssPrefix) { |
| 527 super('', false); |
554 this._selectCallback = selectCallback; | 528 this._selectCallback = selectCallback; |
555 this._cssPrefix = cssPrefix; | 529 this._cssPrefix = cssPrefix; |
556 this.listItemElement.classList.add(className); | 530 this.listItemElement.classList.add(className); |
557 this._iconElement = this.listItemElement.createChild("div", "icon"); | 531 this._iconElement = this.listItemElement.createChild('div', 'icon'); |
558 this._iconElement.classList.add(this._cssPrefix); | 532 this._iconElement.classList.add(this._cssPrefix); |
559 this.listItemElement.createChild("span", "title").textContent = text; | 533 this.listItemElement.createChild('span', 'title').textContent = text; |
560 this.setSecurityState(SecurityAgent.SecurityState.Unknown); | 534 this.setSecurityState(SecurityAgent.SecurityState.Unknown); |
| 535 } |
| 536 |
| 537 /** |
| 538 * @param {!WebInspector.SecurityPanelSidebarTreeElement} a |
| 539 * @param {!WebInspector.SecurityPanelSidebarTreeElement} b |
| 540 * @return {number} |
| 541 */ |
| 542 static SecurityStateComparator(a, b) { |
| 543 return WebInspector.SecurityModel.SecurityStateComparator(a.securityState(),
b.securityState()); |
| 544 } |
| 545 |
| 546 /** |
| 547 * @param {!SecurityAgent.SecurityState} newSecurityState |
| 548 */ |
| 549 setSecurityState(newSecurityState) { |
| 550 if (this._securityState) |
| 551 this._iconElement.classList.remove(this._cssPrefix + '-' + this._securityS
tate); |
| 552 |
| 553 this._securityState = newSecurityState; |
| 554 this._iconElement.classList.add(this._cssPrefix + '-' + newSecurityState); |
| 555 } |
| 556 |
| 557 /** |
| 558 * @return {!SecurityAgent.SecurityState} |
| 559 */ |
| 560 securityState() { |
| 561 return this._securityState; |
| 562 } |
| 563 |
| 564 /** |
| 565 * @override |
| 566 * @return {boolean} |
| 567 */ |
| 568 onselect() { |
| 569 this._selectCallback(); |
| 570 return true; |
| 571 } |
561 }; | 572 }; |
562 | 573 |
563 WebInspector.SecurityPanelSidebarTreeElement.prototype = { | 574 |
| 575 /** |
| 576 * @unrestricted |
| 577 */ |
| 578 WebInspector.SecurityMainView = class extends WebInspector.VBox { |
| 579 /** |
| 580 * @param {!WebInspector.SecurityPanel} panel |
| 581 */ |
| 582 constructor(panel) { |
| 583 super(true); |
| 584 this.registerRequiredCSS('security/mainView.css'); |
| 585 this.registerRequiredCSS('security/lockIcon.css'); |
| 586 this.setMinimumSize(200, 100); |
| 587 |
| 588 this.contentElement.classList.add('security-main-view'); |
| 589 |
| 590 this._panel = panel; |
| 591 |
| 592 this._summarySection = this.contentElement.createChild('div', 'security-summ
ary'); |
| 593 |
| 594 // Info explanations should appear after all others. |
| 595 this._securityExplanationsMain = this.contentElement.createChild('div', 'sec
urity-explanation-list'); |
| 596 this._securityExplanationsExtra = |
| 597 this.contentElement.createChild('div', 'security-explanation-list securi
ty-explanations-extra'); |
| 598 |
| 599 // Fill the security summary section. |
| 600 this._summarySection.createChild('div', 'security-summary-section-title').te
xtContent = |
| 601 WebInspector.UIString('Security Overview'); |
| 602 |
| 603 var lockSpectrum = this._summarySection.createChild('div', 'lock-spectrum'); |
| 604 lockSpectrum.createChild('div', 'lock-icon lock-icon-secure').title = WebIns
pector.UIString('Secure'); |
| 605 lockSpectrum.createChild('div', 'lock-icon lock-icon-neutral').title = WebIn
spector.UIString('Not Secure'); |
| 606 lockSpectrum.createChild('div', 'lock-icon lock-icon-insecure').title = |
| 607 WebInspector.UIString('Not Secure (Broken)'); |
| 608 |
| 609 this._summarySection.createChild('div', 'triangle-pointer-container') |
| 610 .createChild('div', 'triangle-pointer-wrapper') |
| 611 .createChild('div', 'triangle-pointer'); |
| 612 |
| 613 this._summaryText = this._summarySection.createChild('div', 'security-summar
y-text'); |
| 614 } |
| 615 |
| 616 /** |
| 617 * @param {!Element} parent |
| 618 * @param {!SecurityAgent.SecurityStateExplanation} explanation |
| 619 * @return {!Element} |
| 620 */ |
| 621 _addExplanation(parent, explanation) { |
| 622 var explanationSection = parent.createChild('div', 'security-explanation'); |
| 623 explanationSection.classList.add('security-explanation-' + explanation.secur
ityState); |
| 624 |
| 625 explanationSection.createChild('div', 'security-property') |
| 626 .classList.add('security-property-' + explanation.securityState); |
| 627 var text = explanationSection.createChild('div', 'security-explanation-text'
); |
| 628 text.createChild('div', 'security-explanation-title').textContent = explanat
ion.summary; |
| 629 text.createChild('div').textContent = explanation.description; |
| 630 |
| 631 if (explanation.hasCertificate) { |
| 632 text.appendChild(WebInspector.SecurityPanel.createCertificateViewerButton( |
| 633 WebInspector.UIString('View certificate'), this._panel)); |
| 634 } |
| 635 |
| 636 return text; |
| 637 } |
| 638 |
| 639 /** |
| 640 * @param {!SecurityAgent.SecurityState} newSecurityState |
| 641 * @param {!Array<!SecurityAgent.SecurityStateExplanation>} explanations |
| 642 * @param {?SecurityAgent.InsecureContentStatus} insecureContentStatus |
| 643 * @param {boolean} schemeIsCryptographic |
| 644 */ |
| 645 updateSecurityState(newSecurityState, explanations, insecureContentStatus, sch
emeIsCryptographic) { |
| 646 // Remove old state. |
| 647 // It's safe to call this even when this._securityState is undefined. |
| 648 this._summarySection.classList.remove('security-summary-' + this._securitySt
ate); |
| 649 |
| 650 // Add new state. |
| 651 this._securityState = newSecurityState; |
| 652 this._summarySection.classList.add('security-summary-' + this._securityState
); |
| 653 var summaryExplanationStrings = { |
| 654 'unknown': WebInspector.UIString('The security of this page is unknown.'), |
| 655 'insecure': WebInspector.UIString('This page is not secure (broken HTTPS).
'), |
| 656 'neutral': WebInspector.UIString('This page is not secure.'), |
| 657 'secure': WebInspector.UIString('This page is secure (valid HTTPS).') |
| 658 }; |
| 659 this._summaryText.textContent = summaryExplanationStrings[this._securityStat
e]; |
| 660 |
| 661 this._explanations = explanations, this._insecureContentStatus = insecureCon
tentStatus; |
| 662 this._schemeIsCryptographic = schemeIsCryptographic; |
| 663 |
| 664 this._panel.setRanInsecureContentStyle(insecureContentStatus.ranInsecureCont
entStyle); |
| 665 this._panel.setDisplayedInsecureContentStyle(insecureContentStatus.displayed
InsecureContentStyle); |
| 666 |
| 667 this.refreshExplanations(); |
| 668 } |
| 669 |
| 670 refreshExplanations() { |
| 671 this._securityExplanationsMain.removeChildren(); |
| 672 this._securityExplanationsExtra.removeChildren(); |
| 673 for (var explanation of this._explanations) { |
| 674 if (explanation.securityState === SecurityAgent.SecurityState.Info) { |
| 675 this._addExplanation(this._securityExplanationsExtra, explanation); |
| 676 } else { |
| 677 this._addExplanation(this._securityExplanationsMain, explanation); |
| 678 } |
| 679 } |
| 680 |
| 681 this._addMixedContentExplanations(); |
| 682 this._addContentWithCertErrorsExplanations(); |
| 683 |
| 684 // If all resources were served securely, add a Secure explanation. |
| 685 if (this._schemeIsCryptographic && this._insecureContentStatus && |
| 686 (!this._insecureContentStatus.displayedMixedContent && !this._insecureCo
ntentStatus.ranMixedContent && |
| 687 !this._insecureContentStatus.displayedContentWithCertErrors && |
| 688 !this._insecureContentStatus.ranContentWithCertErrors)) { |
| 689 this._addExplanation(this._securityExplanationsMain, /** @type {!SecurityA
gent.SecurityStateExplanation} */ ({ |
| 690 'securityState': SecurityAgent.SecurityState.Secure
, |
| 691 'summary': WebInspector.UIString('Secure Resources'
), |
| 692 'description': WebInspector.UIString('All resources
on this page are served securely.') |
| 693 })); |
| 694 } |
| 695 } |
| 696 |
| 697 _addMixedContentExplanations() { |
| 698 if (!this._schemeIsCryptographic) |
| 699 return; |
| 700 |
| 701 if (this._insecureContentStatus && |
| 702 (this._insecureContentStatus.ranMixedContent || this._insecureContentSta
tus.displayedMixedContent)) { |
| 703 if (this._insecureContentStatus.ranMixedContent) |
| 704 this._addMixedContentExplanation( |
| 705 this._securityExplanationsMain, this._insecureContentStatus.ranInsec
ureContentStyle, |
| 706 WebInspector.UIString('Active Mixed Content'), |
| 707 WebInspector.UIString( |
| 708 'You have recently allowed non-secure content (such as scripts o
r iframes) to run on this site.'), |
| 709 WebInspector.NetworkLogView.MixedContentFilterValues.BlockOverridden
, |
| 710 showBlockOverriddenMixedContentInNetworkPanel); |
| 711 if (this._insecureContentStatus.displayedMixedContent) |
| 712 this._addMixedContentExplanation( |
| 713 this._securityExplanationsMain, this._insecureContentStatus.displaye
dInsecureContentStyle, |
| 714 WebInspector.UIString('Mixed Content'), WebInspector.UIString('The s
ite includes HTTP resources.'), |
| 715 WebInspector.NetworkLogView.MixedContentFilterValues.Displayed, show
DisplayedMixedContentInNetworkPanel); |
| 716 } |
| 717 |
| 718 if (this._panel.filterRequestCount(WebInspector.NetworkLogView.MixedContentF
ilterValues.Blocked) > 0) |
| 719 this._addMixedContentExplanation( |
| 720 this._securityExplanationsExtra, SecurityAgent.SecurityState.Info, |
| 721 WebInspector.UIString('Blocked mixed content'), |
| 722 WebInspector.UIString('Your page requested non-secure resources that w
ere blocked.'), |
| 723 WebInspector.NetworkLogView.MixedContentFilterValues.Blocked, showBloc
kedMixedContentInNetworkPanel); |
| 724 |
564 /** | 725 /** |
565 * @param {!SecurityAgent.SecurityState} newSecurityState | 726 * @param {!Event} e |
566 */ | 727 */ |
567 setSecurityState: function(newSecurityState) | 728 function showDisplayedMixedContentInNetworkPanel(e) { |
568 { | 729 e.consume(); |
569 if (this._securityState) | 730 WebInspector.NetworkPanel.revealAndFilter([{ |
570 this._iconElement.classList.remove(this._cssPrefix + "-" + this._sec
urityState); | 731 filterType: WebInspector.NetworkLogView.FilterType.MixedContent, |
571 | 732 filterValue: WebInspector.NetworkLogView.MixedContentFilterValues.Displa
yed |
572 this._securityState = newSecurityState; | 733 }]); |
573 this._iconElement.classList.add(this._cssPrefix + "-" + newSecurityState
); | 734 } |
574 }, | |
575 | 735 |
576 /** | 736 /** |
577 * @return {!SecurityAgent.SecurityState} | 737 * @param {!Event} e |
578 */ | 738 */ |
579 securityState: function() | 739 function showBlockOverriddenMixedContentInNetworkPanel(e) { |
580 { | 740 e.consume(); |
581 return this._securityState; | 741 WebInspector.NetworkPanel.revealAndFilter([{ |
582 }, | 742 filterType: WebInspector.NetworkLogView.FilterType.MixedContent, |
| 743 filterValue: WebInspector.NetworkLogView.MixedContentFilterValues.BlockO
verridden |
| 744 }]); |
| 745 } |
583 | 746 |
584 /** | 747 /** |
585 * @override | 748 * @param {!Event} e |
586 * @return {boolean} | |
587 */ | 749 */ |
588 onselect: function() | 750 function showBlockedMixedContentInNetworkPanel(e) { |
589 { | 751 e.consume(); |
590 this._selectCallback(); | 752 WebInspector.NetworkPanel.revealAndFilter([{ |
591 return true; | 753 filterType: WebInspector.NetworkLogView.FilterType.MixedContent, |
592 }, | 754 filterValue: WebInspector.NetworkLogView.MixedContentFilterValues.Blocke
d |
593 | 755 }]); |
594 __proto__: TreeElement.prototype | 756 } |
| 757 } |
| 758 |
| 759 /** |
| 760 * @param {!Element} parent |
| 761 * @param {!SecurityAgent.SecurityState} securityState |
| 762 * @param {string} summary |
| 763 * @param {string} description |
| 764 * @param {!WebInspector.NetworkLogView.MixedContentFilterValues} filterKey |
| 765 * @param {!Function} networkFilterFn |
| 766 */ |
| 767 _addMixedContentExplanation(parent, securityState, summary, description, filte
rKey, networkFilterFn) { |
| 768 var mixedContentExplanation = /** @type {!SecurityAgent.SecurityStateExplana
tion} */ ( |
| 769 {'securityState': securityState, 'summary': summary, 'description': desc
ription}); |
| 770 |
| 771 var explanation = this._addExplanation(parent, mixedContentExplanation); |
| 772 |
| 773 var filterRequestCount = this._panel.filterRequestCount(filterKey); |
| 774 if (!filterRequestCount) { |
| 775 // Network instrumentation might not have been enabled for the page |
| 776 // load, so the security panel does not necessarily know a count of |
| 777 // individual mixed requests at this point. Prompt them to refresh |
| 778 // instead of pointing them to the Network panel to get prompted |
| 779 // to refresh. |
| 780 var refreshPrompt = explanation.createChild('div', 'security-mixed-content
'); |
| 781 refreshPrompt.textContent = WebInspector.UIString('Reload the page to reco
rd requests for HTTP resources.'); |
| 782 return; |
| 783 } |
| 784 |
| 785 var requestsAnchor = explanation.createChild('div', 'security-mixed-content
link'); |
| 786 if (filterRequestCount === 1) { |
| 787 requestsAnchor.textContent = WebInspector.UIString('View %d request in Net
work Panel', filterRequestCount); |
| 788 } else { |
| 789 requestsAnchor.textContent = WebInspector.UIString('View %d requests in Ne
twork Panel', filterRequestCount); |
| 790 } |
| 791 requestsAnchor.href = ''; |
| 792 requestsAnchor.addEventListener('click', networkFilterFn); |
| 793 } |
| 794 |
| 795 _addContentWithCertErrorsExplanations() { |
| 796 if (!this._schemeIsCryptographic) |
| 797 return; |
| 798 |
| 799 if (!this._insecureContentStatus) |
| 800 return; |
| 801 |
| 802 if (this._insecureContentStatus.ranContentWithCertErrors) { |
| 803 this._addExplanation( |
| 804 this._securityExplanationsMain, /** @type {!SecurityAgent.SecurityStat
eExplanation} */ ({ |
| 805 'securityState': this._insecureContentStatus.ranInsecureContentStyle
, |
| 806 'summary': WebInspector.UIString('Active content with certificate er
rors'), |
| 807 'description': WebInspector.UIString( |
| 808 'You have recently allowed content loaded with certificate error
s (such as scripts or iframes) to run on this site.') |
| 809 })); |
| 810 } |
| 811 |
| 812 if (this._insecureContentStatus.displayedContentWithCertErrors) { |
| 813 this._addExplanation(this._securityExplanationsMain, /** @type {!SecurityA
gent.SecurityStateExplanation} */ ({ |
| 814 'securityState': this._insecureContentStatus.displa
yedInsecureContentStyle, |
| 815 'summary': WebInspector.UIString('Content with cert
ificate errors'), |
| 816 'description': WebInspector.UIString( |
| 817 'This site includes resources that were loaded
with certificate errors.') |
| 818 })); |
| 819 } |
| 820 } |
595 }; | 821 }; |
596 | 822 |
597 /** | 823 /** |
598 * @param {!WebInspector.SecurityPanelSidebarTreeElement} a | 824 * @unrestricted |
599 * @param {!WebInspector.SecurityPanelSidebarTreeElement} b | |
600 * @return {number} | |
601 */ | 825 */ |
602 WebInspector.SecurityPanelSidebarTreeElement.SecurityStateComparator = function(
a, b) | 826 WebInspector.SecurityOriginView = class extends WebInspector.VBox { |
603 { | 827 /** |
604 return WebInspector.SecurityModel.SecurityStateComparator(a.securityState(),
b.securityState()); | 828 * @param {!WebInspector.SecurityPanel} panel |
605 }; | 829 * @param {!WebInspector.SecurityPanel.Origin} origin |
606 | 830 * @param {!WebInspector.SecurityPanel.OriginState} originState |
607 /** | 831 */ |
608 * @constructor | 832 constructor(panel, origin, originState) { |
609 * @extends {WebInspector.VBox} | 833 super(); |
610 * @param {!WebInspector.SecurityPanel} panel | |
611 */ | |
612 WebInspector.SecurityMainView = function(panel) | |
613 { | |
614 WebInspector.VBox.call(this, true); | |
615 this.registerRequiredCSS("security/mainView.css"); | |
616 this.registerRequiredCSS("security/lockIcon.css"); | |
617 this.setMinimumSize(200, 100); | |
618 | |
619 this.contentElement.classList.add("security-main-view"); | |
620 | |
621 this._panel = panel; | |
622 | |
623 this._summarySection = this.contentElement.createChild("div", "security-summ
ary"); | |
624 | |
625 // Info explanations should appear after all others. | |
626 this._securityExplanationsMain = this.contentElement.createChild("div", "sec
urity-explanation-list"); | |
627 this._securityExplanationsExtra = this.contentElement.createChild("div", "se
curity-explanation-list security-explanations-extra"); | |
628 | |
629 // Fill the security summary section. | |
630 this._summarySection.createChild("div", "security-summary-section-title").te
xtContent = WebInspector.UIString("Security Overview"); | |
631 | |
632 var lockSpectrum = this._summarySection.createChild("div", "lock-spectrum"); | |
633 lockSpectrum.createChild("div", "lock-icon lock-icon-secure").title = WebIns
pector.UIString("Secure"); | |
634 lockSpectrum.createChild("div", "lock-icon lock-icon-neutral").title = WebIn
spector.UIString("Not Secure"); | |
635 lockSpectrum.createChild("div", "lock-icon lock-icon-insecure").title = WebI
nspector.UIString("Not Secure (Broken)"); | |
636 | |
637 this._summarySection.createChild("div", "triangle-pointer-container").create
Child("div", "triangle-pointer-wrapper").createChild("div", "triangle-pointer"); | |
638 | |
639 this._summaryText = this._summarySection.createChild("div", "security-summar
y-text"); | |
640 }; | |
641 | |
642 WebInspector.SecurityMainView.prototype = { | |
643 /** | |
644 * @param {!Element} parent | |
645 * @param {!SecurityAgent.SecurityStateExplanation} explanation | |
646 * @return {!Element} | |
647 */ | |
648 _addExplanation: function(parent, explanation) | |
649 { | |
650 var explanationSection = parent.createChild("div", "security-explanation
"); | |
651 explanationSection.classList.add("security-explanation-" + explanation.s
ecurityState); | |
652 | |
653 explanationSection.createChild("div", "security-property").classList.add
("security-property-" + explanation.securityState); | |
654 var text = explanationSection.createChild("div", "security-explanation-t
ext"); | |
655 text.createChild("div", "security-explanation-title").textContent = expl
anation.summary; | |
656 text.createChild("div").textContent = explanation.description; | |
657 | |
658 if (explanation.hasCertificate) { | |
659 text.appendChild(WebInspector.SecurityPanel.createCertificateViewerB
utton(WebInspector.UIString("View certificate"), this._panel)); | |
660 } | |
661 | |
662 return text; | |
663 }, | |
664 | |
665 /** | |
666 * @param {!SecurityAgent.SecurityState} newSecurityState | |
667 * @param {!Array<!SecurityAgent.SecurityStateExplanation>} explanations | |
668 * @param {?SecurityAgent.InsecureContentStatus} insecureContentStatus | |
669 * @param {boolean} schemeIsCryptographic | |
670 */ | |
671 updateSecurityState: function(newSecurityState, explanations, insecureConten
tStatus, schemeIsCryptographic) | |
672 { | |
673 // Remove old state. | |
674 // It's safe to call this even when this._securityState is undefined. | |
675 this._summarySection.classList.remove("security-summary-" + this._securi
tyState); | |
676 | |
677 // Add new state. | |
678 this._securityState = newSecurityState; | |
679 this._summarySection.classList.add("security-summary-" + this._securityS
tate); | |
680 var summaryExplanationStrings = { | |
681 "unknown": WebInspector.UIString("The security of this page is unkn
own."), | |
682 "insecure": WebInspector.UIString("This page is not secure (broken H
TTPS)."), | |
683 "neutral": WebInspector.UIString("This page is not secure."), | |
684 "secure": WebInspector.UIString("This page is secure (valid HTTPS)
.") | |
685 }; | |
686 this._summaryText.textContent = summaryExplanationStrings[this._security
State]; | |
687 | |
688 this._explanations = explanations, | |
689 this._insecureContentStatus = insecureContentStatus; | |
690 this._schemeIsCryptographic = schemeIsCryptographic; | |
691 | |
692 this._panel.setRanInsecureContentStyle(insecureContentStatus.ranInsecure
ContentStyle); | |
693 this._panel.setDisplayedInsecureContentStyle(insecureContentStatus.displ
ayedInsecureContentStyle); | |
694 | |
695 this.refreshExplanations(); | |
696 }, | |
697 | |
698 refreshExplanations: function() | |
699 { | |
700 this._securityExplanationsMain.removeChildren(); | |
701 this._securityExplanationsExtra.removeChildren(); | |
702 for (var explanation of this._explanations) { | |
703 if (explanation.securityState === SecurityAgent.SecurityState.Info)
{ | |
704 this._addExplanation(this._securityExplanationsExtra, explanatio
n); | |
705 } else { | |
706 this._addExplanation(this._securityExplanationsMain, explanation
); | |
707 } | |
708 } | |
709 | |
710 this._addMixedContentExplanations(); | |
711 this._addContentWithCertErrorsExplanations(); | |
712 | |
713 // If all resources were served securely, add a Secure explanation. | |
714 if (this._schemeIsCryptographic && this._insecureContentStatus && (!this
._insecureContentStatus.displayedMixedContent && !this._insecureContentStatus.ra
nMixedContent && !this._insecureContentStatus.displayedContentWithCertErrors &&
!this._insecureContentStatus.ranContentWithCertErrors)) { | |
715 this._addExplanation(this._securityExplanationsMain, /** @type {!Sec
urityAgent.SecurityStateExplanation} */ ({ | |
716 "securityState": SecurityAgent.SecurityState.Secure, | |
717 "summary": WebInspector.UIString("Secure Resources"), | |
718 "description": WebInspector.UIString("All resources on this page
are served securely.") | |
719 })); | |
720 } | |
721 }, | |
722 | |
723 _addMixedContentExplanations: function() | |
724 { | |
725 if (!this._schemeIsCryptographic) | |
726 return; | |
727 | |
728 if (this._insecureContentStatus && (this._insecureContentStatus.ranMixed
Content || this._insecureContentStatus.displayedMixedContent)) { | |
729 if (this._insecureContentStatus.ranMixedContent) | |
730 this._addMixedContentExplanation(this._securityExplanationsMain,
this._insecureContentStatus.ranInsecureContentStyle, WebInspector.UIString("Act
ive Mixed Content"), WebInspector.UIString("You have recently allowed non-secure
content (such as scripts or iframes) to run on this site."), WebInspector.Netwo
rkLogView.MixedContentFilterValues.BlockOverridden, showBlockOverriddenMixedCont
entInNetworkPanel); | |
731 if (this._insecureContentStatus.displayedMixedContent) | |
732 this._addMixedContentExplanation(this._securityExplanationsMain,
this._insecureContentStatus.displayedInsecureContentStyle, WebInspector.UIStrin
g("Mixed Content"), WebInspector.UIString("The site includes HTTP resources."),
WebInspector.NetworkLogView.MixedContentFilterValues.Displayed, showDisplayedMix
edContentInNetworkPanel); | |
733 } | |
734 | |
735 if (this._panel.filterRequestCount(WebInspector.NetworkLogView.MixedCont
entFilterValues.Blocked) > 0) | |
736 this._addMixedContentExplanation(this._securityExplanationsExtra, Se
curityAgent.SecurityState.Info, WebInspector.UIString("Blocked mixed content"),
WebInspector.UIString("Your page requested non-secure resources that were blocke
d."), WebInspector.NetworkLogView.MixedContentFilterValues.Blocked, showBlockedM
ixedContentInNetworkPanel); | |
737 | |
738 /** | |
739 * @param {!Event} e | |
740 */ | |
741 function showDisplayedMixedContentInNetworkPanel(e) | |
742 { | |
743 e.consume(); | |
744 WebInspector.NetworkPanel.revealAndFilter([ | |
745 { | |
746 filterType: WebInspector.NetworkLogView.FilterType.MixedCont
ent, | |
747 filterValue: WebInspector.NetworkLogView.MixedContentFilterV
alues.Displayed | |
748 } | |
749 ]); | |
750 } | |
751 | |
752 /** | |
753 * @param {!Event} e | |
754 */ | |
755 function showBlockOverriddenMixedContentInNetworkPanel(e) | |
756 { | |
757 e.consume(); | |
758 WebInspector.NetworkPanel.revealAndFilter([ | |
759 { | |
760 filterType: WebInspector.NetworkLogView.FilterType.MixedCont
ent, | |
761 filterValue: WebInspector.NetworkLogView.MixedContentFilterV
alues.BlockOverridden | |
762 } | |
763 ]); | |
764 } | |
765 | |
766 /** | |
767 * @param {!Event} e | |
768 */ | |
769 function showBlockedMixedContentInNetworkPanel(e) | |
770 { | |
771 e.consume(); | |
772 WebInspector.NetworkPanel.revealAndFilter([ | |
773 { | |
774 filterType: WebInspector.NetworkLogView.FilterType.MixedCont
ent, | |
775 filterValue: WebInspector.NetworkLogView.MixedContentFilterV
alues.Blocked | |
776 } | |
777 ]); | |
778 } | |
779 }, | |
780 | |
781 /** | |
782 * @param {!Element} parent | |
783 * @param {!SecurityAgent.SecurityState} securityState | |
784 * @param {string} summary | |
785 * @param {string} description | |
786 * @param {!WebInspector.NetworkLogView.MixedContentFilterValues} filterKey | |
787 * @param {!Function} networkFilterFn | |
788 */ | |
789 _addMixedContentExplanation: function(parent, securityState, summary, descri
ption, filterKey, networkFilterFn) | |
790 { | |
791 var mixedContentExplanation = /** @type {!SecurityAgent.SecurityStateExp
lanation} */ ({ | |
792 "securityState": securityState, | |
793 "summary": summary, | |
794 "description": description | |
795 }); | |
796 | |
797 var explanation = this._addExplanation(parent, mixedContentExplanation); | |
798 | |
799 var filterRequestCount = this._panel.filterRequestCount(filterKey); | |
800 if (!filterRequestCount) { | |
801 // Network instrumentation might not have been enabled for the page | |
802 // load, so the security panel does not necessarily know a count of | |
803 // individual mixed requests at this point. Prompt them to refresh | |
804 // instead of pointing them to the Network panel to get prompted | |
805 // to refresh. | |
806 var refreshPrompt = explanation.createChild("div", "security-mixed-c
ontent"); | |
807 refreshPrompt.textContent = WebInspector.UIString("Reload the page t
o record requests for HTTP resources."); | |
808 return; | |
809 } | |
810 | |
811 var requestsAnchor = explanation.createChild("div", "security-mixed-cont
ent link"); | |
812 if (filterRequestCount === 1) { | |
813 requestsAnchor.textContent = WebInspector.UIString("View %d request
in Network Panel", filterRequestCount); | |
814 } else { | |
815 requestsAnchor.textContent = WebInspector.UIString("View %d requests
in Network Panel", filterRequestCount); | |
816 } | |
817 requestsAnchor.href = ""; | |
818 requestsAnchor.addEventListener("click", networkFilterFn); | |
819 }, | |
820 | |
821 _addContentWithCertErrorsExplanations: function() | |
822 { | |
823 if (!this._schemeIsCryptographic) | |
824 return; | |
825 | |
826 if (!this._insecureContentStatus) | |
827 return; | |
828 | |
829 if (this._insecureContentStatus.ranContentWithCertErrors) { | |
830 this._addExplanation(this._securityExplanationsMain, /** @type {!Sec
urityAgent.SecurityStateExplanation} */ ({ | |
831 "securityState": this._insecureContentStatus.ranInsecureContentS
tyle, | |
832 "summary": WebInspector.UIString("Active content with certificat
e errors"), | |
833 "description": WebInspector.UIString("You have recently allowed
content loaded with certificate errors (such as scripts or iframes) to run on th
is site.") | |
834 })); | |
835 } | |
836 | |
837 if (this._insecureContentStatus.displayedContentWithCertErrors) { | |
838 this._addExplanation(this._securityExplanationsMain, /** @type {!Sec
urityAgent.SecurityStateExplanation} */ ({ | |
839 "securityState": this._insecureContentStatus.displayedInsecureCo
ntentStyle, | |
840 "summary": WebInspector.UIString("Content with certificate error
s"), | |
841 "description": WebInspector.UIString("This site includes resourc
es that were loaded with certificate errors.") | |
842 })); | |
843 } | |
844 }, | |
845 | |
846 | |
847 __proto__: WebInspector.VBox.prototype | |
848 }; | |
849 | |
850 /** | |
851 * @constructor | |
852 * @extends {WebInspector.VBox} | |
853 * @param {!WebInspector.SecurityPanel} panel | |
854 * @param {!WebInspector.SecurityPanel.Origin} origin | |
855 * @param {!WebInspector.SecurityPanel.OriginState} originState | |
856 */ | |
857 WebInspector.SecurityOriginView = function(panel, origin, originState) | |
858 { | |
859 WebInspector.VBox.call(this); | |
860 this._panel = panel; | 834 this._panel = panel; |
861 this.setMinimumSize(200, 100); | 835 this.setMinimumSize(200, 100); |
862 | 836 |
863 this.element.classList.add("security-origin-view"); | 837 this.element.classList.add('security-origin-view'); |
864 this.registerRequiredCSS("security/originView.css"); | 838 this.registerRequiredCSS('security/originView.css'); |
865 this.registerRequiredCSS("security/lockIcon.css"); | 839 this.registerRequiredCSS('security/lockIcon.css'); |
866 | 840 |
867 var titleSection = this.element.createChild("div", "title-section"); | 841 var titleSection = this.element.createChild('div', 'title-section'); |
868 var originDisplay = titleSection.createChild("div", "origin-display"); | 842 var originDisplay = titleSection.createChild('div', 'origin-display'); |
869 this._originLockIcon = originDisplay.createChild("span", "security-property"
); | 843 this._originLockIcon = originDisplay.createChild('span', 'security-property'
); |
870 this._originLockIcon.classList.add("security-property-" + originState.securi
tyState); | 844 this._originLockIcon.classList.add('security-property-' + originState.securi
tyState); |
871 // TODO(lgarron): Highlight the origin scheme. https://crbug.com/523589 | 845 // TODO(lgarron): Highlight the origin scheme. https://crbug.com/523589 |
872 originDisplay.createChild("span", "origin").textContent = origin; | 846 originDisplay.createChild('span', 'origin').textContent = origin; |
873 var originNetworkLink = titleSection.createChild("div", "link"); | 847 var originNetworkLink = titleSection.createChild('div', 'link'); |
874 originNetworkLink.textContent = WebInspector.UIString("View requests in Netw
ork Panel"); | 848 originNetworkLink.textContent = WebInspector.UIString('View requests in Netw
ork Panel'); |
875 function showOriginRequestsInNetworkPanel() | 849 function showOriginRequestsInNetworkPanel() { |
876 { | 850 var parsedURL = new WebInspector.ParsedURL(origin); |
877 var parsedURL = new WebInspector.ParsedURL(origin); | 851 WebInspector.NetworkPanel.revealAndFilter([ |
878 WebInspector.NetworkPanel.revealAndFilter([ | 852 {filterType: WebInspector.NetworkLogView.FilterType.Domain, filterValue:
parsedURL.host}, |
879 { | 853 {filterType: WebInspector.NetworkLogView.FilterType.Scheme, filterValue:
parsedURL.scheme} |
880 filterType: WebInspector.NetworkLogView.FilterType.Domain, | 854 ]); |
881 filterValue: parsedURL.host | 855 } |
882 }, | 856 originNetworkLink.addEventListener('click', showOriginRequestsInNetworkPanel
, false); |
883 { | |
884 filterType: WebInspector.NetworkLogView.FilterType.Scheme, | |
885 filterValue: parsedURL.scheme | |
886 } | |
887 ]); | |
888 } | |
889 originNetworkLink.addEventListener("click", showOriginRequestsInNetworkPanel
, false); | |
890 | |
891 | 857 |
892 if (originState.securityDetails) { | 858 if (originState.securityDetails) { |
893 var connectionSection = this.element.createChild("div", "origin-view-sec
tion"); | 859 var connectionSection = this.element.createChild('div', 'origin-view-secti
on'); |
894 connectionSection.createChild("div", "origin-view-section-title").textCo
ntent = WebInspector.UIString("Connection"); | 860 connectionSection.createChild('div', 'origin-view-section-title').textCont
ent = |
895 | 861 WebInspector.UIString('Connection'); |
896 var table = new WebInspector.SecurityDetailsTable(); | 862 |
897 connectionSection.appendChild(table.element()); | 863 var table = new WebInspector.SecurityDetailsTable(); |
898 table.addRow("Protocol", originState.securityDetails.protocol); | 864 connectionSection.appendChild(table.element()); |
899 if (originState.securityDetails.keyExchange) | 865 table.addRow('Protocol', originState.securityDetails.protocol); |
900 table.addRow("Key Exchange", originState.securityDetails.keyExchange
); | 866 if (originState.securityDetails.keyExchange) |
901 if (originState.securityDetails.keyExchangeGroup) | 867 table.addRow('Key Exchange', originState.securityDetails.keyExchange); |
902 table.addRow("Key Exchange Group", originState.securityDetails.keyEx
changeGroup); | 868 if (originState.securityDetails.keyExchangeGroup) |
903 table.addRow("Cipher", originState.securityDetails.cipher + (originState
.securityDetails.mac ? " with " + originState.securityDetails.mac : "")); | 869 table.addRow('Key Exchange Group', originState.securityDetails.keyExchan
geGroup); |
904 | 870 table.addRow( |
905 // Create the certificate section outside the callback, so that it appea
rs in the right place. | 871 'Cipher', originState.securityDetails.cipher + |
906 var certificateSection = this.element.createChild("div", "origin-view-se
ction"); | 872 (originState.securityDetails.mac ? ' with ' + originState.security
Details.mac : '')); |
907 certificateSection.createChild("div", "origin-view-section-title").textC
ontent = WebInspector.UIString("Certificate"); | 873 |
908 | 874 // Create the certificate section outside the callback, so that it appears
in the right place. |
909 if (originState.securityDetails.signedCertificateTimestampList.length) { | 875 var certificateSection = this.element.createChild('div', 'origin-view-sect
ion'); |
910 // Create the Certificate Transparency section outside the callback,
so that it appears in the right place. | 876 certificateSection.createChild('div', 'origin-view-section-title').textCon
tent = |
911 var sctSection = this.element.createChild("div", "origin-view-sectio
n"); | 877 WebInspector.UIString('Certificate'); |
912 sctSection.createChild("div", "origin-view-section-title").textConte
nt = WebInspector.UIString("Certificate Transparency"); | 878 |
| 879 if (originState.securityDetails.signedCertificateTimestampList.length) { |
| 880 // Create the Certificate Transparency section outside the callback, so
that it appears in the right place. |
| 881 var sctSection = this.element.createChild('div', 'origin-view-section'); |
| 882 sctSection.createChild('div', 'origin-view-section-title').textContent = |
| 883 WebInspector.UIString('Certificate Transparency'); |
| 884 } |
| 885 |
| 886 var sanDiv = this._createSanDiv(originState.securityDetails.sanList); |
| 887 var validFromString = new Date(1000 * originState.securityDetails.validFro
m).toUTCString(); |
| 888 var validUntilString = new Date(1000 * originState.securityDetails.validTo
).toUTCString(); |
| 889 |
| 890 table = new WebInspector.SecurityDetailsTable(); |
| 891 certificateSection.appendChild(table.element()); |
| 892 table.addRow(WebInspector.UIString('Subject'), originState.securityDetails
.subjectName); |
| 893 table.addRow(WebInspector.UIString('SAN'), sanDiv); |
| 894 table.addRow(WebInspector.UIString('Valid From'), validFromString); |
| 895 table.addRow(WebInspector.UIString('Valid Until'), validUntilString); |
| 896 table.addRow(WebInspector.UIString('Issuer'), originState.securityDetails.
issuer); |
| 897 table.addRow( |
| 898 '', WebInspector.SecurityPanel.createCertificateViewerButton2( |
| 899 WebInspector.UIString('Open full certificate details'), origin
)); |
| 900 |
| 901 if (!originState.securityDetails.signedCertificateTimestampList.length) |
| 902 return; |
| 903 |
| 904 // Show summary of SCT(s) of Certificate Transparency. |
| 905 var sctSummaryTable = new WebInspector.SecurityDetailsTable(); |
| 906 sctSummaryTable.element().classList.add('sct-summary'); |
| 907 sctSection.appendChild(sctSummaryTable.element()); |
| 908 for (var i = 0; i < originState.securityDetails.signedCertificateTimestamp
List.length; i++) { |
| 909 var sct = originState.securityDetails.signedCertificateTimestampList[i]; |
| 910 sctSummaryTable.addRow( |
| 911 WebInspector.UIString('SCT'), sct.logDescription + ' (' + sct.origin
+ ', ' + sct.status + ')'); |
| 912 } |
| 913 |
| 914 // Show detailed SCT(s) of Certificate Transparency. |
| 915 var sctTableWrapper = sctSection.createChild('div', 'sct-details'); |
| 916 sctTableWrapper.classList.add('hidden'); |
| 917 for (var i = 0; i < originState.securityDetails.signedCertificateTimestamp
List.length; i++) { |
| 918 var sctTable = new WebInspector.SecurityDetailsTable(); |
| 919 sctTableWrapper.appendChild(sctTable.element()); |
| 920 var sct = originState.securityDetails.signedCertificateTimestampList[i]; |
| 921 sctTable.addRow(WebInspector.UIString('Log Name'), sct.logDescription); |
| 922 sctTable.addRow(WebInspector.UIString('Log ID'), sct.logId.replace(/(.{2
})/g, '$1 ')); |
| 923 sctTable.addRow(WebInspector.UIString('Validation Status'), sct.status); |
| 924 sctTable.addRow(WebInspector.UIString('Source'), sct.origin); |
| 925 sctTable.addRow(WebInspector.UIString('Issued At'), new Date(sct.timesta
mp).toUTCString()); |
| 926 sctTable.addRow(WebInspector.UIString('Hash Algorithm'), sct.hashAlgorit
hm); |
| 927 sctTable.addRow(WebInspector.UIString('Signature Algorithm'), sct.signat
ureAlgorithm); |
| 928 sctTable.addRow(WebInspector.UIString('Signature Data'), sct.signatureDa
ta.replace(/(.{2})/g, '$1 ')); |
| 929 } |
| 930 |
| 931 // Add link to toggle between displaying of the summary of the SCT(s) and
the detailed SCT(s). |
| 932 var toggleSctsDetailsLink = sctSection.createChild('div', 'link'); |
| 933 toggleSctsDetailsLink.classList.add('sct-toggle'); |
| 934 toggleSctsDetailsLink.textContent = WebInspector.UIString('Show full detai
ls'); |
| 935 function toggleSctDetailsDisplay() { |
| 936 var isDetailsShown = !sctTableWrapper.classList.contains('hidden'); |
| 937 if (isDetailsShown) |
| 938 toggleSctsDetailsLink.textContent = WebInspector.UIString('Show full d
etails'); |
| 939 else |
| 940 toggleSctsDetailsLink.textContent = WebInspector.UIString('Hide full d
etails'); |
| 941 sctSummaryTable.element().classList.toggle('hidden'); |
| 942 sctTableWrapper.classList.toggle('hidden'); |
| 943 } |
| 944 toggleSctsDetailsLink.addEventListener('click', toggleSctDetailsDisplay, f
alse); |
| 945 |
| 946 var noteSection = this.element.createChild('div', 'origin-view-section'); |
| 947 // TODO(lgarron): Fix the issue and then remove this section. See comment
in SecurityPanel._processRequest(). |
| 948 noteSection.createChild('div').textContent = |
| 949 WebInspector.UIString('The security details above are from the first i
nspected response.'); |
| 950 } else if (originState.securityState !== SecurityAgent.SecurityState.Unknown
) { |
| 951 var notSecureSection = this.element.createChild('div', 'origin-view-sectio
n'); |
| 952 notSecureSection.createChild('div', 'origin-view-section-title').textConte
nt = |
| 953 WebInspector.UIString('Not Secure'); |
| 954 notSecureSection.createChild('div').textContent = |
| 955 WebInspector.UIString('Your connection to this origin is not secure.')
; |
| 956 } else { |
| 957 var noInfoSection = this.element.createChild('div', 'origin-view-section')
; |
| 958 noInfoSection.createChild('div', 'origin-view-section-title').textContent
= |
| 959 WebInspector.UIString('No Security Information'); |
| 960 noInfoSection.createChild('div').textContent = |
| 961 WebInspector.UIString('No security details are available for this orig
in.'); |
| 962 } |
| 963 } |
| 964 |
| 965 /** |
| 966 * @param {!Array<string>} sanList |
| 967 * *return {!Element} |
| 968 */ |
| 969 _createSanDiv(sanList) { |
| 970 var sanDiv = createElement('div'); |
| 971 if (sanList.length === 0) { |
| 972 sanDiv.textContent = WebInspector.UIString('(N/A)'); |
| 973 sanDiv.classList.add('empty-san'); |
| 974 } else { |
| 975 var truncatedNumToShow = 2; |
| 976 var listIsTruncated = sanList.length > truncatedNumToShow + 1; |
| 977 for (var i = 0; i < sanList.length; i++) { |
| 978 var span = sanDiv.createChild('span', 'san-entry'); |
| 979 span.textContent = sanList[i]; |
| 980 if (listIsTruncated && i >= truncatedNumToShow) |
| 981 span.classList.add('truncated-entry'); |
| 982 } |
| 983 if (listIsTruncated) { |
| 984 var truncatedSANToggle = sanDiv.createChild('div', 'link'); |
| 985 truncatedSANToggle.href = ''; |
| 986 |
| 987 function toggleSANTruncation() { |
| 988 if (sanDiv.classList.contains('truncated-san')) { |
| 989 sanDiv.classList.remove('truncated-san'); |
| 990 truncatedSANToggle.textContent = WebInspector.UIString('Show less'); |
| 991 } else { |
| 992 sanDiv.classList.add('truncated-san'); |
| 993 truncatedSANToggle.textContent = WebInspector.UIString('Show more (%
d total)', sanList.length); |
| 994 } |
913 } | 995 } |
914 | 996 truncatedSANToggle.addEventListener('click', toggleSANTruncation, false)
; |
915 var sanDiv = this._createSanDiv(originState.securityDetails.sanList); | 997 toggleSANTruncation(); |
916 var validFromString = new Date(1000 * originState.securityDetails.validF
rom).toUTCString(); | 998 } |
917 var validUntilString = new Date(1000 * originState.securityDetails.valid
To).toUTCString(); | 999 } |
918 | 1000 return sanDiv; |
919 table = new WebInspector.SecurityDetailsTable(); | 1001 } |
920 certificateSection.appendChild(table.element()); | 1002 |
921 table.addRow(WebInspector.UIString("Subject"), originState.securityDetai
ls.subjectName); | 1003 /** |
922 table.addRow(WebInspector.UIString("SAN"), sanDiv); | 1004 * @param {!SecurityAgent.SecurityState} newSecurityState |
923 table.addRow(WebInspector.UIString("Valid From"), validFromString); | 1005 */ |
924 table.addRow(WebInspector.UIString("Valid Until"), validUntilString); | 1006 setSecurityState(newSecurityState) { |
925 table.addRow(WebInspector.UIString("Issuer"), originState.securityDetail
s.issuer); | 1007 for (var className of Array.prototype.slice.call(this._originLockIcon.classL
ist)) { |
926 table.addRow("", WebInspector.SecurityPanel.createCertificateViewerButto
n2(WebInspector.UIString("Open full certificate details"), origin)); | 1008 if (className.startsWith('security-property-')) |
927 | 1009 this._originLockIcon.classList.remove(className); |
928 if (!originState.securityDetails.signedCertificateTimestampList.length) | 1010 } |
929 return; | 1011 |
930 | 1012 this._originLockIcon.classList.add('security-property-' + newSecurityState); |
931 // Show summary of SCT(s) of Certificate Transparency. | 1013 } |
932 var sctSummaryTable = new WebInspector.SecurityDetailsTable(); | 1014 }; |
933 sctSummaryTable.element().classList.add("sct-summary"); | 1015 |
934 sctSection.appendChild(sctSummaryTable.element()); | 1016 /** |
935 for (var i = 0; i < originState.securityDetails.signedCertificateTimesta
mpList.length; i++) | 1017 * @unrestricted |
936 { | 1018 */ |
937 var sct = originState.securityDetails.signedCertificateTimestampList
[i]; | 1019 WebInspector.SecurityDetailsTable = class { |
938 sctSummaryTable.addRow(WebInspector.UIString("SCT"), sct.logDescript
ion + " (" + sct.origin + ", " + sct.status + ")"); | 1020 constructor() { |
939 } | 1021 this._element = createElement('table'); |
940 | 1022 this._element.classList.add('details-table'); |
941 // Show detailed SCT(s) of Certificate Transparency. | 1023 } |
942 var sctTableWrapper = sctSection.createChild("div", "sct-details"); | 1024 |
943 sctTableWrapper.classList.add("hidden"); | 1025 /** |
944 for (var i = 0; i < originState.securityDetails.signedCertificateTimesta
mpList.length; i++) | 1026 * @return: {!Element} |
945 { | 1027 */ |
946 var sctTable = new WebInspector.SecurityDetailsTable(); | 1028 element() { |
947 sctTableWrapper.appendChild(sctTable.element()); | 1029 return this._element; |
948 var sct = originState.securityDetails.signedCertificateTimestampList
[i]; | 1030 } |
949 sctTable.addRow(WebInspector.UIString("Log Name"), sct.logDescriptio
n); | 1031 |
950 sctTable.addRow(WebInspector.UIString("Log ID"), sct.logId.replace(/
(.{2})/g,"$1 ")); | 1032 /** |
951 sctTable.addRow(WebInspector.UIString("Validation Status"), sct.stat
us); | 1033 * @param {string} key |
952 sctTable.addRow(WebInspector.UIString("Source"), sct.origin); | 1034 * @param {string|!Node} value |
953 sctTable.addRow(WebInspector.UIString("Issued At"), new Date(sct.tim
estamp).toUTCString()); | 1035 */ |
954 sctTable.addRow(WebInspector.UIString("Hash Algorithm"), sct.hashAlg
orithm); | 1036 addRow(key, value) { |
955 sctTable.addRow(WebInspector.UIString("Signature Algorithm"), sct.si
gnatureAlgorithm); | 1037 var row = this._element.createChild('div', 'details-table-row'); |
956 sctTable.addRow(WebInspector.UIString("Signature Data"), sct.signatu
reData.replace(/(.{2})/g,"$1 ")); | 1038 row.createChild('div').textContent = key; |
957 } | 1039 |
958 | 1040 var valueDiv = row.createChild('div'); |
959 // Add link to toggle between displaying of the summary of the SCT(s) an
d the detailed SCT(s). | 1041 if (typeof value === 'string') { |
960 var toggleSctsDetailsLink = sctSection.createChild("div", "link"); | 1042 valueDiv.textContent = value; |
961 toggleSctsDetailsLink.classList.add("sct-toggle"); | |
962 toggleSctsDetailsLink.textContent = WebInspector.UIString("Show full det
ails"); | |
963 function toggleSctDetailsDisplay() | |
964 { | |
965 var isDetailsShown = !sctTableWrapper.classList.contains("hidden"); | |
966 if (isDetailsShown) | |
967 toggleSctsDetailsLink.textContent = WebInspector.UIString("Show
full details"); | |
968 else | |
969 toggleSctsDetailsLink.textContent = WebInspector.UIString("Hide
full details"); | |
970 sctSummaryTable.element().classList.toggle("hidden"); | |
971 sctTableWrapper.classList.toggle("hidden"); | |
972 } | |
973 toggleSctsDetailsLink.addEventListener("click", toggleSctDetailsDisplay,
false); | |
974 | |
975 var noteSection = this.element.createChild("div", "origin-view-section")
; | |
976 // TODO(lgarron): Fix the issue and then remove this section. See commen
t in SecurityPanel._processRequest(). | |
977 noteSection.createChild("div").textContent = WebInspector.UIString("The
security details above are from the first inspected response."); | |
978 } else if (originState.securityState !== SecurityAgent.SecurityState.Unknown
) { | |
979 var notSecureSection = this.element.createChild("div", "origin-view-sect
ion"); | |
980 notSecureSection.createChild("div", "origin-view-section-title").textCon
tent = WebInspector.UIString("Not Secure"); | |
981 notSecureSection.createChild("div").textContent = WebInspector.UIString(
"Your connection to this origin is not secure."); | |
982 } else { | 1043 } else { |
983 var noInfoSection = this.element.createChild("div", "origin-view-section
"); | 1044 valueDiv.appendChild(value); |
984 noInfoSection.createChild("div", "origin-view-section-title").textConten
t = WebInspector.UIString("No Security Information"); | 1045 } |
985 noInfoSection.createChild("div").textContent = WebInspector.UIString("No
security details are available for this origin."); | 1046 } |
986 } | |
987 }; | 1047 }; |
988 | |
989 WebInspector.SecurityOriginView.prototype = { | |
990 | |
991 /** | |
992 * @param {!Array<string>} sanList | |
993 * *return {!Element} | |
994 */ | |
995 _createSanDiv: function(sanList) | |
996 { | |
997 var sanDiv = createElement("div"); | |
998 if (sanList.length === 0) { | |
999 sanDiv.textContent = WebInspector.UIString("(N/A)"); | |
1000 sanDiv.classList.add("empty-san"); | |
1001 } else { | |
1002 var truncatedNumToShow = 2; | |
1003 var listIsTruncated = sanList.length > truncatedNumToShow + 1; | |
1004 for (var i = 0; i < sanList.length; i++) { | |
1005 var span = sanDiv.createChild("span", "san-entry"); | |
1006 span.textContent = sanList[i]; | |
1007 if (listIsTruncated && i >= truncatedNumToShow) | |
1008 span.classList.add("truncated-entry"); | |
1009 } | |
1010 if (listIsTruncated) { | |
1011 var truncatedSANToggle = sanDiv.createChild("div", "link"); | |
1012 truncatedSANToggle.href = ""; | |
1013 | |
1014 function toggleSANTruncation() | |
1015 { | |
1016 if (sanDiv.classList.contains("truncated-san")) { | |
1017 sanDiv.classList.remove("truncated-san"); | |
1018 truncatedSANToggle.textContent = WebInspector.UIString("
Show less"); | |
1019 } else { | |
1020 sanDiv.classList.add("truncated-san"); | |
1021 truncatedSANToggle.textContent = WebInspector.UIString("
Show more (%d total)", sanList.length); | |
1022 } | |
1023 } | |
1024 truncatedSANToggle.addEventListener("click", toggleSANTruncation
, false); | |
1025 toggleSANTruncation(); | |
1026 } | |
1027 } | |
1028 return sanDiv; | |
1029 }, | |
1030 | |
1031 /** | |
1032 * @param {!SecurityAgent.SecurityState} newSecurityState | |
1033 */ | |
1034 setSecurityState: function(newSecurityState) | |
1035 { | |
1036 for (var className of Array.prototype.slice.call(this._originLockIcon.cl
assList)) { | |
1037 if (className.startsWith("security-property-")) | |
1038 this._originLockIcon.classList.remove(className); | |
1039 } | |
1040 | |
1041 this._originLockIcon.classList.add("security-property-" + newSecuritySta
te); | |
1042 }, | |
1043 | |
1044 __proto__: WebInspector.VBox.prototype | |
1045 }; | |
1046 | |
1047 /** | |
1048 * @constructor | |
1049 */ | |
1050 WebInspector.SecurityDetailsTable = function() | |
1051 { | |
1052 this._element = createElement("table"); | |
1053 this._element.classList.add("details-table"); | |
1054 }; | |
1055 | |
1056 WebInspector.SecurityDetailsTable.prototype = { | |
1057 | |
1058 /** | |
1059 * @return: {!Element} | |
1060 */ | |
1061 element: function() | |
1062 { | |
1063 return this._element; | |
1064 }, | |
1065 | |
1066 /** | |
1067 * @param {string} key | |
1068 * @param {string|!Node} value | |
1069 */ | |
1070 addRow: function(key, value) | |
1071 { | |
1072 var row = this._element.createChild("div", "details-table-row"); | |
1073 row.createChild("div").textContent = key; | |
1074 | |
1075 var valueDiv = row.createChild("div"); | |
1076 if (typeof value === "string") { | |
1077 valueDiv.textContent = value; | |
1078 } else { | |
1079 valueDiv.appendChild(value); | |
1080 } | |
1081 } | |
1082 }; | |
OLD | NEW |