1/*
2This file is part of Telegram Desktop,
3the official desktop application for the Telegram messaging service.
4
5For license and copyright information please follow this link:
6https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7*/
8#include "platform/mac/file_bookmark_mac.h"
9
10#include "base/platform/mac/base_utilities_mac.h"
11#include "logs.h"
12
13#include <Cocoa/Cocoa.h>
14#include <CoreFoundation/CFURL.h>
15
16namespace Platform {
17namespace {
18
19#ifdef OS_MAC_STORE
20QMutex BookmarksMutex;
21#endif // OS_MAC_STORE
22
23} // namespace
24
25#ifdef OS_MAC_STORE
26struct FileBookmark::Data {
27	~Data() {
28		if (url) [url release];
29	}
30	NSURL *url = nil;
31	QString name;
32	QByteArray bookmark;
33	int counter = 0;
34};
35#endif // OS_MAC_STORE
36
37FileBookmark::FileBookmark(const QByteArray &bookmark) {
38#ifdef OS_MAC_STORE
39	if (bookmark.isEmpty()) return;
40
41	BOOL isStale = NO;
42	NSError *error = nil;
43	NSURL *url = [NSURL URLByResolvingBookmarkData:bookmark.toNSData() options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&error];
44	if (!url) return;
45
46	if ([url startAccessingSecurityScopedResource]) {
47		data = new Data();
48		data->url = [url retain];
49		data->name = NS2QString([url path]);
50		data->bookmark = bookmark;
51		[url stopAccessingSecurityScopedResource];
52	}
53#endif // OS_MAC_STORE
54}
55
56bool FileBookmark::check() const {
57	if (enable()) {
58		disable();
59		return true;
60	}
61	return false;
62}
63
64bool FileBookmark::enable() const {
65#ifndef OS_MAC_STORE
66	return true;
67#else // OS_MAC_STORE
68	if (!data) return false;
69
70	QMutexLocker lock(&BookmarksMutex);
71	if (data->counter > 0 || [data->url startAccessingSecurityScopedResource] == YES) {
72		++data->counter;
73		return true;
74	}
75	return false;
76#endif // OS_MAC_STORE
77}
78
79void FileBookmark::disable() const {
80#ifdef OS_MAC_STORE
81	if (!data) return;
82
83	QMutexLocker lock(&BookmarksMutex);
84	if (data->counter > 0) {
85		--data->counter;
86		if (!data->counter) {
87			[data->url stopAccessingSecurityScopedResource];
88		}
89	}
90#endif // OS_MAC_STORE
91}
92
93const QString &FileBookmark::name(const QString &original) const {
94#ifndef OS_MAC_STORE
95	return original;
96#else // OS_MAC_STORE
97	return (data && !data->name.isEmpty()) ? data->name : original;
98#endif // OS_MAC_STORE
99}
100
101QByteArray FileBookmark::bookmark() const {
102#ifndef OS_MAC_STORE
103	return QByteArray();
104#else // OS_MAC_STORE
105	return data ? data->bookmark : QByteArray();
106#endif // OS_MAC_STORE
107}
108
109FileBookmark::~FileBookmark() {
110#ifdef OS_MAC_STORE
111	if (data && data->counter > 0) {
112		LOG(("Did not disable() bookmark, counter: %1").arg(data->counter));
113		[data->url stopAccessingSecurityScopedResource];
114	}
115#endif // OS_MAC_STORE
116}
117
118QByteArray PathBookmark(const QString &path) {
119#ifndef OS_MAC_STORE
120	return QByteArray();
121#else // OS_MAC_STORE
122	NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:path.toUtf8().constData()]];
123	if (!url) return QByteArray();
124
125	NSError *error = nil;
126	NSData *data = [url bookmarkDataWithOptions:(NSURLBookmarkCreationWithSecurityScope | NSURLBookmarkCreationSecurityScopeAllowOnlyReadAccess) includingResourceValuesForKeys:nil relativeToURL:nil error:&error];
127	return data ? QByteArray::fromNSData(data) : QByteArray();
128#endif // OS_MAC_STORE
129}
130
131} // namespace Platform
132