Python bindings for Apple's WebKit and JavaScriptCore frameworks on macOS, enabling web browser functionality and JavaScript execution in Python applications
—
This document covers user scripts, content rules, cookie management, and website data handling in WebKit. These features provide control over web content behavior, security policies, and data storage for both security and functionality purposes.
Central management point for user scripts and message handlers.
class WKUserContentController:
def init(self):
"""Initialize a new user content controller."""
def addUserScript_(self, userScript):
"""Add a user script to be injected into web pages.
Args:
userScript: WKUserScript instance to add
"""
def removeAllUserScripts(self):
"""Remove all user scripts from the controller."""
def addScriptMessageHandler_name_(self, scriptMessageHandler, name):
"""Add a script message handler for JavaScript-to-native communication.
Args:
scriptMessageHandler: Object implementing WKScriptMessageHandler protocol
name: String name that JavaScript will use to send messages
"""
def removeScriptMessageHandlerForName_(self, name):
"""Remove a script message handler by name.
Args:
name: String name of the handler to remove
"""
def addContentRuleList_(self, contentRuleList):
"""Add a content rule list for content blocking.
Args:
contentRuleList: WKContentRuleList instance
"""
def removeContentRuleList_(self, contentRuleList):
"""Remove a content rule list.
Args:
contentRuleList: WKContentRuleList instance to remove
"""
def removeAllContentRuleLists(self):
"""Remove all content rule lists."""
@property
def userScripts(self):
"""Get array of all user scripts."""JavaScript code injection into web pages.
class WKUserScript:
def initWithSource_injectionTime_forMainFrameOnly_(self, source, injectionTime, forMainFrameOnly):
"""Initialize a user script with source code and injection settings.
Args:
source: String containing JavaScript source code
injectionTime: WKUserScriptInjectionTime constant
forMainFrameOnly: Boolean - True to inject only in main frame, False for all frames
"""
@property
def source(self):
"""Get the JavaScript source code."""
@property
def injectionTime(self):
"""Get the injection time (document start or end)."""
@property
def isForMainFrameOnly(self):
"""Check if script is only for main frame."""
# User Script Injection Times
WKUserScriptInjectionTimeAtDocumentStart = 0
WKUserScriptInjectionTimeAtDocumentEnd = 1Communication from JavaScript to native code.
class WKScriptMessage:
@property
def body(self):
"""Get the message body (can be string, number, boolean, array, or dictionary)."""
@property
def webView(self):
"""Get the web view that sent the message."""
@property
def frameInfo(self):
"""Get information about the frame that sent the message."""
@property
def name(self):
"""Get the name of the message handler."""
class WKScriptMessageHandler:
def userContentController_didReceiveScriptMessage_(self, userContentController, message):
"""Handle script messages from JavaScript.
Args:
userContentController: The WKUserContentController
message: WKScriptMessage containing the message data
"""Content blocking and modification rules.
class WKContentRuleList:
@property
def identifier(self):
"""Get the unique identifier for this rule list."""
class WKContentRuleListStore:
@classmethod
def defaultStore(cls):
"""Get the default content rule list store."""
def compileContentRuleList_forIdentifier_completionHandler_(self, ruleList, identifier, completionHandler):
"""Compile content rules from JSON.
Args:
ruleList: String containing JSON content rules
identifier: Unique identifier for the rule list
completionHandler: Block called with (WKContentRuleList, NSError)
"""
def lookUpContentRuleListForIdentifier_completionHandler_(self, identifier, completionHandler):
"""Look up an existing content rule list.
Args:
identifier: String identifier of the rule list
completionHandler: Block called with (WKContentRuleList, NSError)
"""
def removeContentRuleListForIdentifier_completionHandler_(self, identifier, completionHandler):
"""Remove a content rule list from storage.
Args:
identifier: String identifier of the rule list to remove
completionHandler: Block called with (NSError,)
"""
def getAvailableContentRuleListIdentifiers_(self, completionHandler):
"""Get identifiers of available content rule lists.
Args:
completionHandler: Block called with (NSArray,)
"""Management of website data including cookies, cache, and local storage.
class WKWebsiteDataStore:
@classmethod
def defaultDataStore(cls):
"""Get the default website data store."""
@classmethod
def nonPersistentDataStore(cls):
"""Create a non-persistent (private) data store."""
def fetchDataRecordsOfTypes_completionHandler_(self, dataTypes, completionHandler):
"""Fetch website data records of specified types.
Args:
dataTypes: Set of WKWebsiteDataType constants
completionHandler: Block called with (NSArray,) of WKWebsiteDataRecord
"""
def removeDataOfTypes_forDataRecords_completionHandler_(self, dataTypes, dataRecords, completionHandler):
"""Remove website data for specific records.
Args:
dataTypes: Set of data types to remove
dataRecords: Array of WKWebsiteDataRecord instances
completionHandler: Block called when removal completes
"""
def removeDataOfTypes_modifiedSince_completionHandler_(self, dataTypes, date, completionHandler):
"""Remove website data modified since a date.
Args:
dataTypes: Set of data types to remove
date: NSDate - remove data modified since this date
completionHandler: Block called when removal completes
"""
@property
def isPersistent(self):
"""Check if the data store is persistent."""
@property
def httpCookieStore(self):
"""Get the HTTP cookie store for this data store."""
# Website Data Types
WKWebsiteDataTypeCookies = "WKWebsiteDataTypeCookies"
WKWebsiteDataTypeDiskCache = "WKWebsiteDataTypeDiskCache"
WKWebsiteDataTypeMemoryCache = "WKWebsiteDataTypeMemoryCache"
WKWebsiteDataTypeOfflineWebApplicationCache = "WKWebsiteDataTypeOfflineWebApplicationCache"
WKWebsiteDataTypeSessionStorage = "WKWebsiteDataTypeSessionStorage"
WKWebsiteDataTypeLocalStorage = "WKWebsiteDataTypeLocalStorage"
WKWebsiteDataTypeWebSQLDatabases = "WKWebsiteDataTypeWebSQLDatabases"
WKWebsiteDataTypeIndexedDBDatabases = "WKWebsiteDataTypeIndexedDBDatabases"HTTP cookie handling and storage.
class WKHTTPCookieStore:
def getAllCookies_(self, completionHandler):
"""Get all HTTP cookies.
Args:
completionHandler: Block called with (NSArray,) of NSHTTPCookie
"""
def setCookie_completionHandler_(self, cookie, completionHandler):
"""Set an HTTP cookie.
Args:
cookie: NSHTTPCookie instance to set
completionHandler: Optional block called when cookie is set
"""
def deleteCookie_completionHandler_(self, cookie, completionHandler):
"""Delete an HTTP cookie.
Args:
cookie: NSHTTPCookie instance to delete
completionHandler: Optional block called when cookie is deleted
"""
def addObserver_(self, observer):
"""Add a cookie change observer.
Args:
observer: Object implementing WKHTTPCookieStoreObserver protocol
"""
def removeObserver_(self, observer):
"""Remove a cookie change observer.
Args:
observer: Observer object to remove
"""
class WKHTTPCookieStoreObserver:
def cookiesDidChangeInCookieStore_(self, cookieStore):
"""Called when cookies change in the store.
Args:
cookieStore: The WKHTTPCookieStore that changed
"""Information about stored website data.
class WKWebsiteDataRecord:
@property
def displayName(self):
"""Get the display name for this data record (typically domain name)."""
@property
def dataTypes(self):
"""Get the set of data types stored for this record."""import WebKit
# Create user content controller
content_controller = WebKit.WKUserContentController.alloc().init()
# Create user script to inject CSS
css_script = """
var style = document.createElement('style');
style.textContent = 'body { background-color: #f0f0f0; }';
document.head.appendChild(style);
"""
user_script = WebKit.WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly_(
css_script,
WebKit.WKUserScriptInjectionTimeAtDocumentEnd,
False # Apply to all frames
)
content_controller.addUserScript_(user_script)
# Configure web view
config = WebKit.WKWebViewConfiguration.alloc().init()
config.setUserContentController_(content_controller)import WebKit
class MessageHandler:
def userContentController_didReceiveScriptMessage_(self, controller, message):
print(f"Received message: {message.body()}")
# Handle the message from JavaScript
# Set up message handler
handler = MessageHandler()
content_controller = WebKit.WKUserContentController.alloc().init()
content_controller.addScriptMessageHandler_name_(handler, "nativeHandler")
# JavaScript can now call: window.webkit.messageHandlers.nativeHandler.postMessage("Hello Python!");import WebKit
# JSON rule list to block ads
content_rules = """
[
{
"trigger": {
"url-filter": ".*",
"resource-type": ["image"],
"if-domain": ["ads.example.com", "tracker.example.com"]
},
"action": {
"type": "block"
}
}
]
"""
store = WebKit.WKContentRuleListStore.defaultStore()
store.compileContentRuleList_forIdentifier_completionHandler_(
content_rules,
"AdBlocker",
lambda rule_list, error: print("Content rules compiled" if rule_list else f"Error: {error}")
)import WebKit
from Foundation import NSHTTPCookie
# Get all cookies
cookie_store = data_store.httpCookieStore()
cookie_store.getAllCookies_(lambda cookies: print(f"Found {len(cookies)} cookies"))
# Create and set a cookie
cookie = NSHTTPCookie.cookieWithProperties_({
"NSHTTPCookieName": "session_id",
"NSHTTPCookieValue": "abc123",
"NSHTTPCookieDomain": "example.com",
"NSHTTPCookiePath": "/"
})
cookie_store.setCookie_completionHandler_(cookie, lambda: print("Cookie set"))These content management features provide powerful control over web content behavior, security policies, and data storage, enabling sophisticated web application development with fine-grained control over the browsing experience.
Install with Tessl CLI
npx tessl i tessl/pypi-pyobjc-framework-webkit