Running a Power App as Edge Extension

Running a Power App as Edge Extension header image

The plus site of starting a new adventure is an empty calendar and a whole lot of new energy! I recently started out at Blis Digital(mind the Dutch) and will be focussing on fusion development with the Power Platform. The first few days I figured that I needed to up my game regarding the Power Platform. And what better way to learn new things then to embrace yourself in the technology. So, I made myself the following challenge: to build a solution to quickly save articles to my reading list. Usually, I read articles through Pocket but there are cases you encounter an article that you need to follow up; therefor I decided to store my articles to a To Do action list. Other options could be to post them to Microsoft Teams as an adaptive card and share them in a broader setting.

So my goal is to get a Power App running as an Edge Extension. The Power App will be using a Flow to send content to ToDo resulting in three main components that we need to create.

  1. Edge Extension
  2. Power App
  3. Flow

My final result looks as follows:

Edge Chrome plugin

Edge extension

I have not, ever before, developed an Edge or Chrome plugin. So the first step in the thought process was to use G̶o̶o̶g̶l̶e̶ Bing to search how those work. Turns out there is this nice tutorial Create an extension. Summing up that its a manifest.json and some supporting icons, html and javascript files. Going through the tutorial helps you understanding the basic structure and requirements. Make sure to sideload your extension and see if all is working correctly.

Now you can’t just add an iframe to your chrome extension, and since we want our extension to allow a user to sign in we also need some code in place to prevent issues signing in.

Our Manifest itself is straight forward. We will be using two files frame.html and frame.js, those must be in the web_accessible_resources. We also will use a contentscript.js file that is added as a content_scripts. Since we will be authenticating users, we need to have access to the cookies from our extension. Adding the "permissions": ["cookies"] fixes that for us. The full manifest.json would look something like this:

{
    "name": "Power App",
    "version": "0.0.0.3",
    "manifest_version": 2,
    "description": "Loading your custom Power App into the browser.",
    "content_scripts": [{
        "js": ["contentscript.js"],
        "matches": ["*://*/*"],
        "all_frames": true
    }],
    "web_accessible_resources": [
        "frame.html",
        "frame.js"
    ],
    "permissions": [
        "cookies"
    ]
}

The contentscript.js will load our frame.html as an iframe. It also will make sure to prevent recursive frame insertion and will only load if the iFrame is not redirecint us to https://login.microsoftonline.com. The login.microsoftonline.com page will fail to render if you are injecting an Iframe so make sure this is in place. Finally we add some querystring parameters origin and title to our loaded frame.html. That way we can capture the page we inject our iframe on. This captured data can be used by our Power App later on. The full contentscript.js looks as follows:

// Avoid recursive frame insertion...
var extensionOrigin = 'chrome-extension://' + chrome.runtime.id;

if (!location.ancestorOrigins.contains(extensionOrigin) && !location.origin.startsWith("https://login.microsoftonline.com")) {

    var iframe = document.createElement('iframe');
    // Must be declared at web_accessible_resources in manifest.json
    iframe.src = chrome.runtime.getURL('frame.html?origin=' + encodeURI(location.href) + "&title=" + encodeURI(document.title));

    // Some styles for a fancy sidebar
    iframe.style.cssText = 'position:fixed;top:0;left:10;display:block;' +
        'width:300px;height:530px;overflow=hidden;z-index:1000;';
    document.body.appendChild(iframe);
}

The frame.html file can be an almost empty HTML file or contain as much styling as you want. I opted for a clean html file with the magic happening here:

<body>
    <div id="iframeplaceholder"></div>
    <script src="frame.js"></script>
</body>

The frame.js is used to get the querystring parameters, add them to our Power App play URL and set that URL as the iFrame. Make sure to update the iframe.src URL to reflect your Power App ID.

const params = new URLSearchParams(window.location.search)

var iframe = document.createElement('iframe');
iframe.src = "https://apps.powerapps.com/play/xxxxxxx?source=iframe&title=" + encodeURI(params.get('title')) + "&url=" + encodeURI(params.get('origin'))

var myFrame = document.getElementById('iframeplaceholder');
myFrame.appendChild(iframe);

This are all the steps required to run a Power App in your Edge Browser. However, make sure to reload your extension when side loading. Changes might not always trickle down as some of the content is cached. My best experience was to reload the extension each time I changed something in the JS or HTML.

The Power App

Once you have your Edge Extension working the Power App can be running whatever you like. To create an application that can create something in To Do I picked a canvas app. There are no ‘real’ requirements on the app side of things, but keep in mind the sizing of your iframe when designing parts the app itself. There is a To-Do connector you can use, but that is slightly limited. I picked the Power Automate connector to model some more options. The Power App itself only uses the two parameters that are passed on, and in return passes those on to the Flow (you could refresh the dataset, however the Flow might not be quick enough so either you have to build in a delay or wait till your flow returns a value before refreshing the dataset).

Passing on parameters can be done using the Param option in the function window. My call to the Flow is linked to the OnSelect and runs as follows:

'PowerApp-ToDo'.Run(Param("title"), Param("url"));

The Flow

The last component is the Flow, it uses the Power App trigger and a single action to create a new ToDo. Since we are passing the title and URL we can use those in the Flow as input parameters for our action using the following expression: @{triggerBody()['Addato-do(V3)_Title']}. The full flow looks like this:

Flow to create ToDo

The reason I picked a Flow over the ToDo action there is available in Power Apps is because the out of the box action is a bit limited. I wanted to populate the body with the URL and simply couldn’t find an easy way to do so with the out of the box action.

Fusion Development 🔥

Now I understand that some of these steps could have been done writing actual code instead of using the Power Platform. However the fact that I could click together a few components and have them interact with my Edge browser really appealed to me. Building a plugin to capture specific data from your browser has become way easier. Something that fits within the fusion development approach you hear a lot about. So instead of diving head first into complex code I decided to play around with the Power App approach and I must admit I am not disappointed.

Loading comments…