Skip to content

Commit

Permalink
Add support for loading the background content for a _WKWebExtensionC…
Browse files Browse the repository at this point in the history
…ontext.

https://webkit.org/b/273269
rdar://126994428

Reviewed by Brian Weinstein.

Added a loadBackgroundContentWithCompletionHandler: method, and changed how the background
load errors are created. This is a step in the direction of having WebExtensionContext
track runtime errors separate from WebExtension (see bug 270580).

* Source/WebCore/en.lproj/Localizable.strings: Updated with update-webkit-localizable-strings.
* Source/WebKit/UIProcess/API/Cocoa/_WKWebExtension.h:
(NS_ERROR_ENUM): Removed _WKWebExtensionErrorBackgroundContentFailedToLoad.
* Source/WebKit/UIProcess/API/Cocoa/_WKWebExtensionContext.h:
(NS_ERROR_ENUM): Added _WKWebExtensionContextErrorNoBackgroundContent and
_WKWebExtensionContextErrorBackgroundContentFailedToLoad.
* Source/WebKit/UIProcess/API/Cocoa/_WKWebExtensionContext.mm:
(-[_WKWebExtensionContext loadBackgroundContentWithCompletionHandler:]): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionCocoa.mm:
(WebKit::toAPI): Removed BackgroundContentFailedToLoad.
(WebKit::WebExtension::createError): Ditto.
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionContextCocoa.mm:
(WebKit::toAPI): Added new error codes.
(WebKit::WebExtensionContext::createError): Ditto.
(WebKit::WebExtensionContext::loadBackgroundContent): Added.
(WebKit::WebExtensionContext::loadBackgroundWebView): Set m_backgroundContentLoadError
instead of recording it on the WebExtension.
(WebKit::WebExtensionContext::didFailNavigation): Ditto.
* Source/WebKit/UIProcess/Extensions/WebExtension.h:
* Source/WebKit/UIProcess/Extensions/WebExtensionContext.h:
(WebKit::WebExtensionContext::backgroundContentLoadError const): Added.

Canonical link: https://commits.webkit.org/277998@main
  • Loading branch information
xeenon committed Apr 25, 2024
1 parent 9f6d74b commit 10d1920
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 17 deletions.
11 changes: 7 additions & 4 deletions Source/WebCore/en.lproj/Localizable.strings
Expand Up @@ -79,12 +79,12 @@
/* Label for an inspectable Web Extension background page */
"%@ — Extension Background Page" = "%@ — Extension Background Page";

/* Label for an inspectable Web Extension service worker */
"%@ — Extension Service Worker" = "%@ — Extension Service Worker";

/* Label for an inspectable Web Extension popup page */
"%@ — Extension Popup Page" = "%@ — Extension Popup Page";

/* Label for an inspectable Web Extension service worker */
"%@ — Extension Service Worker" = "%@ — Extension Service Worker";

/* Label to describe the number of files selected in a file upload control that allows multiple files */
"%d files" = "%d files";

Expand Down Expand Up @@ -1030,6 +1030,9 @@
/* Empty select list */
"No Options Select Popover" = "No Options";

/* WKWebExtensionContextErrorNoBackgroundContent description */
"No background content is available to load." = "No background content is available to load.";

/* Label for only item in menu that appears when clicking on the search field image, when no searches have been performed */
"No recent searches" = "No recent searches";

Expand Down Expand Up @@ -1441,7 +1444,7 @@
/* WKErrorWebContentProcessTerminated description */
"The Web Content process was terminated" = "The Web Content process was terminated";

/* WKWebExtensionErrorBackgroundContentFailedToLoad description */
/* WKWebExtensionContextErrorBackgroundContentFailedToLoad description */
"The background content failed to load due to an error." = "The background content failed to load due to an error.";

/* WebKitErrorGeolocationLocationUnknown description */
Expand Down
2 changes: 0 additions & 2 deletions Source/WebKit/UIProcess/API/Cocoa/_WKWebExtension.h
Expand Up @@ -51,7 +51,6 @@ WK_EXTERN NSErrorDomain const _WKWebExtensionErrorDomain NS_SWIFT_NAME(_WKWebExt
@constant WKWebExtensionErrorInvalidManifestEntry Indicates that an invalid manifest entry was encountered.
@constant WKWebExtensionErrorInvalidDeclarativeNetRequestEntry Indicates that an invalid declarative net request entry was encountered.
@constant WKWebExtensionErrorInvalidBackgroundPersistence Indicates that the extension specified background persistence that was not compatible with the platform or features requested.
@constant WKWebExtensionErrorBackgroundContentFailedToLoad Indicates that an error occurred loading the background content.
*/
typedef NS_ERROR_ENUM(_WKWebExtensionErrorDomain, _WKWebExtensionError) {
_WKWebExtensionErrorUnknown = 1,
Expand All @@ -62,7 +61,6 @@ typedef NS_ERROR_ENUM(_WKWebExtensionErrorDomain, _WKWebExtensionError) {
_WKWebExtensionErrorInvalidManifestEntry,
_WKWebExtensionErrorInvalidDeclarativeNetRequestEntry,
_WKWebExtensionErrorInvalidBackgroundPersistence,
_WKWebExtensionErrorBackgroundContentFailedToLoad,
} NS_SWIFT_NAME(_WKWebExtension.Error) WK_API_AVAILABLE(macos(13.3), ios(16.4));

/*! @abstract This notification is sent whenever a @link WKWebExtension @/link has new errors or errors were cleared. */
Expand Down
13 changes: 13 additions & 0 deletions Source/WebKit/UIProcess/API/Cocoa/_WKWebExtensionContext.h
Expand Up @@ -57,12 +57,16 @@ WK_EXTERN NSErrorDomain const _WKWebExtensionContextErrorDomain NS_SWIFT_NAME(_W
@constant WKWebExtensionContextErrorAlreadyLoaded Indicates that the context is already loaded by a @link WKWebExtensionController @/link.
@constant WKWebExtensionContextErrorNotLoaded Indicates that the context is not loaded by a @link WKWebExtensionController @/link.
@constant WKWebExtensionContextErrorBaseURLAlreadyInUse Indicates that another context is already using the specified base URL.
@constant WKWebExtensionContextErrorNoBackgroundContent Indicates that the extension does not have background content.
@constant WKWebExtensionContextErrorBackgroundContentFailedToLoad Indicates that an error occurred loading the background content.
*/
typedef NS_ERROR_ENUM(_WKWebExtensionContextErrorDomain, _WKWebExtensionContextError) {
_WKWebExtensionContextErrorUnknown = 1,
_WKWebExtensionContextErrorAlreadyLoaded,
_WKWebExtensionContextErrorNotLoaded,
_WKWebExtensionContextErrorBaseURLAlreadyInUse,
_WKWebExtensionContextErrorNoBackgroundContent,
_WKWebExtensionContextErrorBackgroundContentFailedToLoad,
} NS_SWIFT_NAME(_WKWebExtensionContext.Error) WK_API_AVAILABLE(macos(13.3), ios(16.4));

/*!
Expand Down Expand Up @@ -524,6 +528,15 @@ WK_CLASS_AVAILABLE(macos(13.3), ios(16.4))
*/
- (void)setPermissionStatus:(_WKWebExtensionContextPermissionStatus)status forMatchPattern:(_WKWebExtensionMatchPattern *)pattern expirationDate:(nullable NSDate *)expirationDate NS_SWIFT_NAME(setPermissionStatus(_:for:expirationDate:));

/*!
@abstract Loads the background content if needed for the extension.
@param completionHandler A block to be called upon completion of the loading process, with an optional error object.
@discussion This method forces the loading of the background content for the extension that will otherwise be loaded on-demand during specific events.
It is useful when the app requires the background content to be loaded for other reasons. If the background content is already loaded, the completion handler
will be called immediately. An error will occur if the extension does not have any background content to load or loading fails.
*/
- (void)loadBackgroundContentWithCompletionHandler:(void (^)(NSError * _Nullable error))completionHandler;

/*!
@abstract Retrieves the extension action for a given tab, or the default action if `nil` is passed.
@param tab The tab for which to retrieve the extension action, or `nil` to get the default action.
Expand Down
10 changes: 10 additions & 0 deletions Source/WebKit/UIProcess/API/Cocoa/_WKWebExtensionContext.mm
Expand Up @@ -42,6 +42,7 @@
#import "_WKWebExtensionInternal.h"
#import "_WKWebExtensionMatchPatternInternal.h"
#import "_WKWebExtensionTab.h"
#import <wtf/BlockPtr.h>
#import <wtf/URLParser.h>
#import <wtf/cocoa/VectorCocoa.h>

Expand Down Expand Up @@ -537,6 +538,11 @@ - (BOOL)hasContentModificationRules
return _webExtensionContext->hasContentModificationRules();
}

- (void)loadBackgroundContentWithCompletionHandler:(void (^)(NSError *error))completionHandler
{
_webExtensionContext->loadBackgroundContent(makeBlockPtr(completionHandler));
}

- (_WKWebExtensionAction *)actionForTab:(id<_WKWebExtensionTab>)tab
{
if (tab)
Expand Down Expand Up @@ -1086,6 +1092,10 @@ - (BOOL)hasContentModificationRules
return NO;
}

- (void)loadBackgroundContentWithCompletionHandler:(void (^)(NSError *error))completionHandler
{
}

- (_WKWebExtensionAction *)actionForTab:(id<_WKWebExtensionTab>)tab NS_SWIFT_NAME(action(for:))
{
return nil;
Expand Down
6 changes: 0 additions & 6 deletions Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionCocoa.mm
Expand Up @@ -641,8 +641,6 @@ static _WKWebExtensionError toAPI(WebExtension::Error error)
return _WKWebExtensionErrorInvalidManifestEntry;
case WebExtension::Error::InvalidBackgroundPersistence:
return _WKWebExtensionErrorInvalidBackgroundPersistence;
case WebExtension::Error::BackgroundContentFailedToLoad:
return _WKWebExtensionErrorBackgroundContentFailedToLoad;
case WebExtension::Error::InvalidResourceCodeSignature:
return _WKWebExtensionErrorInvalidResourceCodeSignature;
}
Expand Down Expand Up @@ -756,10 +754,6 @@ static _WKWebExtensionError toAPI(WebExtension::Error error)
localizedDescription = WEB_UI_STRING("Invalid `persistent` manifest entry.", "WKWebExtensionErrorInvalidBackgroundPersistence description");
break;

case Error::BackgroundContentFailedToLoad:
localizedDescription = WEB_UI_STRING("The background content failed to load due to an error.", "WKWebExtensionErrorBackgroundContentFailedToLoad description");
break;

case Error::InvalidResourceCodeSignature:
ASSERT(customLocalizedDescription);
break;
Expand Down
Expand Up @@ -196,6 +196,10 @@ static _WKWebExtensionContextError toAPI(WebExtensionContext::Error error)
return _WKWebExtensionContextErrorNotLoaded;
case WebExtensionContext::Error::BaseURLAlreadyInUse:
return _WKWebExtensionContextErrorBaseURLAlreadyInUse;
case WebExtensionContext::Error::NoBackgroundContent:
return _WKWebExtensionContextErrorNoBackgroundContent;
case WebExtensionContext::Error::BackgroundContentFailedToLoad:
return _WKWebExtensionContextErrorBackgroundContentFailedToLoad;
}
}

Expand All @@ -220,6 +224,14 @@ static _WKWebExtensionContextError toAPI(WebExtensionContext::Error error)
case Error::BaseURLAlreadyInUse:
localizedDescription = WEB_UI_STRING("Another extension context is loaded with the same base URL.", "WKWebExtensionContextErrorBaseURLAlreadyInUse description");
break;

case Error::NoBackgroundContent:
localizedDescription = WEB_UI_STRING("No background content is available to load.", "WKWebExtensionContextErrorNoBackgroundContent description");
break;

case Error::BackgroundContentFailedToLoad:
localizedDescription = WEB_UI_STRING("The background content failed to load due to an error.", "WKWebExtensionContextErrorBackgroundContentFailedToLoad description");
break;
}

if (customLocalizedDescription.length)
Expand Down Expand Up @@ -3113,6 +3125,20 @@ static _WKWebExtensionContextError toAPI(WebExtensionContext::Error error)
return { m_baseURL, extension().backgroundContentPath() };
}

void WebExtensionContext::loadBackgroundContent(CompletionHandler<void(NSError *)>&& completionHandler)
{
if (!extension().hasBackgroundContent()) {
if (completionHandler)
completionHandler(createError(Error::NoBackgroundContent));
return;
}

wakeUpBackgroundContentIfNecessary([this, protectedThis = Ref { *this }, completionHandler = WTFMove(completionHandler)]() mutable {
if (completionHandler)
completionHandler(backgroundContentLoadError());
});
}

void WebExtensionContext::loadBackgroundWebViewDuringLoad()
{
ASSERT(isLoaded());
Expand Down Expand Up @@ -3177,8 +3203,7 @@ static _WKWebExtensionContextError toAPI(WebExtensionContext::Error error)
[delegate _webExtensionController:m_extensionController->wrapper() didCreateBackgroundWebView:m_backgroundWebView.get() forExtensionContext:wrapper()];

m_backgroundWebView.get()._remoteInspectionNameOverride = backgroundWebViewInspectionName();

extension().removeError(WebExtension::Error::BackgroundContentFailedToLoad);
m_backgroundContentLoadError = nil;

if (!extension().backgroundContentIsServiceWorker()) {
auto backgroundPage = m_backgroundWebView.get()._page;
Expand All @@ -3190,7 +3215,7 @@ static _WKWebExtensionContextError toAPI(WebExtensionContext::Error error)

[m_backgroundWebView _loadServiceWorker:backgroundContentURL() usingModules:extension().backgroundContentUsesModules() completionHandler:makeBlockPtr([this, protectedThis = Ref { *this }](BOOL success) {
if (!success) {
extension().recordError(extension().createError(WebExtension::Error::BackgroundContentFailedToLoad), WebExtension::SuppressNotification::No);
m_backgroundContentLoadError = createError(Error::BackgroundContentFailedToLoad);
return;
}

Expand Down Expand Up @@ -3487,7 +3512,7 @@ static inline bool isNotRunningInTestRunner()
if (webView != m_backgroundWebView)
return;

extension().recordError(extension().createError(WebExtension::Error::BackgroundContentFailedToLoad, nil, error), WebExtension::SuppressNotification::No);
m_backgroundContentLoadError = createError(Error::BackgroundContentFailedToLoad, nil, error);
}

void WebExtensionContext::webViewWebContentProcessDidTerminate(WKWebView *webView)
Expand Down
1 change: 0 additions & 1 deletion Source/WebKit/UIProcess/Extensions/WebExtension.h
Expand Up @@ -106,7 +106,6 @@ class WebExtension : public API::ObjectImpl<API::Object::Type::WebExtension>, pu
InvalidURLOverrides,
InvalidVersion,
InvalidWebAccessibleResources,
BackgroundContentFailedToLoad,
};

enum class InjectionTime : uint8_t {
Expand Down
7 changes: 7 additions & 0 deletions Source/WebKit/UIProcess/Extensions/WebExtensionContext.h
Expand Up @@ -227,6 +227,8 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
AlreadyLoaded,
NotLoaded,
BaseURLAlreadyInUse,
NoBackgroundContent,
BackgroundContentFailedToLoad,
};

enum class PermissionState : int8_t {
Expand Down Expand Up @@ -459,6 +461,8 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
WKWebView *backgroundWebView() const { return m_backgroundWebView.get(); }
bool safeToLoadBackgroundContent() const { return m_safeToLoadBackgroundContent; }

NSError *backgroundContentLoadError() const { return m_backgroundContentLoadError.get(); }

NSString *backgroundWebViewInspectionName();
void setBackgroundWebViewInspectionName(const String&);

Expand Down Expand Up @@ -500,6 +504,8 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi

void cookiesDidChange(API::HTTPCookieStore&);

void loadBackgroundContent(CompletionHandler<void(NSError *)>&&);

void wakeUpBackgroundContentIfNecessary(CompletionHandler<void()>&&);
void wakeUpBackgroundContentIfNecessaryToFireEvents(EventListenerTypeSet&&, CompletionHandler<void()>&&);

Expand Down Expand Up @@ -889,6 +895,7 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
String m_previousVersion;

RetainPtr<WKWebView> m_backgroundWebView;
RetainPtr<NSError> m_backgroundContentLoadError;
RetainPtr<_WKWebExtensionContextDelegate> m_delegate;

String m_backgroundWebViewInspectionName;
Expand Down

0 comments on commit 10d1920

Please sign in to comment.