Skip to content

Commit

Permalink
Clear activeTab and action tab customization when tab navigates.
Browse files Browse the repository at this point in the history
https://webkit.org/b/263918
rdar://problem/117704349

Reviewed by Brian Weinstein.

Moves the webNavigation load events to WebExtensionContext, since more things will
need to tie into these hooks.

Fixes injected style removal when webPageID is used, so it only removes the styles
when the page they apply to is navigated. Also this was incorrectly behind the
webNavigation permission checks before, when it needs to always happen.

Properly clears the activeTb permission on tab navigation, and fires the onUpdated
events for URL and Title when activeTab comes and goes, as well as any pattern grant.
This matches what Safari currently does when permissions are granted.

Clears the action customizations if the tab navigates. This matches the other browsers
and what Safari currently does.

Fixes the match pattern notifications to use the right constant.

* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionActionCocoa.mm:
(WebKit::WebExtensionAction::clearCustomizations):
(WebKit::WebExtensionAction::setPopupPath):
(WebKit::WebExtensionAction::setLabel):
(WebKit::WebExtensionAction::setBadgeText):
(WebKit::WebExtensionAction::setEnabled):
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionContextCocoa.mm:
(WebKit::WebExtensionContext::postAsyncNotification):
(WebKit::WebExtensionContext::grantPermissionMatchPatterns):
(WebKit::WebExtensionContext::denyPermissionMatchPatterns):
(WebKit::WebExtensionContext::removeGrantedPermissionMatchPatterns):
(WebKit::WebExtensionContext::removeDeniedPermissionMatchPatterns):
(WebKit::WebExtensionContext::permissionState):
(WebKit::WebExtensionContext::setPermissionState):
(WebKit::WebExtensionContext::didChangeTabProperties):
(WebKit::WebExtensionContext::didStartProvisionalLoadForFrame):
(WebKit::WebExtensionContext::didCommitLoadForFrame):
(WebKit::WebExtensionContext::didFinishLoadForFrame):
(WebKit::WebExtensionContext::didFailLoadForFrame):
(WebKit::WebExtensionContext::performAction):
(WebKit::WebExtensionContext::performCommand):
(WebKit::WebExtensionContext::userGesturePerformed):
(WebKit::WebExtensionContext::hasActiveUserGesture const):
(WebKit::WebExtensionContext::clearUserGesture):
(WebKit::WebExtensionContext::loadBackgroundPageListenersFromStorage):
(WebKit::WebExtensionContext::saveBackgroundPageListenersToStorage):
(WebKit::WebExtensionContext::removeInjectedContent):
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionControllerCocoa.mm:
(WebKit::WebExtensionController::didStartProvisionalLoadForFrame):
(WebKit::WebExtensionController::didCommitLoadForFrame):
(WebKit::WebExtensionController::didFinishLoadForFrame):
(WebKit::WebExtensionController::didFailLoadForFrame):
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionTabCocoa.mm:
(WebKit::WebExtensionTab::changedParameters const):
* Source/WebKit/UIProcess/Extensions/WebExtensionAction.h:
* Source/WebKit/UIProcess/Extensions/WebExtensionContext.h:
(WebKit::WebExtensionContext::didChangeTabProperties):
* Source/WebKit/UIProcess/Extensions/WebExtensionController.h:
* Source/WebKit/UIProcess/Extensions/WebExtensionTab.h:
(WebKit::WebExtensionTab::changedParameters):
(WebKit::WebExtensionTab::hasActiveUserGesture):
(WebKit::WebExtensionTab::setActiveUserGesture):
(WebKit::WebExtensionTab::temporaryPermissionMatchPattern):
(WebKit::WebExtensionTab::setTemporaryPermissionMatchPattern):
(WebKit::WebExtensionTab::changedProperties const):
(WebKit::WebExtensionTab::addChangedProperties):
(WebKit::WebExtensionTab::clearChangedProperties):
* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPIAction.mm:
(TestWebKitAPI::TEST):
* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPITabs.mm:
(TestWebKitAPI::TEST):
* Tools/TestWebKitAPI/cocoa/WebExtensionUtilities.mm:
(-[TestWebExtensionTab webView:didCommitNavigation:]):

Canonical link: https://commits.webkit.org/270722@main
  • Loading branch information
xeenon committed Nov 14, 2023
1 parent 47a57e4 commit dfe3191
Show file tree
Hide file tree
Showing 11 changed files with 470 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,20 @@ - (void)invalidateIntrinsicContentSize
return m_extensionContext.get();
}

void WebExtensionAction::clearCustomizations()
{
if (!m_customIcons && !m_customPopupPath.isNull() && !m_customLabel.isNull() && !m_customBadgeText.isNull() && !m_customEnabled)
return;

m_customIcons = nil;
m_customPopupPath = nullString();
m_customLabel = nullString();
m_customBadgeText = nullString();
m_customEnabled = std::nullopt;

propertiesDidChange();
}

void WebExtensionAction::propertiesDidChange()
{
dispatch_async(dispatch_get_main_queue(), makeBlockPtr([this, protectedThis = Ref { *this }]() {
Expand Down Expand Up @@ -226,6 +240,9 @@ - (void)invalidateIntrinsicContentSize

void WebExtensionAction::setPopupPath(String path)
{
if (m_customPopupPath == path)
return;

m_customPopupPath = path;

propertiesDidChange();
Expand Down Expand Up @@ -362,6 +379,9 @@ - (void)invalidateIntrinsicContentSize

void WebExtensionAction::setLabel(String label)
{
if (m_customLabel == label)
return;

m_customLabel = label;

propertiesDidChange();
Expand All @@ -386,6 +406,9 @@ - (void)invalidateIntrinsicContentSize

void WebExtensionAction::setBadgeText(String badgeText)
{
if (m_customBadgeText == badgeText)
return;

m_customBadgeText = badgeText;

propertiesDidChange();
Expand All @@ -410,6 +433,9 @@ - (void)invalidateIntrinsicContentSize

void WebExtensionAction::setEnabled(std::optional<bool> enabled)
{
if (m_customEnabled == enabled)
return;

m_customEnabled = enabled;

propertiesDidChange();
Expand Down
260 changes: 194 additions & 66 deletions Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionContextCocoa.mm

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -259,104 +259,28 @@
return extensions;
}

// MARK: Web Navigation

void WebExtensionController::didStartProvisionalLoadForFrame(WebPageProxyIdentifier pageID, WebExtensionFrameIdentifier frameID, WebExtensionFrameIdentifier parentFrameID, const URL& targetURL, WallTime timestamp)
{
auto eventType = WebExtensionEventListenerType::WebNavigationOnBeforeNavigate;
auto listenerTypes = WebExtensionContext::EventListenerTypeSet { eventType };

for (auto& context : m_extensionContexts) {
if (!context->hasPermission(_WKWebExtensionPermissionWebNavigation))
continue;

if (!context->hasPermission(targetURL))
continue;

auto tab = context->getTab(pageID);
if (!tab)
continue;

context->wakeUpBackgroundContentIfNecessaryToFireEvents(listenerTypes, [&] {
context->sendToProcessesForEvent(eventType, Messages::WebExtensionContextProxy::DispatchWebNavigationEvent(eventType, tab->identifier(), frameID, parentFrameID, targetURL, timestamp));
});
}
for (auto& context : m_extensionContexts)
context->didStartProvisionalLoadForFrame(pageID, frameID, parentFrameID, targetURL, timestamp);
}

void WebExtensionController::didCommitLoadForFrame(WebPageProxyIdentifier pageID, WebExtensionFrameIdentifier frameID, WebExtensionFrameIdentifier parentFrameID, const URL& frameURL, WallTime timestamp)
{
auto committedEventType = WebExtensionEventListenerType::WebNavigationOnCommitted;
auto contentLoadedtype = WebExtensionEventListenerType::WebNavigationOnDOMContentLoaded;
auto listenerTypes = WebExtensionContext::EventListenerTypeSet { committedEventType, contentLoadedtype };

for (auto& context : m_extensionContexts) {
if (!context->hasPermission(_WKWebExtensionPermissionWebNavigation))
continue;

if (!context->hasPermission(frameURL))
continue;

for (auto& styleSheet : context->dynamicallyInjectedUserStyleSheets()) {
auto page = WebProcessProxy::webPage(pageID);
WebUserContentControllerProxy& controller = page.get()->userContentController();
controller.removeUserStyleSheet(styleSheet);
}

context->dynamicallyInjectedUserStyleSheets().clear();

auto tab = context->getTab(pageID);
if (!tab)
continue;

context->wakeUpBackgroundContentIfNecessaryToFireEvents(listenerTypes, [&] {
context->sendToProcessesForEvent(committedEventType, Messages::WebExtensionContextProxy::DispatchWebNavigationEvent(committedEventType, tab->identifier(), frameID, parentFrameID, frameURL, timestamp));
context->sendToProcessesForEvent(contentLoadedtype, Messages::WebExtensionContextProxy::DispatchWebNavigationEvent(contentLoadedtype, tab->identifier(), frameID, parentFrameID, frameURL, timestamp));
});
}
for (auto& context : m_extensionContexts)
context->didCommitLoadForFrame(pageID, frameID, parentFrameID, frameURL, timestamp);
}

void WebExtensionController::didFinishLoadForFrame(WebPageProxyIdentifier pageID, WebExtensionFrameIdentifier frameID, WebExtensionFrameIdentifier parentFrameID, const URL& frameURL, WallTime timestamp)
{
auto eventType = WebExtensionEventListenerType::WebNavigationOnCompleted;
auto listenerTypes = WebExtensionContext::EventListenerTypeSet { eventType };

for (auto& context : m_extensionContexts) {
if (!context->hasPermission(_WKWebExtensionPermissionWebNavigation))
continue;

if (!context->hasPermission(frameURL))
continue;

auto tab = context->getTab(pageID);
if (!tab)
continue;

context->wakeUpBackgroundContentIfNecessaryToFireEvents(listenerTypes, [&] {
context->sendToProcessesForEvent(eventType, Messages::WebExtensionContextProxy::DispatchWebNavigationEvent(eventType, tab->identifier(), frameID, parentFrameID, frameURL, timestamp));
});
}
for (auto& context : m_extensionContexts)
context->didFinishLoadForFrame(pageID, frameID, parentFrameID, frameURL, timestamp);
}

void WebExtensionController::didFailLoadForFrame(WebPageProxyIdentifier pageID, WebExtensionFrameIdentifier frameID, WebExtensionFrameIdentifier parentFrameID, const URL& frameURL, WallTime timestamp)
{
auto eventType = WebExtensionEventListenerType::WebNavigationOnErrorOccurred;
auto listenerTypes = WebExtensionContext::EventListenerTypeSet { eventType };

for (auto& context : m_extensionContexts) {
if (!context->hasPermission(_WKWebExtensionPermissionWebNavigation))
continue;

if (!context->hasPermission(frameURL))
continue;

auto tab = context->getTab(pageID);
if (!tab)
continue;

context->wakeUpBackgroundContentIfNecessaryToFireEvents(listenerTypes, [&] {
context->sendToProcessesForEvent(eventType, Messages::WebExtensionContextProxy::DispatchWebNavigationEvent(eventType, tab->identifier(), frameID, parentFrameID, frameURL, timestamp));
});
}
for (auto& context : m_extensionContexts)
context->didFailLoadForFrame(pageID, frameID, parentFrameID, frameURL, timestamp);
}

} // namespace WebKit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@

WebExtensionTabParameters WebExtensionTab::changedParameters(OptionSet<ChangedProperties> changedProperties) const
{
if (changedProperties.isEmpty())
changedProperties = this->changedProperties();

bool hasPermission = extensionHasPermission();

return {
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/UIProcess/Extensions/WebExtensionAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class WebExtensionAction : public API::ObjectImpl<API::Object::Type::WebExtensio
WebExtensionTab* tab() { return m_tab.get(); }
WebExtensionWindow* window() { return m_window.get(); }

void clearCustomizations();

void propertiesDidChange();

CocoaImage *icon(CGSize);
Expand Down
18 changes: 10 additions & 8 deletions Source/WebKit/UIProcess/Extensions/WebExtensionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@

OBJC_CLASS NSDate;
OBJC_CLASS NSDictionary;
OBJC_CLASS NSMapTable;
OBJC_CLASS NSMutableDictionary;
OBJC_CLASS NSString;
OBJC_CLASS NSURL;
Expand Down Expand Up @@ -242,14 +241,14 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
void grantPermissions(PermissionsSet&&, WallTime expirationDate = WallTime::infinity());
void denyPermissions(PermissionsSet&&, WallTime expirationDate = WallTime::infinity());

void grantPermissionMatchPatterns(MatchPatternSet&&, WallTime expirationDate = WallTime::infinity());
void denyPermissionMatchPatterns(MatchPatternSet&&, WallTime expirationDate = WallTime::infinity());
void grantPermissionMatchPatterns(MatchPatternSet&&, WallTime expirationDate = WallTime::infinity(), EqualityOnly = EqualityOnly::Yes);
void denyPermissionMatchPatterns(MatchPatternSet&&, WallTime expirationDate = WallTime::infinity(), EqualityOnly = EqualityOnly::Yes);

bool removeGrantedPermissions(PermissionsSet&);
bool removeGrantedPermissionMatchPatterns(MatchPatternSet&, EqualityOnly);
bool removeGrantedPermissionMatchPatterns(MatchPatternSet&, EqualityOnly = EqualityOnly::Yes);

bool removeDeniedPermissions(PermissionsSet&);
bool removeDeniedPermissionMatchPatterns(MatchPatternSet&, EqualityOnly);
bool removeDeniedPermissionMatchPatterns(MatchPatternSet&, EqualityOnly = EqualityOnly::Yes);

PermissionsMap::KeysConstIteratorRange currentPermissions() { return grantedPermissions().keys(); }
PermissionMatchPatternsMap::KeysConstIteratorRange currentPermissionMatchPatterns() { return grantedPermissionMatchPatterns().keys(); }
Expand Down Expand Up @@ -296,7 +295,12 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi

void didMoveTab(const WebExtensionTab&, size_t oldIndex, const WebExtensionWindow* oldWindow = nullptr);
void didReplaceTab(const WebExtensionTab& oldTab, const WebExtensionTab& newTab);
void didChangeTabProperties(const WebExtensionTab&, OptionSet<WebExtensionTab::ChangedProperties> = { });
void didChangeTabProperties(WebExtensionTab&, OptionSet<WebExtensionTab::ChangedProperties> = { });

void didStartProvisionalLoadForFrame(WebPageProxyIdentifier, WebExtensionFrameIdentifier, WebExtensionFrameIdentifier parentFrameID, const URL&, WallTime);
void didCommitLoadForFrame(WebPageProxyIdentifier, WebExtensionFrameIdentifier, WebExtensionFrameIdentifier parentFrameID, const URL&, WallTime);
void didFinishLoadForFrame(WebPageProxyIdentifier, WebExtensionFrameIdentifier, WebExtensionFrameIdentifier parentFrameID, const URL&, WallTime);
void didFailLoadForFrame(WebPageProxyIdentifier, WebExtensionFrameIdentifier, WebExtensionFrameIdentifier parentFrameID, const URL&, WallTime);

WebExtensionAction& defaultAction();
Ref<WebExtensionAction> getAction(WebExtensionWindow*);
Expand Down Expand Up @@ -561,8 +565,6 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
ListHashSet<URL> m_cachedPermissionURLs;
HashMap<URL, PermissionState> m_cachedPermissionStates;

RetainPtr<NSMapTable> m_temporaryTabPermissionMatchPatterns;

bool m_requestedOptionalAccessToAllHosts { false };
bool m_hasAccessInPrivateBrowsing { false };
#ifdef NDEBUG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ class WebExtensionController : public API::ObjectImpl<API::Object::Type::WebExte
void addUserContentController(WebUserContentControllerProxy&, ForPrivateBrowsing);
void removeUserContentController(WebUserContentControllerProxy&);

// Web Navigation
void didStartProvisionalLoadForFrame(WebPageProxyIdentifier, WebExtensionFrameIdentifier, WebExtensionFrameIdentifier parentFrameID, const URL&, WallTime);
void didCommitLoadForFrame(WebPageProxyIdentifier, WebExtensionFrameIdentifier, WebExtensionFrameIdentifier parentFrameID, const URL&, WallTime);
void didFinishLoadForFrame(WebPageProxyIdentifier, WebExtensionFrameIdentifier, WebExtensionFrameIdentifier parentFrameID, const URL&, WallTime);
Expand Down
16 changes: 15 additions & 1 deletion Source/WebKit/UIProcess/Extensions/WebExtensionTab.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ OBJC_PROTOCOL(_WKWebExtensionTab);
namespace WebKit {

class WebExtensionContext;
class WebExtensionMatchPattern;
class WebExtensionWindow;
class WebProcessProxy;
struct WebExtensionTabParameters;
Expand Down Expand Up @@ -88,7 +89,7 @@ class WebExtensionTab : public RefCounted<WebExtensionTab>, public CanMakeWeakPt

WebExtensionTabIdentifier identifier() const { return m_identifier; }
WebExtensionTabParameters parameters() const;
WebExtensionTabParameters changedParameters(OptionSet<ChangedProperties>) const;
WebExtensionTabParameters changedParameters(OptionSet<ChangedProperties> = { }) const;

WebExtensionContext* extensionContext() const;

Expand All @@ -99,6 +100,16 @@ class WebExtensionTab : public RefCounted<WebExtensionTab>, public CanMakeWeakPt
bool extensionHasAccess() const;
bool extensionHasPermission() const;

bool hasActiveUserGesture() { return m_activeUserGesture; }
void setActiveUserGesture(bool activeUserGesture) { m_activeUserGesture = activeUserGesture; }

RefPtr<WebExtensionMatchPattern> temporaryPermissionMatchPattern() { return m_temporaryPermissionMatchPattern; }
void setTemporaryPermissionMatchPattern(RefPtr<WebExtensionMatchPattern>&& matchPattern) { m_temporaryPermissionMatchPattern = WTFMove(matchPattern); }

OptionSet<ChangedProperties> changedProperties() const { return m_changedProperties; }
void addChangedProperties(OptionSet<ChangedProperties> properties) { m_changedProperties.add(properties); }
void clearChangedProperties() { m_changedProperties = { }; }

RefPtr<WebExtensionWindow> window(SkipContainsCheck = SkipContainsCheck::No) const;
size_t index() const;

Expand Down Expand Up @@ -171,6 +182,9 @@ class WebExtensionTab : public RefCounted<WebExtensionTab>, public CanMakeWeakPt
WebExtensionTabIdentifier m_identifier;
WeakPtr<WebExtensionContext> m_extensionContext;
WeakObjCPtr<_WKWebExtensionTab> m_delegate;
RefPtr<WebExtensionMatchPattern> m_temporaryPermissionMatchPattern;
OptionSet<ChangedProperties> m_changedProperties;
bool m_activeUserGesture : 1 { false };
mutable bool m_private : 1 { false };
mutable bool m_cachedPrivate : 1 { false };
bool m_respondsToWindow : 1 { false };
Expand Down

0 comments on commit dfe3191

Please sign in to comment.