chrome-devtools-frontend 1.0.1025631 → 1.0.1027150

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/config/owner/LIGHTHOUSE_OWNERS +1 -1
  2. package/docs/triage_guidelines.md +1 -122
  3. package/front_end/core/common/ResourceType.ts +1 -0
  4. package/front_end/core/host/UserMetrics.ts +2 -1
  5. package/front_end/core/i18n/locales/en-US.json +24 -0
  6. package/front_end/core/i18n/locales/en-XL.json +24 -0
  7. package/front_end/core/root/Runtime.ts +1 -0
  8. package/front_end/core/sdk/DOMModel.ts +5 -0
  9. package/front_end/core/sdk/NetworkManager.ts +24 -3
  10. package/front_end/core/sdk/ResourceTreeModel.ts +1 -1
  11. package/front_end/core/sdk/SourceMap.ts +22 -6
  12. package/front_end/core/sdk/sdk-meta.ts +7 -0
  13. package/front_end/devtools_compatibility.js +1 -0
  14. package/front_end/entrypoints/lighthouse_worker/LighthouseWorkerService.ts +6 -3
  15. package/front_end/entrypoints/main/MainImpl.ts +5 -0
  16. package/front_end/generated/ARIAProperties.js +723 -723
  17. package/front_end/generated/InspectorBackendCommands.js +5 -3
  18. package/front_end/generated/SupportedCSSProperties.js +2843 -2832
  19. package/front_end/generated/protocol-mapping.d.ts +14 -0
  20. package/front_end/generated/protocol-proxy-api.d.ts +10 -0
  21. package/front_end/generated/protocol.ts +67 -0
  22. package/front_end/legacy_test_runner/sources_test_runner/DebuggerTestRunner.js +1 -1
  23. package/front_end/models/bindings/CompilerScriptMapping.ts +1 -1
  24. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +38 -11
  25. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +7 -1
  26. package/front_end/models/bindings/IgnoreListManager.ts +35 -22
  27. package/front_end/models/issues_manager/descriptions/clientHintMetaTagAllowListInvalidOrigin.md +1 -1
  28. package/front_end/models/issues_manager/descriptions/clientHintMetaTagModifiedHTML.md +1 -1
  29. package/front_end/models/javascript_metadata/NativeFunctions.js +79 -67
  30. package/front_end/models/source_map_scopes/NamesResolver.ts +34 -0
  31. package/front_end/models/text_utils/TextRange.ts +8 -0
  32. package/front_end/models/timeline_model/TimelineModel.ts +18 -1
  33. package/front_end/panels/console/consoleView.css +4 -0
  34. package/front_end/panels/elements/ElementsTreeOutline.ts +18 -34
  35. package/front_end/panels/elements/TopLayerContainer.ts +51 -29
  36. package/front_end/panels/elements/components/ElementsBreadcrumbs.ts +45 -50
  37. package/front_end/panels/elements/elementsTreeOutline.css +1 -1
  38. package/front_end/panels/lighthouse/LighthouseController.ts +3 -0
  39. package/front_end/panels/lighthouse/LighthousePanel.ts +2 -0
  40. package/front_end/panels/network/NetworkDataGridNode.ts +1 -2
  41. package/front_end/panels/security/SecurityPanel.ts +52 -0
  42. package/front_end/panels/security/originView.css +1 -1
  43. package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +16 -0
  44. package/front_end/panels/sources/CallStackSidebarPane.ts +45 -16
  45. package/front_end/panels/sources/DebuggerPlugin.ts +8 -2
  46. package/front_end/panels/sources/callStackSidebarPane.css +15 -9
  47. package/front_end/panels/sources/navigatorTree.css +3 -3
  48. package/front_end/panels/sources/watchExpressionsSidebarPane.css +6 -0
  49. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +1 -1
  50. package/front_end/ui/components/docs/building-ui-documentation/CreatingComponents.md +172 -1
  51. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +15 -16
  52. package/front_end/ui/components/panel_feedback/previewToggle.css +13 -15
  53. package/front_end/ui/components/text_editor/TextEditor.ts +3 -0
  54. package/front_end/ui/legacy/ListControl.ts +4 -0
  55. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +13 -3
  56. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +5 -4
  57. package/package.json +1 -1
@@ -3952,6 +3952,20 @@ export namespace ProtocolMapping {
3952
3952
  paramsType: [Protocol.Debugger.GetScriptSourceRequest];
3953
3953
  returnType: Protocol.Debugger.GetScriptSourceResponse;
3954
3954
  };
3955
+ 'Debugger.disassembleWasmModule': {
3956
+ paramsType: [Protocol.Debugger.DisassembleWasmModuleRequest];
3957
+ returnType: Protocol.Debugger.DisassembleWasmModuleResponse;
3958
+ };
3959
+ /**
3960
+ * Disassemble the next chunk of lines for the module corresponding to the
3961
+ * stream. If disassembly is complete, this API will invalidate the streamId
3962
+ * and return an empty chunk. Any subsequent calls for the now invalid stream
3963
+ * will return errors.
3964
+ */
3965
+ 'Debugger.nextWasmDisassemblyChunk': {
3966
+ paramsType: [Protocol.Debugger.NextWasmDisassemblyChunkRequest];
3967
+ returnType: Protocol.Debugger.NextWasmDisassemblyChunkResponse;
3968
+ };
3955
3969
  /**
3956
3970
  * This command is deprecated. Use getScriptSource instead.
3957
3971
  */
@@ -3510,6 +3510,16 @@ declare namespace ProtocolProxyApi {
3510
3510
  */
3511
3511
  invoke_getScriptSource(params: Protocol.Debugger.GetScriptSourceRequest): Promise<Protocol.Debugger.GetScriptSourceResponse>;
3512
3512
 
3513
+ invoke_disassembleWasmModule(params: Protocol.Debugger.DisassembleWasmModuleRequest): Promise<Protocol.Debugger.DisassembleWasmModuleResponse>;
3514
+
3515
+ /**
3516
+ * Disassemble the next chunk of lines for the module corresponding to the
3517
+ * stream. If disassembly is complete, this API will invalidate the streamId
3518
+ * and return an empty chunk. Any subsequent calls for the now invalid stream
3519
+ * will return errors.
3520
+ */
3521
+ invoke_nextWasmDisassemblyChunk(params: Protocol.Debugger.NextWasmDisassemblyChunkRequest): Promise<Protocol.Debugger.NextWasmDisassemblyChunkResponse>;
3522
+
3513
3523
  /**
3514
3524
  * This command is deprecated. Use getScriptSource instead.
3515
3525
  */
@@ -236,6 +236,10 @@ export namespace Accessibility {
236
236
  * This `Node`'s role, whether explicit or implicit.
237
237
  */
238
238
  role?: AXValue;
239
+ /**
240
+ * This `Node`'s Chrome raw role.
241
+ */
242
+ chromeRole?: AXValue;
239
243
  /**
240
244
  * The accessible name for this `Node`.
241
245
  */
@@ -1026,6 +1030,7 @@ export namespace Audits {
1026
1030
  DeprecationExample = 'DeprecationExample',
1027
1031
  DocumentDomainSettingWithoutOriginAgentClusterHeader = 'DocumentDomainSettingWithoutOriginAgentClusterHeader',
1028
1032
  EventPath = 'EventPath',
1033
+ ExpectCTHeader = 'ExpectCTHeader',
1029
1034
  GeolocationInsecureOrigin = 'GeolocationInsecureOrigin',
1030
1035
  GeolocationInsecureOriginDeprecatedNotRemoved = 'GeolocationInsecureOriginDeprecatedNotRemoved',
1031
1036
  GetUserMediaInsecureOrigin = 'GetUserMediaInsecureOrigin',
@@ -7049,6 +7054,7 @@ export namespace Network {
7049
7054
  TextTrack = 'TextTrack',
7050
7055
  XHR = 'XHR',
7051
7056
  Fetch = 'Fetch',
7057
+ Prefetch = 'Prefetch',
7052
7058
  EventSource = 'EventSource',
7053
7059
  WebSocket = 'WebSocket',
7054
7060
  Manifest = 'Manifest',
@@ -7420,6 +7426,16 @@ export namespace Network {
7420
7426
  * Whether the request complied with Certificate Transparency policy
7421
7427
  */
7422
7428
  certificateTransparencyCompliance: CertificateTransparencyCompliance;
7429
+ /**
7430
+ * The signature algorithm used by the server in the TLS server signature,
7431
+ * represented as a TLS SignatureScheme code point. Omitted if not
7432
+ * applicable or not known.
7433
+ */
7434
+ serverSignatureAlgorithm?: integer;
7435
+ /**
7436
+ * Whether the connection used Encrypted ClientHello
7437
+ */
7438
+ encryptedClientHello: boolean;
7423
7439
  }
7424
7440
 
7425
7441
  /**
@@ -10309,6 +10325,7 @@ export namespace Page {
10309
10325
  ScreenWakeLock = 'screen-wake-lock',
10310
10326
  Serial = 'serial',
10311
10327
  SharedAutofill = 'shared-autofill',
10328
+ SharedStorage = 'shared-storage',
10312
10329
  StorageAccessAPI = 'storage-access-api',
10313
10330
  SyncXhr = 'sync-xhr',
10314
10331
  TrustTokenRedemption = 'trust-token-redemption',
@@ -14943,6 +14960,17 @@ export namespace Debugger {
14943
14960
  type?: BreakLocationType;
14944
14961
  }
14945
14962
 
14963
+ export interface WasmDisassemblyChunk {
14964
+ /**
14965
+ * The next chunk of disassembled lines.
14966
+ */
14967
+ lines: string[];
14968
+ /**
14969
+ * The bytecode offsets describing the start of each line.
14970
+ */
14971
+ bytecodeOffsets: integer[];
14972
+ }
14973
+
14946
14974
  /**
14947
14975
  * Enum of possible script languages.
14948
14976
  */
@@ -15094,6 +15122,45 @@ export namespace Debugger {
15094
15122
  bytecode?: binary;
15095
15123
  }
15096
15124
 
15125
+ export interface DisassembleWasmModuleRequest {
15126
+ /**
15127
+ * Id of the script to disassemble
15128
+ */
15129
+ scriptId: Runtime.ScriptId;
15130
+ }
15131
+
15132
+ export interface DisassembleWasmModuleResponse extends ProtocolResponseWithError {
15133
+ /**
15134
+ * For large modules, return a stream from which additional chunks of
15135
+ * disassembly can be read successively.
15136
+ */
15137
+ streamId?: string;
15138
+ /**
15139
+ * The total number of lines in the disassembly text.
15140
+ */
15141
+ totalNumberOfLines: integer;
15142
+ /**
15143
+ * The offsets of all function bodies plus one additional entry pointing
15144
+ * one by past the end of the last function.
15145
+ */
15146
+ functionBodyOffsets: integer[];
15147
+ /**
15148
+ * The first chunk of disassembly.
15149
+ */
15150
+ chunk: WasmDisassemblyChunk;
15151
+ }
15152
+
15153
+ export interface NextWasmDisassemblyChunkRequest {
15154
+ streamId: string;
15155
+ }
15156
+
15157
+ export interface NextWasmDisassemblyChunkResponse extends ProtocolResponseWithError {
15158
+ /**
15159
+ * The next chunk of disassembly.
15160
+ */
15161
+ chunk: WasmDisassemblyChunk;
15162
+ }
15163
+
15097
15164
  export interface GetWasmBytecodeRequest {
15098
15165
  /**
15099
15166
  * Id of the Wasm script to get source for.
@@ -291,7 +291,7 @@ SourcesTestRunner.captureStackTraceIntoString = async function(callFrames, async
291
291
  const script = location.script();
292
292
  const uiLocation = await self.Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(location);
293
293
  const isFramework =
294
- uiLocation ? self.Bindings.ignoreListManager.isIgnoreListedUISourceCode(uiLocation.uiSourceCode) : false;
294
+ uiLocation ? self.Bindings.ignoreListManager.isUserIgnoreListedURL(uiLocation.uiSourceCode.url()) : false;
295
295
 
296
296
  if (options.dropFrameworkCallFrames && isFramework) {
297
297
  continue;
@@ -247,7 +247,7 @@ export class CompilerScriptMapping implements DebuggerSourceMapping {
247
247
  const sourceMap = event.data.sourceMap;
248
248
  await this.removeStubUISourceCode(script);
249
249
 
250
- if (IgnoreListManager.instance().isIgnoreListedURL(script.sourceURL, script.isContentScript())) {
250
+ if (IgnoreListManager.instance().isUserIgnoreListedURL(script.sourceURL, script.isContentScript())) {
251
251
  this.sourceMapAttachedForTest(sourceMap);
252
252
  return;
253
253
  }
@@ -656,15 +656,23 @@ class SourceScopeRemoteObject extends SDK.RemoteObject.RemoteObjectImpl {
656
656
  }
657
657
 
658
658
  for (const variable of this.variables) {
659
- let sourceVar;
659
+ let sourceVar: SDK.RemoteObject.RemoteObject|undefined;
660
660
  try {
661
- sourceVar = await getValueTreeForExpression(this.#callFrame, this.#plugin, variable.name, ({
662
- generatePreview: false,
663
- includeCommandLineAPI: true,
664
- objectGroup: 'backtrace',
665
- returnByValue: false,
666
- silent: false,
667
- } as SDK.RuntimeModel.EvaluationOptions));
661
+ const evalResult = await this.#plugin.evaluate(variable.name, getRawLocation(this.#callFrame), this.stopId);
662
+ if (evalResult) {
663
+ sourceVar = new ExtensionRemoteObject(this.#callFrame, evalResult, this.#plugin);
664
+ }
665
+ // For backwards compatibility, fall back to the legacy API if the plugin doesn't define the new one.
666
+ // TODO(crbug.com/1342848) Remove
667
+ if (!sourceVar) {
668
+ sourceVar = await getValueTreeForExpression(this.#callFrame, this.#plugin, variable.name, ({
669
+ generatePreview: false,
670
+ includeCommandLineAPI: true,
671
+ objectGroup: 'backtrace',
672
+ returnByValue: false,
673
+ silent: false,
674
+ } as SDK.RuntimeModel.EvaluationOptions));
675
+ }
668
676
  } catch (e) {
669
677
  console.warn(e);
670
678
  sourceVar = new SDK.RemoteObject.LocalJSONObject(undefined);
@@ -918,7 +926,7 @@ export class DebuggerLanguagePluginManager implements
918
926
  error: string,
919
927
  }|null> {
920
928
  const {script} = callFrame;
921
- const {expression} = options;
929
+ const {expression, returnByValue, throwOnSideEffect} = options;
922
930
  const {plugin} = await this.rawModuleIdAndPluginForScript(script);
923
931
  if (!plugin) {
924
932
  return null;
@@ -929,9 +937,20 @@ export class DebuggerLanguagePluginManager implements
929
937
  return null;
930
938
  }
931
939
 
940
+ if (returnByValue) {
941
+ return {error: 'Cannot return by value'};
942
+ }
943
+ if (throwOnSideEffect) {
944
+ return {error: 'Cannot guarantee side-effect freedom'};
945
+ }
946
+
932
947
  try {
933
- const object = await getValueTreeForExpression(callFrame, plugin, expression, options);
934
- return {object, exceptionDetails: undefined};
948
+ const object = await plugin.evaluate(expression, location, this.stopIdForCallFrame(callFrame));
949
+ if (!object) {
950
+ const object = await getValueTreeForExpression(callFrame, plugin, expression, options);
951
+ return {object, exceptionDetails: undefined};
952
+ }
953
+ return {object: new ExtensionRemoteObject(callFrame, object, plugin), exceptionDetails: undefined};
935
954
  } catch (error) {
936
955
  if (error instanceof FormattingError) {
937
956
  const {exception: object, exceptionDetails} = error;
@@ -1542,4 +1561,12 @@ class ModelData {
1542
1561
  export interface DebuggerLanguagePlugin extends Chrome.DevTools.LanguageExtensionPlugin {
1543
1562
  name: string;
1544
1563
  handleScript(script: SDK.Script.Script): boolean;
1564
+
1565
+ // These are optional in the public interface for compatibility purposes, but ExtensionAPI handles the missing
1566
+ // functions gracefully, so we can mark them non-optional here.
1567
+ // TODO(crbug.com/1342848) Remove
1568
+ evaluate(expression: string, context: Chrome.DevTools.RawLocation, stopId: unknown):
1569
+ Promise<Chrome.DevTools.RemoteObject|null>;
1570
+ getProperties(objectId: Chrome.DevTools.RemoteObjectId): Promise<Chrome.DevTools.PropertyDescriptor[]>;
1571
+ releaseObject(objectId: Chrome.DevTools.RemoteObjectId): Promise<void>;
1545
1572
  }
@@ -509,7 +509,13 @@ export class Location extends LiveLocationWithPool {
509
509
 
510
510
  async isIgnoreListed(): Promise<boolean> {
511
511
  const uiLocation = await this.uiLocation();
512
- return uiLocation ? IgnoreListManager.instance().isIgnoreListedUISourceCode(uiLocation.uiSourceCode) : false;
512
+ if (!uiLocation) {
513
+ return false;
514
+ }
515
+ const manager = this.rawLocation.debuggerModel.sourceMapManager();
516
+ const script = this.rawLocation.script();
517
+ const map = script ? await manager.sourceMapForClientPromise(script) : null;
518
+ return IgnoreListManager.instance().isUserOrSourceMapIgnoreListedUISourceCode(uiLocation.uiSourceCode, map);
513
519
  }
514
520
  }
515
521
 
@@ -28,6 +28,9 @@ export class IgnoreListManager implements SDK.TargetManager.SDKModelObserver<SDK
28
28
  Common.Settings.Settings.instance()
29
29
  .moduleSetting('skipContentScripts')
30
30
  .addChangeListener(this.patternChanged.bind(this));
31
+ Common.Settings.Settings.instance()
32
+ .moduleSetting('automaticallyIgnoreListKnownThirdPartyScripts')
33
+ .addChangeListener(this.patternChanged.bind(this));
31
34
 
32
35
  this.#listeners = new Set();
33
36
 
@@ -97,21 +100,33 @@ export class IgnoreListManager implements SDK.TargetManager.SDKModelObserver<SDK
97
100
  return debuggerModel.setBlackboxPatterns(patterns);
98
101
  }
99
102
 
100
- isIgnoreListedUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
103
+ isUserOrSourceMapIgnoreListedUISourceCode(
104
+ uiSourceCode: Workspace.UISourceCode.UISourceCode, sourceMap: SDK.SourceMap.SourceMap|null): boolean {
101
105
  const projectType = uiSourceCode.project().type();
102
106
  const isContentScript = projectType === Workspace.Workspace.projectTypes.ContentScripts;
103
- if (isContentScript && Common.Settings.Settings.instance().moduleSetting('skipContentScripts').get()) {
107
+ if (this.skipContentScripts && isContentScript) {
104
108
  return true;
105
109
  }
106
110
  const url = this.uiSourceCodeURL(uiSourceCode);
107
- return url ? this.isIgnoreListedURL(url) : false;
111
+ return url ? this.isUserOrSourceMapIgnoreListedURL(url, sourceMap) : false;
112
+ }
113
+
114
+ isUserOrSourceMapIgnoreListedURL(url: Platform.DevToolsPath.UrlString, sourceMap: SDK.SourceMap.SourceMap|null):
115
+ boolean {
116
+ if (this.isUserIgnoreListedURL(url)) {
117
+ return true;
118
+ }
119
+ if (this.automaticallyIgnoreListKnownThirdPartyScripts && sourceMap?.hasIgnoreListHint(url)) {
120
+ return true;
121
+ }
122
+ return false;
108
123
  }
109
124
 
110
- isIgnoreListedURL(url: Platform.DevToolsPath.UrlString, isContentScript?: boolean): boolean {
125
+ isUserIgnoreListedURL(url: Platform.DevToolsPath.UrlString, isContentScript?: boolean): boolean {
111
126
  if (this.#isIgnoreListedURLCache.has(url)) {
112
127
  return Boolean(this.#isIgnoreListedURLCache.get(url));
113
128
  }
114
- if (isContentScript && Common.Settings.Settings.instance().moduleSetting('skipContentScripts').get()) {
129
+ if (isContentScript && this.skipContentScripts) {
115
130
  return true;
116
131
  }
117
132
  const regex = this.getSkipStackFramesPatternSetting().asRegExp();
@@ -137,8 +152,9 @@ export class IgnoreListManager implements SDK.TargetManager.SDKModelObserver<SDK
137
152
 
138
153
  private async updateScriptRanges(script: SDK.Script.Script, sourceMap: SDK.SourceMap.SourceMap|null): Promise<void> {
139
154
  let hasIgnoreListedMappings = false;
140
- if (!IgnoreListManager.instance().isIgnoreListedURL(script.sourceURL, script.isContentScript())) {
141
- hasIgnoreListedMappings = sourceMap ? sourceMap.sourceURLs().some(url => this.isIgnoreListedURL(url)) : false;
155
+ if (!IgnoreListManager.instance().isUserIgnoreListedURL(script.sourceURL, script.isContentScript())) {
156
+ hasIgnoreListedMappings =
157
+ sourceMap?.sourceURLs().some(url => this.isUserOrSourceMapIgnoreListedURL(url, sourceMap)) ?? false;
142
158
  }
143
159
  if (!hasIgnoreListedMappings) {
144
160
  if (scriptToRange.get(script) && await script.setBlackboxedRanges([])) {
@@ -152,21 +168,10 @@ export class IgnoreListManager implements SDK.TargetManager.SDKModelObserver<SDK
152
168
  return;
153
169
  }
154
170
 
155
- const mappings = sourceMap.mappings();
156
- const newRanges: SourceRange[] = [];
157
- if (mappings.length > 0) {
158
- let currentIgnoreListed = false;
159
- if (mappings[0].lineNumber !== 0 || mappings[0].columnNumber !== 0) {
160
- newRanges.push({lineNumber: 0, columnNumber: 0});
161
- currentIgnoreListed = true;
162
- }
163
- for (const mapping of mappings) {
164
- if (mapping.sourceURL && currentIgnoreListed !== this.isIgnoreListedURL(mapping.sourceURL)) {
165
- newRanges.push({lineNumber: mapping.lineNumber, columnNumber: mapping.columnNumber});
166
- currentIgnoreListed = !currentIgnoreListed;
167
- }
168
- }
169
- }
171
+ const newRanges =
172
+ sourceMap
173
+ .findRanges(srcURL => this.isUserOrSourceMapIgnoreListedURL(srcURL, sourceMap), {isStartMatching: true})
174
+ .flatMap(range => [range.start, range.end]);
170
175
 
171
176
  const oldRanges = scriptToRange.get(script) || [];
172
177
  if (!isEqual(oldRanges, newRanges) && await script.setBlackboxedRanges(newRanges)) {
@@ -210,6 +215,14 @@ export class IgnoreListManager implements SDK.TargetManager.SDKModelObserver<SDK
210
215
  }
211
216
  }
212
217
 
218
+ get skipContentScripts(): boolean {
219
+ return Common.Settings.Settings.instance().moduleSetting('skipContentScripts').get();
220
+ }
221
+
222
+ get automaticallyIgnoreListKnownThirdPartyScripts(): boolean {
223
+ return Common.Settings.Settings.instance().moduleSetting('automaticallyIgnoreListKnownThirdPartyScripts').get();
224
+ }
225
+
213
226
  ignoreListContentScripts(): void {
214
227
  Common.Settings.Settings.instance().moduleSetting('skipContentScripts').set(true);
215
228
  }
@@ -1,4 +1,4 @@
1
1
  # Client Hint meta tag contained invalid origin
2
2
 
3
- Items in the accept-ch meta tag allow list must be valid origins.
3
+ Items in the delegate-ch meta tag allow list must be valid origins.
4
4
  No special values (e.g. self, none, and *) are permitted.
@@ -1,4 +1,4 @@
1
1
  # Client Hint meta tag modified by javascript
2
2
 
3
- Only accept-ch meta tags in the original HTML sent from the server
3
+ Only delegate-ch meta tags in the original HTML sent from the server
4
4
  are respected. Any injected via javascript (or other means) are ignored.