WebKit Bugzilla
Attachment 342772 Details for
Bug 186551
: NetworkLoadChecker should not need to hard ref NetworkConnectionToWebProcess
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-186551-20180614160103.patch (text/plain), 19.91 KB, created by
youenn fablet
on 2018-06-14 16:01:05 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
youenn fablet
Created:
2018-06-14 16:01:05 PDT
Size:
19.91 KB
patch
obsolete
>Subversion Revision: 232857 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 3a8797e97a6e345f20d2fdccaefe3746bfff1fd3..3fa69de35678d99eb84d2e628fe2b0e743d0e1d3 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,16 @@ >+2018-06-14 Youenn Fablet <youenn@apple.com> >+ >+ NetworkLoadChecker should not need to hard ref NetworkConnectionToWebProcess >+ https://bugs.webkit.org/show_bug.cgi?id=186551 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ No change of behavior. >+ Add a way to set the client receiving any CSP warning/error notification. >+ >+ * page/csp/ContentSecurityPolicy.h: >+ (WebCore::ContentSecurityPolicy::setClient): >+ > 2018-06-14 Nan Wang <n_wang@apple.com> > > AX: Crash in AccessibilityNodeObject::textUnderElement(WebCore::AccessibilityTextUnderElementMode) const + 536 >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 4df90195ea7526e1729cbf16640d7bf09b6cd532..a86b1e9beaf395a021882c6f3219ad7f9c2f4627 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,33 @@ >+2018-06-14 Youenn Fablet <youenn@apple.com> >+ >+ NetworkLoadChecker should not need to hard ref NetworkConnectionToWebProcess >+ https://bugs.webkit.org/show_bug.cgi?id=186551 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Removed the need for NetworkLoadChecker to reference a NetworkConnectionToWebProcess. >+ Instead a CSP client is given to NetworkLoadChecker when needed. >+ >+ * NetworkProcess/NetworkConnectionToWebProcess.cpp: >+ (WebKit::NetworkConnectionToWebProcess::loadPing): >+ * NetworkProcess/NetworkLoadChecker.cpp: >+ (WebKit::NetworkLoadChecker::NetworkLoadChecker): >+ (WebKit::NetworkLoadChecker::check): >+ (WebKit::NetworkLoadChecker::checkRedirection): >+ (WebKit::NetworkLoadChecker::checkRequest): >+ (WebKit::NetworkLoadChecker::contentSecurityPolicy): >+ (WebKit::NetworkLoadChecker::addConsoleMessage): Deleted. >+ (WebKit::NetworkLoadChecker::sendCSPViolationReport): Deleted. >+ (WebKit::NetworkLoadChecker::enqueueSecurityPolicyViolationEvent): Deleted. >+ * NetworkProcess/NetworkLoadChecker.h: >+ * NetworkProcess/NetworkResourceLoader.cpp: >+ (WebKit::NetworkResourceLoader::start): >+ (WebKit::NetworkResourceLoader::willSendRedirectedRequest): >+ * NetworkProcess/PingLoad.cpp: >+ (WebKit::PingLoad::PingLoad): >+ (WebKit::PingLoad::willPerformHTTPRedirection): >+ * NetworkProcess/PingLoad.h: >+ > 2018-06-14 John Wilander <wilander@apple.com> > > Resource Load Statistics: Shortcut classification for redirect to prevalent resource >diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.h b/Source/WebCore/page/csp/ContentSecurityPolicy.h >index 4da45d4bcaa12115013003c97fd3e803cd53400d..7a57cf541782b2985ac7e67826168e2dbb8cd63f 100644 >--- a/Source/WebCore/page/csp/ContentSecurityPolicy.h >+++ b/Source/WebCore/page/csp/ContentSecurityPolicy.h >@@ -169,6 +169,8 @@ public: > void inheritInsecureNavigationRequestsToUpgradeFromOpener(const ContentSecurityPolicy&); > void setInsecureNavigationRequestsToUpgrade(HashSet<SecurityOriginData>&&); > >+ void setClient(ContentSecurityPolicyClient* client) { m_client = client; } >+ > private: > void logToConsole(const String& message, const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), JSC::ExecState* = nullptr) const; > void updateSourceSelf(const SecurityOrigin&); >diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp >index 7812a8d0fbfe2aca6059b570a1715ecd30eab8d0..8e5d10d8e4d67b480021c116ce7212c6ed7f1e4f 100644 >--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp >+++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp >@@ -262,7 +262,7 @@ void NetworkConnectionToWebProcess::loadPing(NetworkResourceLoadParameters&& loa > }; > > // PingLoad manages its own lifetime, deleting itself when its purpose has been fulfilled. >- new PingLoad(WTFMove(loadParameters), *this, WTFMove(completionHandler)); >+ new PingLoad(WTFMove(loadParameters), WTFMove(completionHandler)); > } > > void NetworkConnectionToWebProcess::didFinishPingLoad(uint64_t pingLoadIdentifier, const ResourceError& error, const ResourceResponse& response) >diff --git a/Source/WebKit/NetworkProcess/NetworkLoadChecker.cpp b/Source/WebKit/NetworkProcess/NetworkLoadChecker.cpp >index 7ab89e89a75f2120bd83d07ca662693bdd7b0c14..a8825109677f3a631cce2673a73202825dedaeb2 100644 >--- a/Source/WebKit/NetworkProcess/NetworkLoadChecker.cpp >+++ b/Source/WebKit/NetworkProcess/NetworkLoadChecker.cpp >@@ -52,12 +52,8 @@ static inline bool isSameOrigin(const URL& url, const SecurityOrigin* origin) > return url.protocolIsData() || url.protocolIsBlob() || !origin || origin->canRequest(url); > } > >-NetworkLoadChecker::NetworkLoadChecker(NetworkConnectionToWebProcess& connection, uint64_t webPageID, uint64_t webFrameID, ResourceLoadIdentifier loadIdentifier, FetchOptions&& options, PAL::SessionID sessionID, HTTPHeaderMap&& originalRequestHeaders, URL&& url, RefPtr<SecurityOrigin>&& sourceOrigin, PreflightPolicy preflightPolicy, String&& referrer) >- : m_connection(connection) >- , m_webPageID(webPageID) >- , m_webFrameID(webFrameID) >- , m_loadIdentifier(loadIdentifier) >- , m_options(WTFMove(options)) >+NetworkLoadChecker::NetworkLoadChecker(FetchOptions&& options, PAL::SessionID sessionID, HTTPHeaderMap&& originalRequestHeaders, URL&& url, RefPtr<SecurityOrigin>&& sourceOrigin, PreflightPolicy preflightPolicy, String&& referrer) >+ : m_options(WTFMove(options)) > , m_sessionID(sessionID) > , m_originalRequestHeaders(WTFMove(originalRequestHeaders)) > , m_url(WTFMove(url)) >@@ -81,7 +77,7 @@ NetworkLoadChecker::NetworkLoadChecker(NetworkConnectionToWebProcess& connection > > NetworkLoadChecker::~NetworkLoadChecker() = default; > >-void NetworkLoadChecker::check(ResourceRequest&& request, ValidationHandler&& handler) >+void NetworkLoadChecker::check(ResourceRequest&& request, WebCore::ContentSecurityPolicyClient* client, ValidationHandler&& handler) > { > ASSERT(!isChecking()); > >@@ -92,7 +88,7 @@ void NetworkLoadChecker::check(ResourceRequest&& request, ValidationHandler&& ha > m_dntHeaderValue = "1"; > request.setHTTPHeaderField(HTTPHeaderName::DNT, m_dntHeaderValue); > } >- checkRequest(WTFMove(request), WTFMove(handler)); >+ checkRequest(WTFMove(request), client, WTFMove(handler)); > } > > void NetworkLoadChecker::prepareRedirectedRequest(ResourceRequest& request) >@@ -101,7 +97,7 @@ void NetworkLoadChecker::prepareRedirectedRequest(ResourceRequest& request) > request.setHTTPHeaderField(HTTPHeaderName::DNT, m_dntHeaderValue); > } > >-void NetworkLoadChecker::checkRedirection(ResourceResponse& redirectResponse, ResourceRequest&& request, ValidationHandler&& handler) >+void NetworkLoadChecker::checkRedirection(ResourceResponse& redirectResponse, ResourceRequest&& request, WebCore::ContentSecurityPolicyClient* client, ValidationHandler&& handler) > { > ASSERT(!isChecking()); > >@@ -128,7 +124,7 @@ void NetworkLoadChecker::checkRedirection(ResourceResponse& redirectResponse, Re > m_previousURL = WTFMove(m_url); > m_url = request.url(); > >- checkRequest(WTFMove(request), WTFMove(handler)); >+ checkRequest(WTFMove(request), client, WTFMove(handler)); > } > > bool NetworkLoadChecker::shouldCrossOriginResourcePolicyPolicyCancelLoad(const ResourceResponse& response) >@@ -191,14 +187,17 @@ auto NetworkLoadChecker::accessControlErrorForValidationHandler(String&& message > return makeUnexpected(ResourceError { String { }, 0, m_url, WTFMove(message), ResourceError::Type::AccessControl }); > } > >-void NetworkLoadChecker::checkRequest(ResourceRequest&& request, ValidationHandler&& handler) >+void NetworkLoadChecker::checkRequest(ResourceRequest&& request, WebCore::ContentSecurityPolicyClient* client, ValidationHandler&& handler) > { > if (auto* contentSecurityPolicy = this->contentSecurityPolicy()) { > if (isRedirected()) { > auto type = m_options.mode == FetchOptions::Mode::Navigate ? ContentSecurityPolicy::InsecureRequestType::Navigation : ContentSecurityPolicy::InsecureRequestType::Load; > contentSecurityPolicy->upgradeInsecureRequestIfNeeded(request, type); > } >- if (!isAllowedByContentSecurityPolicy(request)) { >+ contentSecurityPolicy->setClient(client); >+ bool isAllowed = isAllowedByContentSecurityPolicy(request); >+ contentSecurityPolicy->setClient(nullptr); >+ if (!isAllowed) { > handler(accessControlErrorForValidationHandler(ASCIILiteral { "Blocked by Content Security Policy." })); > return; > } >@@ -385,7 +384,7 @@ ContentSecurityPolicy* NetworkLoadChecker::contentSecurityPolicy() > { > if (!m_contentSecurityPolicy && m_cspResponseHeaders) { > // FIXME: Pass the URL of the protected resource instead of its origin. >- m_contentSecurityPolicy = std::make_unique<ContentSecurityPolicy>(URL { URL { }, m_origin->toString() }, this); >+ m_contentSecurityPolicy = std::make_unique<ContentSecurityPolicy>(URL { URL { }, m_origin->toString() }); > m_contentSecurityPolicy->didReceiveHeaders(*m_cspResponseHeaders, String { m_referrer }, ContentSecurityPolicy::ReportParsingErrors::No); > } > return m_contentSecurityPolicy.get(); >@@ -414,22 +413,4 @@ void NetworkLoadChecker::processContentExtensionRulesForLoad(ResourceRequest&& r > } > #endif // ENABLE(CONTENT_EXTENSIONS) > >-void NetworkLoadChecker::addConsoleMessage(MessageSource messageSource, MessageLevel messageLevel, const String& message, unsigned long) >-{ >- if (m_webPageID && m_webFrameID) >- m_connection->connection().send(Messages::WebPage::AddConsoleMessage { m_webFrameID, messageSource, messageLevel, message, m_loadIdentifier }, m_webPageID); >-} >- >-void NetworkLoadChecker::sendCSPViolationReport(URL&& reportURL, Ref<FormData>&& report) >-{ >- if (m_webPageID && m_webFrameID) >- m_connection->connection().send(Messages::WebPage::SendCSPViolationReport { m_webFrameID, WTFMove(reportURL), IPC::FormDataReference { WTFMove(report) } }, m_webPageID); >-} >- >-void NetworkLoadChecker::enqueueSecurityPolicyViolationEvent(WebCore::SecurityPolicyViolationEvent::Init&& eventInit) >-{ >- if (m_webPageID && m_webFrameID) >- m_connection->connection().send(Messages::WebPage::EnqueueSecurityPolicyViolationEvent { m_webFrameID, WTFMove(eventInit) }, m_webPageID); >-} >- > } // namespace WebKit >diff --git a/Source/WebKit/NetworkProcess/NetworkLoadChecker.h b/Source/WebKit/NetworkProcess/NetworkLoadChecker.h >index 1442639e2575a952f4e75ff4454e80a5946af839..14e73ac36bcabe2b4a1f3937c6db312c976d9af9 100644 >--- a/Source/WebKit/NetworkProcess/NetworkLoadChecker.h >+++ b/Source/WebKit/NetworkProcess/NetworkLoadChecker.h >@@ -37,6 +37,7 @@ > > namespace WebCore { > class ContentSecurityPolicy; >+struct ContentSecurityPolicyClient; > } > > namespace WebKit { >@@ -44,15 +45,15 @@ namespace WebKit { > class NetworkConnectionToWebProcess; > class NetworkCORSPreflightChecker; > >-class NetworkLoadChecker : public WebCore::ContentSecurityPolicyClient, public CanMakeWeakPtr<NetworkLoadChecker> { >+class NetworkLoadChecker : public CanMakeWeakPtr<NetworkLoadChecker> { > public: >- NetworkLoadChecker(NetworkConnectionToWebProcess&, uint64_t webPageID, uint64_t webFrameID, ResourceLoadIdentifier, WebCore::FetchOptions&&, PAL::SessionID, WebCore::HTTPHeaderMap&&, WebCore::URL&&, RefPtr<WebCore::SecurityOrigin>&&, WebCore::PreflightPolicy, String&& referrer); >+ NetworkLoadChecker(WebCore::FetchOptions&&, PAL::SessionID, WebCore::HTTPHeaderMap&&, WebCore::URL&&, RefPtr<WebCore::SecurityOrigin>&&, WebCore::PreflightPolicy, String&& referrer); > ~NetworkLoadChecker(); > > using RequestOrError = Expected<WebCore::ResourceRequest, WebCore::ResourceError>; > using ValidationHandler = CompletionHandler<void(RequestOrError&&)>; >- void check(WebCore::ResourceRequest&&, ValidationHandler&&); >- void checkRedirection(WebCore::ResourceResponse&, WebCore::ResourceRequest&&, ValidationHandler&&); >+ void check(WebCore::ResourceRequest&&, WebCore::ContentSecurityPolicyClient*, ValidationHandler&&); >+ void checkRedirection(WebCore::ResourceResponse&, WebCore::ResourceRequest&&, WebCore::ContentSecurityPolicyClient*, ValidationHandler&&); > void prepareRedirectedRequest(WebCore::ResourceRequest&); > > WebCore::ResourceError validateResponse(WebCore::ResourceResponse&); >@@ -74,7 +75,7 @@ private: > bool isChecking() const { return !!m_corsPreflightChecker; } > bool isRedirected() const { return m_redirectCount; } > >- void checkRequest(WebCore::ResourceRequest&&, ValidationHandler&&); >+ void checkRequest(WebCore::ResourceRequest&&, WebCore::ContentSecurityPolicyClient*, ValidationHandler&&); > > bool isAllowedByContentSecurityPolicy(const WebCore::ResourceRequest&); > >@@ -97,17 +98,6 @@ private: > void processContentExtensionRulesForLoad(WebCore::ResourceRequest&&, ContentExtensionCallback&&); > #endif > >- // ContentSecurityPolicyClient >- void addConsoleMessage(MessageSource, MessageLevel, const String&, unsigned long) final; >- void sendCSPViolationReport(WebCore::URL&&, Ref<WebCore::FormData>&&) final; >- void enqueueSecurityPolicyViolationEvent(WebCore::SecurityPolicyViolationEvent::Init&&) final; >- >- // The connection, web page ID, web frame ID and load identifier are used for CSP reporting. >- Ref<NetworkConnectionToWebProcess> m_connection; >- uint64_t m_webPageID; >- uint64_t m_webFrameID; >- ResourceLoadIdentifier m_loadIdentifier; >- > bool shouldCrossOriginResourcePolicyPolicyCancelLoad(const WebCore::ResourceResponse&); > > WebCore::FetchOptions m_options; >diff --git a/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp b/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp >index c5f675197f83e3b19a5bd125877fbd4ed421921d..602cae1cdf7a54a1e23ec5e7358310d7673af734 100644 >--- a/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp >+++ b/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp >@@ -119,7 +119,7 @@ NetworkResourceLoader::NetworkResourceLoader(NetworkResourceLoadParameters&& par > } > > if (synchronousReply || parameters.shouldRestrictHTTPResponseAccess) { >- m_networkLoadChecker = std::make_unique<NetworkLoadChecker>(m_connection, m_parameters.webPageID, m_parameters.webFrameID, identifier(), FetchOptions { m_parameters.options }, m_parameters.sessionID, HTTPHeaderMap { m_parameters.originalRequestHeaders }, URL { m_parameters.request.url() }, m_parameters.sourceOrigin.copyRef(), m_parameters.preflightPolicy, originalRequest().httpReferrer()); >+ m_networkLoadChecker = std::make_unique<NetworkLoadChecker>(FetchOptions { m_parameters.options }, m_parameters.sessionID, HTTPHeaderMap { m_parameters.originalRequestHeaders }, URL { m_parameters.request.url() }, m_parameters.sourceOrigin.copyRef(), m_parameters.preflightPolicy, originalRequest().httpReferrer()); > if (m_parameters.cspResponseHeaders) > m_networkLoadChecker->setCSPResponseHeaders(ContentSecurityPolicyResponseHeaders { m_parameters.cspResponseHeaders.value() }); > #if ENABLE(CONTENT_EXTENSIONS) >@@ -184,7 +184,7 @@ void NetworkResourceLoader::start() > m_wasStarted = true; > > if (m_networkLoadChecker) { >- m_networkLoadChecker->check(ResourceRequest { originalRequest() }, [this] (auto&& result) { >+ m_networkLoadChecker->check(ResourceRequest { originalRequest() }, this, [this] (auto&& result) { > if (!result.has_value()) { > if (!result.error().isCancellation()) > this->didFailLoading(result.error()); >@@ -576,7 +576,7 @@ void NetworkResourceLoader::willSendRedirectedRequest(ResourceRequest&& request, > m_cache->storeRedirect(request, redirectResponse, redirectRequest); > > if (m_networkLoadChecker) { >- m_networkLoadChecker->checkRedirection(redirectResponse, WTFMove(redirectRequest), [protectedThis = makeRef(*this), this, storedCredentialsPolicy = m_networkLoadChecker->storedCredentialsPolicy(), request = WTFMove(request), redirectResponse](auto&& result) mutable { >+ m_networkLoadChecker->checkRedirection(redirectResponse, WTFMove(redirectRequest), this, [protectedThis = makeRef(*this), this, storedCredentialsPolicy = m_networkLoadChecker->storedCredentialsPolicy(), request = WTFMove(request), redirectResponse](auto&& result) mutable { > if (!result.has_value()) { > if (result.error().isCancellation()) > return; >diff --git a/Source/WebKit/NetworkProcess/PingLoad.cpp b/Source/WebKit/NetworkProcess/PingLoad.cpp >index 1aece4792d2e6ead4b042dbd393c41177b690ac2..f6730f59209160fa93a890cfd1ba1c0895cdaa3a 100644 >--- a/Source/WebKit/NetworkProcess/PingLoad.cpp >+++ b/Source/WebKit/NetworkProcess/PingLoad.cpp >@@ -38,11 +38,11 @@ namespace WebKit { > > using namespace WebCore; > >-PingLoad::PingLoad(NetworkResourceLoadParameters&& parameters, NetworkConnectionToWebProcess& connection, WTF::CompletionHandler<void(const ResourceError&, const ResourceResponse&)>&& completionHandler) >+PingLoad::PingLoad(NetworkResourceLoadParameters&& parameters, WTF::CompletionHandler<void(const ResourceError&, const ResourceResponse&)>&& completionHandler) > : m_parameters(WTFMove(parameters)) > , m_completionHandler(WTFMove(completionHandler)) > , m_timeoutTimer(*this, &PingLoad::timeoutTimerFired) >- , m_networkLoadChecker(makeUniqueRef<NetworkLoadChecker>(connection, m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, FetchOptions { m_parameters.options}, m_parameters.sessionID, WTFMove(m_parameters.originalRequestHeaders), URL { m_parameters.request.url() }, m_parameters.sourceOrigin.copyRef(), m_parameters.preflightPolicy, m_parameters.request.httpReferrer())) >+ , m_networkLoadChecker(makeUniqueRef<NetworkLoadChecker>(FetchOptions { m_parameters.options}, m_parameters.sessionID, WTFMove(m_parameters.originalRequestHeaders), URL { m_parameters.request.url() }, m_parameters.sourceOrigin.copyRef(), m_parameters.preflightPolicy, m_parameters.request.httpReferrer())) > { > > if (m_parameters.cspResponseHeaders) >@@ -55,7 +55,7 @@ PingLoad::PingLoad(NetworkResourceLoadParameters&& parameters, NetworkConnection > // Set a very generous timeout, just in case. > m_timeoutTimer.startOneShot(60000_s); > >- m_networkLoadChecker->check(ResourceRequest { m_parameters.request }, [this] (auto&& result) { >+ m_networkLoadChecker->check(ResourceRequest { m_parameters.request }, nullptr, [this] (auto&& result) { > if (!result.has_value()) { > this->didFinish(result.error()); > return; >@@ -93,7 +93,7 @@ void PingLoad::loadRequest(ResourceRequest&& request) > > void PingLoad::willPerformHTTPRedirection(ResourceResponse&& redirectResponse, ResourceRequest&& request, RedirectCompletionHandler&& completionHandler) > { >- m_networkLoadChecker->checkRedirection(redirectResponse, WTFMove(request), [this, completionHandler = WTFMove(completionHandler)](auto&& result) { >+ m_networkLoadChecker->checkRedirection(redirectResponse, WTFMove(request), nullptr, [this, completionHandler = WTFMove(completionHandler)](auto&& result) { > if (!result.has_value()) { > completionHandler({ }); > this->didFinish(result.error()); >diff --git a/Source/WebKit/NetworkProcess/PingLoad.h b/Source/WebKit/NetworkProcess/PingLoad.h >index b93815a04bde3fa849ee78fb16c31ebb5828f9c8..0031bbd578129f7a284ad2e19f77438f30664e44 100644 >--- a/Source/WebKit/NetworkProcess/PingLoad.h >+++ b/Source/WebKit/NetworkProcess/PingLoad.h >@@ -45,7 +45,7 @@ class NetworkLoadChecker; > > class PingLoad final : private NetworkDataTaskClient { > public: >- PingLoad(NetworkResourceLoadParameters&&, NetworkConnectionToWebProcess&, WTF::CompletionHandler<void(const WebCore::ResourceError&, const WebCore::ResourceResponse&)>&&); >+ PingLoad(NetworkResourceLoadParameters&&, CompletionHandler<void(const WebCore::ResourceError&, const WebCore::ResourceResponse&)>&&); > > private: > ~PingLoad();
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186551
:
342772
|
343742