mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1363169 - Add support for native windows share. r=gijs, r=aklotz
MozReview-Commit-ID: 7quON7Somvr
This commit is contained in:
parent
4590e9df52
commit
ce7a7296b3
@ -1203,6 +1203,12 @@ BrowserPageActions.addSearchEngine = {
|
||||
|
||||
// share URL
|
||||
BrowserPageActions.shareURL = {
|
||||
onCommand(event, buttonNode) {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let currentURI = gURLBar.makeURIReadable(browser.currentURI).displaySpec;
|
||||
this._windowsUIUtils.shareUrl(currentURI, browser.contentTitle);
|
||||
},
|
||||
|
||||
onShowingInPanel(buttonNode) {
|
||||
this._cached = false;
|
||||
},
|
||||
@ -1264,7 +1270,7 @@ BrowserPageActions.shareURL = {
|
||||
};
|
||||
|
||||
// Attach sharingService here so tests can override the implementation
|
||||
XPCOMUtils.defineLazyServiceGetter(BrowserPageActions.shareURL,
|
||||
"_sharingService",
|
||||
"@mozilla.org/widget/macsharingservice;1",
|
||||
"nsIMacSharingService");
|
||||
XPCOMUtils.defineLazyServiceGetters(BrowserPageActions.shareURL, {
|
||||
_sharingService: ["@mozilla.org/widget/macsharingservice;1", "nsIMacSharingService"],
|
||||
_windowsUIUtils: ["@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils"],
|
||||
});
|
||||
|
@ -57,6 +57,10 @@ support-files =
|
||||
subsuite = clipboard
|
||||
[browser_page_action_menu_share_mac.js]
|
||||
skip-if = os != "mac" # Mac only feature
|
||||
[browser_page_action_menu_share_win.js]
|
||||
support-files =
|
||||
browser_page_action_menu_share_win.html
|
||||
skip-if = os != "win" # Windows only feature
|
||||
[browser_pasteAndGo.js]
|
||||
subsuite = clipboard
|
||||
[browser_populateAfterPushState.js]
|
||||
|
@ -0,0 +1,2 @@
|
||||
<!doctype html>
|
||||
<title>Windows Sharing</title>
|
@ -0,0 +1,49 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* global sinon */
|
||||
Services.scriptloader.loadSubScript("resource://testing-common/sinon-2.3.2.js");
|
||||
|
||||
const TEST_URL = getRootDirectory(gTestPath) + "browser_page_action_menu_share_win.html";
|
||||
|
||||
// Keep track of site details we are sharing
|
||||
let sharedUrl, sharedTitle;
|
||||
|
||||
let stub = sinon.stub(BrowserPageActions.shareURL, "_windowsUIUtils").get(() => {
|
||||
return {
|
||||
shareUrl(url, title) {
|
||||
sharedUrl = url;
|
||||
sharedTitle = title;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
stub.restore();
|
||||
delete window.sinon;
|
||||
});
|
||||
|
||||
add_task(async function shareURL() {
|
||||
|
||||
if (!AppConstants.isPlatformAndVersionAtLeast("win", "6.4")) {
|
||||
Assert.ok(true, "We only expose share on windows 10 and above");
|
||||
return;
|
||||
}
|
||||
|
||||
await BrowserTestUtils.withNewTab(TEST_URL, async () => {
|
||||
// Open the panel.
|
||||
await promisePageActionPanelOpen();
|
||||
|
||||
// Click Share URL.
|
||||
let shareURLButton = document.getElementById("pageAction-panel-shareURL");
|
||||
let hiddenPromise = promisePageActionPanelHidden();
|
||||
EventUtils.synthesizeMouseAtCenter(shareURLButton, {});
|
||||
|
||||
await hiddenPromise;
|
||||
|
||||
Assert.equal(sharedUrl, TEST_URL, "Shared correct URL");
|
||||
Assert.equal(sharedTitle, "Windows Sharing", "Shared with the correct title");
|
||||
});
|
||||
});
|
@ -1185,6 +1185,21 @@ if (AppConstants.platform == "macosx") {
|
||||
});
|
||||
}
|
||||
|
||||
if (AppConstants.isPlatformAndVersionAtLeast("win", "6.4")) {
|
||||
gBuiltInActions.push(
|
||||
// Share URL
|
||||
{
|
||||
id: "shareURL",
|
||||
title: "shareURL-title",
|
||||
onBeforePlacedInWindow(buttonNode) {
|
||||
browserPageActions(buttonNode).shareURL.onBeforePlacedInWindow(buttonNode);
|
||||
},
|
||||
onCommand(event, buttonNode) {
|
||||
browserPageActions(buttonNode).shareURL.onCommand(event, buttonNode);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a BrowserPageActions object in a browser window.
|
||||
*
|
||||
|
@ -597,6 +597,10 @@ html|*.urlbar-input:-moz-lwtheme::placeholder,
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
#pageAction-panel-shareURL {
|
||||
list-style-image: url("chrome://browser/skin/share.svg");
|
||||
}
|
||||
|
||||
%include ../shared/urlbarSearchSuggestionsNotification.inc.css
|
||||
|
||||
#search-container {
|
||||
|
@ -41,6 +41,7 @@ browser.jar:
|
||||
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||
* skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||
skin/classic/browser/share.svg (share.svg)
|
||||
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
|
||||
skin/classic/browser/window-controls/close.svg (window-controls/close.svg)
|
||||
skin/classic/browser/window-controls/close-highcontrast.svg (window-controls/close-highcontrast.svg)
|
||||
|
7
browser/themes/windows/share.svg
Normal file
7
browser/themes/windows/share.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">
|
||||
<path fill="context-fill" d="M 15.707 4.293 l -4 -4 a 1 1 0 0 0 -1.414 1.414 L 12.585 4 H 11 a 7.008 7.008 0 0 0 -7 7 a 1 1 0 0 0 2 0 a 5.006 5.006 0 0 1 5 -5 h 1.585 l -2.293 2.293 a 1 1 0 1 0 1.414 1.414 l 4 -4 a 1 1 0 0 0 0.001 -1.414 Z" />
|
||||
<path fill="context-fill" d="M 13 11 a 1 1 0 0 0 -1 1 v 1 a 1 1 0 0 1 -1 1 H 3 a 1 1 0 0 1 -1 -1 V 6 a 1 1 0 0 1 1 -1 h 1 a 1 1 0 0 0 0 -2 H 3 a 3 3 0 0 0 -3 3 v 7 a 3 3 0 0 0 3 3 h 8 a 3 3 0 0 0 3 -3 v -1 a 1 1 0 0 0 -1 -1 Z" />
|
||||
</svg>
|
After Width: | Height: | Size: 781 B |
@ -20,5 +20,9 @@ interface nsIWindowsUIUtils : nsISupports
|
||||
* Update the tablet mode state
|
||||
*/
|
||||
void updateTabletModeState();
|
||||
};
|
||||
|
||||
/**
|
||||
* Share URL
|
||||
*/
|
||||
void shareUrl(in AString shareTitle, in AString urlToShare);
|
||||
};
|
||||
|
@ -35,6 +35,7 @@ using namespace ABI::Windows::UI::ViewManagement;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::ApplicationModel::DataTransfer;
|
||||
|
||||
/* All of this is win10 stuff and we're compiling against win81 headers
|
||||
* for now, so we may need to do some legwork: */
|
||||
@ -90,6 +91,21 @@ public:
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef __IDataTransferManagerInterop_INTERFACE_DEFINED__
|
||||
#define __IDataTransferManagerInterop_INTERFACE_DEFINED__
|
||||
|
||||
typedef interface IDataTransferManagerInterop IDataTransferManagerInterop;
|
||||
|
||||
MIDL_INTERFACE("3A3DCD6C-3EAB-43DC-BCDE-45671CE800C8")
|
||||
IDataTransferManagerInterop : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE GetForWindow(HWND appWindow, REFIID riid, void **dataTransferManager) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE ShowShareUIForWindow(HWND appWindow) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
WindowsUIUtils::WindowsUIUtils() :
|
||||
@ -178,3 +194,124 @@ WindowsUIUtils::UpdateTabletModeState()
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct HStringDeleter
|
||||
{
|
||||
typedef HSTRING pointer;
|
||||
void operator()(pointer aString)
|
||||
{
|
||||
WindowsDeleteString(aString);
|
||||
}
|
||||
};
|
||||
|
||||
typedef mozilla::UniquePtr<HSTRING, HStringDeleter> HStringUniquePtr;
|
||||
|
||||
NS_IMETHODIMP
|
||||
WindowsUIUtils::ShareUrl(const nsAString& aUrlToShare,
|
||||
const nsAString& aShareTitle)
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
if (!IsWin10OrLater()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
HSTRING rawTitle;
|
||||
HRESULT hr = WindowsCreateString(PromiseFlatString(aShareTitle).get(), aShareTitle.Length(), &rawTitle);
|
||||
if (FAILED(hr)) {
|
||||
return NS_OK;
|
||||
}
|
||||
HStringUniquePtr title(rawTitle);
|
||||
|
||||
HSTRING rawUrl;
|
||||
hr = WindowsCreateString(PromiseFlatString(aUrlToShare).get(), aUrlToShare.Length(), &rawUrl);
|
||||
if (FAILED(hr)) {
|
||||
return NS_OK;
|
||||
}
|
||||
HStringUniquePtr url(rawUrl);
|
||||
|
||||
ComPtr<IUriRuntimeClassFactory> uriFactory;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Uri).Get(), &uriFactory);
|
||||
if (FAILED(hr)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ComPtr<IUriRuntimeClass> uri;
|
||||
hr = uriFactory->CreateUri(url.get(), &uri);
|
||||
if (FAILED(hr)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
HWND hwnd = GetForegroundWindow();
|
||||
if (!hwnd) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ComPtr<IDataTransferManagerInterop> dtmInterop;
|
||||
hr = RoGetActivationFactory(HStringReference(
|
||||
RuntimeClass_Windows_ApplicationModel_DataTransfer_DataTransferManager)
|
||||
.Get(), IID_PPV_ARGS(&dtmInterop));
|
||||
if (FAILED(hr)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ComPtr<IDataTransferManager> dtm;
|
||||
hr = dtmInterop->GetForWindow(hwnd, IID_PPV_ARGS(&dtm));
|
||||
if (FAILED(hr)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
auto callback = Callback < ITypedEventHandler<DataTransferManager*, DataRequestedEventArgs* >> (
|
||||
[uri = std::move(uri), title = std::move(title)](IDataTransferManager*, IDataRequestedEventArgs* pArgs) -> HRESULT
|
||||
{
|
||||
ComPtr<IDataRequest> spDataRequest;
|
||||
HRESULT hr = pArgs->get_Request(&spDataRequest);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
ComPtr<IDataPackage> spDataPackage;
|
||||
hr = spDataRequest->get_Data(&spDataPackage);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
ComPtr<IDataPackage2> spDataPackage2;
|
||||
hr = spDataPackage->QueryInterface(IID_PPV_ARGS(&spDataPackage2));
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
ComPtr<IDataPackagePropertySet> spDataPackageProperties;
|
||||
hr = spDataPackage->get_Properties(&spDataPackageProperties);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = spDataPackageProperties->put_Title(title.get());
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = spDataPackage2->SetWebLink(uri.Get());
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
});
|
||||
|
||||
EventRegistrationToken dataRequestedToken;
|
||||
hr = dtm->add_DataRequested(callback.Get(), &dataRequestedToken);
|
||||
if (FAILED(hr)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
hr = dtmInterop->ShowShareUIForWindow(hwnd);
|
||||
if (FAILED(hr)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user