Bugzilla – Attachment 159996 Details for
Bug 128502
Not possible to use the multitasking feature of iOS 13.x
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP patch
0001-Extremely-WIP-do-not-push.patch (text/plain), 54.26 KB, created by
How can I remove my account?
on 2020-04-27 13:20:23 UTC
(
hide
)
Description:
WIP patch
Filename:
MIME Type:
Creator:
How can I remove my account?
Created:
2020-04-27 13:20:23 UTC
Size:
54.26 KB
patch
obsolete
>From bf2aa50ac51ff68c8779b412510e3bd7b1de60fd Mon Sep 17 00:00:00 2001 >From: Tor Lillqvist <tml@collabora.com> >Date: Fri, 24 Apr 2020 10:46:54 +0300 >Subject: [PATCH] Extremely WIP, do not push > >Change-Id: I44a0e8d60bdbc0a885db88475961575c5e95ce88 >--- > common/MobileApp.cpp | 42 ++++++ > common/MobileApp.hpp | 61 +++++++++ > common/SigUtil.cpp | 17 +-- > common/SigUtil.hpp | 25 +++- > ios/Mobile.xcodeproj/project.pbxproj | 12 ++ > ios/Mobile/AppDelegate.mm | 13 +- > ios/Mobile/CODocument.h | 1 + > ios/Mobile/CODocument.mm | 12 +- > ios/Mobile/DocumentViewController.h | 1 - > ios/Mobile/DocumentViewController.mm | 48 ++----- > ios/Mobile/Info.plist.in | 5 + > ios/Mobile/SceneDelegate.h | 18 +++ > ios/Mobile/SceneDelegate.m | 26 ++++ > ios/config.h.in | 4 +- > ios/ios.h | 3 - > ios/ios.mm | 4 +- > kit/ChildSession.cpp | 12 +- > kit/ChildSession.hpp | 2 + > kit/Kit.cpp | 188 +++++++++++++++++++++++---- > kit/Kit.hpp | 7 +- > net/FakeSocket.cpp | 5 + > test/WhiteBoxTests.cpp | 5 + > wsd/DocumentBroker.cpp | 27 ++-- > wsd/DocumentBroker.hpp | 15 ++- > wsd/LOOLWSD.cpp | 64 +++++---- > wsd/LOOLWSD.hpp | 8 +- > 26 files changed, 476 insertions(+), 149 deletions(-) > create mode 100644 common/MobileApp.cpp > create mode 100644 common/MobileApp.hpp > create mode 100644 ios/Mobile/SceneDelegate.h > create mode 100644 ios/Mobile/SceneDelegate.m > >diff --git a/common/MobileApp.cpp b/common/MobileApp.cpp >new file mode 100644 >index 000000000..16c000910 >--- /dev/null >+++ b/common/MobileApp.cpp >@@ -0,0 +1,42 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ >+/* >+ * This file is part of the LibreOffice project. >+ * >+ * 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 http://mozilla.org/MPL/2.0/. >+ */ >+ >+#include <cassert> >+#include <map> >+#include <mutex> >+ >+#include "MobileApp.hpp" >+ >+static std::map<unsigned, DocumentData> idToDocDataMap; >+static std::mutex idToDocDataMapMutex; >+ >+DocumentData &allocateDocumentDataForMobileAppDocId(unsigned docId) >+{ >+ const std::lock_guard<std::mutex> lock(idToDocDataMapMutex); >+ >+ assert(idToDocDataMap.find(docId) == idToDocDataMap.end()); >+ idToDocDataMap[docId] = DocumentData(); >+ return idToDocDataMap[docId]; >+} >+ >+DocumentData &getDocumentDataForMobileAppDocId(unsigned docId) >+{ >+ const std::lock_guard<std::mutex> lock(idToDocDataMapMutex); >+ >+ assert(idToDocDataMap.find(docId) != idToDocDataMap.end()); >+ return idToDocDataMap[docId]; >+} >+ >+void deallocateDocumentDataForMobileAppDocId(unsigned docId) >+{ >+ assert(idToDocDataMap.find(docId) != idToDocDataMap.end()); >+ idToDocDataMap.erase(docId); >+} >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/common/MobileApp.hpp b/common/MobileApp.hpp >new file mode 100644 >index 000000000..fe2fe7958 >--- /dev/null >+++ b/common/MobileApp.hpp >@@ -0,0 +1,61 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ >+/* >+ * This file is part of the LibreOffice project. >+ * >+ * 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 http://mozilla.org/MPL/2.0/. >+ */ >+ >+#pragma once >+ >+#include "config.h" >+ >+#if MOBILEAPP >+ >+#include <LibreOfficeKit/LibreOfficeKit.hxx> >+ >+#ifdef IOS >+#import "CODocument.h" >+#endif >+ >+// On iOS at least we want to be able to have several documents open >+// in the same app process. >+ >+// It is somewhat complicated to make sure we access the same >+// LibreOfficeKit object for the document in both the iOS-specific >+// Objective-C++ code and in the mostly generic Online C++ code. >+ >+// We pass around a numeric ever-increasing document identifier that >+// gets biumped for each document the system asks the app to open. >+ >+// For iOS, it is the static std::atomic<unsigned> appDocIdCounter(1) >+// in CODocument.mm. >+ >+// In practice it will probably be equivalent to the >+// DocumentBroker::DocBrokerId or the, but there might be situations >+// where multi-threading and opening of several documents in sequence >+// very quickly might cause discrepancies, so it is better to usea >+// different counter to be sure. >+ >+struct DocumentData >+{ >+ lok::Document *loKitDocument; >+#ifdef IOS >+ CODocument *coDocument; >+#endif >+ >+ DocumentData() : >+ loKitDocument(nullptr) >+#ifdef IOS >+ , coDocument(nil) >+#endif >+ { >+ } >+}; >+ >+DocumentData &allocateDocumentDataForMobileAppDocId(unsigned docId); >+DocumentData &getDocumentDataForMobileAppDocId(unsigned docId); >+void deallocateDocumentDataForMobileAppDocId(unsigned docId); >+ >+#endif >diff --git a/common/SigUtil.cpp b/common/SigUtil.cpp >index cd4c779dc..2e27308dd 100644 >--- a/common/SigUtil.cpp >+++ b/common/SigUtil.cpp >@@ -38,14 +38,10 @@ > #include "Common.hpp" > #include "Log.hpp" > >+#if !MOBILEAPP > static std::atomic<bool> TerminationFlag(false); > static std::atomic<bool> DumpGlobalState(false); >-#if MOBILEAPP >-std::atomic<bool> MobileTerminationFlag(false); >-#else >-// Mobile defines its own, which is constexpr. > static std::atomic<bool> ShutdownRequestFlag(false); >-#endif > > namespace SigUtil > { >@@ -64,13 +60,6 @@ namespace SigUtil > TerminationFlag = true; > } > >-#if MOBILEAPP >- void resetTerminationFlag() >- { >- TerminationFlag = false; >- } >-#endif >- > bool getDumpGlobalState() > { > return DumpGlobalState; >@@ -80,11 +69,7 @@ namespace SigUtil > { > DumpGlobalState = false; > } >-} > >-#if !MOBILEAPP >-namespace SigUtil >-{ > /// This traps the signal-handler so we don't _Exit > /// while dumping stack trace. It's re-entrant. > /// Used to safely increment and decrement the signal-handler trap. >diff --git a/common/SigUtil.hpp b/common/SigUtil.hpp >index 9bccf0256..e987e5c76 100644 >--- a/common/SigUtil.hpp >+++ b/common/SigUtil.hpp >@@ -12,13 +12,9 @@ > #include <atomic> > #include <mutex> > >-#if MOBILEAPP >-static constexpr bool ShutdownRequestFlag(false); >-extern std::atomic<bool> MobileTerminationFlag; >-#endif >- > namespace SigUtil > { >+#ifndef IOS > /// Get the flag used to commence clean shutdown. > /// requestShutdown() is used to set the flag. > bool getShutdownRequestFlag(); >@@ -32,14 +28,29 @@ namespace SigUtil > /// Only necessary in Mobile. > void resetTerminationFlag(); > #endif >+#else >+ // In the mobile apps we have no need to shut down the app. >+ inline constexpr bool getShutdownRequestFlag() >+ { >+ return false; >+ } >+ >+ inline constexpr bool getTerminationFlag() >+ { >+ return false; >+ } >+ >+ inline void setTerminationFlag() >+ { >+ } >+#endif > >+#if !MOBILEAPP > /// Get the flag to dump internal state. > bool getDumpGlobalState(); > /// Reset the flag to dump internal state. > void resetDumpGlobalState(); > >-#if !MOBILEAPP >- > /// Wait for the signal handler, if any, > /// and prevent _Exit while collecting backtrace. > void waitSigHandlerTrap(); >diff --git a/ios/Mobile.xcodeproj/project.pbxproj b/ios/Mobile.xcodeproj/project.pbxproj >index 783d80923..9d4d6b460 100644 >--- a/ios/Mobile.xcodeproj/project.pbxproj >+++ b/ios/Mobile.xcodeproj/project.pbxproj >@@ -65,6 +65,8 @@ > BEB0E5D921C7CA800085A0CF /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BEB0E5D821C7CA800085A0CF /* Settings.bundle */; }; > BECD984024336DD400016117 /* device-mobile.css in Resources */ = {isa = PBXBuildFile; fileRef = BECD983E24336DD400016117 /* device-mobile.css */; }; > BECD984124336DD400016117 /* device-tablet.css in Resources */ = {isa = PBXBuildFile; fileRef = BECD983F24336DD400016117 /* device-tablet.css */; }; >+ BEDCC84E2452F82800FB02BD /* MobileApp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEDCC84C2452F82800FB02BD /* MobileApp.cpp */; }; >+ BEDCC8992456FFAD00FB02BD /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BEDCC8982456FFAC00FB02BD /* SceneDelegate.m */; }; > BEFB1EE121C29CC70081D757 /* L10n.mm in Sources */ = {isa = PBXBuildFile; fileRef = BEFB1EE021C29CC70081D757 /* L10n.mm */; }; > /* End PBXBuildFile section */ > >@@ -1173,6 +1175,10 @@ > BECBD41423D9C98500DA5582 /* svddrgmt.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svddrgmt.cxx; path = "../../ios-device/svx/source/svdraw/svddrgmt.cxx"; sourceTree = "<group>"; }; > BECD983E24336DD400016117 /* device-mobile.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = "device-mobile.css"; path = "../../../loleaflet/dist/device-mobile.css"; sourceTree = "<group>"; }; > BECD983F24336DD400016117 /* device-tablet.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = "device-tablet.css"; path = "../../../loleaflet/dist/device-tablet.css"; sourceTree = "<group>"; }; >+ BEDCC84C2452F82800FB02BD /* MobileApp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MobileApp.cpp; sourceTree = "<group>"; }; >+ BEDCC84D2452F82800FB02BD /* MobileApp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MobileApp.hpp; sourceTree = "<group>"; }; >+ BEDCC8972456FFAC00FB02BD /* SceneDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = "<group>"; }; >+ BEDCC8982456FFAC00FB02BD /* SceneDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = "<group>"; }; > BEF755A723E8200A008A4BB2 /* drawdoc.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = drawdoc.cxx; path = "../../ios-device/sd/source/core/drawdoc.cxx"; sourceTree = "<group>"; }; > BEF755A823E8200A008A4BB2 /* drawdoc3.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = drawdoc3.cxx; path = "../../ios-device/sd/source/core/drawdoc3.cxx"; sourceTree = "<group>"; }; > BEF755A923E8200A008A4BB2 /* sdiocmpt.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = sdiocmpt.cxx; path = "../../ios-device/sd/source/core/sdiocmpt.cxx"; sourceTree = "<group>"; }; >@@ -1869,6 +1875,8 @@ > BE58E129217F295B00249358 /* Log.hpp */, > BE5EB5BD213FE29900E0826C /* MessageQueue.cpp */, > BE58E12D217F295B00249358 /* MessageQueue.hpp */, >+ BEDCC84C2452F82800FB02BD /* MobileApp.cpp */, >+ BEDCC84D2452F82800FB02BD /* MobileApp.hpp */, > BE58E12A217F295B00249358 /* Png.hpp */, > BE5EB5BF213FE29900E0826C /* Protocol.cpp */, > BE58E12E217F295B00249358 /* Protocol.hpp */, >@@ -2257,6 +2265,8 @@ > BE8D77312136762500AC58EA /* DocumentViewController.mm */, > BEFB1EDF21C29CC70081D757 /* L10n.h */, > BEFB1EE021C29CC70081D757 /* L10n.mm */, >+ BEDCC8972456FFAC00FB02BD /* SceneDelegate.h */, >+ BEDCC8982456FFAC00FB02BD /* SceneDelegate.m */, > BE80E45C21B6CEF100859C97 /* TemplateSectionHeaderView.h */, > BE80E45D21B6CEF200859C97 /* TemplateSectionHeaderView.m */, > BE80E45621B68F5000859C97 /* TemplateCollectionViewController.h */, >@@ -2985,8 +2995,10 @@ > BE5EB5C3213FE29900E0826C /* Session.cpp in Sources */, > BE5EB5D22140039100E0826C /* LOOLWSD.cpp in Sources */, > BEFB1EE121C29CC70081D757 /* L10n.mm in Sources */, >+ BEDCC8992456FFAD00FB02BD /* SceneDelegate.m in Sources */, > BE5EB5C6213FE29900E0826C /* SigUtil.cpp in Sources */, > BE5EB5C1213FE29900E0826C /* Log.cpp in Sources */, >+ BEDCC84E2452F82800FB02BD /* MobileApp.cpp in Sources */, > BE5EB5DA2140363100E0826C /* ios.mm in Sources */, > BE5EB5D421400DC100E0826C /* DocumentBroker.cpp in Sources */, > BEA28377214FFD8C00848631 /* Unit.cpp in Sources */, >diff --git a/ios/Mobile/AppDelegate.mm b/ios/Mobile/AppDelegate.mm >index 074230ff8..632cbce13 100644 >--- a/ios/Mobile/AppDelegate.mm >+++ b/ios/Mobile/AppDelegate.mm >@@ -207,6 +207,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( > > comphelper::LibreOfficeKit::setLanguageTag(LanguageTag(OUString::fromUtf8(OString([app_locale UTF8String])), true)); > >+ // This fires off a thread running the LOKit runLoop() >+ runKitLoopInAThread(); >+ > // Look for the setting indicating the URL for a file containing a list of URLs for template > // documents to download. If set, start a task to download it, and then to download the listed > // templates. >@@ -248,7 +251,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( > > fakeSocketSetLoggingCallback([](const std::string& line) > { >- LOG_TRC_NOFILE(line); >+ LOG_INF(line); > }); > > dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), >@@ -268,6 +271,10 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( > return YES; > } > >+- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options API_AVAILABLE(ios(13.0)) { >+ return [UISceneConfiguration configurationWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; >+} >+ > - (void)applicationWillResignActive:(UIApplication *)application { > } > >@@ -286,16 +293,20 @@ - (void)applicationWillTerminate:(UIApplication *)application { > std::_Exit(1); > } > >+// This method is called when you use the "Share > Open in Collabora Office" functionality in the >+// Files app. Possibly also in other use cases. > - (BOOL)application:(UIApplication *)app openURL:(NSURL *)inputURL options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options { > // Ensure the URL is a file URL > if (!inputURL.isFileURL) { > return NO; > } > >+#if 0 > // If we already have a document open, close it > if (lok_document != nullptr && [DocumentViewController singleton] != nil) { > [[DocumentViewController singleton] bye]; > } >+#endif > > // Reveal / import the document at the URL > DocumentBrowserViewController *documentBrowserViewController = (DocumentBrowserViewController *)self.window.rootViewController; >diff --git a/ios/Mobile/CODocument.h b/ios/Mobile/CODocument.h >index 79f772a1b..7aa262c25 100644 >--- a/ios/Mobile/CODocument.h >+++ b/ios/Mobile/CODocument.h >@@ -19,6 +19,7 @@ > @public > int fakeClientFd; > NSURL *copyFileURL; >+ unsigned appDocId; > } > > @property (weak) DocumentViewController *viewController; >diff --git a/ios/Mobile/CODocument.mm b/ios/Mobile/CODocument.mm >index 7eaa9c90f..c12bd2e91 100644 >--- a/ios/Mobile/CODocument.mm >+++ b/ios/Mobile/CODocument.mm >@@ -32,6 +32,7 @@ > #import "KitHelper.hpp" > #import "Log.hpp" > #import "LOOLWSD.hpp" >+#import "MobileApp.hpp" > #import "Protocol.hpp" > > @implementation CODocument >@@ -40,6 +41,12 @@ - (id)contentsForType:(NSString*)typeName error:(NSError **)errorPtr { > return [NSData dataWithContentsOfFile:[copyFileURL path] options:0 error:errorPtr]; > } > >+// We keep a running count of opening documents here. This is not necessarily in sync with the >+// DocBrokerId in DocumentBroker due to potential parallelism when opening multiple documents in >+// quick succession. >+ >+static std::atomic<unsigned> appDocIdCounter(1); >+ > - (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)errorPtr { > > // If this method is called a second time on the same CODocument object, just ignore it. This >@@ -59,10 +66,13 @@ - (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError > > NSURL *url = [[NSBundle mainBundle] URLForResource:@"loleaflet" withExtension:@"html"]; > NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; >+ appDocId = appDocIdCounter++; >+ allocateDocumentDataForMobileAppDocId(appDocId).coDocument = self; > components.queryItems = @[ [NSURLQueryItem queryItemWithName:@"file_path" value:[copyFileURL absoluteString]], > [NSURLQueryItem queryItemWithName:@"closebutton" value:@"1"], > [NSURLQueryItem queryItemWithName:@"permission" value:@"edit"], >- [NSURLQueryItem queryItemWithName:@"lang" value:app_locale] >+ [NSURLQueryItem queryItemWithName:@"lang" value:app_locale], >+ [NSURLQueryItem queryItemWithName:@"appdocid" value:[NSString stringWithFormat:@"%u", appDocId]], > ]; > > NSURLRequest *request = [[NSURLRequest alloc]initWithURL:components.URL]; >diff --git a/ios/Mobile/DocumentViewController.h b/ios/Mobile/DocumentViewController.h >index 297255999..cb845b302 100644 >--- a/ios/Mobile/DocumentViewController.h >+++ b/ios/Mobile/DocumentViewController.h >@@ -20,7 +20,6 @@ > @property (strong) NSURL *slideshowURL; > > - (void)bye; >-+ (DocumentViewController*)singleton; > > @end > >diff --git a/ios/Mobile/DocumentViewController.mm b/ios/Mobile/DocumentViewController.mm >index 54932be3f..0acd9c6d4 100644 >--- a/ios/Mobile/DocumentViewController.mm >+++ b/ios/Mobile/DocumentViewController.mm >@@ -21,13 +21,12 @@ > #import "FakeSocket.hpp" > #import "LOOLWSD.hpp" > #import "Log.hpp" >+#import "MobileApp.hpp" > #import "SigUtil.hpp" > #import "Util.hpp" > > #import "DocumentViewController.h" > >-static DocumentViewController* theSingleton = nil; >- > @interface DocumentViewController() <WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler, UIScrollViewDelegate, UIDocumentPickerDelegate> { > int closeNotificationPipeForForwardingThread[2]; > NSURL *downloadAsTmpURL; >@@ -78,8 +77,6 @@ @implementation DocumentViewController > - (void)viewDidLoad { > [super viewDidLoad]; > >- theSingleton = self; >- > WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init]; > WKUserContentController *userContentController = [[WKUserContentController alloc] init]; > >@@ -316,10 +313,6 @@ - (void)userContentController:(WKUserContentController *)userContentController d > // is saved by closing it. > fakeSocketClose(self->closeNotificationPipeForForwardingThread[1]); > >- // Flag to make the inter-thread plumbing in the Online >- // bits go away quicker. >- MobileTerminationFlag = true; >- > // Close our end of the fake socket connection to the > // ClientSession thread, so that it terminates > fakeSocketClose(self.document->fakeClientFd); >@@ -347,13 +340,14 @@ - (void)userContentController:(WKUserContentController *)userContentController d > assert(false); > }); > >- // First we simply send it the URL. This corresponds to the GET request with Upgrade to >- // WebSocket. >+ // First we simply send the Online C++ parts the URL and the appDocId. This corresponds >+ // to the GET request with Upgrade to WebSocket. > std::string url([[self.document->copyFileURL absoluteString] UTF8String]); > p.fd = self.document->fakeClientFd; > p.events = POLLOUT; > fakeSocketPoll(&p, 1, -1); >- fakeSocketWrite(self.document->fakeClientFd, url.c_str(), url.size()); >+ std::string message(url + " " + std::to_string(self.document->appDocId)); >+ fakeSocketWrite(self.document->fakeClientFd, message.c_str(), message.size()); > > return; > } else if ([message.body isEqualToString:@"BYE"]) { >@@ -368,7 +362,7 @@ - (void)userContentController:(WKUserContentController *)userContentController d > self.slideshowFile = Util::createRandomTmpDir() + "/slideshow.svg"; > self.slideshowURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:self.slideshowFile.c_str()] isDirectory:NO]; > >- lok_document->saveAs([[self.slideshowURL absoluteString] UTF8String], "svg", nullptr); >+ getDocumentDataForMobileAppDocId(self.document->appDocId).loKitDocument->saveAs([[self.slideshowURL absoluteString] UTF8String], "svg", nullptr); > > // Add a new full-screen WebView displaying the slideshow. > >@@ -422,7 +416,7 @@ - (void)userContentController:(WKUserContentController *)userContentController d > > std::string printFile = Util::createRandomTmpDir() + "/print.pdf"; > NSURL *printURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:printFile.c_str()] isDirectory:NO]; >- lok_document->saveAs([[printURL absoluteString] UTF8String], "pdf", nullptr); >+ getDocumentDataForMobileAppDocId(self.document->appDocId).loKitDocument->saveAs([[printURL absoluteString] UTF8String], "pdf", nullptr); > > UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController]; > UIPrintInfo *printInfo = [UIPrintInfo printInfo]; >@@ -470,7 +464,7 @@ - (void)userContentController:(WKUserContentController *)userContentController d > > std::remove([[downloadAsTmpURL path] UTF8String]); > >- lok_document->saveAs([[downloadAsTmpURL absoluteString] UTF8String], [format UTF8String], nullptr); >+ getDocumentDataForMobileAppDocId(self.document->appDocId).loKitDocument->saveAs([[downloadAsTmpURL absoluteString] UTF8String], [format UTF8String], nullptr); > > // Then verify that it indeed was saved, and then use an > // UIDocumentPickerViewController to ask the user where to store the exported >@@ -518,31 +512,17 @@ - (void)bye { > // Close one end of the socket pair, that will wake up the forwarding thread above > fakeSocketClose(closeNotificationPipeForForwardingThread[0]); > >- // We can't wait for the LOOLWSD::lokit_main_mutex directly here because this is called on the >- // main queue and the main queue must be ready to execute code dispatched by the system APIs >- // used to do document saving. >- dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), >- ^{ >- // Wait for lokit_main thread to exit >- std::lock_guard<std::mutex> lock(LOOLWSD::lokit_main_mutex); >- >- theSingleton = nil; >+ // deallocateDocumentDataForMobileAppDocId(self.document->appDocId); > >- [[NSFileManager defaultManager] removeItemAtURL:self.document->copyFileURL error:nil]; >+ [[NSFileManager defaultManager] removeItemAtURL:self.document->copyFileURL error:nil]; > >- // And only then let the document browsing view show up again. The >- // dismissViewControllerAnimated must be done on the main queue. >- dispatch_async(dispatch_get_main_queue(), >- ^{ >- [self dismissDocumentViewController]; >- }); >+ // The dismissViewControllerAnimated must be done on the main queue. >+ dispatch_async(dispatch_get_main_queue(), >+ ^{ >+ [self dismissDocumentViewController]; > }); > } > >-+ (DocumentViewController*)singleton { >- return theSingleton; >-} >- > @end > > // vim:set shiftwidth=4 softtabstop=4 expandtab: >diff --git a/ios/Mobile/Info.plist.in b/ios/Mobile/Info.plist.in >index 2b716ded1..397c47133 100644 >--- a/ios/Mobile/Info.plist.in >+++ b/ios/Mobile/Info.plist.in >@@ -421,6 +421,11 @@ > <string>share/fonts/truetype/opens___.ttf</string> > @IOSAPP_FONTS@ > </array> >+ <key>UIApplicationSceneManifest</key> >+ <dict> >+ <key>UIApplicationSupportsMultipleScenes</key> >+ <true/> >+ </dict> > <key>UIFileSharingEnabled</key> > <true/> > <key>UILaunchStoryboardName</key> >diff --git a/ios/Mobile/SceneDelegate.h b/ios/Mobile/SceneDelegate.h >new file mode 100644 >index 000000000..d0c8f4d8a >--- /dev/null >+++ b/ios/Mobile/SceneDelegate.h >@@ -0,0 +1,18 @@ >+// -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- >+// >+// This file is part of the LibreOffice project. >+// >+// 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 http://mozilla.org/MPL/2.0/. >+ >+#import <UIKit/UIKit.h> >+ >+@interface SceneDelegate : UIResponder <UIWindowSceneDelegate> >+ >+@property (strong, nonatomic) UIWindow * window; >+ >+@end >+ >+// vim:set shiftwidth=4 softtabstop=4 expandtab: >+ >diff --git a/ios/Mobile/SceneDelegate.m b/ios/Mobile/SceneDelegate.m >new file mode 100644 >index 000000000..7ab90cfb3 >--- /dev/null >+++ b/ios/Mobile/SceneDelegate.m >@@ -0,0 +1,26 @@ >+// -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- >+// >+// This file is part of the LibreOffice project. >+// >+// 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 http://mozilla.org/MPL/2.0/. >+ >+#import <UIKit/UIKit.h> >+ >+#import "SceneDelegate.h" >+ >+@implementation SceneDelegate >+ >+- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions API_AVAILABLE(ios(13.0)) { >+ NSLog(@"foo"); >+} >+ >+- (void)sceneDidBecomeActive:(UIScene *)scene API_AVAILABLE(ios(13.0)) { >+ NSLog(@"bar"); >+} >+ >+@end >+ >+// vim:set shiftwidth=4 softtabstop=4 expandtab: >+ >diff --git a/ios/config.h.in b/ios/config.h.in >index 18ec2613d..05934c203 100644 >--- a/ios/config.h.in >+++ b/ios/config.h.in >@@ -89,10 +89,10 @@ > #undef LT_OBJDIR > > /* Limit the maximum number of open connections */ >-#define MAX_CONNECTIONS 3 >+#define MAX_CONNECTIONS 100 > > /* Limit the maximum number of open documents */ >-#define MAX_DOCUMENTS 1 >+#define MAX_DOCUMENTS 100 > > /* Define to 1 if this is a mobileapp (eg. Android) build. */ > #define MOBILEAPP 1 >diff --git a/ios/ios.h b/ios/ios.h >index a4283cefb..198b9e90a 100644 >--- a/ios/ios.h >+++ b/ios/ios.h >@@ -7,12 +7,9 @@ > * file, You can obtain one at http://mozilla.org/MPL/2.0/. > */ > >-#include <mutex> >- > #include <LibreOfficeKit/LibreOfficeKit.hxx> > > extern int loolwsd_server_socket_fd; >-extern lok::Document *lok_document; > > extern LibreOfficeKit *lo_kit; > >diff --git a/ios/ios.mm b/ios/ios.mm >index 97c49c3e9..b5c6ac65b 100644 >--- a/ios/ios.mm >+++ b/ios/ios.mm >@@ -6,8 +6,6 @@ > // License, v. 2.0. If a copy of the MPL was not distributed with this > // file, You can obtain one at http://mozilla.org/MPL/2.0/. > >-#include <cstring> >- > #include "ios.h" > > #import <Foundation/Foundation.h> >@@ -18,7 +16,7 @@ > } > > int loolwsd_server_socket_fd = -1; >-lok::Document *lok_document = nullptr; >+ > LibreOfficeKit *lo_kit; > > // vim:set shiftwidth=4 softtabstop=4 expandtab: >diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp >index aa9f2545c..137f17ae0 100644 >--- a/kit/ChildSession.cpp >+++ b/kit/ChildSession.cpp >@@ -10,6 +10,7 @@ > #include <config.h> > > #include "ChildSession.hpp" >+#include "MobileApp.hpp" > > #include <climits> > #include <fstream> >@@ -33,10 +34,6 @@ > #include <Poco/Net/AcceptCertificateHandler.h> > #endif > >-#ifdef IOS >-#import "DocumentViewController.h" >-#endif >- > #include <common/FileUtil.hpp> > #include <common/JsonUtil.hpp> > #include <common/Authorization.hpp> >@@ -2447,11 +2444,10 @@ void ChildSession::loKitCallback(const int type, const std::string& payload) > > if (!commandName.isEmpty() && commandName.toString() == ".uno:Save" && !success.isEmpty() && success.toString() == "true") > { >- CODocument *document = [[DocumentViewController singleton] document]; >- >+ CODocument *document = getDocumentDataForMobileAppDocId(_docManager->getMobileAppDocId()).coDocument; > [document saveToURL:[document fileURL] >- forSaveOperation:UIDocumentSaveForOverwriting >- completionHandler:^(BOOL success) { >+ forSaveOperation:UIDocumentSaveForOverwriting >+ completionHandler:^(BOOL success) { > LOG_TRC("ChildSession::loKitCallback() save completion handler gets " << (success?"YES":"NO")); > }]; > } >diff --git a/kit/ChildSession.hpp b/kit/ChildSession.hpp >index fad3061aa..b431a1245 100644 >--- a/kit/ChildSession.hpp >+++ b/kit/ChildSession.hpp >@@ -71,6 +71,8 @@ public: > virtual bool sendFrame(const char* buffer, int length, WSOpCode opCode = WSOpCode::Text) = 0; > > virtual void alertAllUsers(const std::string& cmd, const std::string& kind) = 0; >+ >+ virtual unsigned getMobileAppDocId() = 0; > }; > > struct RecordedEvent >diff --git a/kit/Kit.cpp b/kit/Kit.cpp >index 46eaf55c9..7fd297f8e 100644 >--- a/kit/Kit.cpp >+++ b/kit/Kit.cpp >@@ -54,6 +54,7 @@ > > #include "ChildSession.hpp" > #include <Common.hpp> >+#include <MobileApp.hpp> > #include <FileUtil.hpp> > #include "KitHelper.hpp" > #include "Kit.hpp" >@@ -772,7 +773,8 @@ public: > const std::string& docId, > const std::string& url, > std::shared_ptr<TileQueue> tileQueue, >- const std::shared_ptr<WebSocketHandler>& websocketHandler) >+ const std::shared_ptr<WebSocketHandler>& websocketHandler, >+ unsigned mobileAppDocId) > : _loKit(loKit), > _jailId(jailId), > _docKey(docKey), >@@ -788,7 +790,8 @@ public: > _stop(false), > _isLoading(0), > _editorId(-1), >- _editorChangeWarning(false) >+ _editorChangeWarning(false), >+ _mobileAppDocId(mobileAppDocId) > { > LOG_INF("Document ctor for [" << _docKey << > "] url [" << anonymizeUrl(_url) << "] on child [" << _jailId << >@@ -829,6 +832,11 @@ public: > { > session.second->resetDocManager(); > } >+ >+#ifdef IOS >+ deallocateDocumentDataForMobileAppDocId(_mobileAppDocId); >+#endif >+ > } > > const std::string& getUrl() const { return _url; } >@@ -1267,6 +1275,11 @@ public: > alertAllUsers("errortoall: cmd=" + cmd + " kind=" + kind); > } > >+ unsigned getMobileAppDocId() override >+ { >+ return _mobileAppDocId; >+ } >+ > static void GlobalCallback(const int type, const char* p, void* data) > { > if (SigUtil::getTerminationFlag()) >@@ -1490,9 +1503,6 @@ private: > #endif > LOG_INF("Document [" << anonymizeUrl(_url) << "] has no more views, but has " << > _sessions.size() << " sessions still. Destroying the document."); >-#ifdef IOS >- lok_document = nullptr; >-#endif > #ifdef __ANDROID__ > _loKitDocumentForAndroidOnly.reset(); > #endif >@@ -1737,9 +1747,7 @@ private: > const double totalTime = elapsed/1000.; > LOG_DBG("Returned lokit::documentLoad(" << FileUtil::anonymizeUrl(pURL) << ") in " << totalTime << "ms."); > #ifdef IOS >- // The iOS app (and the Android one) has max one document open at a time, so we can keep >- // a pointer to it in a global. >- lok_document = _loKitDocument.get(); >+ getDocumentDataForMobileAppDocId(_mobileAppDocId).loKitDocument = _loKitDocument.get(); > #endif > if (!_loKitDocument || !_loKitDocument->get()) > { >@@ -2156,6 +2164,8 @@ private: > #ifdef __ANDROID__ > friend std::shared_ptr<lok::Document> getLOKDocumentForAndroidOnly(); > #endif >+ >+ const unsigned _mobileAppDocId; > }; > > #ifdef __ANDROID__ >@@ -2174,10 +2184,38 @@ class KitSocketPoll : public SocketPoll > std::chrono::steady_clock::time_point _pollEnd; > std::shared_ptr<Document> _document; > >-public: > KitSocketPoll() : > SocketPoll("kit") > { >+#ifdef IOS >+ terminationFlag = false; >+#endif >+ } >+ >+public: >+ ~KitSocketPoll() >+ { >+#ifdef IOS >+ std::unique_lock<std::mutex> lock(KSPollsMutex); >+ std::shared_ptr<KitSocketPoll> p; >+ for (const auto& i : KSPolls) >+ if (i.get() == this) >+ p = i; >+ assert(p); >+ KSPolls.erase(p); >+#endif >+ } >+ >+ static std::shared_ptr<KitSocketPoll> create() >+ { >+ KitSocketPoll *p = new KitSocketPoll(); >+ auto result = std::shared_ptr<KitSocketPoll>(p); >+#ifdef IOS >+ std::unique_lock<std::mutex> lock(KSPollsMutex); >+ KSPolls.insert(result); >+ // KSPollsCV.notify_one(); >+#endif >+ return result; > } > > // process pending message-queue events. >@@ -2250,8 +2288,26 @@ public: > { > _document = document; > } >+ >+#ifdef IOS >+ static std::mutex KSPollsMutex; >+ // static std::condition_variable KSPollsCV; >+ static std::set<std::shared_ptr<KitSocketPoll>> KSPolls; >+ >+ std::mutex terminationMutex; >+ std::condition_variable terminationCV; >+ bool terminationFlag; >+#endif > }; > >+#ifdef IOS >+ >+std::mutex KitSocketPoll::KSPollsMutex; >+// std::condition_variable KitSocketPoll::KSPollsCV; >+std::set<std::shared_ptr<KitSocketPoll>> KitSocketPoll::KSPolls; >+ >+#endif >+ > class KitWebSocketHandler final : public WebSocketHandler > { > std::shared_ptr<TileQueue> _queue; >@@ -2259,16 +2315,18 @@ class KitWebSocketHandler final : public WebSocketHandler > std::shared_ptr<lok::Office> _loKit; > std::string _jailId; > std::shared_ptr<Document> _document; >- KitSocketPoll &_ksPoll; >+ std::shared_ptr<KitSocketPoll> _ksPoll; >+ const unsigned _mobileAppDocId; > > public: >- KitWebSocketHandler(const std::string& socketName, const std::shared_ptr<lok::Office>& loKit, const std::string& jailId, KitSocketPoll& ksPoll) : >+ KitWebSocketHandler(const std::string& socketName, const std::shared_ptr<lok::Office>& loKit, const std::string& jailId, std::shared_ptr<KitSocketPoll> ksPoll, unsigned mobileAppDocId) : > WebSocketHandler(/* isClient = */ true, /* isMasking */ false), > _queue(std::make_shared<TileQueue>()), > _socketName(socketName), > _loKit(loKit), > _jailId(jailId), >- _ksPoll(ksPoll) >+ _ksPoll(ksPoll), >+ _mobileAppDocId(mobileAppDocId) > { > } > >@@ -2317,14 +2375,16 @@ protected: > std::string url; > URI::decode(docKey, url); > LOG_INF("New session [" << sessionId << "] request on url [" << url << "]."); >+#ifndef IOS > Util::setThreadName("kit_" + docId); >- >+#endif > if (!_document) > { > _document = std::make_shared<Document>( > _loKit, _jailId, docKey, docId, url, _queue, >- std::static_pointer_cast<WebSocketHandler>(shared_from_this())); >- _ksPoll.setDocument(_document); >+ std::static_pointer_cast<WebSocketHandler>(shared_from_this()), >+ _mobileAppDocId); >+ _ksPoll->setDocument(_document); > } > > // Validate and create session. >@@ -2340,9 +2400,16 @@ protected: > LOG_INF("Terminating immediately due to parent 'exit' command."); > Log::shutdown(); > std::_Exit(EX_SOFTWARE); >+#else >+#ifdef IOS >+ LOG_INF("Setting our KitSocketPoll's termination flag due to 'exit' command."); >+ std::unique_lock<std::mutex> lock(_ksPoll->terminationMutex); >+ _ksPoll->terminationFlag = true; >+ _ksPoll->terminationCV.notify_all(); > #else > LOG_INF("Setting TerminationFlag due to 'exit' command."); > SigUtil::setTerminationFlag(); >+#endif > _document.reset(); > #endif > } >@@ -2392,19 +2459,54 @@ void documentViewCallback(const int type, const char* payload, void* data) > /// Called by LOK main-loop the central location for data processing. > int pollCallback(void* pData, int timeoutUs) > { >+#ifndef IOS > if (!pData) > return 0; > else > return reinterpret_cast<KitSocketPoll*>(pData)->kitPoll(timeoutUs); >+#else >+ std::unique_lock<std::mutex> lock(KitSocketPoll::KSPollsMutex); >+ if (KitSocketPoll::KSPolls.size() == 0) >+ { >+ // KitSocketPoll::KSPollsCV.wait(lock); >+ lock.unlock(); >+ std::this_thread::sleep_for(std::chrono::microseconds(timeoutUs)); >+ } >+ else >+ { >+ std::vector<std::shared_ptr<KitSocketPoll>> v; >+ for (const auto &i : KitSocketPoll::KSPolls) >+ v.push_back(i); >+ lock.unlock(); >+ for (const auto &i : v) >+ i->kitPoll(timeoutUs); >+ } >+ >+ // We never want to exit the main loop >+ return 0; >+#endif > } > > /// Called by LOK main-loop > void wakeCallback(void* pData) > { >+#ifndef IOS > if (!pData) > return; > else > return reinterpret_cast<KitSocketPoll*>(pData)->wakeup(); >+#else >+ std::unique_lock<std::mutex> lock(KitSocketPoll::KSPollsMutex); >+ if (KitSocketPoll::KSPolls.size() == 0) >+ return; >+ >+ std::vector<std::shared_ptr<KitSocketPoll>> v; >+ for (const auto &i : KitSocketPoll::KSPolls) >+ v.push_back(i); >+ lock.unlock(); >+ for (const auto &i : v) >+ i->wakeup(); >+#endif > } > > void setupKitEnvironment() >@@ -2456,10 +2558,9 @@ void lokit_main( > bool queryVersion, > bool displayVersion, > #else >- const std::string& documentUri, > int docBrokerSocket, > #endif >- size_t spareKitId >+ size_t numericIdentifier > ) > { > #if !MOBILEAPP >@@ -2469,7 +2570,7 @@ void lokit_main( > SigUtil::setTerminationSignals(); > #endif > >- Util::setThreadName("kit_spare_" + Util::encodeId(spareKitId, 3)); >+ Util::setThreadName("kit_spare_" + Util::encodeId(numericIdentifier, 3)); > > // Reinitialize logging when forked. > const bool logToFile = std::getenv("LOOL_LOGFILE"); >@@ -2517,8 +2618,6 @@ void lokit_main( > std::shared_ptr<lok::Office> loKit; > Path jailPath; > ChildSession::NoCapsForKit = noCapabilities; >-#else >- AnonymizeUserData = false; > #endif // MOBILEAPP > > try >@@ -2719,8 +2818,11 @@ void lokit_main( > > #else // MOBILEAPP > >- // was not done by the preload >+#ifndef IOS >+ // Was not done by the preload. >+ // For iOS we call it in -[AppDelegate application: didFinishLaunchingWithOptions:] > setupKitEnvironment(); >+#endif > > #if defined(__linux) && !defined(__ANDROID__) > Poco::URI userInstallationURI("file", LO_PATH); >@@ -2747,16 +2849,16 @@ void lokit_main( > > #endif // MOBILEAPP > >- KitSocketPoll mainKit; >- mainKit.runOnClientThread(); // We will do the polling on this thread. >+ auto mainKit = KitSocketPoll::create(); >+ mainKit->runOnClientThread(); // We will do the polling on this thread. > > std::shared_ptr<KitWebSocketHandler> websocketHandler = >- std::make_shared<KitWebSocketHandler>("child_ws", loKit, jailId, mainKit); >+ std::make_shared<KitWebSocketHandler>("child_ws", loKit, jailId, mainKit, numericIdentifier); > > #if !MOBILEAPP >- mainKit.insertNewUnixSocket(MasterLocation, pathAndQuery, websocketHandler); >+ mainKit->insertNewUnixSocket(MasterLocation, pathAndQuery, websocketHandler); > #else >- mainKit.insertNewFakeSocket(docBrokerSocket, websocketHandler); >+ mainKit->insertNewFakeSocket(docBrokerSocket, websocketHandler); > #endif > > LOG_INF("New kit client websocket inserted."); >@@ -2769,6 +2871,7 @@ void lokit_main( > } > #endif > >+#ifndef IOS > if (!LIBREOFFICEKIT_HAS(kit, runLoop)) > { > LOG_ERR("Kit is missing Unipoll API"); >@@ -2778,7 +2881,7 @@ void lokit_main( > > LOG_INF("Kit unipoll loop run"); > >- loKit->runLoop(pollCallback, wakeCallback, &mainKit); >+ loKit->runLoop(pollCallback, wakeCallback, mainKit.get()); > > LOG_INF("Kit unipoll loop run terminated."); > >@@ -2792,6 +2895,11 @@ void lokit_main( > > // Let forkit handle the jail cleanup. > #endif >+ >+#else // IOS >+ std::unique_lock<std::mutex> lock(mainKit->terminationMutex); >+ mainKit->terminationCV.wait(lock,[&]{ return mainKit->terminationFlag; } ); >+#endif // !IOS > } > catch (const Exception& exc) > { >@@ -2813,7 +2921,31 @@ void lokit_main( > > #endif > } >-#endif >+ >+#ifdef IOS >+ >+// In the iOS app we can have several documents opne in the app process at the same time, thus >+// several lokit_main() runnins at the same time. We want just one LO main loop, though, so we start >+// it separately in its own thread. >+ >+void runKitLoopInAThread() >+{ >+ std::thread([&] >+ { >+ Util::setThreadName("lokit_runloop"); >+ >+ std::shared_ptr<lok::Office> loKit = std::make_shared<lok::Office>(lo_kit); >+ int dummy; >+ loKit->runLoop(pollCallback, wakeCallback, &dummy); >+ >+ // Should never return >+ assert(false); >+ }).detach(); >+} >+ >+#endif // IOS >+ >+#endif // !BUILDING_TESTS > > std::string anonymizeUrl(const std::string& url) > { >diff --git a/kit/Kit.hpp b/kit/Kit.hpp >index 1e60fdd3a..a5c6332b8 100644 >--- a/kit/Kit.hpp >+++ b/kit/Kit.hpp >@@ -37,12 +37,15 @@ void lokit_main( > bool queryVersionInfo, > bool displayVersion, > #else >- const std::string& documentUri, > int docBrokerSocket, > #endif >- size_t spareKitId >+ size_t numericIdentifier > ); > >+#ifdef IOS >+void runKitLoopInAThread(); >+#endif >+ > /// We need to get several env. vars right > void setupKitEnvironment(); > >diff --git a/net/FakeSocket.cpp b/net/FakeSocket.cpp >index 0cdd54795..cd1a627af 100644 >--- a/net/FakeSocket.cpp >+++ b/net/FakeSocket.cpp >@@ -242,6 +242,11 @@ static bool checkForPoll(std::vector<FakeSocketPair>& fds, struct pollfd *pollfd > retval = true; > } > } >+ if (fds[pollfds[i].fd/2].shutdown[N]) >+ { >+ pollfds[i].revents |= POLLHUP; >+ retval = true; >+ } > } > } > return retval; >diff --git a/test/WhiteBoxTests.cpp b/test/WhiteBoxTests.cpp >index 66f3e895f..b950c7436 100644 >--- a/test/WhiteBoxTests.cpp >+++ b/test/WhiteBoxTests.cpp >@@ -565,6 +565,11 @@ public: > void alertAllUsers(const std::string& /*cmd*/, const std::string& /*kind*/) override > { > } >+ >+ unsigned getMobileAppDocId() override >+ { >+ return 0; >+ } > }; > > void WhiteBoxTests::testEmptyCellCursor() >diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp >index d9fc339c9..5a5533f64 100644 >--- a/wsd/DocumentBroker.cpp >+++ b/wsd/DocumentBroker.cpp >@@ -152,14 +152,6 @@ public: > > bool continuePolling() override > { >-#if MOBILEAPP >- if (MobileTerminationFlag) >- { >- LOG_TRC("Noticed MobileTerminationFlag."); >- MobileTerminationFlag = false; >- return false; >- } >-#endif > return TerminatingPoll::continuePolling(); > } > >@@ -175,6 +167,14 @@ std::atomic<unsigned> DocumentBroker::DocBrokerId(1); > DocumentBroker::DocumentBroker(const std::string& uri, > const Poco::URI& uriPublic, > const std::string& docKey) : >+ DocumentBroker(uri, uriPublic, docKey, 0) >+{ >+} >+ >+DocumentBroker::DocumentBroker(const std::string& uri, >+ const Poco::URI& uriPublic, >+ const std::string& docKey, >+ unsigned mobileAppDocId) : > _limitLifeSeconds(0), > _uriOrig(uri), > _uriPublic(uriPublic), >@@ -197,7 +197,8 @@ DocumentBroker::DocumentBroker(const std::string& uri, > _lockCtx(new LockContext()), > _tileVersion(0), > _debugRenderedTileCount(0), >- _wopiLoadDuration(0) >+ _wopiLoadDuration(0), >+ _mobileAppDocId(mobileAppDocId) > { > assert(!_docKey.empty()); > assert(!LOOLWSD::ChildRoot.empty()); >@@ -239,7 +240,7 @@ void DocumentBroker::pollThread() > } > while (!_stop && _poll->continuePolling() && !SigUtil::getTerminationFlag() && !SigUtil::getShutdownRequestFlag()); > #else >- _childProcess = getNewChild_Blocks(getPublicUri().getPath()); >+ _childProcess = getNewChild_Blocks(_mobileAppDocId); > #endif > > if (!_childProcess) >@@ -2225,6 +2226,8 @@ void DocumentBroker::getIOStats(uint64_t &sent, uint64_t &recv) > } > } > >+#if !MOBILEAPP >+ > static std::atomic<size_t> NumConverters; > > size_t ConvertToBroker::getInstanceCount() >@@ -2246,7 +2249,6 @@ ConvertToBroker::ConvertToBroker(const std::string& uri, > _limitLifeSeconds = limit_convert_secs; > } > >-#if !MOBILEAPP > bool ConvertToBroker::startConversion(SocketDisposition &disposition, const std::string &id) > { > std::shared_ptr<ConvertToBroker> docBroker = std::static_pointer_cast<ConvertToBroker>(shared_from_this()); >@@ -2294,7 +2296,6 @@ bool ConvertToBroker::startConversion(SocketDisposition &disposition, const std: > }); > return true; > } >-#endif > > void ConvertToBroker::dispose() > { >@@ -2346,6 +2347,8 @@ void ConvertToBroker::setLoaded() > _clientSession->handleMessage(saveasRequest); > } > >+#endif >+ > std::vector<std::shared_ptr<ClientSession>> DocumentBroker::getSessionsTestOnlyUnsafe() > { > std::vector<std::shared_ptr<ClientSession>> result; >diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp >index a5bc5c160..a74ef5ebf 100644 >--- a/wsd/DocumentBroker.hpp >+++ b/wsd/DocumentBroker.hpp >@@ -119,11 +119,15 @@ public: > /// Dummy document broker that is marked to destroy. > DocumentBroker(); > >- /// Construct DocumentBroker with URI, docKey, and root path. > DocumentBroker(const std::string& uri, > const Poco::URI& uriPublic, > const std::string& docKey); > >+ DocumentBroker(const std::string& uri, >+ const Poco::URI& uriPublic, >+ const std::string& docKey, >+ unsigned mobileAppDocId); >+ > virtual ~DocumentBroker(); > > /// Called when removed from the DocBrokers list >@@ -429,8 +433,13 @@ private: > > /// Unique DocBroker ID for tracing and debugging. > static std::atomic<unsigned> DocBrokerId; >+ >+ // Relevant only in the mobile apps >+ const unsigned _mobileAppDocId; > }; > >+#if !MOBILEAPP >+ > class ConvertToBroker : public DocumentBroker > { > const std::string _format; >@@ -446,10 +455,8 @@ public: > const std::string& sOptions); > virtual ~ConvertToBroker(); > >-#if !MOBILEAPP > /// Move socket to this broker for response & do conversion > bool startConversion(SocketDisposition &disposition, const std::string &id); >-#endif > > /// Called when removed from the DocBrokers list > void dispose() override; >@@ -464,4 +471,6 @@ public: > static void removeFile(const std::string &uri); > }; > >+#endif >+ > /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp >index b996c9877..ba3c283e3 100644 >--- a/wsd/LOOLWSD.cpp >+++ b/wsd/LOOLWSD.cpp >@@ -121,6 +121,7 @@ using Poco::Net::PartHandler; > # include <Kit.hpp> > #endif > #include <Log.hpp> >+#include <MobileApp.hpp> > #include <Protocol.hpp> > #include <Session.hpp> > #if ENABLE_SSL >@@ -489,14 +490,12 @@ static size_t addNewChild(const std::shared_ptr<ChildProcess>& child) > } > > #if MOBILEAPP >+#ifndef IOS > std::mutex LOOLWSD::lokit_main_mutex; > #endif >- >-std::shared_ptr<ChildProcess> getNewChild_Blocks( >-#if MOBILEAPP >- const std::string& uri > #endif >- ) >+ >+std::shared_ptr<ChildProcess> getNewChild_Blocks(unsigned mobileAppDocId) > { > std::unique_lock<std::mutex> lock(NewChildrenMutex); > >@@ -525,12 +524,15 @@ std::shared_ptr<ChildProcess> getNewChild_Blocks( > > std::thread([&] > { >- std::lock_guard<std::mutex> lokit_main_lock(LOOLWSD::lokit_main_mutex); >+#ifndef IOS >+ std::lock_guard<std::mutex> lock(LOOLWSD::lokit_main_mutex); > Util::setThreadName("lokit_main"); >- >- // Ugly to have that static global, otoh we know there is just one LOOLWSD >- // object. (Even in real Online.) >- lokit_main(uri, LOOLWSD::prisonerServerSocketFD, 1); >+#else >+ Util::setThreadName("lokit_main_" + Util::encodeId(mobileAppDocId, 3)); >+#endif >+ // Ugly to have that static global LOOLWSD::prisonerServerSocketFD, Otoh we know >+ // there is just one LOOLWSD object. (Even in real Online.) >+ lokit_main(LOOLWSD::prisonerServerSocketFD, mobileAppDocId); > }).detach(); > #endif > >@@ -1817,7 +1819,8 @@ static std::shared_ptr<DocumentBroker> > const std::string& uri, > const std::string& docKey, > const std::string& id, >- const Poco::URI& uriPublic) >+ const Poco::URI& uriPublic, >+ unsigned mobileAppDocId) > { > LOG_INF("Find or create DocBroker for docKey [" << docKey << > "] for session [" << id << "] on url [" << LOOLWSD::anonymizeUrl(uriPublic.toString()) << "]."); >@@ -1889,7 +1892,7 @@ static std::shared_ptr<DocumentBroker> > > // Set the one we just created. > LOG_DBG("New DocumentBroker for docKey [" << docKey << "]."); >- docBroker = std::make_shared<DocumentBroker>(uri, uriPublic, docKey); >+ docBroker = std::make_shared<DocumentBroker>(uri, uriPublic, docKey, mobileAppDocId); > DocBrokers.emplace(docKey, docBroker); > LOG_TRC("Have " << DocBrokers.size() << " DocBrokers after inserting [" << docKey << "]."); > } >@@ -2413,11 +2416,25 @@ private: > socket->eraseFirstInputBytes(map); > #else > Poco::Net::HTTPRequest request; >- // The 2nd parameter is the response to the HULLO message (which we >- // respond with the path of the document) >+ >+#ifdef IOS >+ // The URL of the document is sent over the FakeSocket by the code in >+ // -[DocumentViewController userContentController:didReceiveScriptMessage:] when it gets the >+ // HULLO message from the JavaScript in global.js. >+ >+ // The "app document id", the numeric id of the document, from the appDocIdCounter in CODocument.mm. >+ char *space = strchr(socket->getInBuffer().data(), ' '); >+ assert(space != nullptr); >+ unsigned appDocId = std::strtoul(space + 1, nullptr, 10); >+ >+ handleClientWsUpgrade( >+ request, std::string(socket->getInBuffer().data(), space - socket->getInBuffer().data()), >+ disposition, socket, appDocId); >+#else > handleClientWsUpgrade( > request, std::string(socket->getInBuffer().data(), socket->getInBuffer().size()), > disposition, socket); >+#endif > socket->getInBuffer().clear(); > #endif > } >@@ -2918,7 +2935,6 @@ private: > > throw BadRequestException("Invalid or unknown request."); > } >-#endif > > void handleClientProxyRequest(const Poco::Net::HTTPRequest& request, > std::string url, >@@ -3017,10 +3033,12 @@ private: > }); > } > } >+#endif > > void handleClientWsUpgrade(const Poco::Net::HTTPRequest& request, const std::string& url, > SocketDisposition& disposition, >- const std::shared_ptr<StreamSocket>& socket) >+ const std::shared_ptr<StreamSocket>& socket, >+ unsigned mobileAppDocId = 0) > { > assert(socket && "Must have a valid socket"); > >@@ -3075,7 +3093,7 @@ private: > > // Request a kit process for this doc. > std::shared_ptr<DocumentBroker> docBroker = findOrCreateDocBroker( >- std::static_pointer_cast<ProtocolHandlerInterface>(ws), url, docKey, _id, uriPublic); >+ std::static_pointer_cast<ProtocolHandlerInterface>(ws), url, docKey, _id, uriPublic, mobileAppDocId); > if (docBroker) > { > #if MOBILEAPP >@@ -3428,8 +3446,10 @@ public: > << "[ " << DocBrokers.size() << " ]:\n"; > for (auto &i : DocBrokers) > i.second->dumpState(os); >- os << "Converter count: " << ConvertToBroker::getInstanceCount() << "\n"; > >+#if !MOBILEAPP >+ os << "Converter count: " << ConvertToBroker::getInstanceCount() << "\n"; >+#endif > Socket::InhibitThreadChecks = false; > SocketPoll::InhibitThreadChecks = false; > } >@@ -3442,11 +3462,13 @@ private: > > void wakeupHook() override > { >+#if !MOBILEAPP > if (SigUtil::getDumpGlobalState()) > { > dump_state(); > SigUtil::resetDumpGlobalState(); > } >+#endif > } > }; > /// This thread & poll accepts incoming connections. >@@ -3885,7 +3907,7 @@ void LOOLWSD::cleanup() > > int LOOLWSD::main(const std::vector<std::string>& /*args*/) > { >-#if MOBILEAPP >+#if defined MOBILEAPP && !defined IOS > SigUtil::resetTerminationFlag(); > #endif > >@@ -3906,10 +3928,6 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/) > > UnitWSD::get().returnValue(returnValue); > >-#if MOBILEAPP >- fakeSocketDumpState(); >-#endif >- > LOG_INF("Process [loolwsd] finished."); > return returnValue; > } >diff --git a/wsd/LOOLWSD.hpp b/wsd/LOOLWSD.hpp >index 07561906e..0aa562e45 100644 >--- a/wsd/LOOLWSD.hpp >+++ b/wsd/LOOLWSD.hpp >@@ -33,11 +33,7 @@ class TraceFileWriter; > class DocumentBroker; > class ClipboardCache; > >-std::shared_ptr<ChildProcess> getNewChild_Blocks( >-#if MOBILEAPP >- const std::string& uri >-#endif >- ); >+std::shared_ptr<ChildProcess> getNewChild_Blocks(unsigned mobileAppDocId); > // A WSProcess object in the WSD process represents a descendant process, either the direct child > // process FORKIT or a grandchild KIT process, with which the WSD process communicates through a > // WebSocket. >@@ -259,8 +255,10 @@ public: > static std::set<const Poco::Util::AbstractConfiguration*> PluginConfigurations; > static std::chrono::time_point<std::chrono::system_clock> StartTime; > #if MOBILEAPP >+#ifndef IOS > /// This is used to be able to wait until the lokit main thread has finished (and it is safe to load a new document). > static std::mutex lokit_main_mutex; >+#endif > #endif > > /// For testing only [!] >-- >2.24.2 (Apple Git-127) >
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 Raw
Actions:
View
Attachments on
bug 128502
:
155523
|
159583
|
159612
|
159994
| 159996