fune/toolkit/mozapps/notificationserver/NotificationCallback.h
Nick Alexander a4a59a2ce9 Bug 1805514 - Part 3: Allow JS opaque relaunch data and actions. r=nrishel
This commit replaces two existing launch argument keys, `launchURL`
and `privilegedName`, with an opaque string of data.  Here opaque
means, "does not need to be inspected by the Windows notification
server DLL" (and in general, by the system backend components).

The existing `action` argument key was always intended for this
purpose but was not used in the first implementation.  Here, we make
`action` a stringified JSON object, which is easy for API consumers to
manage and generalizes to (mostly) arbitrary relaunch data.

This JSON object is a compound `notificationData` object containing
both:
- the consumer-provided `opaqueRelaunchData` (generally, an action);
- and implementation-provided details (the alert's name, if
  privileged, etc).
This compound object and the fact that everything transits as strings
makes everything a little more confusing than it really is.

The API to this opaque relaunch data is based on strings for
convenience.  It would be possible to manage JSON objects, perhaps by
using `nsIStructuredCloneContainer` to serialize "structured clone
encodable" JS objects across the process boundaries, but managing the
objects and container in that approach is much more effort than having
the API consumer stringify as desired.

In addition, this patch makes the notification server extract the
Firefox `action` data from the Windows toast `arguments` passed to the
server callback.  Since this fallback data is now provided to Firefox
at launch, there's no need to fetch it from the Windows notification
object; we simply need to know whether to pass through to a Windows
8.1 callback (`tagWasHandled=true`) or to act on the fallback data
(`tagWasHandled=false`).  This is simpler than teaching Firefox to
extract the arguments for toast itself or the appropriate action
button.

Differential Revision: https://phabricator.services.mozilla.com/D182314
2023-07-15 02:34:06 +00:00

73 lines
2.4 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef NotificationCallback_h__
#define NotificationCallback_h__
#include <filesystem>
#include <tuple>
#include <unknwn.h>
#include <wrl.h>
#include "mozilla/Maybe.h"
#include "nsWindowsHelpers.h"
using namespace Microsoft::WRL;
using namespace std::filesystem;
// Windows 10+ declarations.
// TODO remove declarations and add `#include
// <notificationactivationcallback.h>` when Windows 10 is the minimum supported.
typedef struct NOTIFICATION_USER_INPUT_DATA {
LPCWSTR Key;
LPCWSTR Value;
} NOTIFICATION_USER_INPUT_DATA;
MIDL_INTERFACE("53E31837-6600-4A81-9395-75CFFE746F94")
INotificationActivationCallback : public IUnknown {
public:
virtual HRESULT STDMETHODCALLTYPE Activate(
LPCWSTR appUserModelId, LPCWSTR invokedArgs,
const NOTIFICATION_USER_INPUT_DATA* data, ULONG count) = 0;
};
struct ToastArgs {
std::wstring profile;
std::wstring windowsTag;
std::wstring action;
};
class NotificationCallback final
: public RuntimeClass<RuntimeClassFlags<ClassicCom>,
INotificationActivationCallback> {
public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final;
HRESULT STDMETHODCALLTYPE Activate(LPCWSTR appUserModelId,
LPCWSTR invokedArgs,
const NOTIFICATION_USER_INPUT_DATA* data,
ULONG dataCount) final;
explicit NotificationCallback(const GUID& runtimeGuid,
const path& dllInstallDir)
: guid(runtimeGuid), installDir(dllInstallDir) {}
private:
const GUID guid = {};
const path installDir = {};
void HandleActivation(LPCWSTR invokedArgs);
mozilla::Maybe<ToastArgs> ParseToastArguments(LPCWSTR invokedArgs);
std::tuple<path, mozilla::UniquePtr<wchar_t[]>> BuildRunCommand(
const ToastArgs& args);
static mozilla::Maybe<nsAutoHandle> CreatePipe(const std::wstring& tag);
static bool ConnectPipeWithTimeout(const nsAutoHandle& pipe);
static void HandlePipeMessages(const nsAutoHandle& pipe);
static DWORD TransferForegroundPermission(const DWORD pid);
};
#endif