Skip to content

Commit

Permalink
Add EnabledIf to all Web Extensions messages.
Browse files Browse the repository at this point in the history
https://webkit.org/b/270468
rdar://problem/124026371

Reviewed by Brian Weinstein.

Added EnabledIf to all messages, and for APIs that require granted permissions,
use the new isAPIMessageAllowed() which does the permissions checks. This will
prevent a compromised web process from trying to send messages that are not
currently expected by the UI process.

* Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPIActionCocoa.mm:
(WebKit::WebExtensionContext::isActionMessageAllowed): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPIAlarmsCocoa.mm:
(WebKit::WebExtensionContext::isAlarmsMessageAllowed): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPICommandsCocoa.mm:
(WebKit::WebExtensionContext::isCommandsMessageAllowed): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPICookiesCocoa.mm:
(WebKit::WebExtensionContext::isCookiesMessageAllowed): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPIDeclarativeNetRequestCocoa.mm:
(WebKit::WebExtensionContext::isDeclarativeNetRequestMessageAllowed): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPIMenusCocoa.mm:
(WebKit::WebExtensionContext::isMenusMessageAllowed): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPIScriptingCocoa.mm:
(WebKit::WebExtensionContext::isScriptingMessageAllowed): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPIStorageCocoa.mm:
(WebKit::WebExtensionContext::isStorageMessageAllowed): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPIWebNavigationCocoa.mm:
(WebKit::WebExtensionContext::isWebNavigationMessageAllowed): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionContextCocoa.mm:
(WebKit::WebExtensionContext::isDevToolsMessageAllowed): Added.
* Source/WebKit/UIProcess/Extensions/WebExtensionContext.h:
* Source/WebKit/UIProcess/Extensions/WebExtensionContext.messages.in:
* Source/WebKit/UIProcess/Extensions/WebExtensionController.messages.in:
* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPIMenus.mm:
(TEST(WKWebExtensionAPIMenus, ActionMenus)): Reset activeTab, ActionMenusWithActiveTab tests that.
(TEST(WKWebExtensionAPIMenus, ActionMenusWithActiveTab)): Remove activeTab grant, it is granted by manager.
(TEST(WKWebExtensionAPIMenus, MacActiveTabContextMenuItems)): Ditto.
* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPITabs.mm:
(TEST(WKWebExtensionAPITabs, UserGestureWithoutActiveTab)): Reset activeTab, ActiveTab tests that.
* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionDataRecord.mm:
(TEST(WKWebExtensionDataRecord, GetDataRecords)): Grant storage permission.
(TEST(WKWebExtensionDataRecord, GetDataRecordsForMultipleContexts)): Ditto.
(TEST(WKWebExtensionDataRecord, DISABLED_RemoveDataRecords)): Ditto.
(TEST(WKWebExtensionDataRecord, DISABLED_RemoveDataRecordsForMultipleContexts)): Ditto.
* Tools/TestWebKitAPI/cocoa/WebExtensionUtilities.mm:
(-[TestWebExtensionManager initForExtension:extensionControllerConfiguration:]):
Grant all requested API permissions, so it does not need done in each test.
This matches what we do in Safari.

Canonical link: https://commits.webkit.org/275670@main
  • Loading branch information
xeenon committed Mar 5, 2024
1 parent 04d4979 commit 579e387
Show file tree
Hide file tree
Showing 17 changed files with 188 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@
return Ref { context.defaultAction() };
}

bool WebExtensionContext::isActionMessageAllowed()
{
return isLoaded() && (extension().hasAction() || extension().hasBrowserAction() || extension().hasPageAction());
}

void WebExtensionContext::actionGetTitle(std::optional<WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebExtensionTabIdentifier> tabIdentifier, CompletionHandler<void(Expected<String, WebExtensionError>&&)>&& completionHandler)
{
static NSString * const apiName = @"action.getTitle()";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@

namespace WebKit {

bool WebExtensionContext::isAlarmsMessageAllowed()
{
return isLoaded() && hasPermission(_WKWebExtensionPermissionAlarms);
}

void WebExtensionContext::alarmsCreate(const String& name, Seconds initialInterval, Seconds repeatInterval)
{
m_alarmMap.set(name, WebExtensionAlarm::create(name, initialInterval, repeatInterval, [&](const WebExtensionAlarm& alarm) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@

namespace WebKit {

bool WebExtensionContext::isCommandsMessageAllowed()
{
return isLoaded() && extension().hasCommands();
}

void WebExtensionContext::commandsGetAll(CompletionHandler<void(Vector<WebExtensionCommandParameters>)>&& completionHandler)
{
auto results = WTF::map(commands(), [](auto& command) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ static inline URL toURL(const WebCore::Cookie& cookie)
return URL { makeString(cookie.secure ? "https"_s : "http"_s, "://"_s, domain, cookie.path) };
}

bool WebExtensionContext::isCookiesMessageAllowed()
{
return isLoaded() && hasPermission(_WKWebExtensionPermissionCookies);
}

void WebExtensionContext::fetchCookies(WebsiteDataStore& dataStore, const URL& url, const WebExtensionCookieFilterParameters& filterParameters, CompletionHandler<void(Expected<Vector<WebExtensionCookieParameters>, WebExtensionError>&&)>&& completionHandler)
{
if (url.isValid() && !hasPermission(url)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#import "WebExtensionConstants.h"
#import "WebExtensionUtilities.h"
#import "_WKWebExtensionDeclarativeNetRequestSQLiteStore.h"
#import "_WKWebExtensionPermission.h"
#import "_WKWebExtensionSQLiteStore.h"
#import <wtf/BlockPtr.h>
#import <wtf/cocoa/VectorCocoa.h>
Expand All @@ -45,6 +46,11 @@

namespace WebKit {

bool WebExtensionContext::isDeclarativeNetRequestMessageAllowed()
{
return isLoaded() && (hasPermission(_WKWebExtensionPermissionDeclarativeNetRequest) || hasPermission(_WKWebExtensionPermissionDeclarativeNetRequestWithHostAccess));
}

void WebExtensionContext::declarativeNetRequestGetEnabledRulesets(CompletionHandler<void(Vector<String>&&)>&& completionHandler)
{
Vector<String> enabledRulesets;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ static bool isAncestorOrSelf(WebExtensionContext& context, const String& potenti
return false;
}

bool WebExtensionContext::isMenusMessageAllowed()
{
return isLoaded() && (hasPermission(_WKWebExtensionPermissionContextMenus) || hasPermission(_WKWebExtensionPermissionMenus));
}

void WebExtensionContext::menusCreate(const WebExtensionMenuItemParameters& parameters, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&& completionHandler)
{
static NSString * const apiName = @"menus.create()";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@

using namespace WebExtensionDynamicScripts;

bool WebExtensionContext::isScriptingMessageAllowed()
{
return isLoaded() && hasPermission(_WKWebExtensionPermissionScripting);
}

void WebExtensionContext::scriptingExecuteScript(const WebExtensionScriptInjectionParameters& parameters, CompletionHandler<void(Expected<InjectionResults, WebExtensionError>&&)>&& completionHandler)
{
static NSString * const apiName= @"scripting.executeScript()";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@

namespace WebKit {

bool WebExtensionContext::isStorageMessageAllowed()
{
return isLoaded() && (hasPermission(_WKWebExtensionPermissionStorage) || hasPermission(_WKWebExtensionPermissionUnlimitedStorage));
}

void WebExtensionContext::storageGet(WebPageProxyIdentifier webPageProxyIdentifier, WebExtensionDataType dataType, const Vector<String>& keys, CompletionHandler<void(Expected<String, WebExtensionError>&&)>&& completionHandler)
{
static NSString * const callingAPIName = [NSString stringWithFormat:@"%@.get()", (NSString *)toAPIPrefixString(dataType)];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ static WebExtensionFrameParameters frameParametersForFrame(_WKFrameTreeNode *fra
};
}

bool WebExtensionContext::isWebNavigationMessageAllowed()
{
return isLoaded() && hasPermission(_WKWebExtensionPermissionWebNavigation);
}

void WebExtensionContext::webNavigationTraverseFrameTreeForFrame(_WKFrameTreeNode *frame, _WKFrameTreeNode *parentFrame, WebExtensionTab* tab, Vector<WebExtensionFrameParameters> &frames)
{
frames.append(frameParametersForFrame(frame, parentFrame, tab, this, true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3150,6 +3150,17 @@ static _WKWebExtensionContextError toAPI(WebExtensionContext::Error error)
return false;
}

bool WebExtensionContext::isDevToolsMessageAllowed()
{
#if ENABLE(INSPECTOR_EXTENSIONS)
if (!isLoaded())
return false;
return extension().hasInspectorBackgroundPage();
#else
return false;
#endif
}

void WebExtensionContext::loadInspectorBackgroundPagesDuringLoad()
{
ASSERT(isLoaded());
Expand Down
10 changes: 10 additions & 0 deletions Source/WebKit/UIProcess/Extensions/WebExtensionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
void fetchCookies(WebsiteDataStore&, const URL&, const WebExtensionCookieFilterParameters&, CompletionHandler<void(Expected<Vector<WebExtensionCookieParameters>, WebExtensionError>&&)>&&);

// Action APIs
bool isActionMessageAllowed();
void actionGetTitle(std::optional<WebExtensionWindowIdentifier>, std::optional<WebExtensionTabIdentifier>, CompletionHandler<void(Expected<String, WebExtensionError>&&)>&&);
void actionSetTitle(std::optional<WebExtensionWindowIdentifier>, std::optional<WebExtensionTabIdentifier>, const String& title, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
void actionSetIcon(std::optional<WebExtensionWindowIdentifier>, std::optional<WebExtensionTabIdentifier>, const String& iconDictionaryJSON, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
Expand All @@ -632,6 +633,7 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
void fireActionClickedEventIfNeeded(WebExtensionTab*);

// Alarms APIs
bool isAlarmsMessageAllowed();
void alarmsCreate(const String& name, Seconds initialInterval, Seconds repeatInterval);
void alarmsGet(const String& name, CompletionHandler<void(std::optional<WebExtensionAlarmParameters>&&)>&&);
void alarmsClear(const String& name, CompletionHandler<void()>&&);
Expand All @@ -640,11 +642,13 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
void fireAlarmsEventIfNeeded(const WebExtensionAlarm&);

// Commands APIs
bool isCommandsMessageAllowed();
void commandsGetAll(CompletionHandler<void(Vector<WebExtensionCommandParameters>)>&&);
void fireCommandEventIfNeeded(const WebExtensionCommand&, WebExtensionTab*);
void fireCommandChangedEventIfNeeded(const WebExtensionCommand&, const String& oldShortcut);

// Cookies APIs
bool isCookiesMessageAllowed();
void cookiesGet(std::optional<PAL::SessionID>, const String& name, const URL&, CompletionHandler<void(Expected<std::optional<WebExtensionCookieParameters>, WebExtensionError>&&)>&&);
void cookiesGetAll(std::optional<PAL::SessionID>, const URL&, const WebExtensionCookieFilterParameters&, CompletionHandler<void(Expected<Vector<WebExtensionCookieParameters>, WebExtensionError>&&)>&&);
void cookiesSet(std::optional<PAL::SessionID>, const WebExtensionCookieParameters&, CompletionHandler<void(Expected<std::optional<WebExtensionCookieParameters>, WebExtensionError>&&)>&&);
Expand All @@ -653,6 +657,7 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
void fireCookiesChangedEventIfNeeded();

// DeclarativeNetRequest APIs
bool isDeclarativeNetRequestMessageAllowed();
void declarativeNetRequestGetEnabledRulesets(CompletionHandler<void(Vector<String>&&)>&&);
void declarativeNetRequestUpdateEnabledRulesets(const Vector<String>& rulesetIdentifiersToEnable, const Vector<String>& rulesetIdentifiersToDisable, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
void declarativeNetRequestDisplayActionCountAsBadgeText(bool displayActionCountAsBadgeText, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
Expand All @@ -668,6 +673,7 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi

#if ENABLE(INSPECTOR_EXTENSIONS)
// DevTools APIs
bool isDevToolsMessageAllowed();
void devToolsPanelsCreate(WebPageProxyIdentifier, const String& title, const String& iconPath, const String& pagePath, CompletionHandler<void(Expected<Inspector::ExtensionTabID, WebExtensionError>&&)>&&);
void devToolsInspectedWindowEval(WebPageProxyIdentifier, const String& scriptSource, const std::optional<URL>& frameURL, CompletionHandler<void(Expected<Expected<std::span<const uint8_t>, WebCore::ExceptionDetails>, WebExtensionError>&&)>&&);
void devToolsInspectedWindowReload(WebPageProxyIdentifier, const std::optional<bool>& ignoreCache);
Expand All @@ -681,6 +687,7 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
void extensionIsAllowedIncognitoAccess(CompletionHandler<void(bool)>&&);

// Menus APIs
bool isMenusMessageAllowed();
void menusCreate(const WebExtensionMenuItemParameters&, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
void menusUpdate(const String& identifier, const WebExtensionMenuItemParameters&, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
void menusRemove(const String& identifier, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
Expand Down Expand Up @@ -721,6 +728,7 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
void fireRuntimeInstalledEventIfNeeded();

// Scripting APIs
bool isScriptingMessageAllowed();
void scriptingExecuteScript(const WebExtensionScriptInjectionParameters&, CompletionHandler<void(Expected<Vector<WebExtensionScriptInjectionResultParameters>, WebExtensionError>&&)>&&);
void scriptingInsertCSS(const WebExtensionScriptInjectionParameters&, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
void scriptingRemoveCSS(const WebExtensionScriptInjectionParameters&, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
Expand All @@ -731,6 +739,7 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
bool createInjectedContentForScripts(const Vector<WebExtensionRegisteredScriptParameters>&, WebExtensionDynamicScripts::WebExtensionRegisteredScript::FirstTimeRegistration, InjectedContentVector&, NSString *callingAPIName, NSString **errorMessage);

// Storage APIs
bool isStorageMessageAllowed();
void storageGet(WebPageProxyIdentifier, WebExtensionDataType, const Vector<String>& keys, CompletionHandler<void(Expected<String, WebExtensionError>&&)>&&);
void storageGetBytesInUse(WebPageProxyIdentifier, WebExtensionDataType, const Vector<String>& keys, CompletionHandler<void(Expected<size_t, WebExtensionError>&&)>&&);
void storageSet(WebPageProxyIdentifier, WebExtensionDataType, const String& dataJSON, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
Expand Down Expand Up @@ -771,6 +780,7 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
void fireTabsRemovedEventIfNeeded(WebExtensionTabIdentifier, WebExtensionWindowIdentifier, WindowIsClosing);

// WebNavigation APIs
bool isWebNavigationMessageAllowed();
void webNavigationGetFrame(WebExtensionTabIdentifier, WebExtensionFrameIdentifier, CompletionHandler<void(Expected<std::optional<WebExtensionFrameParameters>, WebExtensionError>&&)>&&);
void webNavigationGetAllFrames(WebExtensionTabIdentifier, CompletionHandler<void(Expected<Vector<WebExtensionFrameParameters>, WebExtensionError>&&)>&&);
void webNavigationTraverseFrameTreeForFrame(_WKFrameTreeNode *, _WKFrameTreeNode *parentFrame, WebExtensionTab*, Vector<WebExtensionFrameParameters>&);
Expand Down
Loading

0 comments on commit 579e387

Please sign in to comment.