From d420fad4897a3dffea4987fd52324f472a0f9adc Mon Sep 17 00:00:00 2001 From: udit3333 Date: Fri, 20 Mar 2020 08:28:47 -0700 Subject: [PATCH] Add info bar if blocked elements present in Svg (#1620) * Added logic to check for blocked elements * Added unit tests * Fix warnings from msi solution --- installer/PowerToysSetup/Product.wxs | 12 +-- .../SvgPreviewHandler/SvgPreviewControl.cs | 8 ++ .../SvgPreviewHandler.csproj | 1 + .../Utilities/SvgPreviewHandlerHelper.cs | 66 ++++++++++++ .../SvgPreviewControlTests.cs | 68 +++++++++++- .../SvgPreviewHandlerHelperTests.cs | 102 ++++++++++++++++++ .../UnitTests-SvgPreviewHandler.csproj | 1 + 7 files changed, 251 insertions(+), 7 deletions(-) create mode 100644 src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs create mode 100644 src/modules/previewpane/UnitTests-SvgPreviewHandler/SvgPreviewHandlerHelperTests.cs diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 7eb714d02e..5c1c4c82e8 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -384,9 +384,9 @@ - + - + @@ -403,11 +403,11 @@ - + - + @@ -420,11 +420,11 @@ - + - + diff --git a/src/modules/previewpane/SvgPreviewHandler/SvgPreviewControl.cs b/src/modules/previewpane/SvgPreviewHandler/SvgPreviewControl.cs index 6ce5f48088..d6591ab347 100644 --- a/src/modules/previewpane/SvgPreviewHandler/SvgPreviewControl.cs +++ b/src/modules/previewpane/SvgPreviewHandler/SvgPreviewControl.cs @@ -15,6 +15,7 @@ using System.Xml.Linq; using Common; using Common.Utilities; using PreviewHandlerCommon; +using SvgPreviewHandler.Utilities; namespace SvgPreviewHandler { @@ -58,6 +59,13 @@ namespace SvgPreviewHandler } } + // Add a info bar on top of the Preview if any blocked element is present. + if (SvgPreviewHandlerHelper.CheckBlockedElements(svgData)) + { + this.infoBarAdded = true; + this.AddTextBoxControl(Resource.BlockedElementInfoText); + } + this.AddBrowserControl(svgData); this.Resize += this.FormResized; base.DoPreview(dataSource); diff --git a/src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj b/src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj index c16521b80a..706ac1286d 100644 --- a/src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj +++ b/src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj @@ -107,6 +107,7 @@ + diff --git a/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs b/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs new file mode 100644 index 0000000000..bd906a213a --- /dev/null +++ b/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; + +namespace SvgPreviewHandler.Utilities +{ + /// + /// Helper utilities for Svg Preview Handler. + /// + public class SvgPreviewHandlerHelper + { + /// + /// Dictionary of elements in lower case that are blocked from Svg for preview pane. + /// Reference for list of Svg Elements: https://developer.mozilla.org/en-US/docs/Web/SVG/Element. + /// + private static Dictionary blockedElementsName = new Dictionary + { + { "script", true }, + { "image", true }, + { "feimage", true }, + }; + + /// + /// Check if any of the blocked elements present in Svg. + /// + /// Input Svg. + /// Returns true in case any of the blocked element is present otherwise false. + public static bool CheckBlockedElements(string svgData) + { + bool foundBlockedElement = false; + if (string.IsNullOrWhiteSpace(svgData)) + { + return foundBlockedElement; + } + + // Check if any of the blocked element is present. If failed to parse or iterate over Svg return default false. + // No need to throw because all the external content and script are blocked on the Web Browser Control itself. + try + { + var doc = XDocument.Parse(svgData); + var elements = doc.Descendants().ToList(); + foreach (XElement element in elements) + { + var elementName = element?.Name?.LocalName?.ToLower(); + if (elementName != null && blockedElementsName.ContainsKey(elementName)) + { + foundBlockedElement = true; + + // No need to iterate further since we are displaying info bar with condition of atleast one occurrence of blocked element is present. + break; + } + } + } + catch (Exception) + { + } + + return foundBlockedElement; + } + } +} diff --git a/src/modules/previewpane/UnitTests-SvgPreviewHandler/SvgPreviewControlTests.cs b/src/modules/previewpane/UnitTests-SvgPreviewHandler/SvgPreviewControlTests.cs index fe4568d19d..f81d217a83 100644 --- a/src/modules/previewpane/UnitTests-SvgPreviewHandler/SvgPreviewControlTests.cs +++ b/src/modules/previewpane/UnitTests-SvgPreviewHandler/SvgPreviewControlTests.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; using System.Drawing; using System.IO; using System.Runtime.InteropServices; @@ -157,6 +161,68 @@ namespace UnitTests_SvgPreviewHandler Assert.AreEqual(finalParentWidth, textBox.Width); } + [TestMethod] + public void SvgPreviewControl_ShouldAddTextBox_IfBlockedElementsArePresent() + { + // Arrange + var svgPreviewControl = new SvgPreviewControl(); + var svgBuilder = new StringBuilder(); + svgBuilder.AppendLine(""); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine(""); + + // Act + svgPreviewControl.DoPreview(GetMockStream(svgBuilder.ToString())); + + // Assert + Assert.IsInstanceOfType(svgPreviewControl.Controls[0], typeof(RichTextBox)); + Assert.IsInstanceOfType(svgPreviewControl.Controls[1], typeof(WebBrowserExt)); + Assert.AreEqual(svgPreviewControl.Controls.Count, 2); + } + + [TestMethod] + public void SvgPreviewControl_ShouldNotAddTextBox_IfNoBlockedElementsArePresent() + { + // Arrange + var svgPreviewControl = new SvgPreviewControl(); + var svgBuilder = new StringBuilder(); + svgBuilder.AppendLine(""); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine(""); + + // Act + svgPreviewControl.DoPreview(GetMockStream(svgBuilder.ToString())); + + // Assert + Assert.IsInstanceOfType(svgPreviewControl.Controls[0], typeof(WebBrowserExt)); + Assert.AreEqual(svgPreviewControl.Controls.Count, 1); + } + + [TestMethod] + public void SvgPreviewControl_InfoBarWidthShouldAdjustWithParentControlWidthChanges_IfBlockedElementsArePresent() + { + // Arrange + var svgPreviewControl = new SvgPreviewControl(); + var svgBuilder = new StringBuilder(); + svgBuilder.AppendLine(""); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine(""); + svgPreviewControl.DoPreview(GetMockStream(svgBuilder.ToString())); + var textBox = svgPreviewControl.Controls[0] as RichTextBox; + var incrementParentControlWidth = 5; + var intialParentWidth = svgPreviewControl.Width; + var intitialTextBoxWidth = textBox.Width; + var finalParentWidth = intialParentWidth + incrementParentControlWidth; + + // Act + svgPreviewControl.Width += incrementParentControlWidth; + + // Assert + Assert.AreEqual(intialParentWidth, intitialTextBoxWidth); + Assert.AreEqual(finalParentWidth, textBox.Width); + } + private IStream GetMockStream(string streamData) { var mockStream = new Mock(); diff --git a/src/modules/previewpane/UnitTests-SvgPreviewHandler/SvgPreviewHandlerHelperTests.cs b/src/modules/previewpane/UnitTests-SvgPreviewHandler/SvgPreviewHandlerHelperTests.cs new file mode 100644 index 0000000000..d6caef62a1 --- /dev/null +++ b/src/modules/previewpane/UnitTests-SvgPreviewHandler/SvgPreviewHandlerHelperTests.cs @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SvgPreviewHandler.Utilities; +using System.Text; + +namespace UnitTests_SvgPreviewHandler +{ + [TestClass] + public class SvgPreviewHandlerHelperTests + { + [TestMethod] + public void CheckBlockedElements_ShoudReturnTrue_IfABlockedElementIsPresent() + { + // Arrange + var svgBuilder = new StringBuilder(); + svgBuilder.AppendLine(""); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine(""); + bool foundFilteredElement; + + // Act + foundFilteredElement = SvgPreviewHandlerHelper.CheckBlockedElements(svgBuilder.ToString()); + + // Assert + Assert.IsTrue(foundFilteredElement); + } + + [TestMethod] + public void CheckBlockedElements_ShoudReturnTrue_IfBlockedElementsIsPresentInNestedLevel() + { + // Arrange + var svgBuilder = new StringBuilder(); + svgBuilder.AppendLine(""); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine("\t\t"); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine(""); + bool foundFilteredElement; + + // Act + foundFilteredElement = SvgPreviewHandlerHelper.CheckBlockedElements(svgBuilder.ToString()); + + // Assert + Assert.IsTrue(foundFilteredElement); + } + + [TestMethod] + public void CheckBlockedElements_ShoudReturnTrue_IfMultipleBlockedElementsArePresent() + { + // Arrange + var svgBuilder = new StringBuilder(); + svgBuilder.AppendLine(""); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine(""); + bool foundFilteredElement; + + // Act + foundFilteredElement = SvgPreviewHandlerHelper.CheckBlockedElements(svgBuilder.ToString()); + + // Assert + Assert.IsTrue(foundFilteredElement); + } + + [TestMethod] + public void CheckBlockedElements_ShoudReturnFalse_IfNoBlockedElementsArePresent() + { + // Arrange + var svgBuilder = new StringBuilder(); + svgBuilder.AppendLine(""); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine("\t"); + svgBuilder.AppendLine(""); + bool foundFilteredElement; + + // Act + foundFilteredElement = SvgPreviewHandlerHelper.CheckBlockedElements(svgBuilder.ToString()); + + // Assert + Assert.IsFalse(foundFilteredElement); + } + + [DataTestMethod] + [DataRow("")] + [DataRow(" ")] + [DataRow(null)] + public void CheckBlockedElements_ShoudReturnFalse_IfSvgDataIsNullOrWhiteSpaces(string svgData) + { + // Arrange + bool foundFilteredElement; + + // Act + foundFilteredElement = SvgPreviewHandlerHelper.CheckBlockedElements(svgData); + + // Assert + Assert.IsFalse(foundFilteredElement); + } + } +} diff --git a/src/modules/previewpane/UnitTests-SvgPreviewHandler/UnitTests-SvgPreviewHandler.csproj b/src/modules/previewpane/UnitTests-SvgPreviewHandler/UnitTests-SvgPreviewHandler.csproj index eade21aa65..43af524b86 100644 --- a/src/modules/previewpane/UnitTests-SvgPreviewHandler/UnitTests-SvgPreviewHandler.csproj +++ b/src/modules/previewpane/UnitTests-SvgPreviewHandler/UnitTests-SvgPreviewHandler.csproj @@ -89,6 +89,7 @@ Code +