This commit is contained in:
Wes Kocher 2014-10-12 21:28:12 -07:00
Родитель 11e9c2c186 2809edb97f
Коммит f85451e616
123 изменённых файлов: 1561 добавлений и 3413 удалений

Просмотреть файл

@ -61,6 +61,7 @@ this.EventManager.prototype = {
this.addEventListener('wheel', this, true);
this.addEventListener('scroll', this, true);
this.addEventListener('resize', this, true);
this._preDialogPosition = new WeakMap();
}
this.present(Presentation.tabStateChanged(null, 'newtab'));
@ -78,6 +79,7 @@ this.EventManager.prototype = {
Logger.debug('EventManager.stop');
AccessibilityEventObserver.removeListener(this);
try {
this._preDialogPosition.clear();
this.webProgress.removeProgressListener(this);
this.removeEventListener('wheel', this, true);
this.removeEventListener('scroll', this, true);
@ -272,8 +274,8 @@ this.EventManager.prototype = {
// positioned inside it.
break;
}
this.contentControl.autoMove(
aEvent.accessible, { delay: 500 });
this._preDialogPosition.set(aEvent.accessible.DOMNode, position);
this.contentControl.autoMove(aEvent.accessible, { delay: 500 });
break;
}
case Events.VALUE_CHANGE:
@ -366,7 +368,8 @@ this.EventManager.prototype = {
if (vc.position &&
(Utils.getState(vc.position).contains(States.DEFUNCT) ||
Utils.isInSubtree(vc.position, acc))) {
let position = aEvent.targetPrevSibling || aEvent.targetParent;
let position = this._preDialogPosition.get(aEvent.accessible.DOMNode) ||
aEvent.targetPrevSibling || aEvent.targetParent;
if (!position) {
try {
position = acc.previousSibling;

Просмотреть файл

@ -75,13 +75,13 @@
<div>Phone status bar</div>
<div id="windows">
<button id="back">Back</button>
<div id="appframe"></div>
<div role="dialog" id="alert" hidden>
<h1>This is an alert!</h1>
<p>Do you agree?</p>
<button onclick="hideAlert()">Yes</button>
<button onclick="setTimeout(hideAlert, 500)">Yes</button>
<button onclick="hideAlert()">No</button>
</div>
<div id="appframe"></div>
</div>
<button id="home">Home</button>
</body>

Просмотреть файл

@ -179,16 +179,15 @@
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
// Open dialog in outer doc, while cursor is also in outer doc
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
[ContentMessages.simpleMoveLast,
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
[doc.defaultView.showAlert,
new ExpectedCursorChange(['This is an alert!',
{'string': 'headingLevel', 'args': [1]},
{'string': 'dialog'}])],
[doc.defaultView.hideAlert,
new ExpectedCursorChange(["wow",
{"string": "headingLevel", "args": [1]}, "such app"])],
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
@ -204,8 +203,12 @@
{'string': 'headingLevel', 'args': [1]},
{'string': 'dialog'}])],
// XXX: Place cursor back where it was.
[doc.defaultView.hideAlert,
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['Do you agree?'])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['Yes', {'string': 'pushbutton'}])],
[ContentMessages.activateCurrent(),
new ExpectedClickAction(),
new ExpectedCursorChange(
['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],

Просмотреть файл

@ -59,3 +59,9 @@
<label id="pointerLock-cancel" value="&pointerLock.notification.message;"/>
</popupnotificationcontent>
</popupnotification>
#ifdef E10S_TESTING_ONLY
<popupnotification id="enable-e10s-notification" hidden="true">
<popupnotificationcontent orient="vertical"/>
</popupnotification>
#endif

Просмотреть файл

@ -107,6 +107,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "SignInToWebsiteUX",
XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
"resource:///modules/ContentSearch.jsm");
#ifdef E10S_TESTING_ONLY
XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
"resource://gre/modules/UpdateChannel.jsm");
#endif
XPCOMUtils.defineLazyGetter(this, "ShellService", function() {
try {
return Cc["@mozilla.org/browser/shell-service;1"].
@ -2261,12 +2266,15 @@ let DefaultBrowserCheck = {
let E10SUINotification = {
// Increase this number each time we want to roll out an
// e10s testing period to Nightly users.
CURRENT_NOTICE_COUNT: 0,
CURRENT_NOTICE_COUNT: 1,
CURRENT_PROMPT_PREF: "browser.displayedE10SPrompt.1",
PREVIOUS_PROMPT_PREF: "browser.displayedE10SPrompt",
checkStatus: function() {
let skipE10sChecks = false;
try {
skipE10sChecks = Services.prefs.getBoolPref("browser.tabs.remote.autostart.disabled-because-using-a11y");
skipE10sChecks = (UpdateChannel.get() != "nightly") ||
Services.prefs.getBoolPref("browser.tabs.remote.autostart.disabled-because-using-a11y");
} catch(e) {}
if (skipE10sChecks) {
@ -2312,17 +2320,26 @@ let E10SUINotification = {
let e10sPromptShownCount = 0;
try {
e10sPromptShownCount = Services.prefs.getIntPref("browser.displayedE10SPrompt");
e10sPromptShownCount = Services.prefs.getIntPref(this.CURRENT_PROMPT_PREF);
} catch(e) {}
let isHardwareAccelerated = true;
try {
let win = RecentWindow.getMostRecentBrowserWindow();
let winutils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
isHardwareAccelerated = winutils.layerManagerType != "Basic";
} catch (e) {}
if (!Services.appinfo.inSafeMode &&
!Services.appinfo.accessibilityEnabled &&
!Services.appinfo.keyboardMayHaveIME &&
isHardwareAccelerated &&
e10sPromptShownCount < 5) {
Services.tm.mainThread.dispatch(() => {
try {
this._showE10SPrompt();
Services.prefs.setIntPref("browser.displayedE10SPrompt", e10sPromptShownCount + 1);
Services.prefs.setIntPref(this.CURRENT_PROMPT_PREF, e10sPromptShownCount + 1);
Services.prefs.clearUserPref(this.PREVIOUS_PROMPT_PREF);
} catch (ex) {
Cu.reportError("Failed to show e10s prompt: " + ex);
}
@ -2369,7 +2386,7 @@ let E10SUINotification = {
let browser = win.gBrowser.selectedBrowser;
let promptMessage = "Would you like to help us test multiprocess Nightly (e10s)? You can also enable e10s in Nightly preferences.";
let promptMessage = "Would you like to help us test multiprocess Nightly (e10s)? You can also enable e10s in Nightly preferences. Notable fixes:";
let mainAction = {
label: "Enable and Restart",
accessKey: "E",
@ -2389,7 +2406,7 @@ let E10SUINotification = {
label: "No thanks",
accessKey: "N",
callback: function () {
Services.prefs.setIntPref("browser.displayedE10SPrompt", 5);
Services.prefs.setIntPref(E10SUINotification.CURRENT_PROMPT_PREF, 5);
}
}
];
@ -2399,7 +2416,21 @@ let E10SUINotification = {
persistWhileVisible: true
};
win.PopupNotifications.show(browser, "enable_e10s", promptMessage, null, mainAction, secondaryActions, options);
win.PopupNotifications.show(browser, "enable-e10s", promptMessage, null, mainAction, secondaryActions, options);
let highlights = [
"Less crashing!",
"Improved add-on compatibility and DevTools",
"PDF.js, Web Console, Spellchecking, WebRTC now work"
];
let doorhangerExtraContent = win.document.getElementById("enable-e10s-notification")
.querySelector("popupnotificationcontent");
for (let highlight of highlights) {
let highlightLabel = win.document.createElement("label");
highlightLabel.setAttribute("value", highlight);
doorhangerExtraContent.appendChild(highlightLabel);
}
},
_warnedAboutAccessibility: false,

Просмотреть файл

@ -8,7 +8,6 @@
#include "mozilla/ArrayUtils.h"
#include "js/OldDebugAPI.h"
#include "xpcprivate.h"
#include "XPCWrapper.h"
#include "nsIAppsService.h"

Просмотреть файл

@ -13,7 +13,6 @@
#include "mozilla/dom/MessageEvent.h"
#include "mozilla/dom/ScriptSettings.h"
#include "js/OldDebugAPI.h"
#include "nsNetUtil.h"
#include "nsMimeTypes.h"
#include "nsIPromptFactory.h"

Просмотреть файл

@ -10,7 +10,6 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/net/WebSocketChannel.h"
#include "mozilla/dom/File.h"

Просмотреть файл

@ -21,7 +21,6 @@
#include "imgRequestProxy.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "js/Value.h"
#include "Layers.h"
#include "MediaDecoder.h"

Просмотреть файл

@ -545,6 +545,11 @@ public:
bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
// Returns the principal of the "top level" document; the origin displayed
// in the URL bar of the browser window.
already_AddRefed<nsIPrincipal> GetTopLevelPrincipal();
#endif // MOZ_EME
bool MozAutoplayEnabled() const

Просмотреть файл

@ -3407,6 +3407,11 @@ void HTMLMediaElement::NotifyDecoderPrincipalChanged()
OutputMediaStream* ms = &mOutputStreams[i];
ms->mStream->CombineWithPrincipal(principal);
}
#ifdef MOZ_EME
if (mMediaKeys && NS_FAILED(mMediaKeys->CheckPrincipals())) {
mMediaKeys->Shutdown();
}
#endif
}
void HTMLMediaElement::UpdateMediaSize(nsIntSize size)
@ -4008,16 +4013,34 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
// TODO: Need to shutdown existing MediaKeys instance? bug 1016709.
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
if (aRv.Failed()) {
return nullptr;
}
if (mMediaKeys != aMediaKeys) {
mMediaKeys = aMediaKeys;
if (mMediaKeys == aMediaKeys) {
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
}
if (mDecoder) {
mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy());
if (aMediaKeys && aMediaKeys->IsBoundToMediaElement()) {
promise->MaybeReject(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
return promise.forget();
}
if (mMediaKeys) {
// Existing MediaKeys object. Shut it down.
mMediaKeys->Shutdown();
mMediaKeys = nullptr;
}
mMediaKeys = aMediaKeys;
if (mMediaKeys) {
if (NS_FAILED(mMediaKeys->Bind(this))) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
mMediaKeys = nullptr;
return promise.forget();
}
if (mDecoder) {
mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy());
}
}
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
@ -4063,6 +4086,28 @@ HTMLMediaElement::IsEventAttributeName(nsIAtom* aName)
return aName == nsGkAtoms::onencrypted ||
nsGenericHTMLElement::IsEventAttributeName(aName);
}
already_AddRefed<nsIPrincipal>
HTMLMediaElement::GetTopLevelPrincipal()
{
nsRefPtr<nsIPrincipal> principal;
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(OwnerDoc()->GetParentObject());
nsCOMPtr<nsIDOMWindow> topWindow;
if (!window) {
return nullptr;
}
window->GetTop(getter_AddRefs(topWindow));
nsCOMPtr<nsPIDOMWindow> top = do_QueryInterface(topWindow);
if (!top) {
return nullptr;
}
nsIDocument* doc = top->GetExtantDoc();
if (!doc) {
return nullptr;
}
principal = doc->NodePrincipal();
return principal.forget();
}
#endif // MOZ_EME
NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged()

Просмотреть файл

@ -142,12 +142,12 @@ nsresult FileBlockCache::ReadFromFile(int64_t aOffset,
nsresult res = Seek(aOffset);
if (NS_FAILED(res)) return res;
aBytesRead = PR_Read(mFD, aDest, aBytesToRead);
if (aBytesRead <= 0)
return NS_ERROR_FAILURE;
mFDCurrentPos += aBytesRead;
return NS_OK;
}
@ -327,7 +327,7 @@ nsresult FileBlockCache::MoveBlock(int32_t aSourceBlockIndex, int32_t aDestBlock
// the block to file yet.
mChangeIndexList.PushBack(aDestBlockIndex);
}
// If the source block hasn't yet been written to file then the dest block
// simply contains that same write. Resolve this as a write instead.
if (sourceBlock && sourceBlock->IsWrite()) {

Просмотреть файл

@ -21,7 +21,7 @@ namespace mozilla {
// Manages file I/O for the media cache. Data comes in over the network
// via callbacks on the main thread, however we don't want to write the
// incoming data to the media cache on the main thread, as this could block
// causing UI jank.
// causing UI jank.
//
// So FileBlockCache provides an abstraction for a temporary file accessible
// as an array of blocks, which supports a block move operation, and

Просмотреть файл

@ -31,7 +31,7 @@ class ReentrantMonitorAutoEnter;
* and you don't have much control over the rate. Also, transferring data
* over the Internet can be slow and/or unpredictable, so we want to read
* ahead to buffer and cache as much data as possible.
*
*
* The job of the media cache is to resolve this impedance mismatch.
* The media cache reads data from Necko channels into file-backed storage,
* and offers a random-access file-like API to the stream data
@ -56,25 +56,25 @@ class ReentrantMonitorAutoEnter;
* can distribute data to any thread
* -- The cache exposes APIs so clients can detect what data is
* currently held
*
*
* Note that although HTTP is the most important transport and we only
* support transport-level seeking via HTTP byte-ranges, the media cache
* works with any kind of Necko channels and provides random access to
* cached data even for, e.g., FTP streams.
*
*
* The media cache is not persistent. It does not currently allow
* data from one load to be used by other loads, either within the same
* browser session or across browser sessions. The media cache file
* is marked "delete on close" so it will automatically disappear in the
* event of a browser crash or shutdown.
*
*
* The media cache is block-based. Streams are divided into blocks of a
* fixed size (currently 4K) and we cache blocks. A single cache contains
* blocks for all streams.
*
*
* The cache size is controlled by the media.cache_size preference
* (which is in KB). The default size is 500MB.
*
*
* The replacement policy predicts a "time of next use" for each block
* in the cache. When we need to free a block, the block with the latest
* "time of next use" will be evicted. Blocks are divided into
@ -108,19 +108,19 @@ class ReentrantMonitorAutoEnter;
* next use. READAHEAD_BLOCKS have one linked list per stream, since their
* time of next use depends on stream parameters, but the other lists
* are global.
*
*
* A block containing a current decoder read point can contain data
* both behind and ahead of the read point. It will be classified as a
* PLAYED_BLOCK but we will give it special treatment so it is never
* evicted --- it actually contains the highest-priority readahead data
* as well as played data.
*
*
* "Time of next use" estimates are also used for flow control. When
* reading ahead we can predict the time of next use for the data that
* will be read. If the predicted time of next use is later then the
* prediction for all currently cached blocks, and the cache is full, then
* we should suspend reading from the Necko channel.
*
*
* Unfortunately suspending the Necko channel can't immediately stop the
* flow of data from the server. First our desire to suspend has to be
* transmitted to the server (in practice, Necko stops reading from the
@ -132,7 +132,7 @@ class ReentrantMonitorAutoEnter;
* moving overflowing blocks back into the body of the cache, replacing
* less valuable blocks as they become available. We try to avoid simply
* discarding overflowing readahead data.
*
*
* All changes to the actual contents of the cache happen on the main
* thread, since that's where Necko's notifications happen.
*
@ -142,7 +142,7 @@ class ReentrantMonitorAutoEnter;
* the loading of data from the beginning of the file.) The Necko channel
* is managed through ChannelMediaResource; MediaCache does not
* depend on Necko directly.
*
*
* Every time something changes that might affect whether we want to
* read from a Necko channel, or whether we want to seek on the Necko
* channel --- such as data arriving or data being consumed by the
@ -152,20 +152,20 @@ class ReentrantMonitorAutoEnter;
* offset we should seek to, if any. It is also responsible for trimming
* back the cache size to its desired limit by moving overflowing blocks
* into the main part of the cache.
*
*
* Streams can be opened in non-seekable mode. In non-seekable mode,
* the cache will only call ChannelMediaResource::CacheClientSeek with
* a 0 offset. The cache tries hard not to discard readahead data
* for non-seekable streams, since that could trigger a potentially
* disastrous re-read of the entire stream. It's up to cache clients
* to try to avoid requesting seeks on such streams.
*
*
* MediaCache has a single internal monitor for all synchronization.
* This is treated as the lowest level monitor in the media code. So,
* we must not acquire any MediaDecoder locks or MediaResource locks
* while holding the MediaCache lock. But it's OK to hold those locks
* and then get the MediaCache lock.
*
*
* MediaCache associates a principal with each stream. CacheClientSeek
* can trigger new HTTP requests; due to redirects to other domains,
* each HTTP load can return data with a different principal. This
@ -178,7 +178,7 @@ class MediaCache;
/**
* If the cache fails to initialize then Init will fail, so nonstatic
* methods of this class can assume gMediaCache is non-null.
*
*
* This class can be directly embedded as a value.
*/
class MediaCacheStream {
@ -357,7 +357,7 @@ private:
* constant time. We declare this here so that a stream can contain a
* BlockList of its read-ahead blocks. Blocks are referred to by index
* into the MediaCache::mIndex array.
*
*
* Blocks can belong to more than one list at the same time, because
* the next/prev pointers are not stored in the block.
*/

Просмотреть файл

@ -11,7 +11,9 @@
#include "ImageContainer.h"
#include "SharedThreadPool.h"
#include "mozilla/Preferences.h"
#include "mozilla/Base64.h"
#include "nsIRandomGenerator.h"
#include "nsIServiceManager.h"
#include <stdint.h>
namespace mozilla {
@ -230,4 +232,42 @@ ExtractH264CodecDetails(const nsAString& aCodec,
return true;
}
nsresult
GenerateRandomPathName(nsCString& aOutSalt, uint32_t aLength)
{
nsresult rv;
nsCOMPtr<nsIRandomGenerator> rg =
do_GetService("@mozilla.org/security/random-generator;1", &rv);
if (NS_FAILED(rv)) return rv;
// For each three bytes of random data we will get four bytes of
// ASCII. Request a bit more to be safe and truncate to the length
// we want at the end.
const uint32_t requiredBytesLength =
static_cast<uint32_t>((aLength + 1) / 4 * 3);
uint8_t* buffer;
rv = rg->GenerateRandomBytes(requiredBytesLength, &buffer);
if (NS_FAILED(rv)) return rv;
nsAutoCString temp;
nsDependentCSubstring randomData(reinterpret_cast<const char*>(buffer),
requiredBytesLength);
rv = Base64Encode(randomData, temp);
NS_Free(buffer);
buffer = nullptr;
if (NS_FAILED (rv)) return rv;
temp.Truncate(aLength);
// Base64 characters are alphanumeric (a-zA-Z0-9) and '+' and '/', so we need
// to replace illegal characters -- notably '/'
temp.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '_');
aOutSalt = temp;
return NS_OK;
}
} // end namespace mozilla

Просмотреть файл

@ -257,6 +257,12 @@ ExtractH264CodecDetails(const nsAString& aCodecs,
int16_t& aProfile,
int16_t& aLevel);
// Use a cryptographic quality PRNG to generate raw random bytes
// and convert that to a base64 string suitable for use as a file or URL
// path. This is based on code from nsExternalAppHandler::SetUpTempFile.
nsresult
GenerateRandomPathName(nsCString& aOutSalt, uint32_t aLength);
} // end namespace mozilla
#endif

Просмотреть файл

@ -242,7 +242,7 @@ bool AndroidMediaReader::DecodeVideoFrame(bool &aKeyframeSkip,
-1,
picture);
}
if (!v) {
return false;
}

Просмотреть файл

@ -438,38 +438,11 @@ AndroidMediaResourceServer::AppendRandomPath(nsCString& aUrl)
// and convert that to a base64 string for use as an URL path. This
// is based on code from nsExternalAppHandler::SetUpTempFile.
nsresult rv;
nsCOMPtr<nsIRandomGenerator> rg =
do_GetService("@mozilla.org/security/random-generator;1", &rv);
nsAutoCString salt;
rv = GenerateRandomPathName(salt, 16);
if (NS_FAILED(rv)) return rv;
// For each three bytes of random data we will get four bytes of
// ASCII. Request a bit more to be safe and truncate to the length
// we want at the end.
const uint32_t wantedFileNameLength = 16;
const uint32_t requiredBytesLength =
static_cast<uint32_t>((wantedFileNameLength + 1) / 4 * 3);
uint8_t* buffer;
rv = rg->GenerateRandomBytes(requiredBytesLength, &buffer);
if (NS_FAILED(rv)) return rv;
nsAutoCString tempLeafName;
nsDependentCSubstring randomData(reinterpret_cast<const char*>(buffer),
requiredBytesLength);
rv = Base64Encode(randomData, tempLeafName);
NS_Free(buffer);
buffer = nullptr;
if (NS_FAILED (rv)) return rv;
tempLeafName.Truncate(wantedFileNameLength);
// Base64 characters are alphanumeric (a-zA-Z0-9) and '+' and '/', so we need
// to replace illegal characters -- notably '/'
tempLeafName.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '_');
aUrl += "/";
aUrl += tempLeafName;
aUrl += salt;
return NS_OK;
}
@ -477,7 +450,7 @@ nsresult
AndroidMediaResourceServer::AddResource(mozilla::MediaResource* aResource, nsCString& aUrl)
{
nsCString url = GetURLPrefix();
nsresult rv = AppendRandomPath(url);
nsresult rv = GenerateRandomPathName(url, 16);
if (NS_FAILED (rv)) return rv;
{

Просмотреть файл

@ -36,18 +36,18 @@ CDMProxy::~CDMProxy()
}
void
CDMProxy::Init(PromiseId aPromiseId)
CDMProxy::Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsing)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
nsresult rv = mKeys->GetOrigin(mOrigin);
if (NS_FAILED(rv)) {
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
EME_LOG("Creating CDMProxy for origin='%s'",
NS_ConvertUTF16toUTF8(GetOrigin()).get());
EME_LOG("CDMProxy::Init (%s, %s) %s",
NS_ConvertUTF16toUTF8(aOrigin).get(),
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
(aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"));
if (!mGMPThread) {
nsCOMPtr<mozIGeckoMediaPluginService> mps =
@ -62,8 +62,15 @@ CDMProxy::Init(PromiseId aPromiseId)
return;
}
}
nsRefPtr<nsIRunnable> task(NS_NewRunnableMethodWithArg<uint32_t>(this, &CDMProxy::gmp_Init, aPromiseId));
nsAutoPtr<InitData> data(new InitData());
data->mPromiseId = aPromiseId;
data->mOrigin = aOrigin;
data->mTopLevelOrigin = aTopLevelOrigin;
data->mInPrivateBrowsing = aInPrivateBrowsing;
nsRefPtr<nsIRunnable> task(
NS_NewRunnableMethodWithArg<nsAutoPtr<InitData>>(this,
&CDMProxy::gmp_Init,
data));
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
}
@ -76,26 +83,45 @@ CDMProxy::IsOnGMPThread()
#endif
void
CDMProxy::gmp_Init(uint32_t aPromiseId)
CDMProxy::gmp_Init(nsAutoPtr<InitData> aData)
{
MOZ_ASSERT(IsOnGMPThread());
nsCOMPtr<mozIGeckoMediaPluginService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (!mps) {
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
nsresult rv = mps->GetNodeId(aData->mOrigin,
aData->mTopLevelOrigin,
aData->mInPrivateBrowsing,
mNodeId);
MOZ_ASSERT(!GetNodeId().IsEmpty());
if (NS_FAILED(rv)) {
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
EME_LOG("CDMProxy::gmp_Init (%s, %s) %s NodeId=%s",
NS_ConvertUTF16toUTF8(aData->mOrigin).get(),
NS_ConvertUTF16toUTF8(aData->mTopLevelOrigin).get(),
(aData->mInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"),
GetNodeId().get());
nsTArray<nsCString> tags;
tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem));
nsresult rv = mps->GetGMPDecryptor(&tags, GetOrigin(), &mCDM);
rv = mps->GetGMPDecryptor(&tags, GetNodeId(), &mCDM);
if (NS_FAILED(rv) || !mCDM) {
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
} else {
mCallback = new CDMCallbackProxy(this);
mCDM->Init(mCallback);
nsRefPtr<nsIRunnable> task(NS_NewRunnableMethodWithArg<uint32_t>(this, &CDMProxy::OnCDMCreated, aPromiseId));
nsRefPtr<nsIRunnable> task(
NS_NewRunnableMethodWithArg<uint32_t>(this,
&CDMProxy::OnCDMCreated,
aData->mPromiseId));
NS_DispatchToMainThread(task);
}
}
@ -107,7 +133,8 @@ CDMProxy::OnCDMCreated(uint32_t aPromiseId)
if (mKeys.IsNull()) {
return;
}
mKeys->OnCDMCreated(aPromiseId);
MOZ_ASSERT(!GetNodeId().IsEmpty());
mKeys->OnCDMCreated(aPromiseId, GetNodeId());
}
void
@ -356,10 +383,10 @@ CDMProxy::ResolvePromise(PromiseId aId)
}
}
const nsAString&
CDMProxy::GetOrigin() const
const nsCString&
CDMProxy::GetNodeId() const
{
return mOrigin;
return mNodeId;
}
void

Просмотреть файл

@ -48,7 +48,10 @@ public:
// Main thread only.
// Loads the CDM corresponding to mKeySystem.
// Calls MediaKeys::OnCDMCreated() when the CDM is created.
void Init(PromiseId aPromiseId);
void Init(PromiseId aPromiseId,
const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsing);
// Main thread only.
// Uses the CDM to create a key session.
@ -102,7 +105,7 @@ public:
void Shutdown();
// Threadsafe.
const nsAString& GetOrigin() const;
const nsCString& GetNodeId() const;
// Main thread only.
void OnResolveNewSessionPromise(uint32_t aPromiseId,
@ -165,8 +168,15 @@ public:
private:
struct InitData {
uint32_t mPromiseId;
nsAutoString mOrigin;
nsAutoString mTopLevelOrigin;
bool mInPrivateBrowsing;
};
// GMP thread only.
void gmp_Init(uint32_t aPromiseId);
void gmp_Init(nsAutoPtr<InitData> aData);
// GMP thread only.
void gmp_Shutdown();
@ -286,7 +296,7 @@ private:
// EME plugin must come from this thread.
nsRefPtr<nsIThread> mGMPThread;
nsAutoString mOrigin;
nsCString mNodeId;
GMPDecryptorProxy* mCDM;
CDMCaps mCapabilites;

Просмотреть файл

@ -25,6 +25,7 @@ namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeys,
mElement,
mParent,
mKeySessions,
mPromises,
@ -224,23 +225,85 @@ MediaKeys::Create(const GlobalObject& aGlobal,
// CDMProxy keeps MediaKeys alive until it resolves the promise and thus
// returns the MediaKeys object to JS.
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
if (!window) {
if (!window || !window->GetExtantDoc()) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<MediaKeys> keys = new MediaKeys(window, aKeySystem);
nsRefPtr<Promise> promise(keys->MakePromise(aRv));
return keys->Init(aRv);
}
already_AddRefed<Promise>
MediaKeys::Init(ErrorResult& aRv)
{
nsRefPtr<Promise> promise(MakePromise(aRv));
if (aRv.Failed()) {
return nullptr;
}
if (!IsSupportedKeySystem(aKeySystem)) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
if (!IsSupportedKeySystem(mKeySystem)) {
promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return promise.forget();
}
keys->mProxy = new CDMProxy(keys, aKeySystem);
mProxy = new CDMProxy(this, mKeySystem);
// Determine principal (at creation time) of the MediaKeys object.
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(GetParentObject());
if (!sop) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
mPrincipal = sop->GetPrincipal();
// Determine principal of the "top-level" window; the principal of the
// page that will display in the URL bar.
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(GetParentObject());
if (!window) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsCOMPtr<nsIDOMWindow> topWindow;
window->GetTop(getter_AddRefs(topWindow));
nsCOMPtr<nsPIDOMWindow> top = do_QueryInterface(topWindow);
if (!top || !top->GetExtantDoc()) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
mTopLevelPrincipal = top->GetExtantDoc()->NodePrincipal();
if (!mPrincipal || !mTopLevelPrincipal) {
NS_WARNING("Failed to get principals when creating MediaKeys");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsAutoString origin;
nsresult rv = nsContentUtils::GetUTFOrigin(mPrincipal, origin);
if (NS_FAILED(rv)) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsAutoString topLevelOrigin;
rv = nsContentUtils::GetUTFOrigin(mTopLevelPrincipal, topLevelOrigin);
if (NS_FAILED(rv)) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
if (!window) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsIDocument* doc = window->GetExtantDoc();
const bool inPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc);
EME_LOG("MediaKeys::Create() (%s, %s), %s",
NS_ConvertUTF16toUTF8(origin).get(),
NS_ConvertUTF16toUTF8(topLevelOrigin).get(),
(inPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"));
// The CDMProxy's initialization is asynchronous. The MediaKeys is
// refcounted, and its instance is returned to JS by promise once
@ -250,22 +313,26 @@ MediaKeys::Create(const GlobalObject& aGlobal,
// or its creation has failed. Store the id of the promise returned
// here, and hold a self-reference until that promise is resolved or
// rejected.
MOZ_ASSERT(!keys->mCreatePromiseId, "Should only be created once!");
keys->mCreatePromiseId = keys->StorePromise(promise);
keys->AddRef();
keys->mProxy->Init(keys->mCreatePromiseId);
MOZ_ASSERT(!mCreatePromiseId, "Should only be created once!");
mCreatePromiseId = StorePromise(promise);
AddRef();
mProxy->Init(mCreatePromiseId,
origin,
topLevelOrigin,
inPrivateBrowsing);
return promise.forget();
}
void
MediaKeys::OnCDMCreated(PromiseId aId)
MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId)
{
nsRefPtr<Promise> promise(RetrievePromise(aId));
if (!promise) {
NS_WARNING("MediaKeys tried to resolve a non-existent promise");
return;
}
mNodeId = aNodeId;
nsRefPtr<MediaKeys> keys(this);
promise->MaybeResolve(keys);
if (mCreatePromiseId == aId) {
@ -366,26 +433,58 @@ MediaKeys::GetSession(const nsAString& aSessionId)
return session.forget();
}
nsresult
MediaKeys::GetOrigin(nsString& aOutOrigin)
const nsCString&
MediaKeys::GetNodeId() const
{
MOZ_ASSERT(NS_IsMainThread());
// TODO: Bug 1035637, return a combination of origin and URL bar origin.
return mNodeId;
}
nsIPrincipal* principal = nullptr;
nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(GetParentObject());
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
do_QueryInterface(pWindow);
if (scriptPrincipal) {
principal = scriptPrincipal->GetPrincipal();
bool
MediaKeys::IsBoundToMediaElement() const
{
MOZ_ASSERT(NS_IsMainThread());
return mElement != nullptr;
}
nsresult
MediaKeys::Bind(HTMLMediaElement* aElement)
{
MOZ_ASSERT(NS_IsMainThread());
if (IsBoundToMediaElement()) {
return NS_ERROR_FAILURE;
}
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
nsresult res = nsContentUtils::GetUTFOrigin(principal, aOutOrigin);
mElement = aElement;
nsresult rv = CheckPrincipals();
if (NS_FAILED(rv)) {
mElement = nullptr;
return rv;
}
EME_LOG("EME Origin = '%s'", NS_ConvertUTF16toUTF8(aOutOrigin).get());
return NS_OK;
}
return res;
nsresult
MediaKeys::CheckPrincipals()
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsBoundToMediaElement()) {
return NS_ERROR_FAILURE;
}
nsRefPtr<nsIPrincipal> elementPrincipal(mElement->GetCurrentPrincipal());
nsRefPtr<nsIPrincipal> elementTopLevelPrincipal(mElement->GetTopLevelPrincipal());
if (!elementPrincipal ||
!mPrincipal ||
!elementPrincipal->Equals(mPrincipal) ||
!elementTopLevelPrincipal ||
!mTopLevelPrincipal ||
!elementTopLevelPrincipal->Equals(mTopLevelPrincipal)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
bool

Просмотреть файл

@ -18,6 +18,7 @@
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/MediaKeysBinding.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozIGeckoMediaPluginService.h"
namespace mozilla {
@ -26,6 +27,7 @@ class CDMProxy;
namespace dom {
class MediaKeySession;
class HTMLMediaElement;
typedef nsRefPtrHashtable<nsStringHashKey, MediaKeySession> KeySessionHashMap;
typedef nsRefPtrHashtable<nsUint32HashKey, dom::Promise> PromiseHashMap;
@ -55,6 +57,8 @@ public:
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
nsresult Bind(HTMLMediaElement* aElement);
// Javascript: readonly attribute DOMString keySystem;
void GetKeySystem(nsString& retval) const;
@ -82,7 +86,7 @@ public:
already_AddRefed<MediaKeySession> GetSession(const nsAString& aSessionId);
// Called once a Create() operation succeeds.
void OnCDMCreated(PromiseId aId);
void OnCDMCreated(PromiseId aId, const nsACString& aNodeId);
// Called when GenerateRequest or Load have been called on a MediaKeySession
// and we are waiting for its initialisation to finish.
void OnSessionPending(PromiseId aId, MediaKeySession* aSession);
@ -107,12 +111,22 @@ public:
// Resolves promise with "undefined".
void ResolvePromise(PromiseId aId);
nsresult GetOrigin(nsString& aOutOrigin);
const nsCString& GetNodeId() const;
void Shutdown();
// Returns true if this MediaKeys has been bound to a media element.
bool IsBoundToMediaElement() const;
// Return NS_OK if the principals are the same as when the MediaKeys
// was created, failure otherwise.
nsresult CheckPrincipals();
private:
bool IsInPrivateBrowsing();
already_AddRefed<Promise> Init(ErrorResult& aRv);
// Removes promise from mPromises, and returns it.
already_AddRefed<Promise> RetrievePromise(PromiseId aId);
@ -120,12 +134,19 @@ private:
// and the MediaKeys destructor clears the proxy's reference to the MediaKeys.
nsRefPtr<CDMProxy> mProxy;
nsRefPtr<HTMLMediaElement> mElement;
nsCOMPtr<nsPIDOMWindow> mParent;
nsString mKeySystem;
nsCString mNodeId;
KeySessionHashMap mKeySessions;
PromiseHashMap mPromises;
PendingKeySessionsHashMap mPendingSessions;
PromiseId mCreatePromiseId;
nsRefPtr<nsIPrincipal> mPrincipal;
nsRefPtr<nsIPrincipal> mTopLevelPrincipal;
};
} // namespace dom

Просмотреть файл

@ -242,7 +242,7 @@ EMEAudioDecoder::GmpInit()
tags.AppendElement(NS_LITERAL_CSTRING("aac"));
tags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
nsresult rv = mMPS->GetGMPAudioDecoder(&tags,
mProxy->GetOrigin(),
mProxy->GetNodeId(),
&mGMP);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(mGMP);

Просмотреть файл

@ -233,7 +233,7 @@ EMEH264Decoder::GmpInit()
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
tags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
nsresult rv = mMPS->GetGMPVideoDecoder(&tags,
mProxy->GetOrigin(),
mProxy->GetNodeId(),
&mHost,
&mGMP);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -29,6 +29,21 @@ using mozilla::dom::CrashReporterChild;
#include <unistd.h> // for _exit()
#endif
#if defined(XP_WIN)
// In order to provide EME plugins with a "device binding" capability,
// in the parent we generate and store some random bytes as salt for every
// (origin, urlBarOrigin) pair that uses EME. We store these bytes so
// that every time we revisit the same origin we get the same salt.
// We send this salt to the child on startup. The child collects some
// device specific data and munges that with the salt to create the
// "node id" that we expose to EME plugins. It then overwrites the device
// specific data, and activates the sandbox.
#define HASH_NODE_ID_WITH_DEVICE_ID 1
#include "rlz/lib/machine_id.h"
#include "rlz/lib/string_utils.h"
#include "mozilla/SHA1.h"
#endif
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
#define TARGET_SANDBOX_EXPORTS
#include "mozilla/sandboxTarget.h"
@ -268,20 +283,58 @@ GMPChild::Init(const std::string& aPluginPath,
SendPCrashReporterConstructor(CrashReporter::CurrentThreadId());
#endif
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
mPluginPath = aPluginPath;
return true;
#endif
}
bool
GMPChild::RecvSetNodeId(const nsCString& aNodeId)
{
#ifdef HASH_NODE_ID_WITH_DEVICE_ID
if (!aNodeId.IsEmpty() && !aNodeId.EqualsLiteral("null")) {
string16 deviceId;
int volumeId;
if (!rlz_lib::GetRawMachineId(&deviceId, &volumeId)) {
return false;
}
// TODO: Switch to SHA256.
mozilla::SHA1Sum hash;
hash.update(deviceId.c_str(), deviceId.size() * sizeof(string16::value_type));
hash.update(aNodeId.get(), aNodeId.Length());
hash.update(&volumeId, sizeof(int));
uint8_t digest[mozilla::SHA1Sum::kHashSize];
hash.finish(digest);
if (!rlz_lib::BytesToString(digest, mozilla::SHA1Sum::kHashSize, &mNodeId)) {
return false;
}
// Overwrite device id as it could potentially identify the user, so
// there's no chance a GMP can read it and use it for identity tracking.
volumeId = 0;
memset(&deviceId.front(), '*', sizeof(string16::value_type) * deviceId.size());
deviceId = L"";
} else {
mNodeId = "null";
}
#else
mNodeId = std::string(aNodeId.BeginReading(), aNodeId.EndReading());
#endif
return true;
}
bool
GMPChild::RecvStartPlugin()
{
#ifdef XP_WIN
PreLoadLibraries(aPluginPath);
PreLoadLibraries(mPluginPath);
#endif
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
mozilla::SandboxTarget::Instance()->StartSandbox();
#endif
return LoadPluginLibrary(aPluginPath);
return LoadPluginLibrary(mPluginPath);
}
#ifdef XP_WIN
@ -499,7 +552,7 @@ GMPChild::DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor)
PGMPDecryptorChild*
GMPChild::AllocPGMPDecryptorChild()
{
GMPDecryptorChild* actor = new GMPDecryptorChild(this);
GMPDecryptorChild* actor = new GMPDecryptorChild(this, mNodeId);
actor->AddRef();
return actor;
}

Просмотреть файл

@ -50,6 +50,10 @@ public:
void ShutdownComplete() MOZ_OVERRIDE;
private:
virtual bool RecvSetNodeId(const nsCString& aNodeId) MOZ_OVERRIDE;
virtual bool RecvStartPlugin() MOZ_OVERRIDE;
virtual PCrashReporterChild* AllocPCrashReporterChild(const NativeThreadId& aThread) MOZ_OVERRIDE;
virtual bool DeallocPCrashReporterChild(PCrashReporterChild*) MOZ_OVERRIDE;
@ -88,10 +92,11 @@ private:
PRLibrary* mLib;
GMPGetAPIFunc mGetAPIFunc;
MessageLoop* mGMPMessageLoop;
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
std::string mPluginPath;
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
nsCString mPluginBinaryPath;
#endif
std::string mNodeId;
};
} // namespace gmp

Просмотреть файл

@ -26,9 +26,10 @@
namespace mozilla {
namespace gmp {
GMPDecryptorChild::GMPDecryptorChild(GMPChild* aPlugin)
GMPDecryptorChild::GMPDecryptorChild(GMPChild* aPlugin, const std::string& aNodeId)
: mSession(nullptr)
, mPlugin(aPlugin)
, mNodeId(aNodeId)
{
MOZ_ASSERT(mPlugin);
}
@ -176,9 +177,8 @@ void
GMPDecryptorChild::GetNodeId(const char** aOutNodeId,
uint32_t* aOutNodeIdLength)
{
static const char* id = "placeholder_node_id";
*aOutNodeId = id;
*aOutNodeIdLength = strlen(id);
*aOutNodeId = mNodeId.c_str();
*aOutNodeIdLength = mNodeId.size();
}
void

Просмотреть файл

@ -10,6 +10,7 @@
#include "gmp-decryption.h"
#include "mozilla/gmp/GMPTypes.h"
#include "GMPEncryptedBufferDataImpl.h"
#include <string>
namespace mozilla {
namespace gmp {
@ -23,7 +24,7 @@ class GMPDecryptorChild : public GMPDecryptorCallback
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPDecryptorChild);
explicit GMPDecryptorChild(GMPChild* aPlugin);
explicit GMPDecryptorChild(GMPChild* aPlugin, const std::string& aNodeId);
void Init(GMPDecryptor* aSession);
@ -122,6 +123,8 @@ private:
// Only call into this on the (GMP process) main thread.
GMPDecryptor* mSession;
GMPChild* mPlugin;
const std::string mNodeId;
};
} // namespace gmp

Просмотреть файл

@ -150,6 +150,22 @@ GMPParent::LoadProcess()
return NS_ERROR_FAILURE;
}
LOGD(("%s::%s: Created new process %p", __CLASS__, __FUNCTION__, (void *)mProcess));
bool ok = SendSetNodeId(mNodeId);
if (!ok) {
mProcess->Delete();
mProcess = nullptr;
return NS_ERROR_FAILURE;
}
LOGD(("%s::%s: Failed to send node id %p", __CLASS__, __FUNCTION__, (void *)mProcess));
ok = SendStartPlugin();
if (!ok) {
mProcess->Delete();
mProcess = nullptr;
return NS_ERROR_FAILURE;
}
LOGD(("%s::%s: Failed to send start %p", __CLASS__, __FUNCTION__, (void *)mProcess));
}
mState = GMPStateLoaded;
@ -680,7 +696,7 @@ GMPParent::DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor)
PGMPStorageParent*
GMPParent::AllocPGMPStorageParent()
{
GMPStorageParent* p = new GMPStorageParent(mOrigin, this);
GMPStorageParent* p = new GMPStorageParent(mNodeId, this);
mStorage.AppendElement(p); // Addrefs, released in DeallocPGMPStorageParent.
return p;
}
@ -695,8 +711,12 @@ GMPParent::DeallocPGMPStorageParent(PGMPStorageParent* aActor)
}
bool
GMPParent::RecvPGMPStorageConstructor(PGMPStorageParent* actor)
GMPParent::RecvPGMPStorageConstructor(PGMPStorageParent* aActor)
{
GMPStorageParent* p = (GMPStorageParent*)aActor;
if (NS_WARN_IF(NS_FAILED(p->Init()))) {
return false;
}
return true;
}
@ -877,24 +897,24 @@ GMPParent::ReadGMPMetaData()
}
bool
GMPParent::CanBeSharedCrossOrigin() const
GMPParent::CanBeSharedCrossNodeIds() const
{
return mOrigin.IsEmpty();
return mNodeId.IsEmpty();
}
bool
GMPParent::CanBeUsedFrom(const nsAString& aOrigin) const
GMPParent::CanBeUsedFrom(const nsACString& aNodeId) const
{
return (mOrigin.IsEmpty() && State() == GMPStateNotLoaded) ||
mOrigin.Equals(aOrigin);
return (mNodeId.IsEmpty() && State() == GMPStateNotLoaded) ||
mNodeId == aNodeId;
}
void
GMPParent::SetOrigin(const nsAString& aOrigin)
GMPParent::SetNodeId(const nsACString& aNodeId)
{
MOZ_ASSERT(!aOrigin.IsEmpty());
MOZ_ASSERT(CanBeUsedFrom(aOrigin));
mOrigin = aOrigin;
MOZ_ASSERT(!aNodeId.IsEmpty());
MOZ_ASSERT(CanBeUsedFrom(aNodeId));
mNodeId = aNodeId;
}
bool

Просмотреть файл

@ -99,26 +99,28 @@ public:
GMPState State() const;
nsIThread* GMPThread();
// A GMP can either be a single instance shared across all origins (like
// A GMP can either be a single instance shared across all NodeIds (like
// in the OpenH264 case), or we can require a new plugin instance for every
// origin running the plugin (as in the EME plugin case).
// NodeIds running the plugin (as in the EME plugin case).
//
// Plugins are associated with an origin by calling SetOrigin() before
// A NodeId is a hash of the ($urlBarOrigin, $ownerDocOrigin) pair.
//
// Plugins are associated with an NodeIds by calling SetNodeId() before
// loading.
//
// If a plugin has no origin specified and it is loaded, it is assumed to
// be shared across origins.
// If a plugin has no NodeId specified and it is loaded, it is assumed to
// be shared across NodeIds.
// Specifies that a GMP can only work with the specified origin.
void SetOrigin(const nsAString& aOrigin);
// Specifies that a GMP can only work with the specified NodeIds.
void SetNodeId(const nsACString& aNodeId);
// Returns true if a plugin can be or is being used across multiple origins.
bool CanBeSharedCrossOrigin() const;
// Returns true if a plugin can be or is being used across multiple NodeIds.
bool CanBeSharedCrossNodeIds() const;
// A GMP can be used from an origin if it's already been set to work with
// that origin, or if it's not been set to work with any origin and has
// not yet been loaded (i.e. it's not shared across origins).
bool CanBeUsedFrom(const nsAString& aOrigin) const;
// A GMP can be used from a NodeId if it's already been set to work with
// that NodeId, or if it's not been set to work with any NodeId and has
// not yet been loaded (i.e. it's not shared across NodeIds).
bool CanBeUsedFrom(const nsACString& aNodeId) const;
already_AddRefed<nsIFile> GetDirectory() {
return nsCOMPtr<nsIFile>(mDirectory).forget();
@ -184,9 +186,9 @@ private:
nsTArray<nsRefPtr<GMPTimerParent>> mTimers;
nsTArray<nsRefPtr<GMPStorageParent>> mStorage;
nsCOMPtr<nsIThread> mGMPThread;
// Origin the plugin is assigned to, or empty if the the plugin is not
// assigned to an origin.
nsAutoString mOrigin;
// NodeId the plugin is assigned to, or empty if the the plugin is not
// assigned to a NodeId.
nsAutoCString mNodeId;
bool mAsyncShutdownRequired;
bool mAsyncShutdownInProgress;

Просмотреть файл

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPService.h"
#include "prio.h"
#include "prlog.h"
#include "GMPParent.h"
#include "GMPVideoDecoderParent.h"
@ -22,9 +23,15 @@
#include "nsComponentManagerUtils.h"
#include "mozilla/Preferences.h"
#include "runnable_utils.h"
#include "VideoUtils.h"
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
#include "mozilla/Sandbox.h"
#endif
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsHashKeys.h"
#include "nsIFile.h"
namespace mozilla {
@ -154,7 +161,7 @@ GeckoMediaPluginService::~GeckoMediaPluginService()
MOZ_ASSERT(mAsyncShutdownPlugins.IsEmpty());
}
void
nsresult
GeckoMediaPluginService::Init()
{
MOZ_ASSERT(NS_IsMainThread());
@ -163,15 +170,37 @@ GeckoMediaPluginService::Init()
MOZ_ASSERT(obsService);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "profile-change-teardown", false)));
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false)));
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "last-pb-context-exited", false)));
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
prefs->AddObserver("media.gmp.plugin.crash", this, false);
}
#ifndef MOZ_WIDGET_GONK
// Directory service is main thread only, so cache the profile dir here
// so that we can use it off main thread.
// We only do this on non-B2G, as this fails in multi-process Gecko.
// TODO: Make this work in multi-process Gecko.
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mStorageBaseDir));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mStorageBaseDir->AppendNative(NS_LITERAL_CSTRING("gmp"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mStorageBaseDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)) {
return rv;
}
#endif
// Kick off scanning for plugins
nsCOMPtr<nsIThread> thread;
unused << GetThread(getter_AddRefs(thread));
return GetThread(getter_AddRefs(thread));
}
void
@ -288,6 +317,13 @@ GeckoMediaPluginService::Observe(nsISupports* aSubject,
if (gmpThread) {
gmpThread->Shutdown();
}
} else if (!strcmp("last-pb-context-exited", aTopic)) {
// When Private Browsing mode exits, all we need to do is clear
// mTempNodeIds. This drops all the node ids we've cached in memory
// for PB origin-pairs. If we try to open an origin-pair for non-PB
// mode, we'll get the NodeId salt stored on-disk, and if we try to
// open a PB mode origin-pair, we'll re-generate new salt.
mTempNodeIds.Clear();
}
return NS_OK;
}
@ -324,7 +360,7 @@ GeckoMediaPluginService::GetThread(nsIThread** aThread)
NS_IMETHODIMP
GeckoMediaPluginService::GetGMPAudioDecoder(nsTArray<nsCString>* aTags,
const nsAString& aOrigin,
const nsACString& aNodeId,
GMPAudioDecoderProxy** aGMPAD)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
@ -335,7 +371,7 @@ GeckoMediaPluginService::GetGMPAudioDecoder(nsTArray<nsCString>* aTags,
return NS_ERROR_FAILURE;
}
nsRefPtr<GMPParent> gmp = SelectPluginForAPI(aOrigin,
nsRefPtr<GMPParent> gmp = SelectPluginForAPI(aNodeId,
NS_LITERAL_CSTRING("decode-audio"),
*aTags);
if (!gmp) {
@ -355,7 +391,7 @@ GeckoMediaPluginService::GetGMPAudioDecoder(nsTArray<nsCString>* aTags,
NS_IMETHODIMP
GeckoMediaPluginService::GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
const nsAString& aOrigin,
const nsACString& aNodeId,
GMPVideoHost** aOutVideoHost,
GMPVideoDecoderProxy** aGMPVD)
{
@ -368,7 +404,7 @@ GeckoMediaPluginService::GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
return NS_ERROR_FAILURE;
}
nsRefPtr<GMPParent> gmp = SelectPluginForAPI(aOrigin,
nsRefPtr<GMPParent> gmp = SelectPluginForAPI(aNodeId,
NS_LITERAL_CSTRING("decode-video"),
*aTags);
#ifdef PR_LOGGING
@ -394,7 +430,7 @@ GeckoMediaPluginService::GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
NS_IMETHODIMP
GeckoMediaPluginService::GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
const nsAString& aOrigin,
const nsACString& aNodeId,
GMPVideoHost** aOutVideoHost,
GMPVideoEncoderProxy** aGMPVE)
{
@ -407,7 +443,7 @@ GeckoMediaPluginService::GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
return NS_ERROR_FAILURE;
}
nsRefPtr<GMPParent> gmp = SelectPluginForAPI(aOrigin,
nsRefPtr<GMPParent> gmp = SelectPluginForAPI(aNodeId,
NS_LITERAL_CSTRING("encode-video"),
*aTags);
#ifdef PR_LOGGING
@ -432,7 +468,7 @@ GeckoMediaPluginService::GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
NS_IMETHODIMP
GeckoMediaPluginService::GetGMPDecryptor(nsTArray<nsCString>* aTags,
const nsAString& aOrigin,
const nsACString& aNodeId,
GMPDecryptorProxy** aDecryptor)
{
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
@ -451,7 +487,7 @@ GeckoMediaPluginService::GetGMPDecryptor(nsTArray<nsCString>* aTags,
return NS_ERROR_FAILURE;
}
nsRefPtr<GMPParent> gmp = SelectPluginForAPI(aOrigin,
nsRefPtr<GMPParent> gmp = SelectPluginForAPI(aNodeId,
NS_LITERAL_CSTRING("eme-decrypt"),
*aTags);
if (!gmp) {
@ -658,7 +694,7 @@ GeckoMediaPluginService::RemovePluginDirectory(const nsAString& aDirectory)
}
NS_IMETHODIMP
GeckoMediaPluginService::HasPluginForAPI(const nsAString& aOrigin,
GeckoMediaPluginService::HasPluginForAPI(const nsACString& aNodeId,
const nsACString& aAPI,
nsTArray<nsCString>* aTags,
bool* aResult)
@ -667,19 +703,19 @@ GeckoMediaPluginService::HasPluginForAPI(const nsAString& aOrigin,
NS_ENSURE_ARG(aResult);
nsCString temp(aAPI);
GMPParent *parent = SelectPluginForAPI(aOrigin, temp, *aTags, false);
GMPParent *parent = SelectPluginForAPI(aNodeId, temp, *aTags, false);
*aResult = !!parent;
return NS_OK;
}
GMPParent*
GeckoMediaPluginService::SelectPluginForAPI(const nsAString& aOrigin,
GeckoMediaPluginService::SelectPluginForAPI(const nsACString& aNodeId,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags,
bool aCloneCrossOrigin)
bool aCloneCrossNodeIds)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread || !aCloneCrossOrigin,
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread || !aCloneCrossNodeIds,
"Can't clone GMP plugins on non-GMP threads.");
GMPParent* gmpToClone = nullptr;
@ -698,14 +734,13 @@ GeckoMediaPluginService::SelectPluginForAPI(const nsAString& aOrigin,
if (!supportsAllTags) {
continue;
}
if (aOrigin.IsEmpty()) {
if (gmp->CanBeSharedCrossOrigin()) {
if (aNodeId.IsEmpty()) {
if (gmp->CanBeSharedCrossNodeIds()) {
return gmp;
}
} else if (gmp->CanBeUsedFrom(aOrigin)) {
if (!aOrigin.IsEmpty()) {
gmp->SetOrigin(aOrigin);
}
} else if (gmp->CanBeUsedFrom(aNodeId)) {
MOZ_ASSERT(!aNodeId.IsEmpty());
gmp->SetNodeId(aNodeId);
return gmp;
}
@ -717,10 +752,10 @@ GeckoMediaPluginService::SelectPluginForAPI(const nsAString& aOrigin,
// Plugin exists, but we can't use it due to cross-origin separation. Create a
// new one.
if (aCloneCrossOrigin && gmpToClone) {
if (aCloneCrossNodeIds && gmpToClone) {
GMPParent* clone = ClonePlugin(gmpToClone);
if (!aOrigin.IsEmpty()) {
clone->SetOrigin(aOrigin);
if (!aNodeId.IsEmpty()) {
clone->SetNodeId(aNodeId);
}
return clone;
}
@ -855,5 +890,256 @@ GeckoMediaPluginService::ReAddOnGMPThread(nsRefPtr<GMPParent>& aOld)
NS_DispatchToCurrentThread(WrapRunnableNM(&Dummy, aOld));
}
NS_IMETHODIMP
GeckoMediaPluginService::GetStorageDir(nsIFile** aOutFile)
{
#ifndef MOZ_WIDGET_GONK
if (NS_WARN_IF(!mStorageBaseDir)) {
return NS_ERROR_FAILURE;
}
return mStorageBaseDir->Clone(aOutFile);
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
static nsresult
WriteToFile(nsIFile* aPath,
const nsCString& aFileName,
const nsCString& aData)
{
nsCOMPtr<nsIFile> path;
nsresult rv = aPath->Clone(getter_AddRefs(path));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = path->AppendNative(aFileName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
PRFileDesc* f = nullptr;
rv = path->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE, PR_IRWXU, &f);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
int32_t len = PR_Write(f, aData.get(), aData.Length());
PR_Close(f);
if (NS_WARN_IF(len < 0 || (size_t)len != aData.Length())) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
static nsresult
ReadFromFile(nsIFile* aPath,
const nsCString& aFileName,
nsCString& aOutData,
int32_t aMaxLength)
{
nsCOMPtr<nsIFile> path;
nsresult rv = aPath->Clone(getter_AddRefs(path));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = path->AppendNative(aFileName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
PRFileDesc* f = nullptr;
rv = path->OpenNSPRFileDesc(PR_RDONLY | PR_CREATE_FILE, PR_IRWXU, &f);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
auto size = PR_Seek(f, 0, PR_SEEK_END);
PR_Seek(f, 0, PR_SEEK_SET);
if (size > aMaxLength) {
return NS_ERROR_FAILURE;
}
aOutData.SetLength(size);
auto len = PR_Read(f, aOutData.BeginWriting(), size);
PR_Close(f);
if (NS_WARN_IF(len != size)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
GeckoMediaPluginService::IsPersistentStorageAllowed(const nsACString& aNodeId,
bool* aOutAllowed)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
NS_ENSURE_ARG(aOutAllowed);
*aOutAllowed = mPersistentStorageAllowed.Get(aNodeId);
return NS_OK;
}
NS_IMETHODIMP
GeckoMediaPluginService::GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsing,
nsACString& aOutId)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
LOGD(("%s::%s: (%s, %s), %s", __CLASS__, __FUNCTION__,
NS_ConvertUTF16toUTF8(aOrigin).get(),
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
(aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing")));
#ifdef MOZ_WIDGET_GONK
NS_WARNING("GeckoMediaPluginService::GetNodeId Not implemented on B2G");
return NS_ERROR_NOT_IMPLEMENTED;
#endif
nsresult rv;
const uint32_t NodeIdSaltLength = 32;
if (aOrigin.EqualsLiteral("null") ||
aOrigin.IsEmpty() ||
aTopLevelOrigin.EqualsLiteral("null") ||
aTopLevelOrigin.IsEmpty()) {
// At least one of the (origin, topLevelOrigin) is null or empty;
// probably a local file. Generate a random node id, and don't store
// it so that the GMP's storage is temporary and not shared.
nsAutoCString salt;
rv = GenerateRandomPathName(salt, NodeIdSaltLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
aOutId = salt;
mPersistentStorageAllowed.Put(salt, false);
return NS_OK;
}
const uint32_t hash = AddToHash(HashString(aOrigin),
HashString(aTopLevelOrigin));
if (aInPrivateBrowsing) {
// For PB mode, we store the node id, indexed by the origin pair,
// so that if the same origin pair is opened in this session, it gets
// the same node id.
nsCString* salt = nullptr;
if (!(salt = mTempNodeIds.Get(hash))) {
// No salt stored, generate and temporarily store some for this id.
nsAutoCString newSalt;
rv = GenerateRandomPathName(newSalt, NodeIdSaltLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
salt = new nsCString(newSalt);
mTempNodeIds.Put(hash, salt);
mPersistentStorageAllowed.Put(*salt, false);
}
aOutId = *salt;
return NS_OK;
}
// Otherwise, try to see if we've previously generated and stored salt
// for this origin pair.
nsCOMPtr<nsIFile> path; // $profileDir/gmp/
rv = GetStorageDir(getter_AddRefs(path));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = path->AppendNative(NS_LITERAL_CSTRING("id"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// $profileDir/gmp/id/
rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700);
if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsAutoCString hashStr;
hashStr.AppendInt((int64_t)hash);
// $profileDir/gmp/id/$hash
rv = path->AppendNative(hashStr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700);
if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIFile> saltFile;
rv = path->Clone(getter_AddRefs(saltFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = saltFile->AppendNative(NS_LITERAL_CSTRING("salt"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsAutoCString salt;
bool exists = false;
rv = saltFile->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!exists) {
// No stored salt for this origin. Generate salt, and store it and
// the origin on disk.
nsresult rv = GenerateRandomPathName(salt, NodeIdSaltLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(salt.Length() == NodeIdSaltLength);
// $profileDir/gmp/id/$hash/salt
rv = WriteToFile(path, NS_LITERAL_CSTRING("salt"), salt);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// $profileDir/gmp/id/$hash/origin
rv = WriteToFile(path,
NS_LITERAL_CSTRING("origin"),
NS_ConvertUTF16toUTF8(aOrigin));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// $profileDir/gmp/id/$hash/topLevelOrigin
rv = WriteToFile(path,
NS_LITERAL_CSTRING("topLevelOrigin"),
NS_ConvertUTF16toUTF8(aTopLevelOrigin));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
rv = ReadFromFile(path,
NS_LITERAL_CSTRING("salt"),
salt,
NodeIdSaltLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
aOutId = salt;
mPersistentStorageAllowed.Put(salt, true);
return NS_OK;
}
} // namespace gmp
} // namespace mozilla

Просмотреть файл

@ -17,6 +17,8 @@
#include "nsIThread.h"
#include "nsThreadUtils.h"
#include "nsITimer.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
template <class> struct already_AddRefed;
@ -32,7 +34,7 @@ public:
static already_AddRefed<GeckoMediaPluginService> GetGeckoMediaPluginService();
GeckoMediaPluginService();
void Init();
nsresult Init();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_MOZIGECKOMEDIAPLUGINSERVICE
@ -45,10 +47,10 @@ public:
private:
~GeckoMediaPluginService();
GMPParent* SelectPluginForAPI(const nsAString& aOrigin,
GMPParent* SelectPluginForAPI(const nsACString& aNodeId,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags,
bool aCloneCrossOrigin = true);
bool aCloneCrossNodeIds = true);
void UnloadPlugins();
void CrashPlugins();
@ -111,6 +113,18 @@ private:
nsTArray<nsRefPtr<GMPParent>> mAsyncShutdownPlugins; // GMP Thread only.
nsCOMPtr<nsITimer> mAsyncShutdownTimeout; // GMP Thread only.
#ifndef MOZ_WIDGET_GONK
nsCOMPtr<nsIFile> mStorageBaseDir;
#endif
// Hashes of (origin,topLevelOrigin) to the node id for
// non-persistent sessions.
nsClassHashtable<nsUint32HashKey, nsCString> mTempNodeIds;
// Hashes node id to whether that node id is allowed to store data
// persistently on disk.
nsDataHashtable<nsCStringHashKey, bool> mPersistentStorageAllowed;
};
} // namespace gmp

Просмотреть файл

@ -8,9 +8,16 @@
#include "plhash.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "GMPParent.h"
#include "gmp-storage.h"
#include "mozilla/unused.h"
#include "nsTHashtable.h"
#include "nsDataHashtable.h"
#include "prio.h"
#include "mozIGeckoMediaPluginService.h"
#include "nsContentCID.h"
#include "nsServiceManagerUtils.h"
namespace mozilla {
@ -35,55 +42,38 @@ extern PRLogModuleInfo* GetGMPLog();
namespace gmp {
class GetTempDirTask : public nsRunnable
{
public:
NS_IMETHOD Run() {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIFile> tmpFile;
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
tmpFile->GetPath(mPath);
return NS_OK;
}
nsString mPath;
};
// We store the records in files in the system temp dir.
// We store the records in files in the profile dir.
// $profileDir/gmp/storage/$nodeId/
static nsresult
GetGMPStorageDir(nsIFile** aTempDir, const nsString& aOrigin)
GetGMPStorageDir(nsIFile** aTempDir, const nsCString& aNodeId)
{
if (NS_WARN_IF(!aTempDir)) {
return NS_ERROR_INVALID_ARG;
}
// Directory service is main thread only...
nsRefPtr<GetTempDirTask> task = new GetTempDirTask();
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
mozilla::SyncRunnable::DispatchToThread(mainThread, task);
nsCOMPtr<mozIGeckoMediaPluginService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (NS_WARN_IF(!mps)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIFile> tmpFile;
nsresult rv = NS_NewLocalFile(task->mPath, false, getter_AddRefs(tmpFile));
nsresult rv = mps->GetStorageDir(getter_AddRefs(tmpFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = tmpFile->AppendNative(nsDependentCString("mozilla-gmp-storage"));
rv = tmpFile->AppendNative(NS_LITERAL_CSTRING("storage"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// TODO: When aOrigin is the same node-id as the GMP sees in the child
// process (a UUID or somesuch), we can just append it un-hashed here.
// This should reduce the chance of hash collsions exposing data.
nsAutoString nodeIdHash;
nodeIdHash.AppendInt(HashString(static_cast<const char16_t*>(aOrigin.get())));
rv = tmpFile->Append(nodeIdHash);
rv = tmpFile->Create(nsIFile::DIRECTORY_TYPE, 0700);
if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = tmpFile->AppendNative(aNodeId);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -98,19 +88,11 @@ GetGMPStorageDir(nsIFile** aTempDir, const nsString& aOrigin)
return NS_OK;
}
GMPStorageParent::GMPStorageParent(const nsString& aOrigin,
GMPParent* aPlugin)
: mOrigin(aOrigin)
, mPlugin(aPlugin)
, mShutdown(false)
{
}
enum OpenFileMode { ReadWrite, Truncate };
nsresult
OpenStorageFile(const nsCString& aRecordName,
const nsString& aNodeId,
const nsCString& aNodeId,
const OpenFileMode aMode,
PRFileDesc** aOutFD)
{
@ -134,36 +116,231 @@ OpenStorageFile(const nsCString& aRecordName,
return f->OpenNSPRFileDesc(mode, PR_IRWXU, aOutFD);
}
PLDHashOperator
CloseFile(const nsACString& key, PRFileDesc*& entry, void* cx)
{
if (PR_Close(entry) != PR_SUCCESS) {
NS_WARNING("GMPDiskStorage Failed to clsose file.");
}
return PL_DHASH_REMOVE;
}
class GMPDiskStorage : public GMPStorage {
public:
GMPDiskStorage(const nsCString& aNodeId)
: mNodeId(aNodeId)
{
}
~GMPDiskStorage() {
mFiles.Enumerate(CloseFile, nullptr);
MOZ_ASSERT(!mFiles.Count());
}
virtual GMPErr Open(const nsCString& aRecordName) MOZ_OVERRIDE
{
MOZ_ASSERT(!IsOpen(aRecordName));
PRFileDesc* fd = nullptr;
if (NS_FAILED(OpenStorageFile(aRecordName, mNodeId, ReadWrite, &fd))) {
NS_WARNING("Failed to open storage file.");
return GMPGenericErr;
}
mFiles.Put(aRecordName, fd);
return GMPNoErr;
}
virtual bool IsOpen(const nsCString& aRecordName) MOZ_OVERRIDE {
return mFiles.Contains(aRecordName);
}
virtual GMPErr Read(const nsCString& aRecordName,
nsTArray<uint8_t>& aOutBytes) MOZ_OVERRIDE
{
PRFileDesc* fd = mFiles.Get(aRecordName);
if (!fd) {
return GMPGenericErr;
}
int32_t len = PR_Seek(fd, 0, PR_SEEK_END);
PR_Seek(fd, 0, PR_SEEK_SET);
if (len > GMP_MAX_RECORD_SIZE) {
// Refuse to read big records.
return GMPQuotaExceededErr;
}
aOutBytes.SetLength(len);
auto bytesRead = PR_Read(fd, aOutBytes.Elements(), len);
return (bytesRead == len) ? GMPNoErr : GMPGenericErr;
}
virtual GMPErr Write(const nsCString& aRecordName,
const nsTArray<uint8_t>& aBytes) MOZ_OVERRIDE
{
PRFileDesc* fd = mFiles.Get(aRecordName);
if (!fd) {
return GMPGenericErr;
}
// Write operations overwrite the entire record. So re-open the file
// in truncate mode, to clear its contents.
PR_Close(fd);
mFiles.Remove(aRecordName);
if (NS_FAILED(OpenStorageFile(aRecordName, mNodeId, Truncate, &fd))) {
return GMPGenericErr;
}
mFiles.Put(aRecordName, fd);
int32_t bytesWritten = PR_Write(fd, aBytes.Elements(), aBytes.Length());
return (bytesWritten == (int32_t)aBytes.Length()) ? GMPNoErr : GMPGenericErr;
}
virtual void Close(const nsCString& aRecordName) MOZ_OVERRIDE
{
PRFileDesc* fd = mFiles.Get(aRecordName);
if (fd) {
if (PR_Close(fd) == PR_SUCCESS) {
mFiles.Remove(aRecordName);
} else {
NS_WARNING("GMPDiskStorage Failed to clsose file.");
}
}
}
private:
nsDataHashtable<nsCStringHashKey, PRFileDesc*> mFiles;
const nsAutoCString mNodeId;
};
class GMPMemoryStorage : public GMPStorage {
public:
virtual GMPErr Open(const nsCString& aRecordName) MOZ_OVERRIDE
{
MOZ_ASSERT(!IsOpen(aRecordName));
Record* record = nullptr;
if (!mRecords.Get(aRecordName, &record)) {
record = new Record();
mRecords.Put(aRecordName, record);
}
record->mIsOpen = true;
return GMPNoErr;
}
virtual bool IsOpen(const nsCString& aRecordName) MOZ_OVERRIDE {
Record* record = nullptr;
if (!mRecords.Get(aRecordName, &record)) {
return false;
}
return record->mIsOpen;
}
virtual GMPErr Read(const nsCString& aRecordName,
nsTArray<uint8_t>& aOutBytes) MOZ_OVERRIDE
{
Record* record = nullptr;
if (!mRecords.Get(aRecordName, &record)) {
return GMPGenericErr;
}
aOutBytes = record->mData;
return GMPNoErr;
}
virtual GMPErr Write(const nsCString& aRecordName,
const nsTArray<uint8_t>& aBytes) MOZ_OVERRIDE
{
Record* record = nullptr;
if (!mRecords.Get(aRecordName, &record)) {
return GMPClosedErr;
}
record->mData = aBytes;
return GMPNoErr;
}
virtual void Close(const nsCString& aRecordName) MOZ_OVERRIDE
{
Record* record = nullptr;
if (!mRecords.Get(aRecordName, &record)) {
return;
}
if (!record->mData.Length()) {
// Record is empty, delete.
mRecords.Remove(aRecordName);
} else {
record->mIsOpen = false;
}
}
private:
struct Record {
Record() : mIsOpen(false) {}
nsTArray<uint8_t> mData;
bool mIsOpen;
};
nsClassHashtable<nsCStringHashKey, Record> mRecords;
};
GMPStorageParent::GMPStorageParent(const nsCString& aNodeId,
GMPParent* aPlugin)
: mNodeId(aNodeId)
, mPlugin(aPlugin)
, mShutdown(false)
{
}
nsresult
GMPStorageParent::Init()
{
if (NS_WARN_IF(mNodeId.IsEmpty())) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<mozIGeckoMediaPluginService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (NS_WARN_IF(!mps)) {
return NS_ERROR_FAILURE;
}
bool persistent = false;
if (NS_WARN_IF(NS_FAILED(mps->IsPersistentStorageAllowed(mNodeId, &persistent)))) {
return NS_ERROR_FAILURE;
}
if (persistent) {
mStorage = MakeUnique<GMPDiskStorage>(mNodeId);
} else {
mStorage = MakeUnique<GMPMemoryStorage>();
}
return NS_OK;
}
bool
GMPStorageParent::RecvOpen(const nsCString& aRecordName)
{
if (mShutdown) {
return true;
return false;
}
if (mOrigin.EqualsASCII("null")) {
// Refuse to open storage if the page is the "null" origin; if the page
// is opened from disk.
NS_WARNING("Refusing to open storage for null origin");
if (mNodeId.EqualsLiteral("null")) {
// Refuse to open storage if the page is opened from local disk,
// or shared across origin.
NS_WARNING("Refusing to open storage for null NodeId");
unused << SendOpenComplete(aRecordName, GMPGenericErr);
return true;
}
if (aRecordName.IsEmpty() || mFiles.Contains(aRecordName)) {
if (aRecordName.IsEmpty()) {
unused << SendOpenComplete(aRecordName, GMPGenericErr);
return true;
}
if (mStorage->IsOpen(aRecordName)) {
unused << SendOpenComplete(aRecordName, GMPRecordInUse);
return true;
}
PRFileDesc* fd = nullptr;
nsresult rv = OpenStorageFile(aRecordName, mOrigin, ReadWrite, &fd);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to open storage file.");
unused << SendOpenComplete(aRecordName, GMPGenericErr);
return true;
}
mFiles.Put(aRecordName, fd);
unused << SendOpenComplete(aRecordName, GMPNoErr);
auto err = mStorage->Open(aRecordName);
MOZ_ASSERT(GMP_FAILED(err) || mStorage->IsOpen(aRecordName));
unused << SendOpenComplete(aRecordName, err);
return true;
}
@ -174,29 +351,16 @@ GMPStorageParent::RecvRead(const nsCString& aRecordName)
LOGD(("%s::%s: %p record=%s", __CLASS__, __FUNCTION__, this, aRecordName.get()));
if (mShutdown) {
return true;
return false;
}
PRFileDesc* fd = mFiles.Get(aRecordName);
nsTArray<uint8_t> data;
if (!fd) {
if (!mStorage->IsOpen(aRecordName)) {
unused << SendReadComplete(aRecordName, GMPClosedErr, data);
return true;
} else {
unused << SendReadComplete(aRecordName, mStorage->Read(aRecordName, data), data);
}
int32_t len = PR_Seek(fd, 0, PR_SEEK_END);
PR_Seek(fd, 0, PR_SEEK_SET);
if (len > GMP_MAX_RECORD_SIZE) {
// Refuse to read big records.
unused << SendReadComplete(aRecordName, GMPQuotaExceededErr, data);
return true;
}
data.SetLength(len);
auto bytesRead = PR_Read(fd, data.Elements(), len);
auto res = (bytesRead == len) ? GMPNoErr : GMPGenericErr;
unused << SendReadComplete(aRecordName, res, data);
return true;
}
@ -207,32 +371,21 @@ GMPStorageParent::RecvWrite(const nsCString& aRecordName,
LOGD(("%s::%s: %p record=%s", __CLASS__, __FUNCTION__, this, aRecordName.get()));
if (mShutdown) {
return false;
}
if (!mStorage->IsOpen(aRecordName)) {
unused << SendWriteComplete(aRecordName, GMPClosedErr);
return true;
}
if (aBytes.Length() > GMP_MAX_RECORD_SIZE) {
unused << SendWriteComplete(aRecordName, GMPQuotaExceededErr);
return true;
}
PRFileDesc* fd = mFiles.Get(aRecordName);
if (!fd) {
unused << SendWriteComplete(aRecordName, GMPGenericErr);
return true;
}
unused << SendWriteComplete(aRecordName, mStorage->Write(aRecordName, aBytes));
// Write operations overwrite the entire record. So re-open the file
// in truncate mode, to clear its contents.
PR_Close(fd);
mFiles.Remove(aRecordName);
if (NS_FAILED(OpenStorageFile(aRecordName, mOrigin, Truncate, &fd))) {
unused << SendWriteComplete(aRecordName, GMPGenericErr);
return true;
}
mFiles.Put(aRecordName, fd);
int32_t bytesWritten = PR_Write(fd, aBytes.Elements(), aBytes.Length());
auto res = (bytesWritten == (int32_t)aBytes.Length()) ? GMPNoErr : GMPGenericErr;
unused << SendWriteComplete(aRecordName, res);
return true;
}
@ -245,12 +398,8 @@ GMPStorageParent::RecvClose(const nsCString& aRecordName)
return true;
}
PRFileDesc* fd = mFiles.Get(aRecordName);
if (!fd) {
return true;
}
PR_Close(fd);
mFiles.Remove(aRecordName);
mStorage->Close(aRecordName);
return true;
}
@ -261,13 +410,6 @@ GMPStorageParent::ActorDestroy(ActorDestroyReason aWhy)
Shutdown();
}
PLDHashOperator
CloseFile(const nsACString& key, PRFileDesc*& entry, void* cx)
{
PR_Close(entry);
return PL_DHASH_REMOVE;
}
void
GMPStorageParent::Shutdown()
{
@ -279,8 +421,8 @@ GMPStorageParent::Shutdown()
mShutdown = true;
unused << SendShutdown();
mFiles.Enumerate(CloseFile, nullptr);
MOZ_ASSERT(!mFiles.Count());
mStorage = nullptr;
}
} // namespace gmp

Просмотреть файл

@ -8,20 +8,33 @@
#include "mozilla/gmp/PGMPStorageParent.h"
#include "gmp-storage.h"
#include "nsTHashtable.h"
#include "nsDataHashtable.h"
#include "prio.h"
#include "mozilla/UniquePtr.h"
namespace mozilla {
namespace gmp {
class GMPParent;
class GMPStorage {
public:
virtual ~GMPStorage() {}
virtual GMPErr Open(const nsCString& aRecordName) = 0;
virtual bool IsOpen(const nsCString& aRecordName) = 0;
virtual GMPErr Read(const nsCString& aRecordName,
nsTArray<uint8_t>& aOutBytes) = 0;
virtual GMPErr Write(const nsCString& aRecordName,
const nsTArray<uint8_t>& aBytes) = 0;
virtual void Close(const nsCString& aRecordName) = 0;
};
class GMPStorageParent : public PGMPStorageParent {
public:
NS_INLINE_DECL_REFCOUNTING(GMPStorageParent)
GMPStorageParent(const nsString& aOrigin, GMPParent* aPlugin);
GMPStorageParent(const nsCString& aNodeId,
GMPParent* aPlugin);
nsresult Init();
void Shutdown();
protected:
@ -35,8 +48,9 @@ protected:
private:
~GMPStorageParent() {}
nsDataHashtable<nsCStringHashKey, PRFileDesc*> mFiles;
const nsString mOrigin;
UniquePtr<GMPStorage> mStorage;
const nsCString mNodeId;
nsRefPtr<GMPParent> mPlugin;
bool mShutdown;
};

Просмотреть файл

@ -40,6 +40,8 @@ child:
async PGMPVideoDecoder();
async PGMPVideoEncoder();
async SetNodeId(nsCString nodeId);
async StartPlugin();
async BeginAsyncShutdown();
async CrashPluginNow();
};

Просмотреть файл

@ -1,34 +1,34 @@
/* -*- 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 protocol PGMP;
include GMPTypes;
using GMPErr from "gmp-errors.h";
namespace mozilla {
namespace gmp {
async protocol PGMPStorage
{
manager PGMP;
child:
OpenComplete(nsCString aRecordName, GMPErr aStatus);
ReadComplete(nsCString aRecordName, GMPErr aStatus, uint8_t[] aBytes);
WriteComplete(nsCString aRecordName, GMPErr aStatus);
Shutdown();
parent:
Open(nsCString aRecordName);
Read(nsCString aRecordName);
Write(nsCString aRecordName, uint8_t[] aBytes);
Close(nsCString aRecordName);
__delete__();
};
} // namespace gmp
} // namespace mozilla
/* -*- 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 protocol PGMP;
include GMPTypes;
using GMPErr from "gmp-errors.h";
namespace mozilla {
namespace gmp {
async protocol PGMPStorage
{
manager PGMP;
child:
OpenComplete(nsCString aRecordName, GMPErr aStatus);
ReadComplete(nsCString aRecordName, GMPErr aStatus, uint8_t[] aBytes);
WriteComplete(nsCString aRecordName, GMPErr aStatus);
Shutdown();
parent:
Open(nsCString aRecordName);
Read(nsCString aRecordName);
Write(nsCString aRecordName, uint8_t[] aBytes);
Close(nsCString aRecordName);
__delete__();
};
} // namespace gmp
} // namespace mozilla

Просмотреть файл

@ -90,6 +90,11 @@ UNIFIED_SOURCES += [
'GMPVideoPlaneImpl.cpp',
]
if CONFIG['OS_TARGET'] == 'WINNT':
DIRS += [
'rlz',
]
IPDL_SOURCES += [
'GMPTypes.ipdlh',
'PGMP.ipdl',

Просмотреть файл

@ -6,6 +6,7 @@
#include "nsISupports.idl"
#include "nsIThread.idl"
#include "nsIPrincipal.idl"
#include "nsIFile.idl"
%{C++
#include "nsTArray.h"
@ -25,9 +26,10 @@ class GMPVideoHost;
[ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
[ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy);
[scriptable, uuid(6ea374fc-32ad-46f6-ae9d-80b668f4fd49)]
[scriptable, uuid(b350d3b6-00c9-4602-bdfe-84c2be8d1e7a)]
interface mozIGeckoMediaPluginService : nsISupports
{
/**
* The GMP thread. Callable from any thread.
*/
@ -38,7 +40,7 @@ interface mozIGeckoMediaPluginService : nsISupports
* Callable on any thread
*/
[noscript]
boolean hasPluginForAPI([optional] in AString origin,
boolean hasPluginForAPI([optional] in ACString nodeId,
in ACString api,
in TagArray tags);
@ -50,7 +52,7 @@ interface mozIGeckoMediaPluginService : nsISupports
*/
[noscript]
GMPVideoDecoderProxy getGMPVideoDecoder(in TagArray tags,
[optional] in AString origin,
[optional] in ACString nodeId,
out GMPVideoHost outVideoHost);
/**
@ -61,7 +63,7 @@ interface mozIGeckoMediaPluginService : nsISupports
*/
[noscript]
GMPVideoEncoderProxy getGMPVideoEncoder(in TagArray tags,
[optional] in AString origin,
[optional] in ACString nodeId,
out GMPVideoHost outVideoHost);
// Returns an audio decoder that supports the specified tags.
@ -69,13 +71,13 @@ interface mozIGeckoMediaPluginService : nsISupports
// other tags such as for EME keysystem.
// Callable only on GMP thread.
GMPAudioDecoderProxy getGMPAudioDecoder(in TagArray tags,
[optional] in AString origin);
[optional] in ACString nodeId);
// Returns a decryption session manager that supports the specified tags.
// The array of tags should at least contain a key system tag, and optionally
// other tags.
// Callable only on GMP thread.
GMPDecryptorProxy getGMPDecryptor(in TagArray tags, in AString origin);
GMPDecryptorProxy getGMPDecryptor(in TagArray tags, in ACString nodeId);
/**
* Add a directory to scan for gecko media plugins.
@ -88,4 +90,24 @@ interface mozIGeckoMediaPluginService : nsISupports
* @note Main-thread API.
*/
void removePluginDirectory(in AString directory);
/**
* Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
*/
ACString getNodeId(in AString origin,
in AString topLevelOrigin,
in bool inPrivateBrowsingMode);
/**
* Returns true if the given node id is allowed to store things
* persistently on disk. Private Browsing and local content are not
* allowed to store persistent data.
*/
bool isPersistentStorageAllowed(in ACString nodeId);
/**
* Returns the directory to use as the base for storing data about GMPs.
*/
nsIFile getStorageDir();
};

Просмотреть файл

@ -0,0 +1,14 @@
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Просмотреть файл

@ -0,0 +1,6 @@
Code taken from rlz project: https://code.google.com/p/rlz/
Revision: 134, then with unused code stripped out.
Note: base/ contains wrappers/dummies to provide implementations of the
Chromium APIs that this code relies upon.

Просмотреть файл

@ -0,0 +1,27 @@
/* -*- 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/. */
// The scoped_ptr.h our IPC copy of Chromium's code does not include
// scoped_array, so adapt it to nsAutoArrayPtr here.
#ifndef FAKE_SCOPED_PTR_H_
#define FAKE_SCOPED_PTR_H_
#include "mozilla/ArrayUtils.h"
#include "nsAutoPtr.h"
template<class T>
class scoped_array : public nsAutoArrayPtr<T> {
public:
scoped_array(T* t) : nsAutoArrayPtr<T>(t) {}
void reset(T* t) {
scoped_array<T> other(t);
operator=(other);
}
};
#define arraysize mozilla::ArrayLength
#endif

Просмотреть файл

@ -0,0 +1,12 @@
/* -*- 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/. */
#ifndef FAKE_STRING16_H
#define FAKE_STRING16_H
#include <string>
typedef std::wstring string16;
#endif

Просмотреть файл

@ -0,0 +1,14 @@
/* -*- 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/. */
#ifndef FAKE_ASSERT_H_
#define FAKE_ASSERT_H_
#include <assert.h>
#define ASSERT_STRING(x) { assert(false); }
#define VERIFY(x) { assert(x); };
#endif

Просмотреть файл

@ -0,0 +1,21 @@
// Copyright 2012 Google Inc. All Rights Reserved.
// Use of this source code is governed by an Apache-style license that can be
// found in the COPYING file.
#ifndef RLZ_LIB_MACHINE_ID_H_
#define RLZ_LIB_MACHINE_ID_H_
#include "base/string16.h"
#include <string>
namespace rlz_lib {
// Retrieves a raw machine identifier string and a machine-specific
// 4 byte value. GetMachineId() will SHA1 |data|, append |more_data|, compute
// the Crc8 of that, and return a hex-encoded string of that data.
bool GetRawMachineId(string16* data, int* more_data);
} // namespace rlz_lib
#endif // RLZ_LIB_MACHINE_ID_H_

Просмотреть файл

@ -0,0 +1,34 @@
// Copyright 2010 Google Inc. All Rights Reserved.
// Use of this source code is governed by an Apache-style license that can be
// found in the COPYING file.
//
// String manipulation functions used in the RLZ library.
#include "rlz/lib/string_utils.h"
namespace rlz_lib {
bool BytesToString(const unsigned char* data,
int data_len,
std::string* string) {
if (!string)
return false;
string->clear();
if (data_len < 1 || !data)
return false;
static const char kHex[] = "0123456789ABCDEF";
// Fix the buffer size to begin with to avoid repeated re-allocation.
string->resize(data_len * 2);
int index = data_len;
while (index--) {
string->at(2 * index) = kHex[data[index] >> 4]; // high digit
string->at(2 * index + 1) = kHex[data[index] & 0x0F]; // low digit
}
return true;
}
} // namespace rlz_lib

Просмотреть файл

@ -0,0 +1,20 @@
// Copyright 2010 Google Inc. All Rights Reserved.
// Use of this source code is governed by an Apache-style license that can be
// found in the COPYING file.
//
// String manipulation functions used in the RLZ library.
#ifndef RLZ_LIB_STRING_UTILS_H_
#define RLZ_LIB_STRING_UTILS_H_
#include <string>
namespace rlz_lib {
bool BytesToString(const unsigned char* data,
int data_len,
std::string* string);
}; // namespace
#endif // RLZ_LIB_STRING_UTILS_H_

Просмотреть файл

@ -0,0 +1,20 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
# Note: build rlz in its own moz.build, so it doesn't pickup any of
# Chromium IPC's headers used in the moz.build of the parent file.
UNIFIED_SOURCES += [
'lib/string_utils.cc',
'win/lib/machine_id_win.cc',
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True
LOCAL_INCLUDES += [
'..',
]

Просмотреть файл

@ -0,0 +1,131 @@
// Copyright 2011 Google Inc. All Rights Reserved.
// Use of this source code is governed by an Apache-style license that can be
// found in the COPYING file.
#include <windows.h>
#include <Sddl.h> // For ConvertSidToStringSidW.
#include <string>
#include "base/memory/scoped_ptr.h"
#include "base/string16.h"
#include "rlz/lib/assert.h"
namespace rlz_lib {
namespace {
bool GetSystemVolumeSerialNumber(int* number) {
if (!number)
return false;
*number = 0;
// Find the system root path (e.g: C:\).
wchar_t system_path[MAX_PATH + 1];
if (!GetSystemDirectoryW(system_path, MAX_PATH))
return false;
wchar_t* first_slash = wcspbrk(system_path, L"\\/");
if (first_slash != NULL)
*(first_slash + 1) = 0;
DWORD number_local = 0;
if (!GetVolumeInformationW(system_path, NULL, 0, &number_local, NULL, NULL,
NULL, 0))
return false;
*number = (int)number_local;
return true;
}
bool GetComputerSid(const wchar_t* account_name, SID* sid, DWORD sid_size) {
static const DWORD kStartDomainLength = 128; // reasonable to start with
scoped_array<wchar_t> domain_buffer(new wchar_t[kStartDomainLength]);
DWORD domain_size = kStartDomainLength;
DWORD sid_dword_size = sid_size;
SID_NAME_USE sid_name_use;
BOOL success = ::LookupAccountNameW(NULL, account_name, sid,
&sid_dword_size, domain_buffer.get(),
&domain_size, &sid_name_use);
if (!success && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// We could have gotten the insufficient buffer error because
// one or both of sid and szDomain was too small. Check for that
// here.
if (sid_dword_size > sid_size)
return false;
if (domain_size > kStartDomainLength)
domain_buffer.reset(new wchar_t[domain_size]);
success = ::LookupAccountNameW(NULL, account_name, sid, &sid_dword_size,
domain_buffer.get(), &domain_size,
&sid_name_use);
}
return success != FALSE;
}
std::wstring ConvertSidToString(SID* sid) {
std::wstring sid_string;
#if _WIN32_WINNT >= 0x500
wchar_t* sid_buffer = NULL;
if (ConvertSidToStringSidW(sid, &sid_buffer)) {
sid_string = sid_buffer;
LocalFree(sid_buffer);
}
#else
SID_IDENTIFIER_AUTHORITY* sia = ::GetSidIdentifierAuthority(sid);
if(sia->Value[0] || sia->Value[1]) {
base::SStringPrintf(
&sid_string, L"S-%d-0x%02hx%02hx%02hx%02hx%02hx%02hx",
SID_REVISION, (USHORT)sia->Value[0], (USHORT)sia->Value[1],
(USHORT)sia->Value[2], (USHORT)sia->Value[3], (USHORT)sia->Value[4],
(USHORT)sia->Value[5]);
} else {
ULONG authority = 0;
for (int i = 2; i < 6; ++i) {
authority <<= 8;
authority |= sia->Value[i];
}
base::SStringPrintf(&sid_string, L"S-%d-%lu", SID_REVISION, authority);
}
int sub_auth_count = *::GetSidSubAuthorityCount(sid);
for(int i = 0; i < sub_auth_count; ++i)
base::StringAppendF(&sid_string, L"-%lu", *::GetSidSubAuthority(sid, i));
#endif
return sid_string;
}
} // namespace
bool GetRawMachineId(string16* sid_string, int* volume_id) {
// Calculate the Windows SID.
wchar_t computer_name[MAX_COMPUTERNAME_LENGTH + 1] = {0};
DWORD size = arraysize(computer_name);
if (!GetComputerNameW(computer_name, &size)) {
return false;
}
char sid_buffer[SECURITY_MAX_SID_SIZE];
SID* sid = reinterpret_cast<SID*>(sid_buffer);
if (GetComputerSid(computer_name, sid, SECURITY_MAX_SID_SIZE)) {
*sid_string = ConvertSidToString(sid);
}
// Get the system drive volume serial number.
*volume_id = 0;
if (!GetSystemVolumeSerialNumber(volume_id)) {
ASSERT_STRING("GetMachineId: Failed to retrieve volume serial number");
*volume_id = 0;
}
return true;
}
} // namespace rlz_lib

Просмотреть файл

@ -297,7 +297,7 @@ TheoraState::DecodeHeader(ogg_packet* aPacket)
&mComment,
&mSetup,
aPacket);
// We must determine when we've read the last header packet.
// th_decode_headerin() does not tell us when it's read the last header, so
// we must keep track of the headers externally.
@ -350,7 +350,7 @@ int64_t TheoraState::Time(th_info* aInfo, int64_t aGranulepos)
}
// Implementation of th_granule_frame inlined here to operate
// on the th_info structure instead of the theora_state.
int shift = aInfo->keyframe_granule_shift;
int shift = aInfo->keyframe_granule_shift;
ogg_int64_t iframe = aGranulepos >> shift;
ogg_int64_t pframe = aGranulepos - (iframe << shift);
int64_t frameno = iframe + pframe - TH_VERSION_CHECK(aInfo, 3, 2, 1);
@ -380,7 +380,7 @@ TheoraState::MaxKeyframeOffset()
// Therefore the maximum possible time by which any frame could be offset
// from a keyframe is the duration of (1 << granule_shift) - 1) frames.
int64_t frameDuration;
// Max number of frames keyframe could possibly be offset.
int64_t keyframeDiff = (1 << mInfo.keyframe_granule_shift) - 1;
@ -492,7 +492,7 @@ void TheoraState::ReconstructTheoraGranulepos()
// Theora 3.2.1+ granulepos store frame number [1..N], so granulepos
// should be > 0.
// Theora 3.2.0 granulepos store the frame index [0..(N-1)], so
// granulepos should be >= 0.
// granulepos should be >= 0.
NS_ASSERTION(granulepos >= version_3_2_1,
"Invalid granulepos for Theora version");
@ -724,7 +724,7 @@ nsresult VorbisState::ReconstructVorbisGranulepos()
if (packet->e_o_s && packet->granulepos >= mGranulepos) {
samples = packet->granulepos - mGranulepos;
}
mGranulepos = packet->granulepos;
RecordVorbisPacketSamples(packet, samples);
return NS_OK;
@ -1088,7 +1088,7 @@ SkeletonState::SkeletonState(ogg_page* aBosPage) :
{
MOZ_COUNT_CTOR(SkeletonState);
}
SkeletonState::~SkeletonState()
{
MOZ_COUNT_DTOR(SkeletonState);
@ -1223,11 +1223,11 @@ bool SkeletonState::DecodeIndex(ogg_packet* aPacket)
{
return (mActive = false);
}
int64_t sizeofIndex = aPacket->bytes - INDEX_KEYPOINT_OFFSET;
int64_t maxNumKeyPoints = sizeofIndex / MIN_KEY_POINT_SIZE;
if (aPacket->bytes < minPacketSize.value() ||
numKeyPoints > maxNumKeyPoints ||
numKeyPoints > maxNumKeyPoints ||
numKeyPoints < 0)
{
// Packet size is less than the theoretical minimum size, or the packet is
@ -1244,7 +1244,7 @@ bool SkeletonState::DecodeIndex(ogg_packet* aPacket)
}
nsAutoPtr<nsKeyFrameIndex> keyPoints(new nsKeyFrameIndex(startTime, endTime));
p = aPacket->packet + INDEX_KEYPOINT_OFFSET;
const unsigned char* limit = aPacket->packet + aPacket->bytes;
int64_t numKeyPointsRead = 0;

Просмотреть файл

@ -65,7 +65,7 @@ nsresult RawReader::ReadMetadata(MediaInfo* aInfo,
return NS_ERROR_FAILURE; // Invalid data
// Determine and verify frame display size.
float pixelAspectRatio = static_cast<float>(mMetadata.aspectNumerator) /
float pixelAspectRatio = static_cast<float>(mMetadata.aspectNumerator) /
mMetadata.aspectDenominator;
nsIntSize display(mMetadata.frameWidth, mMetadata.frameHeight);
ScaleDisplayByAspectRatio(display, pixelAspectRatio);
@ -126,7 +126,7 @@ RawReader::IsMediaSeekable()
return false;
}
// Helper method that either reads until it gets aLength bytes
// Helper method that either reads until it gets aLength bytes
// or returns false
bool RawReader::ReadFromResource(MediaResource *aResource, uint8_t* aBuf,
uint32_t aLength)

Просмотреть файл

@ -350,7 +350,7 @@ skip-if = toolkit == 'gonk' && debug
[test_delay_load.html]
skip-if = buildapp == 'b2g' # bug 1021676
[test_encryptedMediaExtensions.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
[test_error_in_video_document.html]
skip-if = toolkit == 'android' # bug 608634
[test_error_on_404.html]

Просмотреть файл

@ -265,7 +265,7 @@ nsresult WaveReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime,
return NS_ERROR_FAILURE;
}
double d = BytesToTime(GetDataLength());
NS_ASSERTION(d < INT64_MAX / USECS_PER_S, "Duration overflow");
NS_ASSERTION(d < INT64_MAX / USECS_PER_S, "Duration overflow");
int64_t duration = static_cast<int64_t>(d * USECS_PER_S);
double seekTime = std::min(aTarget, duration) / static_cast<double>(USECS_PER_S);
int64_t position = RoundDownToFrame(static_cast<int64_t>(TimeToBytes(seekTime)));
@ -291,7 +291,7 @@ nsresult WaveReader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime)
NS_ASSERTION(endOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
// We need to round the buffered ranges' times to microseconds so that they
// have the same precision as the currentTime and duration attribute on
// have the same precision as the currentTime and duration attribute on
// the media element.
aBuffered->Add(RoundToUsecs(BytesToTime(startOffset - mWavePCMOffset)),
RoundToUsecs(BytesToTime(endOffset - mWavePCMOffset)));

Просмотреть файл

@ -71,20 +71,20 @@ class WebMPacketQueue : private nsDeque {
WebMPacketQueue()
: nsDeque(new PacketQueueDeallocator())
{}
~WebMPacketQueue() {
Reset();
}
inline int32_t GetSize() {
inline int32_t GetSize() {
return nsDeque::GetSize();
}
inline void Push(NesteggPacketHolder* aItem) {
NS_ASSERTION(aItem, "NULL pushed to WebMPacketQueue");
nsDeque::Push(aItem);
}
inline void PushFront(NesteggPacketHolder* aItem) {
NS_ASSERTION(aItem, "NULL pushed to WebMPacketQueue");
nsDeque::PushFront(aItem);
@ -93,7 +93,7 @@ class WebMPacketQueue : private nsDeque {
inline NesteggPacketHolder* PopFront() {
return static_cast<NesteggPacketHolder*>(nsDeque::PopFront());
}
void Reset() {
while (GetSize() > 0) {
delete PopFront();
@ -116,7 +116,7 @@ public:
// If the Theora granulepos has not been captured, it may read several packets
// until one with a granulepos has been captured, to ensure that all packets
// read have valid time info.
// read have valid time info.
virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
int64_t aTimeThreshold);

Просмотреть файл

@ -6,7 +6,6 @@
#include "mozilla/dom/DOMException.h"
#include "jsprf.h"
#include "js/OldDebugAPI.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/dom/Exceptions.h"

Просмотреть файл

@ -45,7 +45,6 @@
// Helper Classes
#include "nsJSUtils.h"
#include "jsapi.h" // for JSAutoRequest
#include "js/OldDebugAPI.h" // for JS_ClearWatchPointsForObject
#include "jswrapper.h"
#include "nsReadableUtils.h"
#include "nsDOMClassInfo.h"

Просмотреть файл

@ -43,7 +43,7 @@
#include "xpcpublic.h"
#include "js/OldDebugAPI.h"
#include "jsapi.h"
#include "jswrapper.h"
#include "nsIArray.h"
#include "nsIObjectInputStream.h"

Просмотреть файл

@ -13,7 +13,6 @@
#include "nsJSUtils.h"
#include "jsapi.h"
#include "js/OldDebugAPI.h"
#include "jsfriendapi.h"
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"

Просмотреть файл

@ -18,7 +18,6 @@
#include "AccessCheck.h"
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
#include "nsIDOMGlobalPropertyInitializer.h"

Просмотреть файл

@ -6,7 +6,6 @@
#include "mozilla/dom/Exceptions.h"
#include "js/GCAPI.h"
#include "js/OldDebugAPI.h"
#include "jsapi.h"
#include "jsprf.h"
#include "mozilla/CycleCollectedJSRuntime.h"

Просмотреть файл

@ -6,7 +6,6 @@
#include "jsapi.h"
#include "js/CharacterEncoding.h"
#include "js/OldDebugAPI.h"
#include "nsJSON.h"
#include "nsIXPConnect.h"
#include "nsIXPCScriptable.h"

Просмотреть файл

@ -8,7 +8,7 @@
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "js/OldDebugAPI.h"
#include "jsapi.h"
namespace mozilla {
namespace dom {

Просмотреть файл

@ -8,7 +8,6 @@
#include "RuntimeService.h"
#include "jsapi.h"
#include "js/OldDebugAPI.h"
#include "mozilla/dom/RegisterWorkerBindings.h"
#include "mozilla/OSFileConstants.h"

Просмотреть файл

@ -23,7 +23,6 @@
#include <algorithm>
#include "BackgroundChild.h"
#include "GeckoProfiler.h"
#include "js/OldDebugAPI.h"
#include "jsfriendapi.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/CycleCollectedJSRuntime.h"

Просмотреть файл

@ -31,7 +31,6 @@
#include <algorithm>
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "js/MemoryMetrics.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"

Просмотреть файл

@ -6,7 +6,6 @@
#include "nsXBLSerialize.h"
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "nsXBLPrototypeBinding.h"
#include "nsIXPConnect.h"
#include "nsContentUtils.h"

Просмотреть файл

@ -15,7 +15,6 @@
#include "base/basictypes.h"
#include "jsapi.h"
#include "js/OldDebugAPI.h"
#include "xpcpublic.h"

Просмотреть файл

@ -9,7 +9,6 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "jswrapper.h"
#include "js/OldDebugAPI.h"
#include "mozilla/ModuleUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsMemory.h"

Просмотреть файл

@ -11,7 +11,6 @@
#include "nsString.h"
#include "nsPrintfCString.h"
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
namespace mozilla {
namespace jsipc {

Просмотреть файл

@ -1,43 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 js_OldDebugAPI_h
#define js_OldDebugAPI_h
/*
* JS debugger API.
*/
#include "mozilla/NullPtr.h"
#include "jsapi.h"
#include "jsbytecode.h"
#include "js/CallArgs.h"
#include "js/TypeDecls.h"
typedef enum JSTrapStatus {
JSTRAP_ERROR,
JSTRAP_CONTINUE,
JSTRAP_RETURN,
JSTRAP_THROW,
JSTRAP_LIMIT
} JSTrapStatus;
/************************************************************************/
extern JS_PUBLIC_API(JSScript *)
JS_GetFunctionScript(JSContext *cx, JS::HandleFunction fun);
/************************************************************************/
extern JS_PUBLIC_API(const char *)
JS_GetScriptFilename(JSScript *script);
extern JS_PUBLIC_API(unsigned)
JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
#endif /* js_OldDebugAPI_h */

Просмотреть файл

@ -75,14 +75,7 @@ EvalCacheHashPolicy::match(const EvalCacheEntry &cacheEntry, const EvalCacheLook
cacheEntry.pc == l.pc;
}
// There are two things we want to do with each script executed in EvalKernel:
// 1. notify OldDebugAPI about script creation/destruction
// 2. add the script to the eval cache when EvalKernel is finished
//
// NB: Although the eval cache keeps a script alive wrt to the JS engine, from
// an OldDebugAPI user's perspective, we want each eval() to create and
// destroy a script. This hides implementation details and means we don't have
// to deal with calls to JS_GetScriptObject for scripts in the eval cache.
// Add the script to the eval cache when EvalKernel is finished
class EvalScriptGuard
{
JSContext *cx_;

Просмотреть файл

@ -92,7 +92,7 @@ LBlock::init(TempAllocator &alloc)
// Allocate space for the LPhis.
if (!phis_.init(alloc, numLPhis))
return nullptr;
return false;
// For each MIR phi, set up LIR phis as appropriate. We'll fill in their
// operands on each incoming edge, and set their definitions at the start of

Просмотреть файл

@ -8,7 +8,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "jsapi-tests/tests.h"
BEGIN_TEST(test_cloneScript)

Просмотреть файл

@ -7,7 +7,6 @@
#include "jscntxt.h"
#include "js/OldDebugAPI.h"
#include "jsapi-tests/tests.h"
using namespace js;

Просмотреть файл

@ -9,7 +9,6 @@
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "jsapi-tests/tests.h"
using namespace js;

Просмотреть файл

@ -25,7 +25,6 @@
#include "js/Id.h"
/* LegacyIntTypes.h is deliberately exempted from this requirement */
#include "js/MemoryMetrics.h"
#include "js/OldDebugAPI.h"
#include "js/ProfilingStack.h"
#include "js/PropertyKey.h"
#include "js/RequiredDefines.h"

Просмотреть файл

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "jsapi-tests/tests.h"
static bool sErrorReportMuted = false;

Просмотреть файл

@ -5,7 +5,8 @@
* 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 "js/OldDebugAPI.h"
#include "jsapi.h"
#include "jsapi-tests/tests.h"
const char code[] =

Просмотреть файл

@ -4593,6 +4593,36 @@ JS_GetGlobalFromScript(JSScript *script)
return &script->global();
}
JS_PUBLIC_API(const char *)
JS_GetScriptFilename(JSScript *script)
{
// This is called from ThreadStackHelper which can be called from another
// thread or inside a signal hander, so we need to be careful in case a
// copmacting GC is currently moving things around.
return script->maybeForwardedFilename();
}
JS_PUBLIC_API(unsigned)
JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script)
{
return script->lineno();
}
JS_PUBLIC_API(JSScript *)
JS_GetFunctionScript(JSContext *cx, HandleFunction fun)
{
if (fun->isNative())
return nullptr;
if (fun->isInterpretedLazy()) {
AutoCompartment funCompartment(cx, fun);
JSScript *script = fun->getOrCreateScript(cx);
if (!script)
MOZ_CRASH();
return script;
}
return fun->nonLazyScript();
}
JS_PUBLIC_API(bool)
JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
const char *name, unsigned nargs, const char *const *argnames,

Просмотреть файл

@ -3473,6 +3473,15 @@ JS_CompileUCScript(JSContext *cx, JS::HandleObject obj,
extern JS_PUBLIC_API(JSObject *)
JS_GetGlobalFromScript(JSScript *script);
extern JS_PUBLIC_API(const char *)
JS_GetScriptFilename(JSScript *script);
extern JS_PUBLIC_API(unsigned)
JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
extern JS_PUBLIC_API(JSScript *)
JS_GetFunctionScript(JSContext *cx, JS::HandleFunction fun);
/*
* |fun| will always be set. On failure, it will be set to nullptr.
*/

Просмотреть файл

@ -41,7 +41,6 @@
#include "gc/Marking.h"
#include "jit/Ion.h"
#include "js/CharacterEncoding.h"
#include "js/OldDebugAPI.h"
#include "vm/Debugger.h"
#include "vm/HelperThreads.h"
#include "vm/Shape.h"

Просмотреть файл

@ -44,7 +44,6 @@
#include "gc/Marking.h"
#include "jit/BaselineJIT.h"
#include "js/MemoryMetrics.h"
#include "js/OldDebugAPI.h"
#include "vm/ArgumentsObject.h"
#include "vm/Interpreter.h"
#include "vm/ProxyObject.h"

Просмотреть файл

@ -37,7 +37,6 @@
#include "jit/Ion.h"
#include "jit/IonCode.h"
#include "js/MemoryMetrics.h"
#include "js/OldDebugAPI.h"
#include "js/Utility.h"
#include "vm/ArgumentsObject.h"
#include "vm/Compression.h"

Просмотреть файл

@ -11,7 +11,6 @@
#include "gc/Barrier.h"
#include "js/HashTable.h"
#include "js/OldDebugAPI.h"
namespace js {

Просмотреть файл

@ -75,7 +75,6 @@ EXPORTS.js += [
'../public/Id.h',
'../public/LegacyIntTypes.h',
'../public/MemoryMetrics.h',
'../public/OldDebugAPI.h',
'../public/Principals.h',
'../public/ProfilingFrameIterator.h',
'../public/ProfilingStack.h',
@ -252,7 +251,6 @@ UNIFIED_SOURCES += [
'vm/MemoryMetrics.cpp',
'vm/Monitor.cpp',
'vm/NativeObject.cpp',
'vm/OldDebugAPI.cpp',
'vm/PIC.cpp',
'vm/Probes.cpp',
'vm/PropertyKey.cpp',

Просмотреть файл

@ -64,7 +64,6 @@
#include "jit/arm/Simulator-arm.h"
#include "jit/Ion.h"
#include "js/Debug.h"
#include "js/OldDebugAPI.h"
#include "js/StructuredClone.h"
#include "perf/jsperf.h"
#include "shell/jsheaptools.h"

Просмотреть файл

@ -21,6 +21,14 @@
#include "vm/GlobalObject.h"
#include "vm/SavedStacks.h"
typedef enum JSTrapStatus {
JSTRAP_ERROR,
JSTRAP_CONTINUE,
JSTRAP_RETURN,
JSTRAP_THROW,
JSTRAP_LIMIT
} JSTrapStatus;
namespace js {
class Breakpoint;

Просмотреть файл

@ -34,7 +34,6 @@
#include "jit/BaselineJIT.h"
#include "jit/Ion.h"
#include "jit/IonAnalysis.h"
#include "js/OldDebugAPI.h"
#include "vm/Debugger.h"
#include "vm/Opcodes.h"
#include "vm/Shape.h"

Просмотреть файл

@ -1,72 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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/. */
/*
* JS debugging API.
*/
#include "js/OldDebugAPI.h"
#include <string.h>
#include "jscntxt.h"
#include "jsfun.h"
#include "jsgc.h"
#include "jsobj.h"
#include "jsopcode.h"
#include "jsprf.h"
#include "jsscript.h"
#include "jsstr.h"
#include "jstypes.h"
#include "frontend/SourceNotes.h"
#include "vm/Debugger.h"
#include "vm/Shape.h"
#include "jsatominlines.h"
#include "jsinferinlines.h"
#include "jsscriptinlines.h"
#include "vm/Debugger-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/Stack-inl.h"
using namespace js;
using namespace js::gc;
using mozilla::PodZero;
JS_PUBLIC_API(JSScript *)
JS_GetFunctionScript(JSContext *cx, HandleFunction fun)
{
if (fun->isNative())
return nullptr;
if (fun->isInterpretedLazy()) {
AutoCompartment funCompartment(cx, fun);
JSScript *script = fun->getOrCreateScript(cx);
if (!script)
MOZ_CRASH();
return script;
}
return fun->nonLazyScript();
}
/************************************************************************/
JS_PUBLIC_API(const char *)
JS_GetScriptFilename(JSScript *script)
{
// This is called from ThreadStackHelper which can be called from another
// thread or inside a signal hander, so we need to be careful in case a
// copmacting GC is currently moving things around.
return script->maybeForwardedFilename();
}
JS_PUBLIC_API(unsigned)
JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script)
{
return script->lineno();
}

Просмотреть файл

@ -17,7 +17,6 @@
#ifdef CHECK_OSIPOINT_REGISTERS
#include "jit/Registers.h" // for RegisterDump
#endif
#include "js/OldDebugAPI.h"
struct JSCompartment;
struct JSGenerator;

Просмотреть файл

@ -45,8 +45,6 @@
#include "mozilla/Preferences.h"
#include "mozilla/dom/ScriptSettings.h"
#include "js/OldDebugAPI.h"
using namespace mozilla;
using namespace mozilla::scache;
using namespace xpc;

Просмотреть файл

@ -8,7 +8,6 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "nsJSPrincipals.h"

Просмотреть файл

@ -21,7 +21,6 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "nsJSPrincipals.h"
#include "xpcprivate.h" // For xpc::OptionsBase
#include "jswrapper.h"

Просмотреть файл

@ -11,7 +11,6 @@
#include "AccessCheck.h"
#include "jsfriendapi.h"
#include "jsproxy.h"
#include "js/OldDebugAPI.h"
#include "js/StructuredClone.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"

Просмотреть файл

@ -6,7 +6,6 @@
#include "xpcprivate.h"
#include "jsprf.h"
#include "js/OldDebugAPI.h"
#ifdef XP_WIN
#include <windows.h>

Просмотреть файл

@ -35,7 +35,6 @@
#include "jsfriendapi.h"
#include "jsprf.h"
#include "js/MemoryMetrics.h"
#include "js/OldDebugAPI.h"
#include "mozilla/dom/GeneratedAtomList.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Element.h"

Просмотреть файл

@ -8,7 +8,6 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "jsprf.h"
#include "js/OldDebugAPI.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsServiceManagerUtils.h"
#include "nsComponentManagerUtils.h"

Просмотреть файл

@ -13,7 +13,6 @@
#include "xpcprivate.h"
#include "XPCWrapper.h"
#include "jsfriendapi.h"
#include "js/OldDebugAPI.h"
#include "nsJSEnvironment.h"
#include "nsThreadUtils.h"
#include "nsDOMJSUtils.h"

Просмотреть файл

@ -171,7 +171,7 @@ WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoEncoder(&tags,
NS_LITERAL_STRING(""),
NS_LITERAL_CSTRING(""),
&mHost,
&mGMP)))) {
mMPS = nullptr;
@ -255,7 +255,7 @@ WebrtcGmpVideoEncoder::Encode_g(const webrtc::I420VideoFrame* aInputImage,
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoEncoder(&tags,
NS_LITERAL_STRING(""),
NS_LITERAL_CSTRING(""),
&mHost,
&mGMP)))) {
mGMP = nullptr;
@ -558,7 +558,7 @@ WebrtcGmpVideoDecoder::InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoDecoder(&tags,
NS_LITERAL_STRING(""),
NS_LITERAL_CSTRING(""),
&mHost,
&mGMP)))) {
mMPS = nullptr;

Просмотреть файл

@ -203,7 +203,7 @@ int VcmSIPCCBinding::getVideoCodecsGmp()
// H.264 only for now
bool has_gmp;
nsresult rv;
rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_STRING(""),
rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING(""),
NS_LITERAL_CSTRING("encode-video"),
&tags,
&has_gmp);
@ -211,7 +211,7 @@ int VcmSIPCCBinding::getVideoCodecsGmp()
return 0;
}
rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_STRING(""),
rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING(""),
NS_LITERAL_CSTRING("decode-video"),
&tags,
&has_gmp);

Просмотреть файл

@ -261,4 +261,4 @@ user_pref("browser.uitour.url", "http://%(server)s/uitour-dummy/tour");
user_pref("media.eme.enabled", true);
// Don't prompt about e10s
user_pref("browser.displayedE10SPrompt", 5);
user_pref("browser.displayedE10SPrompt.1", 5);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше