diff --git a/AgileWorks/AgileWorks/WebView/View/SubView/SubViewStack.swift b/AgileWorks/AgileWorks/WebView/View/SubView/SubViewStack.swift
index 2329a0d8a442a4c4a799f680e15c9ce8ec31ad12..ab641f10154373acfb2631964127b07b36ff8aef 100644
--- a/AgileWorks/AgileWorks/WebView/View/SubView/SubViewStack.swift
+++ b/AgileWorks/AgileWorks/WebView/View/SubView/SubViewStack.swift
@@ -23,6 +23,8 @@ class SubViewStack: NSObject {
}
func push(_ webView: WKWebView, superView: UIView) {
+ // 回転時リサイズ設定
+ webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
webViews.append(webView)
webView.uiDelegate = self
webView.allowsBackForwardNavigationGestures = true
@@ -30,6 +32,7 @@ class SubViewStack: NSObject {
let swipeRightGesture: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(self.handleRight(sender:)))
swipeRightGesture.numberOfTouchesRequired = 1
swipeRightGesture.direction = .right
+ swipeRightGesture.delegate = self
webView.addGestureRecognizer(swipeRightGesture)
superView.addSubview(webView)
}
@@ -77,4 +80,7 @@ extension SubViewStack: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
+ func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
+ return true
+ }
}
diff --git a/AgileWorks/AgileWorks/WebView/View/WebViewController.storyboard b/AgileWorks/AgileWorks/WebView/View/WebViewController.storyboard
index ea412d4def5377dbeae03062ef39db5471a2701a..bca840b46d55ad67828b83b8a9d527a9e2d97d55 100644
--- a/AgileWorks/AgileWorks/WebView/View/WebViewController.storyboard
+++ b/AgileWorks/AgileWorks/WebView/View/WebViewController.storyboard
@@ -20,7 +20,7 @@
-
+
@@ -70,7 +70,7 @@
-
+
diff --git a/AgileWorks/AgileWorks/WebView/View/WebViewController.swift b/AgileWorks/AgileWorks/WebView/View/WebViewController.swift
index bae50cab81989f10fdbb52e65e9766ad878917f6..3299374b5048be8b7051e5d6dde80a48055084fc 100644
--- a/AgileWorks/AgileWorks/WebView/View/WebViewController.swift
+++ b/AgileWorks/AgileWorks/WebView/View/WebViewController.swift
@@ -18,6 +18,7 @@ class WebViewController: UIViewController {
@IBOutlet private var closeButton: UIBarButtonItem!
@IBOutlet private var menuButton: UIBarButtonItem!
var mainWebView: WKWebView!
+ var subWebView: WKWebView!
// 別ウインドウで開いたときの子ウインドウスタック
var subViewStack = SubViewStack()
var loadURL: String!
@@ -95,7 +96,7 @@ class WebViewController: UIViewController {
let configuration = WKWebViewConfiguration()
configuration.userContentController = userContentController
configuration.applicationNameForUserAgent = kCustomUserAgent
- mainWebView = WKWebView(frame: self.formView.frame, configuration: configuration)
+ mainWebView = WKWebView(frame: self.formView.bounds, configuration: configuration)
// スクロール設定
mainWebView.scrollView.bounces = true
@@ -418,10 +419,11 @@ extension WebViewController: WKUIDelegate {
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame?.isMainFrame != true {
- let webView = WKWebView(frame: self.formView.frame, configuration: configuration)
- webView.load(navigationAction.request)
- subViewStack.push(webView, superView: view)
- return webView
+ subWebView = WKWebView(frame: self.formView.bounds, configuration: configuration)
+ subWebView.navigationDelegate = self
+ subViewStack.push(subWebView, superView: mainWebView)
+ subWebView.load(navigationAction.request)
+ return subWebView
}
return nil
}
@@ -438,6 +440,132 @@ extension WebViewController: WKUIDelegate {
}
extension WebViewController: WKNavigationDelegate {
+ func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
+ if let attachmentFileName = attachmentFileName(ofResponce: navigationResponse),
+ let url = navigationResponse.response.url {
+ download(url: url, saveAs: attachmentFileName)
+ decisionHandler(.cancel)
+ } else {
+ decisionHandler(.allow)
+ }
+ }
+
+ private func attachmentFileName(ofResponce navigationResponse: WKNavigationResponse) -> String? {
+ guard let response = navigationResponse.response as? HTTPURLResponse,
+ let contentDisposition = response.allHeaderFields["Content-Disposition"] as? String
+ else { return nil }
+ print(response.allHeaderFields)
+ if let (fileNameStar: fileNameStar, fileName: fileName) = getAttachmentFileName(contentDisposition: contentDisposition) {
+ if let name = fileNameStar, let decoded = parseFilenameStar(name) {
+ return decoded
+ } else if let name = fileName {
+ return parseFilename(name)
+ }
+ }
+ return nil
+ }
+
+ private func getAttachmentFileName(contentDisposition: String) -> (fileNameStar: String?, fileName: String?)? {
+ var isAttachment = false
+ var fileNameStar: String?
+ var fileName: String?
+ for keyValue in contentDisposition.split(separator: ";") {
+ let keyValuePair = keyValue.split(separator: "=", maxSplits: 2)
+ let key = keyValuePair[0].trimmingCharacters(in: .whitespaces)
+ switch key {
+ case "attachment":
+ isAttachment = true
+
+ case "filename*":
+ if keyValuePair.count >= 2 {
+ fileNameStar = keyValuePair[1].trimmingCharacters(in: .whitespaces)
+ }
+
+ case "filename":
+ if keyValuePair.count >= 2 {
+ fileName = keyValuePair[1].trimmingCharacters(in: .whitespaces)
+ }
+
+ default:
+ break
+ }
+ }
+ if isAttachment {
+ return (fileNameStar: fileNameStar, fileName: fileName)
+ } else {
+ return nil
+ }
+ }
+
+ private func parseFilenameStar(_ encoded: String) -> String? {
+ // RFC 5987 のパターン (ややルーズ)
+ guard let pattern = try? NSRegularExpression(pattern: "^([^']+)'([^']*)'(.*)$", options: []) else { return nil }
+ let results = pattern.matches(in: encoded, options: [], range: NSRange(0.. Substring {
+ let first = str.index(str.startIndex, offsetBy: nsRange.location)
+ let last = str.index(first, offsetBy: nsRange.length)
+ return str[first.. String {
+ // 非標準だが "" で囲まれているパターンもある
+ if (str.count >= 2) && str.hasPrefix("\"") && str.hasSuffix("\"") {
+ let first = str.index(after: str.startIndex)
+ let last = str.index(before: str.endIndex)
+ return String(str[first.. URLRequest {
+ var request = URLRequest(url: url)
+ let formHost = KeychainDataStore().readServerURL()!
+ // WebView と同じセッションでダウンロードできるように Cookie 設定。
+ // 他サイトへのアクセス時に Cookie を漏らさないよう、ホスト名とパスを確認しておく。
+ if (url.host == formHost) && url.path.starts(with: "/AgileWorks/Broker/") {
+ request.setValue("JSESSIONID=\(KeychainDataStore().readSessionID()!)", forHTTPHeaderField: "Cookie")
+ }
+ return request
+ }
}
extension WebViewController: SubViewStackEventDelegate {