Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Enable scanning of chromium content #967

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/AutomationReference.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ Cause each scan to save a test file, even if no errors are reported. The default

The `WithAlwaysSaveTestFile` method returns the `Config.Builder` configured to always save a test file.

##### `WithTestAllChromiumContent`

Cause all Chromium HTML content to be included in scan results. The default is to omit Chromium HTML content from the scan results. This is intended only for use by browser development teams and should be omitted in other scenarios.

###### Return object

The `WithTestAllChromiumContent` method returns the `Config.Builder` configured to always save a test file.
DaveTryon marked this conversation as resolved.
Show resolved Hide resolved

##### Build

Build an instance of `Config`.
Expand Down
1 change: 1 addition & 0 deletions src/Actions/Actions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
<ProjectReference Include="..\Desktop\Desktop.csproj" />
<ProjectReference Include="..\Rules\Rules.csproj" />
<ProjectReference Include="..\Win32\Win32.csproj" />
</ItemGroup>

Expand Down
13 changes: 13 additions & 0 deletions src/Actions/Actions/SelectAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Axe.Windows.Core.Misc;
using Axe.Windows.Desktop.Settings;
using Axe.Windows.Desktop.UIAutomation;
using Axe.Windows.Rules;
using System;
using System.Linq;

Expand Down Expand Up @@ -391,6 +392,18 @@ public static void ClearDefaultInstance()
DefaultInstance = null;
}
}

/// <summary>
/// Allow testing of all Chromium content
/// </summary>
public static bool ShouldTestAllChromiumContent
{
get => RulesSettings.ShouldTestAllChromiumContent;
set
{
RulesSettings.ShouldTestAllChromiumContent = value;
}
}
#endregion

#region IDisposable Support
Expand Down
5 changes: 5 additions & 0 deletions src/Automation/AxeWindowsActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,10 @@ public void RegisterCustomUIAPropertiesFromConfig(string path)
Core.CustomObjects.Config conf = CustomUIAAction.ReadConfigFromFile(path);
CustomUIAAction.RegisterCustomProperties(conf.Properties);
}

public void SetShouldTestAllChromiumContent(bool shouldTestAllChromiumContent)
{
SelectAction.ShouldTestAllChromiumContent = shouldTestAllChromiumContent;
}
} // class
} // namespace
13 changes: 13 additions & 0 deletions src/Automation/Data/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public class Config
/// <summary>Override the default behavior of only saving a11ytest files if errors are found.</summary>
public bool AlwaysSaveTestFile { get; private set; }

/// <summary>Override the default behavior or not testing Chromium content.</summary>
DaveTryon marked this conversation as resolved.
Show resolved Hide resolved
public bool TestAllChromiumContent { get; private set; }

/// <summary>
/// Custom handling of DPI awareness. The default handling is to set the entire process as DPI-aware
/// before running the scan, and to leave it in that state after the scan completes. If your process
Expand Down Expand Up @@ -130,6 +133,15 @@ public Builder WithAlwaysSaveTestFile()
return this;
}

/// <summary>
/// Configure Axe.Windows to test all Chromium content. By default, Chromium content is not tested.
/// </summary>
public Builder WithTestAllChromiumContent()
{
_config.TestAllChromiumContent = true;
return this;
}

/// <summary>
/// Build an instance of <see cref="Config"/>
/// </summary>
Expand All @@ -144,6 +156,7 @@ public Config Build()
CustomUIAConfigPath = _config.CustomUIAConfigPath,
DPIAwareness = _config.DPIAwareness,
AlwaysSaveTestFile = _config.AlwaysSaveTestFile,
TestAllChromiumContent = _config.TestAllChromiumContent,
};
}
} // Builder
Expand Down
7 changes: 7 additions & 0 deletions src/Automation/Interfaces/IAxeWindowsActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,12 @@ internal interface IAxeWindowsActions
/// </summary>
/// <param name="path"></param>
void RegisterCustomUIAPropertiesFromConfig(string path);

/// <summary>
/// Specify how Chromium content should be evaluated
/// </summary>
/// <param name="shouldTestAllChromiumContent">This can be set to true allow browser teams to test and debug code that converts from HTML to UIA.
DaveTryon marked this conversation as resolved.
Show resolved Hide resolved
/// It should be set to false for all other scenarios.</param>
void SetShouldTestAllChromiumContent(bool shouldTestAllChromiumContent);
} // interface
} // namespace
1 change: 1 addition & 0 deletions src/Automation/SnapshotCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ private static void ScanAndProcessResults(Config config, IScanTools scanTools, L
var dpiAwarenessObject = scanTools.DpiAwareness.Enable();
try
{
scanTools.Actions.SetShouldTestAllChromiumContent(config.TestAllChromiumContent);
resultList.Add(scanTools.Actions.Scan(rootElement, (element, elementId) =>
{
return ProcessResults(element, elementId, config, scanTools, multipleTopLevelWindowsExist, targetIndex, rootElements.Count(), actionContext);
Expand Down
10 changes: 7 additions & 3 deletions src/AutomationTests/SnapshotCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private void SetupDpiAwarenessMock(object dataFromEnable)
_scanToolsMock.Setup(x => x.DpiAwareness).Returns(_dpiAwarenessMock.Object);
}

private void SetupScanToolsMock(bool withResultsAssembler = true, bool withOutputFileHelper = false)
private void SetupScanToolsMock(bool withResultsAssembler = true, bool withOutputFileHelper = false, bool withShouldTestAllChromiumContent = true)
{
_scanToolsMock.Setup(x => x.TargetElementLocator).Returns(_targetElementLocatorMock.Object);
_scanToolsMock.Setup(x => x.Actions).Returns(_actionsMock.Object);
Expand All @@ -92,6 +92,10 @@ private void SetupScanToolsMock(bool withResultsAssembler = true, bool withOutpu
{
_scanToolsMock.Setup(x => x.OutputFileHelper).Returns(_outputFileHelperMock.Object);
}
if (withShouldTestAllChromiumContent)
{
_actionsMock.Setup(x => x.SetShouldTestAllChromiumContent(false));
}
}

private void SetupActionsMock(string expectedPath = "")
Expand Down Expand Up @@ -190,7 +194,7 @@ public async Task ExecuteAsync_NullAxeWindowsActions_ThrowsException()
[Timeout(1000)]
public async Task ExecuteAsync_NullDpiAwareness_ThrowsException()
{
SetupScanToolsMock(withResultsAssembler: false);
SetupScanToolsMock(withResultsAssembler: false, withShouldTestAllChromiumContent: false);
_scanToolsMock.Setup(x => x.DpiAwareness).Returns<IDPIAwareness>(null);

var action = new Func<Task>(() => SnapshotCommand.ExecuteAsync(_minimalConfig, _scanToolsMock.Object, CancellationToken.None));
Expand All @@ -204,7 +208,7 @@ public async Task ExecuteAsync_NullDpiAwareness_ThrowsException()
[Timeout(1000)]
public async Task ExecuteAsync_TargetElementLocatorReturnsNull_PassesNullToScan()
{
SetupScanToolsMock(withResultsAssembler: false);
SetupScanToolsMock(withResultsAssembler: false, withShouldTestAllChromiumContent: false);
_scanToolsMock.Setup(x => x.DpiAwareness).Returns(_dpiAwarenessMock.Object);
SetupTargetElementLocatorMock(overrideElements: true, elements: null);

Expand Down
1 change: 1 addition & 0 deletions src/CLI/IOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ internal interface IOptions
int DelayInSeconds { get; }
string CustomUia { get; }
bool AlwaysSaveTestFile { get; }
bool TestAllChromiumContent { get; }
}
}
3 changes: 3 additions & 0 deletions src/CLI/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public class Options : IOptions
[Option(Required = false, HelpText = "AlwaysSaveTestFile", ResourceType = typeof(Resources.OptionsHelpText))]
public bool AlwaysSaveTestFile { get; set; }

[Option(Required = false, HelpText = "TestAllChromiumContent", ResourceType = typeof(Resources.OptionsHelpText))]
public bool TestAllChromiumContent { get; set; }

// CommandLineParser will never set this value!
public VerbosityLevel VerbosityLevel { get; set; } = VerbosityLevel.Default;
}
Expand Down
1 change: 1 addition & 0 deletions src/CLI/OptionsEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public static IOptions ProcessInputs(Options rawInputs, IProcessHelper processHe
DelayInSeconds = delayInSeconds,
CustomUia = rawInputs.CustomUia,
AlwaysSaveTestFile = rawInputs.AlwaysSaveTestFile,
TestAllChromiumContent = rawInputs.TestAllChromiumContent,
};
}

Expand Down
39 changes: 23 additions & 16 deletions src/CLI/README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,36 @@ If you run the tool without parameters, you'll be presented with the help screen
AxeWindowsCLI 2.2.1
Copyright c 2020

--processid Process Id
--processid Process Id

--processname Process Name
--processname Process Name

--outputdirectory Output directory
--outputdirectory Output directory

--scanid Scan ID
--scanid Scan ID

--verbosity Verbosity level (Quiet/Default/Verbose)
--verbosity Verbosity level (Quiet/Default/Verbose)

--showthirdpartynotices Display Third Party Notices (opens file in browser
without executing scan). If specified, all other
options will be ignored.
--showthirdpartynotices Display Third Party Notices (opens file in browser
without executing scan). If specified, all other
options will be ignored.

--delayinseconds How many seconds to delay before triggering the
scan. Valid range is 0 to 60 seconds, with a
default of 0.
--delayinseconds How many seconds to delay before triggering the
scan. Valid range is 0 to 60 seconds, with a
default of 0.

--customuia The path to a configuration file specifying custom
UI Automation attributes
--customuia The path to a configuration file specifying custom
UI Automation attributes

--alwayssavetestfile If specified, always save the test file. By
default, the test file is saved only if errors are
found.
--alwayssavetestfile If specified, always save the test file. By
default, the test file is saved only if errors are
found.

--testallchromiumcontent If specified, causes Chromium HTML content to be
scanned. Chromium HTML content is ignored without
this flag. This is intended primarily for browser
development teams and is discouraged for other
scenarios.
```

To scan an application, you need to specify the application's process via either the `--processId` or `--processName` parameters
Expand All @@ -60,6 +66,7 @@ showThirdPartyNotices|If specified, displays the third party notices for compone
delayInSeconds|Optionally inserts a delay before triggering the scan. This allows transient controls (menus, drop-down-lists, etc.) to be scanned.
customUia|Optionally provides a path to a [custom UIA configuration file](../../docs/CustomUIA.md). By default, only system-defined UIA properties will be included in the scan.
alwayssavetestfile|Optionally causes the test file to always be saved. By default, the test file is saved only if errors are found.
testAllChromiumContent|Optionally causes Chromium HTML content to be scanned. Chromium HTML content is ignored without this flag. This is intended primarily for browser development teams and is discouraged for other scenarios.

### Scan results
A summary of scan results will be displayed after the scan is run. In addition, an `.a11ytest` file will be generated if 1 or more errors were detected or if the `alwayssavetestfile` option was specified. The location of this file will be reported in the tool output (see the documentation of the `--outputDirectory` and `--scanId` parameters for ways to alter the name or location of the output file). This file can then be opened with **Accessibility Insights for Windows**, which is freely available at http://accessibilityinsights.io. If you scan an application with multiple top-level windows, an `.a11ytest` file will be generated for _each_ top-level window, even if no errors are detected.
Expand Down
9 changes: 9 additions & 0 deletions src/CLI/Resources/OptionsHelpText.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/CLI/Resources/OptionsHelpText.resx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@
<data name="ShowThirdPartyNotices" xml:space="preserve">
<value>Display Third Party Notices (opens file in browser without executing scan). If specified, all other options will be ignored.</value>
</data>
<data name="TestAllChromiumContent" xml:space="preserve">
<value>If specified, causes Chromium HTML content to be scanned. Chromium HTML content is ignored without this flag. This is intended primarily for browser development teams and is discouraged for other scenarios.</value>
</data>
<data name="Verbosity" xml:space="preserve">
<value>Verbosity level (Quiet/Default/Verbose)</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions src/CLI/ScanRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ private static IScanner BuildScanner(IOptions options)
if (options.AlwaysSaveTestFile)
builder = builder.WithAlwaysSaveTestFile();

if (options.TestAllChromiumContent)
builder = builder.WithTestAllChromiumContent();

return ScannerFactory.CreateScanner(builder.Build());
}
}
Expand Down
18 changes: 17 additions & 1 deletion src/CLITests/OptionsEvaluatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ private void VerifyAllMocks()
private static void ValidateOptions(IOptions options, string processName = TestProcessName,
int processId = TestProcessId, string outputDirectory = null, string scanId = null,
VerbosityLevel verbosityLevel = VerbosityLevel.Default, int delayInSeconds = 0,
bool alwaysWriteTestFile = false)
bool alwaysWriteTestFile = false, bool testAllChromiumContent = false)
{
Assert.AreEqual(processName, options.ProcessName);
Assert.AreEqual(processId, options.ProcessId);
Expand All @@ -41,6 +41,7 @@ private void VerifyAllMocks()
Assert.AreEqual(verbosityLevel, options.VerbosityLevel);
Assert.AreEqual(delayInSeconds, options.DelayInSeconds);
Assert.AreEqual(alwaysWriteTestFile, options.AlwaysSaveTestFile);
Assert.AreEqual(testAllChromiumContent, options.TestAllChromiumContent);
}

[TestMethod]
Expand Down Expand Up @@ -304,5 +305,20 @@ public void ProcessInputs_SpecifiesAlwaysSaveTestFile_SetsSaveTestFile()
processId: TestProcessId, alwaysWriteTestFile: true);
VerifyAllMocks();
}

[TestMethod]
[Timeout(1000)]
public void ProcessInputs_SpecifiesTestAllChromiumContent_SetsTestAllChromiumContent()
{
_processHelperMock.Setup(x => x.ProcessIdFromName(TestProcessName)).Returns(TestProcessId);
Options input = new Options
{
ProcessName = TestProcessName,
TestAllChromiumContent = true,
};
ValidateOptions(OptionsEvaluator.ProcessInputs(input, _processHelperMock.Object),
processId: TestProcessId, testAllChromiumContent: true);
VerifyAllMocks();
}
}
}
2 changes: 2 additions & 0 deletions src/Rules/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
[assembly: NeutralResourcesLanguage("en-US")]

#if ENABLE_SIGNING
[assembly: InternalsVisibleTo("Axe.Windows.Actions,PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
[assembly: InternalsVisibleTo("RulesTests,PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2,PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
#else
[assembly: InternalsVisibleTo("Axe.Windows.Actions")]
[assembly: InternalsVisibleTo("RulesTests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
#endif
6 changes: 6 additions & 0 deletions src/Rules/PropertyConditions/ElementGroups.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ namespace Axe.Windows.Rules.PropertyConditions
/// </summary>
static class ElementGroups
{
/// <summary>
/// This can be set to true allow browser teams to test and debug code that converts from HTML to UIA.
/// It should be set to false for all other scenarios.
/// </summary>
// the following occurs for xaml expand/collapse controls
private static readonly Condition FocusableGroup = Group & IsKeyboardFocusable & (WPF | XAML);

Expand Down Expand Up @@ -48,6 +52,8 @@ static class ElementGroups
public static Condition WinFormsEdit = Edit & WinForms;
public static Condition IsChromiumDocument = Chrome & Document;
public static Condition IsChromiumContent = (IsChromiumDocument | AnyAncestor(IsChromiumDocument))[ConditionDescriptions.IsChromiumContent];
public static ValueCondition<bool> ShouldTestAllChromiumContentValueCondition = new ValueCondition<bool>((e) => RulesSettings.ShouldTestAllChromiumContent, "TestAllChromiumContent");
public static Condition ShouldTestAllChromiumContent = ShouldTestAllChromiumContentValueCondition == true;
public static Condition AllowSameNameAndControlType = CreateAllowSameNameAndControlTypeCondition();

private static Condition CreateMinMaxCloseButtonCondition()
Expand Down
2 changes: 1 addition & 1 deletion src/Rules/Rule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ abstract class Rule : IRule
{
public RuleInfo Info { get; private set; }
public Condition Condition { get; }
protected static Condition DefaultExcludedCondition => IsChromiumContent;
protected static Condition DefaultExcludedCondition => IsChromiumContent - ShouldTestAllChromiumContent;

protected Rule(Condition excludedCondition)
{
Expand Down
21 changes: 21 additions & 0 deletions src/Rules/RulesSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Axe.Windows.Rules
{
/// <summary>
/// This class contains settings that influence the behavior of the rules engine. It is currently
/// static for simplicity. This is a potential problem in the scenario of concurrent scans where the
/// settings change in the middle of a scan. Given the very limited scope of the current settings,
/// we are choosing to accept this limitation for now.
/// </summary>
internal static class RulesSettings
{
/// <summary>
/// This setting controls whether the rules engine should test all Chromium content. This exists
/// to allow browser teams to debug code that converts from HTML to UIA. It should be set to false
/// in all other scenarios.
/// </summary>
internal static bool ShouldTestAllChromiumContent { get; set; }
}
}