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

github.com/nextcloud/desktop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJocelyn Turcotte <jturcotte@woboq.com>2017-07-04 17:58:55 +0300
committerChristian Kamm <mail@ckamm.de>2017-07-07 11:49:51 +0300
commit7a4daf799aa8f256f2f5c9fd492993fc51de93fe (patch)
treeba534fa58be121398c1609b599f62c27915e2ce6 /shell_integration
parent389499d639d0cda1afb93a7e62463d487631f054 (diff)
shell/windows: Use a submenu to include private link actions
Refactor things a bit to be able to reuse some code and clean things up.
Diffstat (limited to 'shell_integration')
-rw-r--r--shell_integration/windows/OCContextMenu/OCClientInterface.cpp39
-rw-r--r--shell_integration/windows/OCContextMenu/OCClientInterface.h11
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenu.cpp159
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenu.h6
-rw-r--r--shell_integration/windows/OCUtil/RemotePathChecker.cpp11
-rw-r--r--shell_integration/windows/OCUtil/StringUtil.h17
6 files changed, 168 insertions, 75 deletions
diff --git a/shell_integration/windows/OCContextMenu/OCClientInterface.cpp b/shell_integration/windows/OCContextMenu/OCClientInterface.cpp
index 05b23ec09..56facf600 100644
--- a/shell_integration/windows/OCContextMenu/OCClientInterface.cpp
+++ b/shell_integration/windows/OCContextMenu/OCClientInterface.cpp
@@ -45,7 +45,7 @@ OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
if (!socket.Connect(pipename)) {
return {};
}
- socket.SendMsg(L"SHARE_MENU_TITLE\n");
+ socket.SendMsg(L"GET_STRINGS\n");
ContextMenuInfo info;
std::wstring response;
@@ -56,9 +56,21 @@ OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
wstring responsePath = response.substr(14); // length of REGISTER_PATH
info.watchedDirectories.push_back(responsePath);
}
- else if (StringUtil::begins_with(response, wstring(L"SHARE_MENU_TITLE:"))) {
- info.shareMenuTitle = response.substr(17); // length of SHARE_MENU_TITLE:
- break; // Stop once we received the last sent request
+ else if (StringUtil::begins_with(response, wstring(L"STRING:"))) {
+ wstring stringName, stringValue;
+ if (!StringUtil::extractChunks(response, stringName, stringValue))
+ continue;
+ if (stringName == L"SHARE_MENU_TITLE")
+ info.shareMenuTitle = move(stringValue);
+ else if (stringName == L"CONTEXT_MENU_TITLE")
+ info.contextMenuTitle = move(stringValue);
+ else if (stringName == L"COPY_PRIVATE_LINK_TITLE")
+ info.copyLinkMenuTitle = move(stringValue);
+ else if (stringName == L"EMAIL_PRIVATE_LINK_TITLE")
+ info.emailLinkMenuTitle = move(stringValue);
+ }
+ else if (StringUtil::begins_with(response, wstring(L"GET_STRINGS:END"))) {
+ break; // Stop once we completely received the last sent request
}
}
else {
@@ -69,7 +81,22 @@ OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
return info;
}
-void OCClientInterface::ShareObject(const std::wstring &path)
+void OCClientInterface::RequestShare(const std::wstring &path)
+{
+ SendRequest(L"SHARE", path);
+}
+
+void OCClientInterface::RequestCopyLink(const std::wstring &path)
+{
+ SendRequest(L"COPY_PRIVATE_LINK", path);
+}
+
+void OCClientInterface::RequestEmailLink(const std::wstring &path)
+{
+ SendRequest(L"EMAIL_PRIVATE_LINK", path);
+}
+
+void OCClientInterface::SendRequest(wchar_t *verb, const std::wstring &path)
{
auto pipename = CommunicationSocket::DefaultPipePath();
@@ -82,7 +109,7 @@ void OCClientInterface::ShareObject(const std::wstring &path)
}
wchar_t msg[SOCK_BUFFER] = { 0 };
- if (SUCCEEDED(StringCchPrintf(msg, SOCK_BUFFER, L"SHARE:%s\n", path.c_str())))
+ if (SUCCEEDED(StringCchPrintf(msg, SOCK_BUFFER, L"%s:%s\n", verb, path.c_str())))
{
socket.SendMsg(msg);
}
diff --git a/shell_integration/windows/OCContextMenu/OCClientInterface.h b/shell_integration/windows/OCContextMenu/OCClientInterface.h
index 00d4470ea..74e6364fe 100644
--- a/shell_integration/windows/OCContextMenu/OCClientInterface.h
+++ b/shell_integration/windows/OCContextMenu/OCClientInterface.h
@@ -45,10 +45,19 @@ class OCClientInterface
public:
struct ContextMenuInfo {
std::vector<std::wstring> watchedDirectories;
+ std::wstring contextMenuTitle;
std::wstring shareMenuTitle;
+ std::wstring copyLinkMenuTitle;
+ std::wstring emailLinkMenuTitle;
};
static ContextMenuInfo FetchInfo();
- static void ShareObject(const std::wstring &path);
+
+ static void RequestShare(const std::wstring &path);
+ static void RequestCopyLink(const std::wstring &path);
+ static void RequestEmailLink(const std::wstring &path);
+
+private:
+ static void SendRequest(wchar_t *verb, const std::wstring &path);
};
#endif //ABSTRACTSOCKETHANDLER_H
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenu.cpp b/shell_integration/windows/OCContextMenu/OCContextMenu.cpp
index a5558fc0a..bda86b86d 100644
--- a/shell_integration/windows/OCContextMenu/OCContextMenu.cpp
+++ b/shell_integration/windows/OCContextMenu/OCContextMenu.cpp
@@ -25,19 +25,12 @@
extern HINSTANCE g_hInst;
extern long g_cDllRef;
-#define IDM_SHARE 0
-
-
+#define IDM_SHARE 0
+#define IDM_COPYLINK 1
+#define IDM_EMAILLINK 2
OCContextMenu::OCContextMenu(void)
: m_cRef(1)
- , m_pszMenuText(L"&Share")
- , m_pszVerb("ocshare")
- , m_pwszVerb(L"ocshare")
- , m_pszVerbCanonicalName("OCShareViaOC")
- , m_pwszVerbCanonicalName(L"OCShareViaOC")
- , m_pszVerbHelpText("Share via ownCloud")
- , m_pwszVerbHelpText(L"Share via ownCloud")
{
InterlockedIncrement(&g_cDllRef);
}
@@ -48,9 +41,19 @@ OCContextMenu::~OCContextMenu(void)
}
-void OCContextMenu::OnVerbDisplayFileName(HWND hWnd)
+void OCContextMenu::OnVerbShare(HWND hWnd)
+{
+ OCClientInterface::RequestShare(std::wstring(m_szSelectedFile));
+}
+
+void OCContextMenu::OnVerbCopyLink(HWND hWnd)
+{
+ OCClientInterface::RequestCopyLink(std::wstring(m_szSelectedFile));
+}
+
+void OCContextMenu::OnVerbEmailLink(HWND hWnd)
{
- OCClientInterface::ShareObject(std::wstring(m_szSelectedFile));
+ OCClientInterface::RequestEmailLink(std::wstring(m_szSelectedFile));
}
@@ -164,29 +167,61 @@ IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
}
- InsertSeperator(hMenu, indexMenu);
- indexMenu++;
-
- assert(!info.shareMenuTitle.empty());
- MENUITEMINFO mii = { sizeof(mii) };
- mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE;
- mii.wID = idCmdFirst + IDM_SHARE;
- mii.fType = MFT_STRING;
- mii.dwTypeData = &info.shareMenuTitle[0];
- mii.fState = MFS_ENABLED;
- if (!InsertMenuItem(hMenu, indexMenu, TRUE, &mii))
+ InsertSeperator(hMenu, indexMenu++);
+
+ HMENU hSubmenu = CreateMenu();
{
- return HRESULT_FROM_WIN32(GetLastError());
+ MENUITEMINFO mii = { sizeof(mii) };
+ mii.fMask = MIIM_SUBMENU | MIIM_FTYPE | MIIM_STRING;
+ mii.hSubMenu = hSubmenu;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = &info.contextMenuTitle[0];
+
+ if (!InsertMenuItem(hMenu, indexMenu++, TRUE, &mii))
+ return HRESULT_FROM_WIN32(GetLastError());
}
+ InsertSeperator(hMenu, indexMenu++);
- indexMenu++;
- InsertSeperator(hMenu, indexMenu);
+ UINT indexSubMenu = 0;
+ {
+ assert(!info.shareMenuTitle.empty());
+ MENUITEMINFO mii = { sizeof(mii) };
+ mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING;
+ mii.wID = idCmdFirst + IDM_SHARE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = &info.shareMenuTitle[0];
+
+ if (!InsertMenuItem(hSubmenu, indexSubMenu++, TRUE, &mii))
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+ {
+ assert(!info.copyLinkMenuTitle.empty());
+ MENUITEMINFO mii = { sizeof(mii) };
+ mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING;
+ mii.wID = idCmdFirst + IDM_COPYLINK;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = &info.copyLinkMenuTitle[0];
+
+ if (!InsertMenuItem(hSubmenu, indexSubMenu++, TRUE, &mii))
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+ {
+ assert(!info.emailLinkMenuTitle.empty());
+ MENUITEMINFO mii = { sizeof(mii) };
+ mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING;
+ mii.wID = idCmdFirst + IDM_EMAILLINK;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = &info.emailLinkMenuTitle[0];
+
+ if (!InsertMenuItem(hSubmenu, indexSubMenu++, TRUE, &mii))
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
// Return an HRESULT value with the severity set to SEVERITY_SUCCESS.
// Set the code value to the offset of the largest command identifier
// that was assigned, plus one (1).
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_SHARE + 1));
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_EMAILLINK + 1));
}
IFACEMETHODIMP OCContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
@@ -197,12 +232,16 @@ IFACEMETHODIMP OCContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
if (HIWORD(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW))
{
// Is the verb supported by this context menu extension?
- if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, m_pwszVerb) == 0)
- {
- OnVerbDisplayFileName(pici->hwnd);
+ if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, L"ocshare") == 0) {
+ OnVerbShare(pici->hwnd);
}
- else
- {
+ else if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, L"occopylink") == 0) {
+ OnVerbCopyLink(pici->hwnd);
+ }
+ else if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, L"ocemaillink") == 0) {
+ OnVerbEmailLink(pici->hwnd);
+ }
+ else {
// If the verb is not recognized by the context menu handler, it
// must return E_FAIL to allow it to be passed on to the other
// context menu handlers that might implement that verb.
@@ -216,12 +255,16 @@ IFACEMETHODIMP OCContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
// Is the command identifier offset supported by this context menu
// extension?
- if (LOWORD(pici->lpVerb) == IDM_SHARE)
- {
- OnVerbDisplayFileName(pici->hwnd);
+ if (LOWORD(pici->lpVerb) == IDM_SHARE) {
+ OnVerbShare(pici->hwnd);
+ }
+ else if (LOWORD(pici->lpVerb) == IDM_COPYLINK) {
+ OnVerbCopyLink(pici->hwnd);
+ }
+ else if (LOWORD(pici->lpVerb) == IDM_EMAILLINK) {
+ OnVerbEmailLink(pici->hwnd);
}
- else
- {
+ else {
// If the verb is not recognized by the context menu handler, it
// must return E_FAIL to allow it to be passed on to the other
// context menu handlers that might implement that verb.
@@ -237,31 +280,33 @@ IFACEMETHODIMP OCContextMenu::GetCommandString(UINT_PTR idCommand,
{
HRESULT hr = E_INVALIDARG;
- if (idCommand == IDM_SHARE)
- {
- switch (uFlags)
- {
- case GCS_HELPTEXTW:
- // Only useful for pre-Vista versions of Windows that have a
- // Status bar.
- hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
- m_pwszVerbHelpText);
- break;
-
- case GCS_VERBW:
- // GCS_VERBW is an optional feature that enables a caller to
- // discover the canonical name for the verb passed in through
+ switch (idCommand) {
+ case IDM_SHARE:
+ if (uFlags == GCS_VERBW) {
+ // GCS_VERBW is an optional feature that enables a caller to
+ // discover the canonical name for the verb passed in through
// idCommand.
hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
- m_pwszVerbCanonicalName);
- break;
-
- default:
- hr = S_OK;
+ L"OCShareViaOC");
+ }
+ break;
+ case IDM_COPYLINK:
+ if (uFlags == GCS_VERBW) {
+ hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
+ L"OCCopyLink");
+ }
+ break;
+ case IDM_EMAILLINK:
+ if (uFlags == GCS_VERBW) {
+ hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
+ L"OCEmailLink");
}
+ break;
+ default:
+ break;
}
- // If the command (idCommand) is not supported by this context menu
+ // If the idCommand or uFlags is not supported by this context menu
// extension handler, return E_INVALIDARG.
return hr;
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenu.h b/shell_integration/windows/OCContextMenu/OCContextMenu.h
index 49834fce0..7fe3e2ade 100644
--- a/shell_integration/windows/OCContextMenu/OCContextMenu.h
+++ b/shell_integration/windows/OCContextMenu/OCContextMenu.h
@@ -46,8 +46,10 @@ private:
// The name of the selected file.
wchar_t m_szSelectedFile[MAX_PATH];
- // The method that handles the "display" verb.
- void OnVerbDisplayFileName(HWND hWnd);
+ // The method that handles the "ocshare" verb.
+ void OnVerbShare(HWND hWnd);
+ void OnVerbCopyLink(HWND hWnd);
+ void OnVerbEmailLink(HWND hWnd);
PWSTR m_pszMenuText;
PCSTR m_pszVerb;
diff --git a/shell_integration/windows/OCUtil/RemotePathChecker.cpp b/shell_integration/windows/OCUtil/RemotePathChecker.cpp
index 4a13c1cd5..37caee182 100644
--- a/shell_integration/windows/OCUtil/RemotePathChecker.cpp
+++ b/shell_integration/windows/OCUtil/RemotePathChecker.cpp
@@ -111,17 +111,10 @@ void RemotePathChecker::workerThreadLoop()
} else if (StringUtil::begins_with(response, wstring(L"STATUS:")) ||
StringUtil::begins_with(response, wstring(L"BROADCAST:"))) {
- auto statusBegin = response.find(L':', 0);
- assert(statusBegin != std::wstring::npos);
-
- auto statusEnd = response.find(L':', statusBegin + 1);
- if (statusEnd == std::wstring::npos) {
- // the command do not contains two colon?
+ wstring responseStatus, responsePath;
+ if (!StringUtil::extractChunks(response, responseStatus, responsePath))
continue;
- }
- auto responseStatus = response.substr(statusBegin+1, statusEnd - statusBegin-1);
- auto responsePath = response.substr(statusEnd+1);
auto state = _StrToFileState(responseStatus);
bool wasAsked = asked.erase(responsePath) > 0;
diff --git a/shell_integration/windows/OCUtil/StringUtil.h b/shell_integration/windows/OCUtil/StringUtil.h
index 0f52d51dd..8ec325aa9 100644
--- a/shell_integration/windows/OCUtil/StringUtil.h
+++ b/shell_integration/windows/OCUtil/StringUtil.h
@@ -17,6 +17,7 @@
#pragma once
#include <string>
+#include <cassert>
class __declspec(dllexport) StringUtil {
public:
@@ -44,6 +45,22 @@ public:
return (childLength == parentLength || childLength > parentLength && (child[parentLength] == L'\\' || child[parentLength - 1] == L'\\'))
&& wcsncmp(child, parent, parentLength) == 0;
}
+
+ static bool extractChunks(const std::wstring &source, std::wstring &secondChunk, std::wstring &thirdChunk) {
+ auto statusBegin = source.find(L':', 0);
+ assert(statusBegin != std::wstring::npos);
+
+ auto statusEnd = source.find(L':', statusBegin + 1);
+ if (statusEnd == std::wstring::npos) {
+ // the command do not contains two colon?
+ return false;
+ }
+
+ // Assume the caller extracted the chunk before the first colon.
+ secondChunk = source.substr(statusBegin + 1, statusEnd - statusBegin - 1);
+ thirdChunk = source.substr(statusEnd + 1);
+ return true;
+ }
};
#endif // STRINGUTIL_H