From e8024f1cb64493b736592e6012cbab852d380aff Mon Sep 17 00:00:00 2001 From: Brandon Date: Wed, 30 Oct 2024 11:45:59 -0400 Subject: [PATCH] Add CSP Support --- .../web/webui/crw_web_ui_scheme_handler.mm | 126 ++++++++++++++++++ .../ios/web/webui/url_fetcher_block_adapter.h | 27 ++++ .../web/webui/url_fetcher_block_adapter.mm | 21 +++ 3 files changed, 174 insertions(+) create mode 100644 chromium_src/ios/web/webui/crw_web_ui_scheme_handler.mm create mode 100644 chromium_src/ios/web/webui/url_fetcher_block_adapter.h create mode 100644 chromium_src/ios/web/webui/url_fetcher_block_adapter.mm diff --git a/chromium_src/ios/web/webui/crw_web_ui_scheme_handler.mm b/chromium_src/ios/web/webui/crw_web_ui_scheme_handler.mm new file mode 100644 index 000000000000..9773e76f10ec --- /dev/null +++ b/chromium_src/ios/web/webui/crw_web_ui_scheme_handler.mm @@ -0,0 +1,126 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "base/strings/sys_string_conversions.h" +#include "net/http/http_response_headers.h" +#include "services/network/public/mojom/url_response_head.mojom.h" + +#define startURLSchemeTask originalStartURLSchemeTask + +#include "src/ios/web/webui/crw_web_ui_scheme_handler.mm" + +#undef startURLSchemeTask + +@interface CRWWebUISchemeHandler (Override) +- (void)webView:(WKWebView*)webView + startURLSchemeTask:(id)urlSchemeTask; +@end + +@implementation CRWWebUISchemeHandler (Override) +- (void)webView:(WKWebView*)webView + startURLSchemeTask:(id)urlSchemeTask { + GURL URL = net::GURLWithNSURL(urlSchemeTask.request.URL); + // Check the mainDocumentURL as the URL might be one of the subresource, so + // not a WebUI URL itself. + NSInteger errorCode = GetErrorCodeForUrl( + net::GURLWithNSURL(urlSchemeTask.request.mainDocumentURL)); + if (errorCode != 0) { + NSError* error = [NSError + errorWithDomain:NSURLErrorDomain + code:errorCode + userInfo:@{ + NSURLErrorFailingURLErrorKey : urlSchemeTask.request.URL, + NSURLErrorFailingURLStringErrorKey : + urlSchemeTask.request.URL.absoluteString + }]; + [urlSchemeTask didFailWithError:error]; + return; + } + + __weak CRWWebUISchemeHandler* weakSelf = self; + std::unique_ptr adapter = + std::make_unique( + URL, _URLLoaderFactory, + ^(NSData* data, web::URLFetcherBlockAdapter* fetcher) { + CRWWebUISchemeHandler* strongSelf = weakSelf; + if (!strongSelf || + strongSelf.map->find(urlSchemeTask) == strongSelf.map->end()) { + return; + } + + NSString* mimeType = @"text/html"; + base::FilePath filePath = + base::FilePath(fetcher->getUrl().ExtractFileName()); + if (filePath.Extension() == ".js") { + mimeType = @"text/javascript; charset=UTF-8"; + } else if (filePath.Extension() == ".css") { + mimeType = @"text/css; charset=UTF-8"; + } else if (filePath.Extension() == ".svg") { + mimeType = @"image/svg+xml"; + } + + const network::mojom::URLResponseHeadPtr responseHead = + fetcher->getResponse(); + if (responseHead) { + const scoped_refptr headers = + responseHead->headers; + if (headers) { + // const std::string& raw_headers = headers->raw_headers(); + + NSMutableDictionary* responseHeaders = + [strongSelf parseHeaders:headers]; + + if (![responseHeaders objectForKey:@"Content-Type"]) { + [responseHeaders setObject:mimeType forKey:@"Content-Type"]; + } + + NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] + initWithURL:urlSchemeTask.request.URL + statusCode:200 + HTTPVersion:@"HTTP/1.1" + headerFields:responseHeaders]; + + [urlSchemeTask didReceiveResponse:response]; + [urlSchemeTask didReceiveData:data]; + [urlSchemeTask didFinish]; + [weakSelf removeFetcher:fetcher]; + return; + } + } + + NSDictionary* headers = @{ + @"Content-Type" : mimeType, + @"Access-Control-Allow-Origin" : @"*" + }; + + NSHTTPURLResponse* response = + [[NSHTTPURLResponse alloc] initWithURL:urlSchemeTask.request.URL + statusCode:200 + HTTPVersion:@"HTTP/1.1" + headerFields:headers]; + + [urlSchemeTask didReceiveResponse:response]; + [urlSchemeTask didReceiveData:data]; + [urlSchemeTask didFinish]; + [weakSelf removeFetcher:fetcher]; + }); + _map.insert(std::make_pair(urlSchemeTask, std::move(adapter))); + _map.find(urlSchemeTask)->second->Start(); +} + +- (NSMutableDictionary*)parseHeaders: + (const scoped_refptr&)headers { + NSMutableDictionary* result = [[NSMutableDictionary alloc] init]; + + std::size_t iterator = 0; + std::string name, value; + while (headers->EnumerateHeaderLines(&iterator, &name, &value)) { + [result setObject:base::SysUTF8ToNSString(value) + forKey:base::SysUTF8ToNSString(name)]; + } + + return result; +} +@end diff --git a/chromium_src/ios/web/webui/url_fetcher_block_adapter.h b/chromium_src/ios/web/webui/url_fetcher_block_adapter.h new file mode 100644 index 000000000000..38ebdf2347ef --- /dev/null +++ b/chromium_src/ios/web/webui/url_fetcher_block_adapter.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_IOS_WEB_WEBUI_URL_FETCHER_BLOCK_ADAPTER_H_ +#define BRAVE_CHROMIUM_SRC_IOS_WEB_WEBUI_URL_FETCHER_BLOCK_ADAPTER_H_ + +#include "base/memory/raw_ptr.h" +#include "services/network/public/mojom/url_response_head.mojom.h" + +#define completion_handler_ \ + completion_handler_; \ + \ + public: \ + const network::mojom::URLResponseHeadPtr getResponse() { \ + return response_.Clone(); \ + } \ + \ + private: \ + network::mojom::URLResponseHeadPtr response_ + +#include "src/ios/web/webui/url_fetcher_block_adapter.h" // IWYU pragma: export + +#undef completion_handler_ + +#endif // BRAVE_CHROMIUM_SRC_IOS_WEB_WEBUI_URL_FETCHER_BLOCK_ADAPTER_H_ diff --git a/chromium_src/ios/web/webui/url_fetcher_block_adapter.mm b/chromium_src/ios/web/webui/url_fetcher_block_adapter.mm new file mode 100644 index 000000000000..beba3959dde5 --- /dev/null +++ b/chromium_src/ios/web/webui/url_fetcher_block_adapter.mm @@ -0,0 +1,21 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "ios/web/webui/url_fetcher_block_adapter.h" + +#include "services/network/public/cpp/simple_url_loader.h" + +#define GetFinalURL \ + GetFinalURL(); \ + } \ + \ + response_ = url_loader_->TakeResponseInfo(); \ + \ + if (!response_body) { \ + void + +#include "src/ios/web/webui/url_fetcher_block_adapter.mm" + +#undef GetFinalURL