author | KuoE0 <kuoe0.tw@gmail.com> |
Thu, 28 Apr 2016 15:05:25 +0800 | |
changeset 295177 | 4f95de9b438f19200f3399814348ea6dda563bc1 |
parent 295176 | eaa9bd3a5d1b59b142dfaadab6ee3b43ffc11c7c |
child 295178 | c2da65057928abc7fb07c061c0581b743a7baec1 |
push id | 75837 |
push user | gachen@mozilla.com |
push date | Thu, 28 Apr 2016 07:07:10 +0000 |
treeherder | mozilla-inbound@c2da65057928 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | schien, smaug |
bugs | 1208417 |
milestone | 49.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -16,17 +16,16 @@ Cu.import("resource://gre/modules/AppsUt Cu.import('resource://gre/modules/UserAgentOverrides.jsm'); Cu.import('resource://gre/modules/Keyboard.jsm'); Cu.import('resource://gre/modules/ErrorPage.jsm'); Cu.import('resource://gre/modules/AlertsHelper.jsm'); Cu.import('resource://gre/modules/RequestSyncService.jsm'); Cu.import('resource://gre/modules/SystemUpdateService.jsm'); if (isGonk) { - Cu.import('resource://gre/modules/MultiscreenHandler.jsm'); Cu.import('resource://gre/modules/NetworkStatsService.jsm'); Cu.import('resource://gre/modules/ResourceStatsService.jsm'); } Cu.import('resource://gre/modules/KillSwitchMain.jsm'); // Identity Cu.import('resource://gre/modules/SignInToWebsite.jsm');
deleted file mode 100644 --- a/b2g/components/MultiscreenHandler.jsm +++ /dev/null @@ -1,92 +0,0 @@ -/* 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/. */ - -"use strict"; - -this.EXPORTED_SYMBOLS = ["MultiscreenHandler"]; - -const Ci = Components.interfaces; -const Cu = Components.utils; - -Cu.import("resource://gre/modules/Services.jsm"); - -function debug(aStr) { - // dump("MultiscreenHandler: " + aStr + "\n"); -} - -var window = Services.wm.getMostRecentWindow("navigator:browser"); - -// Multi-screen support on b2g. The following implementation will open a new -// top-level window once we receive a display connected event. -var MultiscreenHandler = { - - topLevelWindows: new Map(), - - init: function init() { - Services.obs.addObserver(this, "display-changed", false); - Services.obs.addObserver(this, "xpcom-shutdown", false); - }, - - uninit: function uninit() { - Services.obs.removeObserver(this, "display-changed"); - Services.obs.removeObserver(this, "xpcom-shutdown"); - }, - - observe: function observe(aSubject, aTopic, aData) { - switch (aTopic) { - case "display-changed": - this.handleDisplayChangeEvent(aSubject); - break - case "xpcom-shutdown": - this.uninit(); - break - } - }, - - openTopLevelWindow: function openTopLevelWindow(aDisplay) { - if (this.topLevelWindows.get(aDisplay.id)) { - debug("Top level window for display id: " + aDisplay.id + " has been opened."); - return; - } - - let flags = Services.prefs.getCharPref("toolkit.defaultChromeFeatures") + - ",mozDisplayId=" + aDisplay.id; - let remoteShellURL = Services.prefs.getCharPref("b2g.multiscreen.chrome_remote_url") + - "#" + aDisplay.id; - let win = Services.ww.openWindow(null, remoteShellURL, "myTopWindow" + aDisplay.id, flags, null); - - this.topLevelWindows.set(aDisplay.id, win); - }, - - closeTopLevelWindow: function closeTopLevelWindow(aDisplay) { - let win = this.topLevelWindows.get(aDisplay.id); - - if (win) { - win.close(); - this.topLevelWindows.delete(aDisplay.id); - } - }, - - handleDisplayChangeEvent: function handleDisplayChangeEvent(aSubject) { - - let display = aSubject.QueryInterface(Ci.nsIDisplayInfo); - let name = "multiscreen.enabled"; - let req = window.navigator.mozSettings.createLock().get(name); - - req.addEventListener("success", () => { - let isMultiscreenEnabled = req.result[name]; - if (display.connected) { - if (isMultiscreenEnabled) { - this.openTopLevelWindow(display); - } - } else { - this.closeTopLevelWindow(display); - } - }); - }, - -}; - -MultiscreenHandler.init(); -this.MultiscreenHandler = MultiscreenHandler;
--- a/b2g/components/moz.build +++ b/b2g/components/moz.build @@ -63,17 +63,16 @@ EXTRA_JS_MODULES += [ 'DebuggerActors.js', 'ErrorPage.jsm', 'Frames.jsm', 'FxAccountsMgmtService.jsm', 'KillSwitchMain.jsm', 'LogCapture.jsm', 'LogParser.jsm', 'LogShake.jsm', - 'MultiscreenHandler.jsm', 'OrientationChangeHandler.jsm', 'PersistentDataBlock.jsm', 'SafeMode.jsm', 'Screenshot.jsm', 'SignInToWebsite.jsm', 'SystemAppProxy.jsm', 'TelURIParser.jsm', 'WebappsUpdater.jsm',
--- a/dom/presentation/interfaces/nsIPresentationDevice.idl +++ b/dom/presentation/interfaces/nsIPresentationDevice.idl @@ -30,8 +30,10 @@ interface nsIPresentationDevice : nsISup * @throws NS_ERROR_FAILURE if the establishment fails */ nsIPresentationControlChannel establishControlChannel(in DOMString url, in DOMString presentationId); // Do something when presentation session is disconnected. void disconnect(); }; + +
new file mode 100644 --- /dev/null +++ b/dom/presentation/provider/DisplayDeviceProvider.cpp @@ -0,0 +1,318 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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 "DisplayDeviceProvider.h" +#include "mozilla/Logging.h" +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" +#include "mozilla/unused.h" +#include "nsIObserverService.h" +#include "nsIServiceManager.h" +#include "nsIWindowWatcher.h" +#include "nsNetUtil.h" +#include "nsPIDOMWindow.h" +#include "nsSimpleURI.h" +#include "nsThreadUtils.h" + +static mozilla::LazyLogModule gDisplayDeviceProviderLog("DisplayDeviceProvider"); + +#define LOG(format) MOZ_LOG(gDisplayDeviceProviderLog, mozilla::LogLevel::Debug, format) + +#define DISPLAY_CHANGED_NOTIFICATION "display-changed" +#define DEFAULT_CHROME_FEATURES_PREF "toolkit.defaultChromeFeatures" +#define CHROME_REMOTE_URL_PREF "b2g.multiscreen.chrome_remote_url" + +namespace mozilla { +namespace dom { +namespace presentation { + +NS_IMPL_ISUPPORTS(DisplayDeviceProvider::HDMIDisplayDevice, + nsIPresentationDevice, + nsIPresentationLocalDevice) + +// nsIPresentationDevice +NS_IMETHODIMP +DisplayDeviceProvider::HDMIDisplayDevice::GetId(nsACString& aId) +{ + aId = mWindowId; + return NS_OK; +} + +NS_IMETHODIMP +DisplayDeviceProvider::HDMIDisplayDevice::GetName(nsACString& aName) +{ + aName = mName; + return NS_OK; +} + +NS_IMETHODIMP +DisplayDeviceProvider::HDMIDisplayDevice::GetType(nsACString& aType) +{ + aType = mType; + return NS_OK; +} + +NS_IMETHODIMP +DisplayDeviceProvider::HDMIDisplayDevice::GetWindowId(nsACString& aWindowId) +{ + aWindowId = mWindowId; + return NS_OK; +} + +NS_IMETHODIMP +DisplayDeviceProvider::HDMIDisplayDevice + ::EstablishControlChannel(const nsAString& aUrl, + const nsAString& aPresentationId, + nsIPresentationControlChannel** aControlChannel) +{ + nsresult rv = OpenTopLevelWindow(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + RefPtr<DisplayDeviceProvider> provider = mProvider.get(); + if (NS_WARN_IF(!provider)) { + return NS_ERROR_FAILURE; + } + return provider->RequestSession(this, aUrl, aPresentationId, aControlChannel); +} + +NS_IMETHODIMP +DisplayDeviceProvider::HDMIDisplayDevice::Disconnect() +{ + nsresult rv = CloseTopLevelWindow(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK;; +} + +nsresult +DisplayDeviceProvider::HDMIDisplayDevice::OpenTopLevelWindow() +{ + MOZ_ASSERT(!mWindow); + + nsresult rv; + nsAutoCString flags(Preferences::GetCString(DEFAULT_CHROME_FEATURES_PREF)); + if (flags.IsEmpty()) { + return NS_ERROR_NOT_AVAILABLE; + } + flags.AppendLiteral(",mozDisplayId="); + flags.AppendInt(mScreenId); + + nsAutoCString remoteShellURLString(Preferences::GetCString(CHROME_REMOTE_URL_PREF)); + remoteShellURLString.AppendLiteral("#"); + remoteShellURLString.Append(mWindowId); + + // URI validation + nsCOMPtr<nsIURI> remoteShellURL; + rv = NS_NewURI(getter_AddRefs(remoteShellURL), remoteShellURLString); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = remoteShellURL->GetSpec(remoteShellURLString); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsCOMPtr<nsIWindowWatcher> ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID); + MOZ_ASSERT(ww); + + rv = ww->OpenWindow(nullptr, + remoteShellURLString.get(), + "_blank", + flags.get(), + nullptr, + getter_AddRefs(mWindow)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} + +nsresult +DisplayDeviceProvider::HDMIDisplayDevice::CloseTopLevelWindow() +{ + MOZ_ASSERT(mWindow); + + nsCOMPtr<nsPIDOMWindowOuter> piWindow = nsPIDOMWindowOuter::From(mWindow); + nsresult rv = piWindow->Close(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} + +NS_IMPL_ISUPPORTS(DisplayDeviceProvider, + nsIObserver, + nsIPresentationDeviceProvider) + +DisplayDeviceProvider::~DisplayDeviceProvider() +{ + Uninit(); +} + +nsresult +DisplayDeviceProvider::Init() +{ + // Provider must be initialized only once. + if (mInitialized) { + return NS_OK; + } + + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + MOZ_ASSERT(obs); + + obs->AddObserver(this, DISPLAY_CHANGED_NOTIFICATION, false); + + mDevice = new HDMIDisplayDevice(this); + + mInitialized = true; + return NS_OK; +} + +nsresult +DisplayDeviceProvider::Uninit() +{ + // Provider must be deleted only once. + if (!mInitialized) { + return NS_OK; + } + + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (obs) { + obs->RemoveObserver(this, DISPLAY_CHANGED_NOTIFICATION); + } + + // Remove device from device manager when the provider is uninit + RemoveExternalScreen(); + + mInitialized = false; + return NS_OK; +} + +nsresult +DisplayDeviceProvider::AddExternalScreen() +{ + MOZ_ASSERT(mDeviceListener); + + nsresult rv; + nsCOMPtr<nsIPresentationDeviceListener> listener; + rv = GetListener(getter_AddRefs(listener)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = listener->AddDevice(mDevice); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} + +nsresult +DisplayDeviceProvider::RemoveExternalScreen() +{ + MOZ_ASSERT(mDeviceListener); + + nsresult rv; + nsCOMPtr<nsIPresentationDeviceListener> listener; + rv = GetListener(getter_AddRefs(listener)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = listener->RemoveDevice(mDevice); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + mDevice->Disconnect(); + return NS_OK; +} + +// nsIPresentationDeviceProvider +NS_IMETHODIMP +DisplayDeviceProvider::GetListener(nsIPresentationDeviceListener** aListener) +{ + if (NS_WARN_IF(!aListener)) { + return NS_ERROR_INVALID_POINTER; + } + + nsresult rv; + nsCOMPtr<nsIPresentationDeviceListener> listener = + do_QueryReferent(mDeviceListener, &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + listener.forget(aListener); + + return NS_OK; +} + +NS_IMETHODIMP +DisplayDeviceProvider::SetListener(nsIPresentationDeviceListener* aListener) +{ + mDeviceListener = do_GetWeakReference(aListener); + nsresult rv = mDeviceListener ? Init() : Uninit(); + if(NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; +} + +NS_IMETHODIMP +DisplayDeviceProvider::ForceDiscovery() +{ + return NS_OK; +} + +// nsIObserver +NS_IMETHODIMP +DisplayDeviceProvider::Observe(nsISupports* aSubject, + const char* aTopic, + const char16_t* aData) +{ + if (!strcmp(aTopic, DISPLAY_CHANGED_NOTIFICATION)) { + nsCOMPtr<nsIDisplayInfo> displayInfo = do_QueryInterface(aSubject); + MOZ_ASSERT(displayInfo); + + int32_t type; + bool isConnected; + displayInfo->GetConnected(&isConnected); + // XXX The ID is as same as the type of display. + // See Bug 1138287 and nsScreenManagerGonk::AddScreen() for more detail. + displayInfo->GetId(&type); + + if (type == DisplayType::DISPLAY_EXTERNAL) { + nsresult rv = isConnected ? AddExternalScreen() : RemoveExternalScreen(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + } + } + + return NS_OK; +} + +nsresult +DisplayDeviceProvider::RequestSession(HDMIDisplayDevice* aDevice, + const nsAString& aUrl, + const nsAString& aPresentationId, + nsIPresentationControlChannel** aControlChannel) +{ + // Implement in part 3 + return NS_OK; +} + +} // namespace presentation +} // namespace dom +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/dom/presentation/provider/DisplayDeviceProvider.h @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_presentation_provider_DisplayDeviceProvider_h +#define mozilla_dom_presentation_provider_DisplayDeviceProvider_h + +#include "mozilla/RefPtr.h" +#include "mozilla/WeakPtr.h" +#include "nsCOMPtr.h" +#include "nsIDOMWindow.h" +#include "nsIDisplayInfo.h" +#include "nsIObserver.h" +#include "nsIPresentationDeviceProvider.h" +#include "nsIPresentationLocalDevice.h" +#include "nsIWindowWatcher.h" +#include "nsString.h" +#include "nsTArray.h" +#include "nsWeakReference.h" + +namespace mozilla { +namespace dom { +namespace presentation { + +// Consistent definition with the definition in +// widget/gonk/libdisplay/GonkDisplay.h. +enum DisplayType { + DISPLAY_PRIMARY, + DISPLAY_EXTERNAL, + DISPLAY_VIRTUAL, + NUM_DISPLAY_TYPES +}; + +class DisplayDeviceProvider final : public nsIObserver + , public nsIPresentationDeviceProvider + , public SupportsWeakPtr<DisplayDeviceProvider> +{ +private: + class HDMIDisplayDevice final : public nsIPresentationLocalDevice + { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPRESENTATIONDEVICE + NS_DECL_NSIPRESENTATIONLOCALDEVICE + + // mScreenId is as same as the definition of display type. + explicit HDMIDisplayDevice(DisplayDeviceProvider* aProvider) + : mScreenId(DisplayType::DISPLAY_EXTERNAL) + , mName("HDMI") + , mType("external") + , mWindowId("hdmi") + , mProvider(aProvider) + {} + + nsresult OpenTopLevelWindow(); + nsresult CloseTopLevelWindow(); + + const nsCString& Id() const { return mWindowId; } + + private: + virtual ~HDMIDisplayDevice() = default; + + // Due to the limitation of nsWinodw, mScreenId must be an integer. + // And mScreenId is also align to the display type defined in + // widget/gonk/libdisplay/GonkDisplay.h. + // HDMI display is DisplayType::DISPLAY_EXTERNAL. + uint32_t mScreenId; + nsCString mName; + nsCString mType; + nsCString mWindowId; + + nsCOMPtr<mozIDOMWindowProxy> mWindow; + // weak pointer + // Provider hold a strong pointer to the device. Use weak pointer to prevent + // the reference cycle. + WeakPtr<DisplayDeviceProvider> mProvider; + }; + +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + NS_DECL_NSIPRESENTATIONDEVICEPROVIDER + // For using WeakPtr when MOZ_REFCOUNTED_LEAK_CHECKING defined + MOZ_DECLARE_WEAKREFERENCE_TYPENAME(DisplayDeviceProvider) + + nsresult RequestSession(HDMIDisplayDevice* aDevice, + const nsAString& aUrl, + const nsAString& aPresentationId, + nsIPresentationControlChannel** aControlChannel); +private: + virtual ~DisplayDeviceProvider(); + + nsresult Init(); + nsresult Uninit(); + + nsresult AddExternalScreen(); + nsresult RemoveExternalScreen(); + + // Now support HDMI display only and there should be only one HDMI display. + nsCOMPtr<nsIPresentationLocalDevice> mDevice = nullptr; + // weak pointer + // PresentationDeviceManager (mDeviceListener) hold strong pointer to + // DisplayDeviceProvider. Use nsWeakPtr to avoid reference cycle. + nsWeakPtr mDeviceListener = nullptr; + bool mInitialized = false; +}; + +} // mozilla +} // dom +} // presentation + +#endif // mozilla_dom_presentation_provider_DisplayDeviceProvider_h +
--- a/dom/presentation/provider/MulticastDNSDeviceProvider.cpp +++ b/dom/presentation/provider/MulticastDNSDeviceProvider.cpp @@ -1050,14 +1050,15 @@ MulticastDNSDeviceProvider::Device::Esta } return mProvider->RequestSession(this, aUrl, aPresentationId, aRetVal); } NS_IMETHODIMP MulticastDNSDeviceProvider::Device::Disconnect() { + // No need to do anything when disconnect. return NS_OK; } } // namespace presentation } // namespace dom } // namespace mozilla
--- a/dom/presentation/provider/PresentationDeviceProviderModule.cpp +++ b/dom/presentation/provider/PresentationDeviceProviderModule.cpp @@ -1,41 +1,56 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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 "DisplayDeviceProvider.h" #include "MulticastDNSDeviceProvider.h" #include "mozilla/ModuleUtils.h" #define MULTICAST_DNS_PROVIDER_CID \ {0x814f947a, 0x52f7, 0x41c9, \ { 0x94, 0xa1, 0x36, 0x84, 0x79, 0x72, 0x84, 0xac }} +#define DISPLAY_DEVICE_PROVIDER_CID \ + { 0x515d9879, 0xfe0b, 0x4d9f, \ + { 0x89, 0x49, 0x7f, 0xa7, 0x65, 0x6c, 0x01, 0x0e } } + +#define DISPLAY_DEVICE_PROVIDER_CONTRACT_ID "@mozilla.org/presentation-device/displaydevice-provider;1" #define MULTICAST_DNS_PROVIDER_CONTRACT_ID "@mozilla.org/presentation-device/multicastdns-provider;1" using mozilla::dom::presentation::MulticastDNSDeviceProvider; +using mozilla::dom::presentation::DisplayDeviceProvider; NS_GENERIC_FACTORY_CONSTRUCTOR(MulticastDNSDeviceProvider) NS_DEFINE_NAMED_CID(MULTICAST_DNS_PROVIDER_CID); +NS_GENERIC_FACTORY_CONSTRUCTOR(DisplayDeviceProvider) +NS_DEFINE_NAMED_CID(DISPLAY_DEVICE_PROVIDER_CID); + static const mozilla::Module::CIDEntry kPresentationDeviceProviderCIDs[] = { { &kMULTICAST_DNS_PROVIDER_CID, false, nullptr, MulticastDNSDeviceProviderConstructor }, + { &kDISPLAY_DEVICE_PROVIDER_CID, false, nullptr, DisplayDeviceProviderConstructor }, { nullptr } }; static const mozilla::Module::ContractIDEntry kPresentationDeviceProviderContracts[] = { { MULTICAST_DNS_PROVIDER_CONTRACT_ID, &kMULTICAST_DNS_PROVIDER_CID }, + { DISPLAY_DEVICE_PROVIDER_CONTRACT_ID, &kDISPLAY_DEVICE_PROVIDER_CID }, { nullptr } }; static const mozilla::Module::CategoryEntry kPresentationDeviceProviderCategories[] = { #if defined(MOZ_WIDGET_COCOA) || defined(MOZ_WIDGET_ANDROID) || (defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 16) { PRESENTATION_DEVICE_PROVIDER_CATEGORY, "MulticastDNSDeviceProvider", MULTICAST_DNS_PROVIDER_CONTRACT_ID }, #endif +#if defined(MOZ_WIDGET_GONK) + { PRESENTATION_DEVICE_PROVIDER_CATEGORY, "DisplayDeviceProvider", DISPLAY_DEVICE_PROVIDER_CONTRACT_ID }, +#endif { nullptr } }; static const mozilla::Module kPresentationDeviceProviderModule = { mozilla::Module::kVersion, kPresentationDeviceProviderCIDs, kPresentationDeviceProviderContracts, kPresentationDeviceProviderCategories
--- a/dom/presentation/provider/moz.build +++ b/dom/presentation/provider/moz.build @@ -5,16 +5,17 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXTRA_COMPONENTS += [ 'BuiltinProviders.manifest', 'TCPPresentationServer.js' ] UNIFIED_SOURCES += [ + 'DisplayDeviceProvider.cpp', 'MulticastDNSDeviceProvider.cpp', 'PresentationDeviceProviderModule.cpp', ] include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' if CONFIG['GNU_CXX']: