Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
authorErik Verbruggen <erik@verbruggen.consulting>2021-11-10 20:05:55 +0300
committerErik Verbruggen <erik@verbruggen.consulting>2021-11-19 19:40:50 +0300
commit16acce08b9039aaecdb8f3bf372eea3b04fbc0d9 (patch)
tree7ec4877dd08e8e15ae152882118a0f8e0c4d0d08 /src/gui
parent3535be9cf8686f1a6ea9ae73a4399e2106a43bfa (diff)
macOS: Use local socket to communicate with finder extensionwork/macos-use-local-socket
https://github.com/owncloud/client/issues/6343
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/guiutility_mac.mm10
-rw-r--r--src/gui/socketapi/CMakeLists.txt4
-rw-r--r--src/gui/socketapi/socketapi.cpp37
-rw-r--r--src/gui/socketapi/socketapi.h2
-rw-r--r--src/gui/socketapi/socketapisocket_mac.h69
-rw-r--r--src/gui/socketapi/socketapisocket_mac.mm273
6 files changed, 23 insertions, 372 deletions
diff --git a/src/gui/guiutility_mac.mm b/src/gui/guiutility_mac.mm
index 65e05ab6a..0aa7e114e 100644
--- a/src/gui/guiutility_mac.mm
+++ b/src/gui/guiutility_mac.mm
@@ -19,6 +19,7 @@
#include <QProcess>
#import <Foundation/NSBundle.h>
+#import <Foundation/NSFileManager.h>
namespace OCC {
@@ -54,9 +55,12 @@ void Utility::startShellIntegration()
QString Utility::socketApiSocketPath()
{
// This must match the code signing Team setting of the extension
- // Example for developer builds (with ad-hoc signing identity): "" "com.owncloud.desktopclient" ".socketApi"
- // Example for official signed packages: "9B5WD74GWJ." "com.owncloud.desktopclient" ".socketApi"
- return QLatin1String(SOCKETAPI_TEAM_IDENTIFIER_PREFIX "." APPLICATION_REV_DOMAIN ".socketApi");
+ // Example for all builds: "9B5WD74GWJ" "." "com.owncloud.desktopclient"
+ NSString *appGroupId = @SOCKETAPI_TEAM_IDENTIFIER_PREFIX "." APPLICATION_REV_DOMAIN;
+
+ NSURL *container = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:appGroupId];
+ NSURL *socketPath = [container URLByAppendingPathComponent:@"GUI.socket" isDirectory:false];
+ return QString::fromNSString(socketPath.path);
}
} // namespace OCC
diff --git a/src/gui/socketapi/CMakeLists.txt b/src/gui/socketapi/CMakeLists.txt
index 78ce96cfd..0f28db92e 100644
--- a/src/gui/socketapi/CMakeLists.txt
+++ b/src/gui/socketapi/CMakeLists.txt
@@ -2,7 +2,3 @@ target_sources(owncloudCore PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/socketapi.cpp
${CMAKE_CURRENT_SOURCE_DIR}/socketuploadjob.cpp
)
-
-if( APPLE )
- target_sources(owncloudCore PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/socketapisocket_mac.mm)
-endif()
diff --git a/src/gui/socketapi/socketapi.cpp b/src/gui/socketapi/socketapi.cpp
index c1dad9184..e83166932 100644
--- a/src/gui/socketapi/socketapi.cpp
+++ b/src/gui/socketapi/socketapi.cpp
@@ -37,37 +37,30 @@
#include "syncfileitem.h"
#include "theme.h"
-#include <array>
+#include <QAction>
+#include <QApplication>
#include <QBitArray>
-#include <QUrl>
-#include <QMetaMethod>
-#include <QMetaObject>
-#include <QStringList>
-#include <QScopedPointer>
-#include <QFile>
+#include <QBuffer>
+#include <QClipboard>
#include <QDir>
-#include <QApplication>
-#include <QLocalSocket>
-#include <QStringBuilder>
-#include <QMessageBox>
+#include <QFile>
#include <QFileDialog>
-
-
-#include <QAction>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
-#include <QWidget>
-#include <QBuffer>
-
-#include <QClipboard>
-
+#include <QLocalSocket>
+#include <QMessageBox>
+#include <QMetaMethod>
+#include <QMetaObject>
#include <QProcess>
+#include <QScopedPointer>
#include <QStandardPaths>
+#include <QStringBuilder>
+#include <QStringList>
+#include <QUrl>
+#include <QWidget>
-#ifdef Q_OS_MAC
-#include <CoreFoundation/CoreFoundation.h>
-#endif
+#include <array>
// This is the version that is returned when the client asks for the VERSION.
diff --git a/src/gui/socketapi/socketapi.h b/src/gui/socketapi/socketapi.h
index 84229b1dd..1fc8e4546 100644
--- a/src/gui/socketapi/socketapi.h
+++ b/src/gui/socketapi/socketapi.h
@@ -22,7 +22,7 @@
#include "config.h"
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_MAC) && 0
#include "socketapisocket_mac.h"
#else
#include <QLocalServer>
diff --git a/src/gui/socketapi/socketapisocket_mac.h b/src/gui/socketapi/socketapisocket_mac.h
deleted file mode 100644
index cbacdf028..000000000
--- a/src/gui/socketapi/socketapisocket_mac.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) by Jocelyn Turcotte <jturcotte@woboq.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#ifndef SOCKETAPISOCKET_OSX_H
-#define SOCKETAPISOCKET_OSX_H
-
-#include <QAbstractSocket>
-#include <QIODevice>
-
-class SocketApiServerPrivate;
-class SocketApiSocketPrivate;
-
-class SocketApiSocket : public QIODevice
-{
- Q_OBJECT
-public:
- SocketApiSocket(QObject *parent, SocketApiSocketPrivate *p);
- ~SocketApiSocket() override;
-
- qint64 readData(char *data, qint64 maxlen) override;
- qint64 writeData(const char *data, qint64 len) override;
-
- bool isSequential() const override { return true; }
- qint64 bytesAvailable() const override;
- bool canReadLine() const override;
-
-signals:
- void disconnected();
-
-private:
- // Use Qt's p-impl system to hide objective-c types from C++ code including this file
- Q_DECLARE_PRIVATE(SocketApiSocket)
- QScopedPointer<SocketApiSocketPrivate> d_ptr;
- friend class SocketApiServerPrivate;
-};
-
-class SocketApiServer : public QObject
-{
- Q_OBJECT
-public:
- SocketApiServer();
- ~SocketApiServer() override;
-
- void close();
- bool listen(const QString &name);
- SocketApiSocket *nextPendingConnection();
-
- static bool removeServer(const QString &) { return false; }
-
-signals:
- void newConnection();
-
-private:
- Q_DECLARE_PRIVATE(SocketApiServer)
- QScopedPointer<SocketApiServerPrivate> d_ptr;
-};
-
-#endif // SOCKETAPISOCKET_OSX_H
diff --git a/src/gui/socketapi/socketapisocket_mac.mm b/src/gui/socketapi/socketapisocket_mac.mm
deleted file mode 100644
index 938494e21..000000000
--- a/src/gui/socketapi/socketapisocket_mac.mm
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) by Jocelyn Turcotte <jturcotte@woboq.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "socketapisocket_mac.h"
-#import <Cocoa/Cocoa.h>
-
-@protocol ChannelProtocol <NSObject>
-
-- (void)sendMessage:(NSData *)msg;
-
-@end
-
-@protocol RemoteEndProtocol <NSObject, ChannelProtocol>
-
-- (void)registerTransmitter:(id)tx;
-
-@end
-
-@interface LocalEnd : NSObject <ChannelProtocol>
-
-@property (atomic) SocketApiSocketPrivate *wrapper;
-
-- (instancetype)initWithWrapper:(SocketApiSocketPrivate *)wrapper;
-
-@end
-
-@interface Server : NSObject
-
-@property (atomic) SocketApiServerPrivate *wrapper;
-
-- (instancetype)initWithWrapper:(SocketApiServerPrivate *)wrapper;
-- (void)registerClient:(NSDistantObject<RemoteEndProtocol> *)remoteEnd;
-
-@end
-
-class SocketApiSocketPrivate
-{
-public:
- SocketApiSocket *q_ptr;
-
- SocketApiSocketPrivate(NSDistantObject<ChannelProtocol> *remoteEnd);
- ~SocketApiSocketPrivate();
-
- // release remoteEnd
- void disconnectRemote();
-
- NSDistantObject<ChannelProtocol> *remoteEnd;
- LocalEnd *localEnd;
- QByteArray inBuffer;
- bool isRemoteDisconnected = false;
-};
-
-class SocketApiServerPrivate
-{
-public:
- SocketApiServer *q_ptr;
-
- SocketApiServerPrivate();
- ~SocketApiServerPrivate();
-
- QList<SocketApiSocket *> pendingConnections;
- NSConnection *connection;
- Server *server;
-};
-
-
-@implementation LocalEnd
-
-@synthesize wrapper = _wrapper;
-
-- (instancetype)initWithWrapper:(SocketApiSocketPrivate *)wrapper
-{
- self = [super init];
- self.wrapper = wrapper;
- return self;
-}
-
-- (void)sendMessage:(NSData *)msg
-{
- if (self.wrapper) {
- self.wrapper->inBuffer += QByteArray::fromRawNSData(msg);
- emit self.wrapper->q_ptr->readyRead();
- }
-}
-
-- (void)connectionDidDie:(NSNotification *)notification
-{
- // The NSConnectionDidDieNotification docs say to disconnect from NSConnection here
- [[NSNotificationCenter defaultCenter] removeObserver:self];
-
- if (self.wrapper) {
- self.wrapper->disconnectRemote();
- emit self.wrapper->q_ptr->disconnected();
- }
-}
-@end
-
-@implementation Server
-
-@synthesize wrapper = _wrapper;
-
-- (instancetype)initWithWrapper:(SocketApiServerPrivate *)wrapper
-{
- self = [super init];
- self.wrapper = wrapper;
- return self;
-}
-
-- (void)registerClient:(NSDistantObject<RemoteEndProtocol> *)remoteEnd
-{
- // This saves a few mach messages that would otherwise be needed to query the interface
- [remoteEnd setProtocolForProxy:@protocol(RemoteEndProtocol)];
-
- SocketApiServer *server = self.wrapper->q_ptr;
- SocketApiSocketPrivate *socketPrivate = new SocketApiSocketPrivate(remoteEnd);
- SocketApiSocket *socket = new SocketApiSocket(server, socketPrivate);
- self.wrapper->pendingConnections.append(socket);
- emit server->newConnection();
-
- [remoteEnd registerTransmitter:socketPrivate->localEnd];
-}
-@end
-
-
-SocketApiSocket::SocketApiSocket(QObject *parent, SocketApiSocketPrivate *p)
- : QIODevice(parent)
- , d_ptr(p)
-{
- Q_D(SocketApiSocket);
- d->q_ptr = this;
- open(ReadWrite);
-}
-
-SocketApiSocket::~SocketApiSocket()
-{
-}
-
-qint64 SocketApiSocket::readData(char *data, qint64 maxlen)
-{
- Q_D(SocketApiSocket);
- qint64 len = std::min(maxlen, static_cast<qint64>(d->inBuffer.size()));
- if (len < 0 || len > std::numeric_limits<int>::max()) {
- return -1;
- }
-
- memcpy(data, d->inBuffer.constData(), static_cast<size_t>(len));
- d->inBuffer.remove(0, static_cast<int>(len));
- return len;
-}
-
-qint64 SocketApiSocket::writeData(const char *data, qint64 len)
-{
- Q_D(SocketApiSocket);
- if (d->isRemoteDisconnected) {
- return -1;
- }
-
- if (len < std::numeric_limits<NSUInteger>::min() || len > std::numeric_limits<NSUInteger>::max()) {
- return -1;
- }
-
- @try {
- // FIXME: The NSConnection will make this block unless the function is marked as "oneway"
- // in the protocol. This isn't async and reduces our performances but this currectly avoids
- // a Mach queue deadlock during requests bursts of the legacy OwnCloudFinder extension.
- // Since FinderSync already runs in a separate process, blocking isn't too critical.
- NSData *payload = QByteArray::fromRawData(data, static_cast<int>(len)).toRawNSData();
- [d->remoteEnd sendMessage:payload];
- return len;
- } @catch (NSException *) {
- // connectionDidDie can be notified too late, also interpret any sending exception as a disconnection.
- d->disconnectRemote();
- emit disconnected();
- return -1;
- }
-}
-
-qint64 SocketApiSocket::bytesAvailable() const
-{
- Q_D(const SocketApiSocket);
- return d->inBuffer.size() + QIODevice::bytesAvailable();
-}
-
-bool SocketApiSocket::canReadLine() const
-{
- Q_D(const SocketApiSocket);
- return d->inBuffer.indexOf('\n', int(pos())) != -1 || QIODevice::canReadLine();
-}
-
-SocketApiSocketPrivate::SocketApiSocketPrivate(NSDistantObject<ChannelProtocol> *remoteEnd)
- : remoteEnd(remoteEnd)
- , localEnd([[LocalEnd alloc] initWithWrapper:this])
-{
- [remoteEnd retain];
- // (Ab)use our objective-c object just to catch the notification
- [[NSNotificationCenter defaultCenter] addObserver:localEnd
- selector:@selector(connectionDidDie:)
- name:NSConnectionDidDieNotification
- object:[remoteEnd connectionForProxy]];
-}
-
-SocketApiSocketPrivate::~SocketApiSocketPrivate()
-{
- disconnectRemote();
-
- // The DO vended localEnd might still be referenced by the connection
- localEnd.wrapper = nil;
- [localEnd release];
-}
-
-void SocketApiSocketPrivate::disconnectRemote()
-{
- if (isRemoteDisconnected)
- return;
- isRemoteDisconnected = true;
-
- [remoteEnd release];
-}
-
-SocketApiServer::SocketApiServer()
- : d_ptr(new SocketApiServerPrivate)
-{
- Q_D(SocketApiServer);
- d->q_ptr = this;
-}
-
-SocketApiServer::~SocketApiServer()
-{
-}
-
-void SocketApiServer::close()
-{
- // Assume we'll be destroyed right after
-}
-
-bool SocketApiServer::listen(const QString &name)
-{
- Q_D(SocketApiServer);
- // Set the name of the root object
- return [d->connection registerName:name.toNSString()];
-}
-
-SocketApiSocket *SocketApiServer::nextPendingConnection()
-{
- Q_D(SocketApiServer);
- return d->pendingConnections.takeFirst();
-}
-
-SocketApiServerPrivate::SocketApiServerPrivate()
-{
- // Create the connection and server object to vend over Disributed Objects
- connection = [[NSConnection alloc] init];
- server = [[Server alloc] initWithWrapper:this];
- [connection setRootObject:server];
-}
-
-SocketApiServerPrivate::~SocketApiServerPrivate()
-{
- [connection release];
- server.wrapper = nil;
- [server release];
-}