Merge mozilla-central and mozilla-inbound

This commit is contained in:
Matt Brubeck 2012-01-19 11:13:07 -08:00
commit c0ac5a1f10
50 changed files with 1847 additions and 216 deletions

View File

@ -74,7 +74,7 @@ static const NSString* AXRoles [] = {
NSAccessibilityGroupRole, // ROLE_CELL
@"AXLink", // ROLE_LINK. 10.4+ the attr first define in SDK 10.4, so we define it here too. ROLE_LINK
@"AXHelpTag", // ROLE_HELPBALLOON
NSAccessibilityUnknownRole, // ROLE_CHARACTER. unusued on OS X
NSAccessibilityUnknownRole, // ROLE_CHARACTER. unused on OS X
NSAccessibilityListRole, // ROLE_LIST
NSAccessibilityRowRole, // ROLE_LISTITEM
NSAccessibilityOutlineRole, // ROLE_OUTLINE

View File

@ -932,6 +932,8 @@ xpicleanup@BIN_SUFFIX@
#endif
components/txEXSLTRegExFunctions.js
components/Weave.js
components/Webapps.js
components/Webapps.manifest
components/WebContentConverter.js
defaults/autoconfig/platform.js
defaults/autoconfig/prefcalls.js
@ -1057,6 +1059,7 @@ xpicleanup@BIN_SUFFIX@
modules/tabview/AllTabs.jsm
modules/tabview/groups.jsm
modules/tabview/utils.jsm
modules/Webapps.jsm
modules/WindowDraggingUtils.jsm
#ifdef XP_WIN
modules/WindowsJumpLists.jsm
@ -1147,6 +1150,7 @@ xpicleanup@BIN_SUFFIX@
components/directory.xpt
components/docshell.xpt
components/dom.xpt
components/dom_apps.xpt
components/dom_base.xpt
#ifdef MOZ_B2G_RIL
components/dom_telephony.xpt

View File

@ -1999,6 +1999,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
LOG(PR_LOG_DEBUG, ("%p Cloned decoder %p from %p", this, decoder.get(), aOriginal));
if (!decoder->Init(this)) {
LOG(PR_LOG_DEBUG, ("%p Failed to init cloned decoder %p", this, decoder.get()));
return NS_ERROR_FAILURE;
}
@ -2010,6 +2011,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
nsMediaStream* stream = originalStream->CloneData(decoder);
if (!stream) {
LOG(PR_LOG_DEBUG, ("%p Failed to cloned stream for decoder %p", this, decoder.get()));
return NS_ERROR_FAILURE;
}
@ -2017,6 +2019,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
nsresult rv = decoder->Load(stream, nsnull, aOriginal);
if (NS_FAILED(rv)) {
LOG(PR_LOG_DEBUG, ("%p Failed to load decoder/stream for decoder %p", this, decoder.get()));
return rv;
}

View File

@ -193,6 +193,7 @@ nsresult nsBuiltinDecoder::Load(nsMediaStream* aStream,
nsresult rv = aStream->Open(aStreamListener);
if (NS_FAILED(rv)) {
LOG(PR_LOG_DEBUG, ("%p Failed to open stream!", this));
delete aStream;
return rv;
}
@ -245,6 +246,7 @@ nsresult nsBuiltinDecoder::ScheduleStateMachineThread()
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
NS_ASSERTION(mDecoderStateMachine,
"Must have state machine to start state machine thread");
NS_ENSURE_STATE(mDecoderStateMachine);
if (mShuttingDown)
return NS_OK;
@ -258,6 +260,7 @@ nsresult nsBuiltinDecoder::Play()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
NS_ASSERTION(mDecoderStateMachine != nsnull, "Should have state machine.");
nsresult res = ScheduleStateMachineThread();
NS_ENSURE_SUCCESS(res,res);
if (mPlayState == PLAY_STATE_SEEKING) {
@ -832,29 +835,19 @@ void nsBuiltinDecoder::ChangeState(PlayState aState)
}
mPlayState = aState;
switch (aState) {
case PLAY_STATE_PAUSED:
/* No action needed */
break;
case PLAY_STATE_PLAYING:
mDecoderStateMachine->Play();
break;
case PLAY_STATE_SEEKING:
mDecoderStateMachine->Seek(mRequestedSeekTime);
mRequestedSeekTime = -1.0;
break;
case PLAY_STATE_LOADING:
/* No action needed */
break;
case PLAY_STATE_START:
/* No action needed */
break;
case PLAY_STATE_ENDED:
/* No action needed */
break;
case PLAY_STATE_SHUTDOWN:
/* No action needed */
break;
if (mDecoderStateMachine) {
switch (aState) {
case PLAY_STATE_PLAYING:
mDecoderStateMachine->Play();
break;
case PLAY_STATE_SEEKING:
mDecoderStateMachine->Seek(mRequestedSeekTime);
mRequestedSeekTime = -1.0;
break;
default:
/* No action needed */
break;
}
}
mReentrantMonitor.NotifyAll();
}
@ -973,7 +966,9 @@ void nsBuiltinDecoder::Resume(bool aForceBuffering)
}
if (aForceBuffering) {
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mDecoderStateMachine->StartBuffering();
if (mDecoderStateMachine) {
mDecoderStateMachine->StartBuffering();
}
}
}

View File

@ -45,6 +45,7 @@
#include "mozilla/mozalloc.h"
#include "VideoUtils.h"
#include "nsTimeRanges.h"
#include "nsDeque.h"
#include "mozilla/Preferences.h"
#include "mozilla/StdInt.h"
@ -229,6 +230,17 @@ public:
return mStateMachineThread;
}
// Requests that a decode thread be created for aStateMachine. The thread
// may be created immediately, or after some delay, once a thread becomes
// available. The request can be cancelled using CancelCreateDecodeThread().
// It's the callers responsibility to not call this more than once for any
// given state machine.
nsresult RequestCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine);
// Cancels a request made by RequestCreateDecodeThread to create a decode
// thread for aStateMachine.
nsresult CancelCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine);
// Maximum number of active decode threads allowed. When more
// than this number are active the thread creation will fail.
static const PRUint32 MAX_DECODE_THREADS = 25;
@ -238,16 +250,17 @@ public:
// call with any other monitor held to avoid deadlock.
PRUint32 GetDecodeThreadCount();
// Keep track of the fact that a decode thread was created.
// Call on any thread. Holds the internal monitor so don't
// call with any other monitor held to avoid deadlock.
void NoteDecodeThreadCreated();
// Keep track of the fact that a decode thread was destroyed.
// Call on any thread. Holds the internal monitor so don't
// call with any other monitor held to avoid deadlock.
void NoteDecodeThreadDestroyed();
#ifdef DEBUG
// Returns true if aStateMachine has a pending request for a
// decode thread.
bool IsQueued(nsBuiltinDecoderStateMachine* aStateMachine);
#endif
private:
// Holds global instance of StateMachineTracker.
// Writable on main thread only.
@ -271,6 +284,10 @@ private:
// only, read from the decoder threads. Synchronized via
// the mMonitor.
nsIThread* mStateMachineThread;
// Queue of state machines waiting for decode threads. Entries at the front
// get their threads first.
nsDeque mPending;
};
StateMachineTracker* StateMachineTracker::mInstance = nsnull;
@ -296,7 +313,23 @@ void StateMachineTracker::EnsureGlobalStateMachine()
}
mStateMachineCount++;
}
#ifdef DEBUG
bool StateMachineTracker::IsQueued(nsBuiltinDecoderStateMachine* aStateMachine)
{
ReentrantMonitorAutoEnter mon(mMonitor);
PRInt32 size = mPending.GetSize();
for (int i = 0; i < size; ++i) {
nsBuiltinDecoderStateMachine* m =
static_cast<nsBuiltinDecoderStateMachine*>(mPending.ObjectAt(i));
if (m == aStateMachine) {
return true;
}
}
return false;
}
#endif
void StateMachineTracker::CleanupGlobalStateMachine()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
@ -305,6 +338,7 @@ void StateMachineTracker::CleanupGlobalStateMachine()
mStateMachineCount--;
if (mStateMachineCount == 0) {
LOG(PR_LOG_DEBUG, ("Destroying media state machine thread"));
NS_ASSERTION(mPending.GetSize() == 0, "Shouldn't all requests be handled by now?");
{
ReentrantMonitorAutoEnter mon(mMonitor);
nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(mStateMachineThread);
@ -319,16 +353,22 @@ void StateMachineTracker::CleanupGlobalStateMachine()
}
}
void StateMachineTracker::NoteDecodeThreadCreated()
{
ReentrantMonitorAutoEnter mon(mMonitor);
++mDecodeThreadCount;
}
void StateMachineTracker::NoteDecodeThreadDestroyed()
{
ReentrantMonitorAutoEnter mon(mMonitor);
--mDecodeThreadCount;
while (mDecodeThreadCount < MAX_DECODE_THREADS && mPending.GetSize() > 0) {
nsBuiltinDecoderStateMachine* m =
static_cast<nsBuiltinDecoderStateMachine*>(mPending.PopFront());
nsresult rv;
{
ReentrantMonitorAutoExit exitMon(mMonitor);
rv = m->StartDecodeThread();
}
if (NS_SUCCEEDED(rv)) {
++mDecodeThreadCount;
}
}
}
PRUint32 StateMachineTracker::GetDecodeThreadCount()
@ -337,6 +377,45 @@ PRUint32 StateMachineTracker::GetDecodeThreadCount()
return mDecodeThreadCount;
}
nsresult StateMachineTracker::CancelCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine) {
ReentrantMonitorAutoEnter mon(mMonitor);
PRInt32 size = mPending.GetSize();
for (PRInt32 i = 0; i < size; ++i) {
void* m = static_cast<nsBuiltinDecoderStateMachine*>(mPending.ObjectAt(i));
if (m == aStateMachine) {
mPending.RemoveObjectAt(i);
break;
}
}
NS_ASSERTION(!IsQueued(aStateMachine), "State machine should no longer have queued request.");
return NS_OK;
}
nsresult StateMachineTracker::RequestCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine)
{
NS_ENSURE_STATE(aStateMachine);
ReentrantMonitorAutoEnter mon(mMonitor);
if (mPending.GetSize() > 0 || mDecodeThreadCount + 1 >= MAX_DECODE_THREADS) {
// If there's already state machines in the queue, or we've exceeded the
// limit, append the state machine to the queue of state machines waiting
// for a decode thread. This ensures state machines already waiting get
// their threads first.
mPending.Push(aStateMachine);
return NS_OK;
}
nsresult rv;
{
ReentrantMonitorAutoExit exitMon(mMonitor);
rv = aStateMachine->StartDecodeThread();
}
if (NS_SUCCEEDED(rv)) {
++mDecodeThreadCount;
}
NS_ASSERTION(mDecodeThreadCount <= MAX_DECODE_THREADS,
"Should keep to thread limit!");
return NS_OK;
}
nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder,
nsBuiltinDecoderReader* aReader,
bool aRealTime) :
@ -367,6 +446,7 @@ nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDe
mDispatchedRunEvent(false),
mDecodeThreadWaiting(false),
mRealTime(aRealTime),
mRequestedNewDecodeThread(false),
mEventManager(aDecoder)
{
MOZ_COUNT_CTOR(nsBuiltinDecoderStateMachine);
@ -386,6 +466,10 @@ nsBuiltinDecoderStateMachine::~nsBuiltinDecoderStateMachine()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
MOZ_COUNT_DTOR(nsBuiltinDecoderStateMachine);
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
"Should not have a pending request for a new decode thread");
NS_ASSERTION(!mRequestedNewDecodeThread,
"Should not have (or flagged) a pending request for a new decode thread");
if (mTimer)
mTimer->Cancel();
mTimer = nsnull;
@ -1191,6 +1275,14 @@ void nsBuiltinDecoderStateMachine::StopDecodeThread()
{
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
if (mRequestedNewDecodeThread) {
// We've requested that the decode be created, but it hasn't been yet.
// Cancel that request.
NS_ASSERTION(!mDecodeThread,
"Shouldn't have a decode thread until after request processed");
StateMachineTracker::Instance().CancelCreateDecodeThread(this);
mRequestedNewDecodeThread = false;
}
mStopDecodeThread = true;
mDecoder->GetReentrantMonitor().NotifyAll();
if (mDecodeThread) {
@ -1203,6 +1295,10 @@ void nsBuiltinDecoderStateMachine::StopDecodeThread()
mDecodeThread = nsnull;
mDecodeThreadIdle = false;
}
NS_ASSERTION(!mRequestedNewDecodeThread,
"Any pending requests for decode threads must be canceled and unflagged");
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
"Any pending requests for decode threads must be canceled");
}
void nsBuiltinDecoderStateMachine::StopAudioThread()
@ -1221,52 +1317,68 @@ void nsBuiltinDecoderStateMachine::StopAudioThread()
}
nsresult
nsBuiltinDecoderStateMachine::StartDecodeThread()
nsBuiltinDecoderStateMachine::ScheduleDecodeThread()
{
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
PRUint32 count = 0;
bool created = false;
{
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
count = StateMachineTracker::Instance().GetDecodeThreadCount();
}
mStopDecodeThread = false;
if ((mDecodeThread && !mDecodeThreadIdle) || mState >= DECODER_STATE_COMPLETED)
if (mState >= DECODER_STATE_COMPLETED) {
return NS_OK;
if (!mDecodeThread && count > StateMachineTracker::MAX_DECODE_THREADS) {
// Have to run one iteration of the state machine loop to ensure the
// shutdown state is processed.
ScheduleStateMachine();
mState = DECODER_STATE_SHUTDOWN;
return NS_ERROR_FAILURE;
}
if (!mDecodeThread) {
nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
nsnull,
MEDIA_THREAD_STACK_SIZE);
if (NS_FAILED(rv)) {
// Have to run one iteration of the state machine loop to ensure the
// shutdown state is processed.
ScheduleStateMachine();
mState = DECODER_STATE_SHUTDOWN;
return rv;
if (mDecodeThread) {
NS_ASSERTION(!mRequestedNewDecodeThread,
"Shouldn't have requested new decode thread when we have a decode thread");
// We already have a decode thread...
if (mDecodeThreadIdle) {
// ... and it's not been shutdown yet, wake it up.
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
mDecodeThreadIdle = false;
}
created = true;
return NS_OK;
} else if (!mRequestedNewDecodeThread) {
// We don't already have a decode thread, request a new one.
mRequestedNewDecodeThread = true;
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
StateMachineTracker::Instance().RequestCreateDecodeThread(this);
}
return NS_OK;
}
nsresult
nsBuiltinDecoderStateMachine::StartDecodeThread()
{
NS_ASSERTION(StateMachineTracker::Instance().GetDecodeThreadCount() <
StateMachineTracker::MAX_DECODE_THREADS,
"Should not have reached decode thread limit");
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
"Should not already have a pending request for a new decode thread.");
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
NS_ASSERTION(!mDecodeThread, "Should not have decode thread yet");
NS_ASSERTION(mRequestedNewDecodeThread, "Should have requested this...");
mRequestedNewDecodeThread = false;
nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
nsnull,
MEDIA_THREAD_STACK_SIZE);
if (NS_FAILED(rv)) {
// Give up, report error to media element.
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::DecodeError);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
return rv;
}
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
mDecodeThreadIdle = false;
if (created) {
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
StateMachineTracker::Instance().NoteDecodeThreadCreated();
}
return NS_OK;
}
@ -1282,6 +1394,7 @@ nsBuiltinDecoderStateMachine::StartAudioThread()
nsnull,
MEDIA_THREAD_STACK_SIZE);
if (NS_FAILED(rv)) {
LOG(PR_LOG_DEBUG, ("%p Changed state to SHUTDOWN because failed to create audio thread", mDecoder.get()));
mState = DECODER_STATE_SHUTDOWN;
return rv;
}
@ -1639,7 +1752,7 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
case DECODER_STATE_DECODING_METADATA: {
// Ensure we have a decode thread to decode metadata.
return StartDecodeThread();
return ScheduleDecodeThread();
}
case DECODER_STATE_DECODING: {
@ -1663,7 +1776,7 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
// We're playing and/or our decode buffers aren't full. Ensure we have
// an active decode thread.
if (NS_FAILED(StartDecodeThread())) {
if (NS_FAILED(ScheduleDecodeThread())) {
NS_WARNING("Failed to start media decode thread!");
return NS_ERROR_FAILURE;
}
@ -1728,7 +1841,7 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
case DECODER_STATE_SEEKING: {
// Ensure we have a decode thread to perform the seek.
return StartDecodeThread();
return ScheduleDecodeThread();
}
case DECODER_STATE_COMPLETED: {

View File

@ -253,6 +253,12 @@ public:
// earlier, in which case the request is discarded.
nsresult ScheduleStateMachine(PRInt64 aUsecs);
// Creates and starts a new decode thread. Don't call this directly,
// request a new decode thread by calling
// StateMachineTracker::RequestCreateDecodeThread().
// The decoder monitor must not be held. Called on the state machine thread.
nsresult StartDecodeThread();
// Timer function to implement ScheduleStateMachine(aUsecs).
void TimeoutExpired();
@ -352,7 +358,8 @@ protected:
// here. Called on the audio thread.
PRUint32 PlayFromAudioQueue(PRUint64 aFrameOffset, PRUint32 aChannels);
// Stops the decode thread. The decoder monitor must be held with exactly
// Stops the decode thread, and if we have a pending request for a new
// decode thread it is canceled. The decoder monitor must be held with exactly
// one lock count. Called on the state machine thread.
void StopDecodeThread();
@ -360,9 +367,11 @@ protected:
// one lock count. Called on the state machine thread.
void StopAudioThread();
// Starts the decode thread. The decoder monitor must be held with exactly
// one lock count. Called on the state machine thread.
nsresult StartDecodeThread();
// Ensures the decode thread is running if it already exists, or requests
// a new decode thread be started if there currently is no decode thread.
// The decoder monitor must be held with exactly one lock count. Called on
// the state machine thread.
nsresult ScheduleDecodeThread();
// Starts the audio thread. The decoder monitor must be held with exactly
// one lock count. Called on the state machine thread.
@ -625,6 +634,10 @@ protected:
// True is we are decoding a realtime stream, like a camera stream
bool mRealTime;
// True if we've requested a new decode thread, but it has not yet been
// created. Synchronized by the decoder monitor.
bool mRequestedNewDecodeThread;
PRUint32 mBufferingWait;
PRInt64 mLowDataThresholdUsecs;

View File

@ -150,6 +150,7 @@ _TEST_FILES = \
test_source_write.html \
test_standalone.html \
test_timeupdate_small_files.html \
test_too_many_elements.html \
test_volume.html \
test_video_to_canvas.html \
use_large_cache.js \

View File

@ -8,4 +8,4 @@ load 493915-1.html
skip-if(Android) load 495794-1.html
load 492286-1.xhtml
load 576612-1.html
load 691096-1.html
skip-if(Android) load 691096-1.html # Android sound API can't handle playing large number of sounds at once.

View File

@ -5,9 +5,9 @@
// These are small test files, good for just seeing if something loads. We
// really only need one test file per backend here.
var gSmallTests = [
{ name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
{ name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233 },
{ name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
{ name:"seek.webm", type:"video/webm", duration:3.966 },
{ name:"bogus.duh", type:"bogus/duh" }
];
@ -299,6 +299,14 @@ function getPlayableVideo(candidates) {
return null;
}
function getPlayableAudio(candidates) {
var v = document.createElement("audio");
var resources = candidates.filter(function(x){return /^audio/.test(x.type) && v.canPlayType(x.type);});
if (resources.length > 0)
return resources[0];
return null;
}
// Number of tests to run in parallel. Warning: Each media element requires
// at least 3 threads (4 on Linux), and on Linux each thread uses 10MB of
// virtual address space. Beware!

View File

@ -0,0 +1,68 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=713381
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 713381</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=713381">Mozilla Bug 713381</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<p>Received loadeddata event for <span id="result">0</span> <span id="expected"></span>audio elements.</p>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 713381 **/
const num = 500;
var loadeddata = 0;
var result = document.getElementById("result");
document.getElementById("expected").innerHTML = " of " + num + " ";
var finish = function(testNum) {
return function() {
ok(true, "Received loadeddata event for instance " + testNum );
loadeddata++;
if (loadeddata == num) {
ok(true, "Should receive loadeddata events for all " + num + " elements.");
SimpleTest.finish();
}
}
};
var resource = getPlayableAudio(gSmallTests);
if (resource == null) {
todo(false, "No types supported");
} else {
SimpleTest.waitForExplicitFinish();
// Load the resource, and play it to ensure it's entirely downloaded.
// Once it's played through, create a large number of audio elements which
// are the same resource. These will share data with the other resource, and
// so be really cheap to create.
var res = new Audio(resource.name);
res.addEventListener("ended",
function() {
for (var i=0; i<num; ++i) {
var a = new Audio(resource.name);
a.addEventListener("loadeddata", finish(i), false);
}
}, false);
res.play();
}
setInterval(function() { result.innerHTML = loadeddata; }, 1000);
</script>
</pre>
</body>
</html>

View File

@ -66,8 +66,13 @@ DIRS = \
interfaces/notification \
interfaces/svg \
interfaces/smil \
$(NULL)
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
DIRS += \
interfaces/apps \
$(NULL)
endif
DIRS += \
base \

View File

@ -79,6 +79,11 @@ LOCAL_INCLUDES += -I$(topsrcdir)/dom/system/android \
$(NULL)
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
LOCAL_INCLUDES += -I$(topsrcdir)/dom/system/b2g \
$(NULL)
endif
EXPORTS += nsGeoPositionIPCSerialiser.h
include $(topsrcdir)/config/config.mk

View File

@ -88,6 +88,10 @@
#include "AndroidLocationProvider.h"
#endif
#ifdef MOZ_WIDGET_GONK
#include "GonkGPSGeolocationProvider.h"
#endif
#include "nsIDOMDocument.h"
#include "nsIDocument.h"
@ -577,6 +581,13 @@ nsresult nsGeolocationService::Init()
if (provider)
mProviders.AppendObject(provider);
#endif
#ifdef MOZ_WIDGET_GONK
provider = GonkGPSGeolocationProvider::GetSingleton();
if (provider)
mProviders.AppendObject(provider);
#endif
return NS_OK;
}

View File

@ -0,0 +1,185 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Kan-Ru Chen <kchen@mozilla.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <pthread.h>
#include <hardware/gps.h>
#include "mozilla/Preferences.h"
#include "nsGeoPosition.h"
#include "GonkGPSGeolocationProvider.h"
using namespace mozilla;
NS_IMPL_ISUPPORTS1(GonkGPSGeolocationProvider, nsIGeolocationProvider)
GonkGPSGeolocationProvider* GonkGPSGeolocationProvider::sSingleton;
static void
LocationCallback(GpsLocation* location)
{
nsRefPtr<GonkGPSGeolocationProvider> provider =
GonkGPSGeolocationProvider::GetSingleton();
nsCOMPtr<nsIGeolocationUpdate> callback = provider->GetLocationCallback();
if (!callback)
return;
nsRefPtr<nsGeoPosition> somewhere = new nsGeoPosition(location->latitude,
location->longitude,
location->altitude,
location->accuracy,
location->accuracy,
location->bearing,
location->speed,
location->timestamp);
callback->Update(somewhere);
}
typedef void *(*pthread_func)(void *);
/** Callback for creating a thread that can call into the JS codes.
*/
static pthread_t
CreateThreadCallback(const char* name, void (*start)(void *), void* arg)
{
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
/* Unfortunately pthread_create and the callback disagreed on what
* start function should return.
*/
pthread_create(&thread, &attr, reinterpret_cast<pthread_func>(start), arg);
return thread;
}
static GpsCallbacks gCallbacks = {
sizeof(GpsCallbacks),
LocationCallback,
NULL, /* StatusCallback */
NULL, /* SvStatusCallback */
NULL, /* NmeaCallback */
NULL, /* SetCapabilitiesCallback */
NULL, /* AcquireWakelockCallback */
NULL, /* ReleaseWakelockCallback */
CreateThreadCallback,
};
GonkGPSGeolocationProvider::GonkGPSGeolocationProvider()
: mStarted(false)
{
mGpsInterface = GetGPSInterface();
}
GonkGPSGeolocationProvider::~GonkGPSGeolocationProvider()
{
Shutdown();
sSingleton = NULL;
}
/* static */ already_AddRefed<GonkGPSGeolocationProvider>
GonkGPSGeolocationProvider::GetSingleton()
{
if (!sSingleton)
sSingleton = new GonkGPSGeolocationProvider();
NS_ADDREF(sSingleton);
return sSingleton;
}
already_AddRefed<nsIGeolocationUpdate>
GonkGPSGeolocationProvider::GetLocationCallback()
{
nsCOMPtr<nsIGeolocationUpdate> callback = mLocationCallback;
return callback.forget();
}
const GpsInterface*
GonkGPSGeolocationProvider::GetGPSInterface()
{
hw_module_t* module;
if (hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module))
return NULL;
hw_device_t* device;
if (module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device))
return NULL;
gps_device_t* gps_device = (gps_device_t *)device;
return gps_device->get_gps_interface(gps_device);
}
NS_IMETHODIMP
GonkGPSGeolocationProvider::Startup()
{
if (mStarted)
return NS_OK;
NS_ENSURE_TRUE(mGpsInterface, NS_ERROR_FAILURE);
PRInt32 update = Preferences::GetInt("geo.default.update", 1000);
mGpsInterface->init(&gCallbacks);
mGpsInterface->start();
mGpsInterface->set_position_mode(GPS_POSITION_MODE_STANDALONE,
GPS_POSITION_RECURRENCE_PERIODIC,
update, 0, 0);
return NS_OK;
}
NS_IMETHODIMP
GonkGPSGeolocationProvider::Watch(nsIGeolocationUpdate* aCallback)
{
mLocationCallback = aCallback;
return NS_OK;
}
NS_IMETHODIMP
GonkGPSGeolocationProvider::Shutdown()
{
if (!mStarted)
return NS_OK;
mGpsInterface->stop();
mGpsInterface->cleanup();
return NS_OK;
}

View File

@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Kan-Ru Chen <kchen@mozilla.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef GonkGPSGeolocationProvider_h
#define GonkGPSGeolocationProvider_h
#include <hardware/gps.h> // for GpsInterface
#include "nsIGeolocationProvider.h"
class GonkGPSGeolocationProvider : public nsIGeolocationProvider
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIGEOLOCATIONPROVIDER
static already_AddRefed<GonkGPSGeolocationProvider> GetSingleton();
already_AddRefed<nsIGeolocationUpdate> GetLocationCallback();
private:
/* Client should use GetSingleton() to get the provider instance. */
GonkGPSGeolocationProvider();
GonkGPSGeolocationProvider(const GonkGPSGeolocationProvider &);
GonkGPSGeolocationProvider & operator = (const GonkGPSGeolocationProvider &);
~GonkGPSGeolocationProvider();
const GpsInterface* GetGPSInterface();
static GonkGPSGeolocationProvider* sSingleton;
bool mStarted;
const GpsInterface* mGpsInterface;
nsCOMPtr<nsIGeolocationUpdate> mLocationCallback;
};
#endif /* GonkGPSGeolocationProvider_h */

View File

@ -55,7 +55,10 @@ CPPSRCS = \
$(NULL)
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
CPPSRCS += AudioManager.cpp
CPPSRCS += \
AudioManager.cpp \
GonkGPSGeolocationProvider.cpp \
$(NULL)
endif
XPIDLSRCS = \
@ -65,6 +68,7 @@ XPIDLSRCS = \
LOCAL_INCLUDES = \
-I$(topsrcdir)/dom/base \
-I$(topsrcdir)/dom/src/geolocation \
-I$(topsrcdir)/dom/telephony \
-I$(topsrcdir)/dom/wifi \
-I$(topsrcdir)/content/events/src \

View File

@ -14,8 +14,8 @@ SimpleTest.waitForFocus(function () opener.framesetWindowLoaded(window));
<frame src="data:text/html,&lt;html id='f7'&gt;&lt;body id='framebody4'&gt;&lt;input id='f8'&gt;&lt;body&gt;&lt;/html&gt;">
</frameset>
<noframes>
<input id="unusued1"/>
<input id="unusued2" tabindex="1"/>
<input id="unused1"/>
<input id="unused2" tabindex="1"/>
</noframes>
</frameset>

View File

@ -116,6 +116,7 @@ DrawTargetCG::~DrawTargetCG()
CGColorSpaceRelease(mColorSpace);
if (mCg)
CGContextRelease(mCg);
free(mData);
}
TemporaryRef<SourceSurface>
@ -845,7 +846,6 @@ DrawTargetCG::Init(const IntSize &aSize, SurfaceFormat &)
// XXX: currently we allocate ourselves so that we can easily return a gfxImageSurface
// we might not need to later if once we don't need to support gfxImageSurface
//XXX: currently Init implicitly clears, that can often be a waste of time
// XXX: leaked
mData = calloc(mSize.height * stride, 1);
// XXX: what should we do if this fails?
mCg = CGBitmapContextCreate (mData,

View File

@ -131,12 +131,19 @@ endif
EXPORTS_NAMESPACES = gfxipc mozilla/layers
EXPORTS_gfxipc = ShadowLayerUtils.h
EXPORTS_mozilla/layers =\
CompositorCocoaWidgetHelper.h \
CompositorChild.h \
CompositorParent.h \
ShadowLayers.h \
ShadowLayersChild.h \
ShadowLayersParent.h \
ShadowLayersManager.h \
$(NULL)
CPPSRCS += \
CompositorCocoaWidgetHelper.cpp \
CompositorChild.cpp \
CompositorParent.cpp \
ShadowLayers.cpp \
ShadowLayerChild.cpp \
ShadowLayersChild.cpp \

View File

@ -50,7 +50,11 @@ SurfaceToTexture(ID3D10Device *aDevice,
gfxASurface *aSurface,
const gfxIntSize &aSize)
{
if (aSurface && aSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
if (!aSurface) {
return NULL;
}
if (aSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
void *data = aSurface->GetData(&gKeyD3D10Texture);
if (data) {
nsRefPtr<ID3D10Texture2D> texture = static_cast<ID3D10Texture2D*>(data);
@ -67,7 +71,7 @@ SurfaceToTexture(ID3D10Device *aDevice,
if (!imageSurface) {
imageSurface = new gfxImageSurface(aSize,
gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
context->SetSource(aSurface);
context->SetOperator(gfxContext::OPERATOR_SOURCE);
@ -75,13 +79,13 @@ SurfaceToTexture(ID3D10Device *aDevice,
}
D3D10_SUBRESOURCE_DATA data;
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
imageSurface->GetSize().width,
imageSurface->GetSize().height,
1, 1);
desc.Usage = D3D10_USAGE_IMMUTABLE;
data.pSysMem = imageSurface->Data();
data.SysMemPitch = imageSurface->Stride();

View File

@ -0,0 +1,93 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=2 ts=2 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Content App.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benoit Girard <bgirard@mozilla.com>
* Ali Juma <ajuma@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "CompositorChild.h"
#include "CompositorParent.h"
#include "LayerManagerOGL.h"
#include "mozilla/layers/ShadowLayersChild.h"
using mozilla::layers::ShadowLayersChild;
namespace mozilla {
namespace layers {
CompositorChild::CompositorChild(LayerManager *aLayerManager)
: mLayerManager(aLayerManager)
{
MOZ_COUNT_CTOR(CompositorChild);
}
CompositorChild::~CompositorChild()
{
MOZ_COUNT_DTOR(CompositorChild);
}
void
CompositorChild::Destroy()
{
mLayerManager = NULL;
size_t numChildren = ManagedPLayersChild().Length();
NS_ABORT_IF_FALSE(0 == numChildren || 1 == numChildren,
"compositor must only have 0 or 1 layer forwarder");
if (numChildren) {
ShadowLayersChild* layers =
static_cast<ShadowLayersChild*>(ManagedPLayersChild()[0]);
layers->Destroy();
}
SendStop();
}
PLayersChild*
CompositorChild::AllocPLayers(const LayersBackend &backend)
{
return new ShadowLayersChild();
}
bool
CompositorChild::DeallocPLayers(PLayersChild* actor)
{
delete actor;
return true;
}
} // namespace layers
} // namespace mozilla

View File

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Content App.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benoit Girard <bgirard@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_layers_CompositorChild_h
#define mozilla_layers_CompositorChild_h
#include "mozilla/layers/PCompositorChild.h"
namespace mozilla {
namespace layers {
class LayerManager;
class CompositorParent;
class CompositorChild : public PCompositorChild
{
NS_INLINE_DECL_REFCOUNTING(CompositorChild)
public:
CompositorChild(LayerManager *aLayerManager);
virtual ~CompositorChild();
void Destroy();
protected:
virtual PLayersChild* AllocPLayers(const LayersBackend &aBackend);
virtual bool DeallocPLayers(PLayersChild *aChild);
private:
nsRefPtr<LayerManager> mLayerManager;
DISALLOW_EVIL_CONSTRUCTORS(CompositorChild);
};
} // layers
} // mozilla
#endif // mozilla_layers_CompositorChild_h

View File

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=2 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Content App.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benoit Girard <bgirard@mozilla.com>
* Ali Juma <ajuma@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "CompositorParent.h"
#include "CompositorCocoaWidgetHelper.h"
#include "nsDebug.h"
namespace mozilla {
namespace layers {
namespace compositor {
LayerManager*
GetLayerManager(CompositorParent* aParent)
{
return aParent->GetLayerManager();
}
}
}
}

View File

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Content App.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benoit Girard <bgirard@mozilla.com>
* Ali Juma <ajuma@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_layers_CompositorCocoaWidgetHelper_h
#define mozilla_layers_CompositorCocoaWidgetHelper_h
// Note we can't include IPDL-generated headers here, since this file is being
// used as a workaround for Bug 719036.
namespace mozilla {
namespace layers {
class CompositorParent;
class LayerManager;
namespace compositor {
// Needed when we cannot directly include CompositorParent.h since it includes
// an IPDL-generated header (e.g. in widget/cocoa/nsChildView.mm; see Bug 719036).
LayerManager* GetLayerManager(CompositorParent* aParent);
}
}
}
#endif // mozilla_layers_CompositorCocoaWidgetHelper_h

View File

@ -0,0 +1,159 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=2 ts=2 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Content App.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benoit Girard <bgirard@mozilla.com>
* Ali Juma <ajuma@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "CompositorParent.h"
#include "ShadowLayersParent.h"
#include "LayerManagerOGL.h"
#include "nsIWidget.h"
namespace mozilla {
namespace layers {
CompositorParent::CompositorParent(nsIWidget* aWidget)
: mStopped(false), mWidget(aWidget)
{
MOZ_COUNT_CTOR(CompositorParent);
}
CompositorParent::~CompositorParent()
{
MOZ_COUNT_DTOR(CompositorParent);
}
void
CompositorParent::Destroy()
{
NS_ABORT_IF_FALSE(ManagedPLayersParent().Length() == 0,
"CompositorParent destroyed before managed PLayersParent");
// Ensure that the layer manager is destroyed on the compositor thread.
mLayerManager = NULL;
}
bool
CompositorParent::RecvStop()
{
mStopped = true;
Destroy();
return true;
}
void
CompositorParent::ScheduleComposition()
{
CancelableTask *composeTask = NewRunnableMethod(this, &CompositorParent::Composite);
MessageLoop::current()->PostTask(FROM_HERE, composeTask);
}
void
CompositorParent::Composite()
{
if (mStopped || !mLayerManager) {
return;
}
mLayerManager->EndEmptyTransaction();
}
// Go down shadow layer tree, setting properties to match their non-shadow
// counterparts.
static void
SetShadowProperties(Layer* aLayer)
{
// FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
ShadowLayer* shadow = aLayer->AsShadowLayer();
shadow->SetShadowTransform(aLayer->GetTransform());
shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
shadow->SetShadowClipRect(aLayer->GetClipRect());
for (Layer* child = aLayer->GetFirstChild();
child; child = child->GetNextSibling()) {
SetShadowProperties(child);
}
}
void
CompositorParent::ShadowLayersUpdated()
{
const nsTArray<PLayersParent*>& shadowParents = ManagedPLayersParent();
NS_ABORT_IF_FALSE(shadowParents.Length() <= 1,
"can only support at most 1 ShadowLayersParent");
if (shadowParents.Length()) {
Layer* root = static_cast<ShadowLayersParent*>(shadowParents[0])->GetRoot();
mLayerManager->SetRoot(root);
SetShadowProperties(root);
}
ScheduleComposition();
}
PLayersParent*
CompositorParent::AllocPLayers(const LayersBackend &backendType)
{
if (backendType == LayerManager::LAYERS_OPENGL) {
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(mWidget);
mWidget = NULL;
mLayerManager = layerManager;
if (!layerManager->Initialize()) {
NS_ERROR("Failed to init OGL Layers");
return NULL;
}
ShadowLayerManager* slm = layerManager->AsShadowManager();
if (!slm) {
return NULL;
}
return new ShadowLayersParent(slm, this);
} else {
NS_ERROR("Unsupported backend selected for Async Compositor");
return NULL;
}
}
bool
CompositorParent::DeallocPLayers(PLayersParent* actor)
{
delete actor;
return true;
}
} // namespace layers
} // namespace mozilla

View File

@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Content App.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benoit Girard <bgirard@mozilla.com>
* Ali Juma <ajuma@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_layers_CompositorParent_h
#define mozilla_layers_CompositorParent_h
#include "mozilla/layers/PCompositorParent.h"
#include "mozilla/layers/PLayersParent.h"
#include "ShadowLayersManager.h"
class nsIWidget;
namespace mozilla {
namespace layers {
class LayerManager;
class CompositorParent : public PCompositorParent,
public ShadowLayersManager
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
public:
CompositorParent(nsIWidget* aWidget);
virtual ~CompositorParent();
virtual bool RecvStop() MOZ_OVERRIDE;
virtual void ShadowLayersUpdated() MOZ_OVERRIDE;
void Destroy();
LayerManager* GetLayerManager() { return mLayerManager; }
protected:
virtual PLayersParent* AllocPLayers(const LayersBackend &backendType);
virtual bool DeallocPLayers(PLayersParent* aLayers);
private:
void ScheduleComposition();
void Composite();
nsRefPtr<LayerManager> mLayerManager;
bool mStopped;
nsIWidget* mWidget;
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
};
} // layers
} // mozilla
#endif // mozilla_layers_CompositorParent_h

View File

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benoit Girard <bgirard@mozilla.com>
* Ali Juma <ajuma@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
include protocol PLayers;
using mozilla::LayersBackend;
using mozilla::null_t;
namespace mozilla {
namespace layers {
/**
* The PCompositor protocol is used to manage communication between
* the main thread and the compositor thread context. It's primary
* purpose is to manage the PLayers sub protocol.
*/
// This should really be 'sync', but we're using 'rpc' as a workaround
// for Bug 716631.
rpc protocol PCompositor
{
// A Compositor manages a single Layer Manager (PLayers)
manages PLayers;
parent:
// Clean up in preparation for destruction.
sync Stop();
sync PLayers(LayersBackend backend);
};
} // layers
} // mozilla

View File

@ -38,7 +38,7 @@
*
* ***** END LICENSE BLOCK ***** */
//include protocol PCompositor;
include protocol PCompositor;
include protocol PLayer;
include protocol PRenderFrame;
@ -226,7 +226,7 @@ union EditReply {
sync protocol PLayers {
manager PRenderFrame /*or PCompositor or PMedia or PPlugin*/;
manager PRenderFrame or PCompositor;
manages PLayer;
parent:

View File

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Content App.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ali Juma <ajuma@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_layers_ShadowLayersManager_h
#define mozilla_layers_ShadowLayersManager_h
namespace mozilla {
namespace layout {
class RenderFrameParent;
}
namespace layers {
class CompositorParent;
class ShadowLayersManager
{
public:
virtual void ShadowLayersUpdated() = 0;
};
} // layers
} // mozilla
#endif // mozilla_layers_ShadowLayersManager_h

View File

@ -47,6 +47,7 @@
#include "mozilla/unused.h"
#include "mozilla/layout/RenderFrameParent.h"
#include "CompositorParent.h"
#include "gfxSharedImageSurface.h"
@ -121,11 +122,11 @@ ShadowChild(const OpRemoveChild& op)
//--------------------------------------------------
// ShadowLayersParent
ShadowLayersParent::ShadowLayersParent(ShadowLayerManager* aManager)
: mDestroyed(false)
ShadowLayersParent::ShadowLayersParent(ShadowLayerManager* aManager,
ShadowLayersManager* aLayersManager)
: mLayerManager(aManager), mShadowLayersManager(aLayersManager), mDestroyed(false)
{
MOZ_COUNT_CTOR(ShadowLayersParent);
mLayerManager = aManager;
}
ShadowLayersParent::~ShadowLayersParent()
@ -382,7 +383,7 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
// other's buffer contents.
ShadowLayerManager::PlatformSyncBeforeReplyUpdate();
Frame()->ShadowLayersUpdated();
mShadowLayersManager->ShadowLayersUpdated();
return true;
}
@ -400,12 +401,6 @@ ShadowLayersParent::DeallocPLayer(PLayerParent* actor)
return true;
}
RenderFrameParent*
ShadowLayersParent::Frame()
{
return static_cast<RenderFrameParent*>(Manager());
}
void
ShadowLayersParent::DestroySharedSurface(gfxSharedImageSurface* aSurface)
{

View File

@ -43,6 +43,7 @@
#include "mozilla/layers/PLayersParent.h"
#include "ShadowLayers.h"
#include "ShadowLayersManager.h"
namespace mozilla {
@ -63,7 +64,7 @@ class ShadowLayersParent : public PLayersParent,
typedef InfallibleTArray<EditReply> EditReplyArray;
public:
ShadowLayersParent(ShadowLayerManager* aManager);
ShadowLayersParent(ShadowLayerManager* aManager, ShadowLayersManager* aLayersManager);
~ShadowLayersParent();
void Destroy();
@ -83,9 +84,8 @@ protected:
NS_OVERRIDE virtual bool DeallocPLayer(PLayerParent* actor);
private:
RenderFrameParent* Frame();
nsRefPtr<ShadowLayerManager> mLayerManager;
ShadowLayersManager* mShadowLayersManager;
// Hold the root because it might be grafted under various
// containers in the "real" layer tree
nsRefPtr<ContainerLayer> mRoot;

View File

@ -1,4 +1,5 @@
IPDLSRCS = \
PCompositor.ipdl \
PLayer.ipdl \
PLayers.ipdl \
$(NULL)

View File

@ -648,7 +648,7 @@ RenderFrameParent::AllocPLayers(LayerManager::LayersBackend* aBackendType)
return nsnull;
}
*aBackendType = lm->GetBackendType();
return new ShadowLayersParent(slm);
return new ShadowLayersParent(slm, this);
}
bool

View File

@ -42,6 +42,7 @@
#define mozilla_layout_RenderFrameParent_h
#include "mozilla/layout/PRenderFrameParent.h"
#include "mozilla/layers/ShadowLayersManager.h"
#include <map>
#include "nsDisplayList.h"
@ -59,7 +60,8 @@ class ShadowLayersParent;
namespace layout {
class RenderFrameParent : public PRenderFrameParent
class RenderFrameParent : public PRenderFrameParent,
public mozilla::layers::ShadowLayersManager
{
typedef mozilla::layers::FrameMetrics FrameMetrics;
typedef mozilla::layers::ContainerLayer ContainerLayer;
@ -84,7 +86,7 @@ public:
void ContentViewScaleChanged(nsContentView* aView);
void ShadowLayersUpdated();
virtual void ShadowLayersUpdated() MOZ_OVERRIDE;
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsSubDocumentFrame* aFrame,

View File

@ -173,7 +173,7 @@ public class AboutHomeContent extends ScrollView {
activity.stopManagingCursor(mCursor);
ContentResolver resolver = GeckoApp.mAppContext.getContentResolver();
mCursor = BrowserDB.filter(resolver, "", NUMBER_OF_TOP_SITES_PORTRAIT, "about:%");
mCursor = BrowserDB.getTopSites(resolver, NUMBER_OF_TOP_SITES_PORTRAIT);
activity.startManagingCursor(mCursor);
mTopSitesAdapter = new TopSitesCursorAdapter(activity,

View File

@ -63,13 +63,9 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface {
private static final Uri BOOKMARKS_CONTENT_URI_POST_11 = Uri.parse("content://com.android.browser/bookmarks");
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter) {
private Cursor filterAllSites(ContentResolver cr, String[] projection, CharSequence constraint, int limit, CharSequence urlFilter) {
Cursor c = cr.query(Browser.BOOKMARKS_URI,
new String[] { URL_COLUMN_ID,
BookmarkColumns.URL,
BookmarkColumns.TITLE,
BookmarkColumns.FAVICON,
URL_COLUMN_THUMBNAIL },
projection,
// The length restriction on URL is for the same reason as in the general bookmark query
// (see comment earlier in this file).
(urlFilter != null ? "(" + Browser.BookmarkColumns.URL + " NOT LIKE ? ) AND " : "" ) +
@ -86,6 +82,28 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface {
return new AndroidDBCursor(c);
}
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
return filterAllSites(cr,
new String[] { URL_COLUMN_ID,
BookmarkColumns.URL,
BookmarkColumns.TITLE,
BookmarkColumns.FAVICON },
constraint,
limit,
null);
}
public Cursor getTopSites(ContentResolver cr, int limit) {
return filterAllSites(cr,
new String[] { URL_COLUMN_ID,
BookmarkColumns.URL,
BookmarkColumns.TITLE,
URL_COLUMN_THUMBNAIL },
"",
limit,
BrowserDB.ABOUT_PAGES_URL_FILTER);
}
public void updateVisitedHistory(ContentResolver cr, String uri) {
Browser.updateVisitedHistory(cr, uri, true);
}

View File

@ -42,6 +42,8 @@ import android.database.Cursor;
import android.graphics.drawable.BitmapDrawable;
public class BrowserDB {
public static String ABOUT_PAGES_URL_FILTER = "about:%";
public static interface URLColumns {
public static String URL = "url";
public static String TITLE = "title";
@ -53,7 +55,9 @@ public class BrowserDB {
private static BrowserDBIface sDb;
public interface BrowserDBIface {
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter);
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit);
public Cursor getTopSites(ContentResolver cr, int limit);
public void updateVisitedHistory(ContentResolver cr, String uri);
@ -87,12 +91,12 @@ public class BrowserDB {
sDb = new LocalBrowserDB(BrowserContract.DEFAULT_PROFILE);
}
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter) {
return sDb.filter(cr, constraint, limit, urlFilter);
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
return sDb.filter(cr, constraint, limit);
}
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
return sDb.filter(cr, constraint, limit, null);
public static Cursor getTopSites(ContentResolver cr, int limit) {
return sDb.getTopSites(cr, limit);
}
public static void updateVisitedHistory(ContentResolver cr, String uri) {

View File

@ -80,13 +80,9 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
return uri.buildUpon().appendQueryParameter(BrowserContract.PARAM_PROFILE, mProfile).build();
}
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter) {
private Cursor filterAllSites(ContentResolver cr, String[] projection, CharSequence constraint, int limit, CharSequence urlFilter) {
Cursor c = cr.query(appendProfileAndLimit(History.CONTENT_URI, limit),
new String[] { History._ID,
History.URL,
History.TITLE,
History.FAVICON,
History.THUMBNAIL },
projection,
(urlFilter != null ? "(" + History.URL + " NOT LIKE ? ) AND " : "" ) +
"(" + History.URL + " LIKE ? OR " + History.TITLE + " LIKE ?)",
urlFilter == null ? new String[] {"%" + constraint.toString() + "%", "%" + constraint.toString() + "%"} :
@ -100,6 +96,28 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
return new LocalDBCursor(c);
}
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
return filterAllSites(cr,
new String[] { History._ID,
History.URL,
History.TITLE,
History.FAVICON },
constraint,
limit,
null);
}
public Cursor getTopSites(ContentResolver cr, int limit) {
return filterAllSites(cr,
new String[] { History._ID,
History.URL,
History.TITLE,
History.THUMBNAIL },
"",
limit,
BrowserDB.ABOUT_PAGES_URL_FILTER);
}
private void truncateHistory(ContentResolver cr) {
Cursor cursor = null;

View File

@ -424,6 +424,7 @@ OS_LIBS += \
-lui \
-lmedia \
-lhardware_legacy \
-lhardware \
$(NULL)
endif

View File

@ -48,9 +48,13 @@ LPCTSTR UACHelper::PrivsToDisable[] = {
SE_ASSIGNPRIMARYTOKEN_NAME,
SE_AUDIT_NAME,
SE_BACKUP_NAME,
// From testing ReadDirectoryChanges still succeeds even with a low
// integrity process with the following privilege disabled.
SE_CHANGE_NOTIFY_NAME,
// CreateProcess will succeed but the app will fail to launch on some WinXP
// machines if SE_CHANGE_NOTIFY_NAME is disabled. In particular this happens
// for limited user accounts on those machines. The define is kept here as a
// reminder that it should never be re-added.
// This permission is for directory watching but also from MSDN: "This
// privilege also causes the system to skip all traversal access checks."
// SE_CHANGE_NOTIFY_NAME,
SE_CREATE_GLOBAL_NAME,
SE_CREATE_PAGEFILE_NAME,
SE_CREATE_PERMANENT_NAME,

View File

@ -248,6 +248,77 @@ NS_IMETHODIMP nsOSHelperAppService::GetFromTypeAndExtension(const nsACString& aT
return nsExternalHelperAppService::GetFromTypeAndExtension(aType, aFileExt, aMIMEInfo);
}
// Returns the MIME types an application bundle explicitly claims to handle.
// Returns NULL if aAppRef doesn't explicitly claim to handle any MIME types.
// If the return value is non-NULL, the caller is responsible for freeing it.
// This isn't necessarily the same as the MIME types the application bundle
// is registered to handle in the Launch Services database. (For example
// the Preview application is normally registered to handle the application/pdf
// MIME type, even though it doesn't explicitly claim to handle *any* MIME
// types in its Info.plist. This is probably because Preview does explicitly
// claim to handle the com.adobe.pdf UTI, and Launch Services somehow
// translates this into a claim to support the application/pdf MIME type.
// Launch Services doesn't provide any APIs (documented or undocumented) to
// query which MIME types a given application is registered to handle. So any
// app that wants this information (e.g. the Default Apps pref pane) needs to
// iterate through the entire Launch Services database -- a process which can
// take several seconds.)
static CFArrayRef GetMIMETypesHandledByApp(FSRef *aAppRef)
{
CFURLRef appURL = ::CFURLCreateFromFSRef(kCFAllocatorDefault, aAppRef);
if (!appURL) {
return NULL;
}
CFDictionaryRef infoDict = ::CFBundleCopyInfoDictionaryForURL(appURL);
::CFRelease(appURL);
if (!infoDict) {
return NULL;
}
CFTypeRef cfObject = ::CFDictionaryGetValue(infoDict, CFSTR("CFBundleDocumentTypes"));
::CFRelease(infoDict);
if (!cfObject || (::CFGetTypeID(cfObject) != ::CFArrayGetTypeID())) {
return NULL;
}
CFArrayRef docTypes = static_cast<CFArrayRef>(cfObject);
CFIndex docTypesCount = ::CFArrayGetCount(docTypes);
if (docTypesCount == 0) {
return NULL;
}
CFMutableArrayRef mimeTypes =
::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
for (CFIndex i = 0; i < docTypesCount; ++i) {
cfObject = ::CFArrayGetValueAtIndex(docTypes, i);
if (!cfObject || (::CFGetTypeID(cfObject) != ::CFDictionaryGetTypeID())) {
continue;
}
CFDictionaryRef typeDict = static_cast<CFDictionaryRef>(cfObject);
// When this key is present (on OS X 10.5 and later), its contents
// take precedence over CFBundleTypeMIMETypes (and CFBundleTypeExtensions
// and CFBundleTypeOSTypes).
cfObject = ::CFDictionaryGetValue(typeDict, CFSTR("LSItemContentTypes"));
if (cfObject && (::CFGetTypeID(cfObject) == ::CFArrayGetTypeID())) {
continue;
}
cfObject = ::CFDictionaryGetValue(typeDict, CFSTR("CFBundleTypeMIMETypes"));
if (!cfObject || (::CFGetTypeID(cfObject) != ::CFArrayGetTypeID())) {
continue;
}
CFArrayRef mimeTypeHolder = static_cast<CFArrayRef>(cfObject);
CFArrayAppendArray(mimeTypes, mimeTypeHolder,
::CFRangeMake(0, ::CFArrayGetCount(mimeTypeHolder)));
}
if (!::CFArrayGetCount(mimeTypes)) {
::CFRelease(mimeTypes);
mimeTypes = NULL;
}
return mimeTypes;
}
// aMIMEType and aFileExt might not match, If they don't we set *aFound to
// false and return a minimal nsIMIMEInfo structure.
already_AddRefed<nsIMIMEInfo>
@ -281,22 +352,25 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
FSRef typeAppFSRef;
FSRef extAppFSRef;
CFStringRef cfMIMEType = NULL;
if (!aMIMEType.IsEmpty()) {
CFURLRef appURL = NULL;
// CFStringCreateWithCString() can fail even if we're not out of memory --
// for example if the 'cStr' parameter is something very wierd (like "ÿÿ~"
// aka "\xFF\xFF~"), or possibly if it can't be interpreted as using what's
// specified in the 'encoding' parameter. See bug 548719.
CFStringRef CFType = ::CFStringCreateWithCString(NULL, flatType.get(), kCFStringEncodingUTF8);
if (CFType) {
err = ::LSCopyApplicationForMIMEType(CFType, kLSRolesAll, &appURL);
cfMIMEType = ::CFStringCreateWithCString(NULL, flatType.get(),
kCFStringEncodingUTF8);
if (cfMIMEType) {
err = ::LSCopyApplicationForMIMEType(cfMIMEType, kLSRolesAll, &appURL);
if ((err == noErr) && appURL && ::CFURLGetFSRef(appURL, &typeAppFSRef)) {
haveAppForType = true;
PR_LOG(mLog, PR_LOG_DEBUG, ("LSCopyApplicationForMIMEType found a default application\n"));
}
if (appURL)
if (appURL) {
::CFRelease(appURL);
::CFRelease(CFType);
}
}
}
if (!aFileExt.IsEmpty()) {
@ -304,15 +378,15 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
// for example if the 'cStr' parameter is something very wierd (like "ÿÿ~"
// aka "\xFF\xFF~"), or possibly if it can't be interpreted as using what's
// specified in the 'encoding' parameter. See bug 548719.
CFStringRef CFExt = ::CFStringCreateWithCString(NULL, flatExt.get(), kCFStringEncodingUTF8);
if (CFExt) {
err = ::LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, CFExt,
CFStringRef cfExt = ::CFStringCreateWithCString(NULL, flatExt.get(), kCFStringEncodingUTF8);
if (cfExt) {
err = ::LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, cfExt,
kLSRolesAll, &extAppFSRef, nsnull);
if (err == noErr) {
haveAppForExt = true;
PR_LOG(mLog, PR_LOG_DEBUG, ("LSGetApplicationForInfo found a default application\n"));
}
::CFRelease(CFExt);
::CFRelease(cfExt);
}
}
@ -329,13 +403,52 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
*aFound = true;
}
} else if (haveAppForExt) {
// If aMIMEType isn't empty, it doesn't match aFileExt.
// If aMIMEType isn't empty, it doesn't match aFileExt, which should mean
// that we haven't found a matching app. But make an exception for an app
// that also explicitly claims to handle aMIMEType, or which doesn't claim
// to handle any MIME types. This helps work around the following Apple
// design flaw:
//
// Launch Services is somewhat unreliable about registering Apple apps to
// handle MIME types. Probably this is because Apple has officially
// deprecated support for MIME types (in favor of UTIs). As a result,
// most of Apple's own apps don't explicitly claim to handle any MIME
// types (instead they claim to handle one or more UTIs). So Launch
// Services must contain logic to translate support for a given UTI into
// support for one or more MIME types, and it doesn't always do this
// correctly. For example DiskImageMounter isn't (by default) registered
// to handle the application/x-apple-diskimage MIME type. See bug 675356.
//
// Apple has also deprecated support for file extensions, and Apple apps
// also don't register to handle them. But for some reason Launch Services
// is (apparently) better about translating support for a given UTI into
// support for one or more file extensions. It's not at all clear why.
if (aMIMEType.IsEmpty()) {
extAppIsDefault = true;
*aFound = true;
} else {
CFArrayRef extAppMIMETypes = GetMIMETypesHandledByApp(&extAppFSRef);
if (extAppMIMETypes) {
if (cfMIMEType) {
if (::CFArrayContainsValue(extAppMIMETypes,
::CFRangeMake(0, ::CFArrayGetCount(extAppMIMETypes)),
cfMIMEType)) {
extAppIsDefault = true;
*aFound = true;
}
}
::CFRelease(extAppMIMETypes);
} else {
extAppIsDefault = true;
*aFound = true;
}
}
}
if (cfMIMEType) {
::CFRelease(cfMIMEType);
}
if (aMIMEType.IsEmpty()) {
if (haveAppForExt) {
// If aMIMEType is empty and we've found a default app for aFileExt, try
@ -382,26 +495,26 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
return nsnull;
}
CFStringRef CFAppName = NULL;
CFStringRef cfAppName = NULL;
if (typeAppIsDefault) {
app->InitWithFSRef(&typeAppFSRef);
::LSCopyItemAttribute((const FSRef *) &typeAppFSRef, kLSRolesAll,
kLSItemDisplayName, (CFTypeRef *) &CFAppName);
kLSItemDisplayName, (CFTypeRef *) &cfAppName);
} else {
app->InitWithFSRef(&extAppFSRef);
::LSCopyItemAttribute((const FSRef *) &extAppFSRef, kLSRolesAll,
kLSItemDisplayName, (CFTypeRef *) &CFAppName);
kLSItemDisplayName, (CFTypeRef *) &cfAppName);
}
if (CFAppName) {
if (cfAppName) {
nsAutoTArray<UniChar, 255> buffer;
CFIndex appNameLength = ::CFStringGetLength(CFAppName);
CFIndex appNameLength = ::CFStringGetLength(cfAppName);
buffer.SetLength(appNameLength);
::CFStringGetCharacters(CFAppName, CFRangeMake(0, appNameLength),
::CFStringGetCharacters(cfAppName, CFRangeMake(0, appNameLength),
buffer.Elements());
nsAutoString appName;
appName.Assign(buffer.Elements(), appNameLength);
mimeInfoMac->SetDefaultDescription(appName);
::CFRelease(CFAppName);
::CFRelease(cfAppName);
}
mimeInfoMac->SetDefaultApplication(app);
@ -424,21 +537,22 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
mimeInfoMac->AppendExtension(preferredExt);
}
CFStringRef CFType = ::CFStringCreateWithCString(NULL, mimeType.get(), kCFStringEncodingUTF8);
CFStringRef CFTypeDesc = NULL;
if (::LSCopyKindStringForMIMEType(CFType, &CFTypeDesc) == noErr) {
CFStringRef cfType = ::CFStringCreateWithCString(NULL, mimeType.get(), kCFStringEncodingUTF8);
CFStringRef cfTypeDesc = NULL;
if (::LSCopyKindStringForMIMEType(cfType, &cfTypeDesc) == noErr) {
nsAutoTArray<UniChar, 255> buffer;
CFIndex typeDescLength = ::CFStringGetLength(CFTypeDesc);
CFIndex typeDescLength = ::CFStringGetLength(cfTypeDesc);
buffer.SetLength(typeDescLength);
::CFStringGetCharacters(CFTypeDesc, CFRangeMake(0, typeDescLength),
::CFStringGetCharacters(cfTypeDesc, CFRangeMake(0, typeDescLength),
buffer.Elements());
nsAutoString typeDesc;
typeDesc.Assign(buffer.Elements(), typeDescLength);
mimeInfoMac->SetDescription(typeDesc);
}
if (CFTypeDesc)
::CFRelease(CFTypeDesc);
::CFRelease(CFType);
if (cfTypeDesc) {
::CFRelease(cfTypeDesc);
}
::CFRelease(cfType);
}
PR_LOG(mLog, PR_LOG_DEBUG, ("OS gave us: type '%s' found '%i'\n", mimeType.get(), *aFound));

View File

@ -119,6 +119,10 @@ namespace mozilla {
namespace gl {
class TextureImage;
}
namespace layers {
class LayerManagerOGL;
}
}
#ifndef NP_NO_CARBON
@ -295,6 +299,9 @@ typedef NSInteger NSEventGestureAxis;
#ifdef __LP64__
BOOL *mSwipeAnimationCancelled;
#endif
// Whether this uses off-main-thread compositing.
BOOL mUsingOMTCompositor;
}
// class initialization
@ -327,6 +334,8 @@ typedef NSInteger NSEventGestureAxis;
// If so, we shouldn't focus or unfocus a plugin.
- (BOOL)isInFailingLeftClickThrough;
- (void)setGLContext:(NSOpenGLContext *)aGLContext;
// Simple gestures support
//
// XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
@ -348,6 +357,8 @@ typedef NSInteger NSEventGestureAxis;
- (void)maybeTrackScrollEventAsSwipe:(NSEvent *)anEvent
scrollOverflow:(PRInt32)overflow;
#endif
- (void)setUsingOMTCompositor:(BOOL)aUseOMTC;
@end
class ChildViewMouseTracker {
@ -433,7 +444,7 @@ public:
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor, PRUint32 aHotspotX, PRUint32 aHotspotY);
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, bool aDoCapture, bool aConsumeRollupEvent);
NS_IMETHOD SetTitle(const nsAString& title);
@ -486,6 +497,7 @@ public:
already_AddRefed<nsAccessible> GetDocumentAccessible();
#endif
virtual void CreateCompositor();
virtual gfxASurface* GetThebesSurface();
virtual void DrawOver(LayerManager* aManager, nsIntRect aRect);

View File

@ -87,6 +87,7 @@
#include "Layers.h"
#include "LayerManagerOGL.h"
#include "GLContext.h"
#include "mozilla/layers/CompositorCocoaWidgetHelper.h"
#include "mozilla/Preferences.h"
@ -1772,6 +1773,22 @@ NSView<mozView>* nsChildView::GetEditorView()
#pragma mark -
void
nsChildView::CreateCompositor()
{
nsBaseWidget::CreateCompositor();
if (mCompositorChild) {
LayerManagerOGL *manager =
static_cast<LayerManagerOGL*>(compositor::GetLayerManager(mCompositorParent));
NSOpenGLContext *glContext =
(NSOpenGLContext *) manager->gl()->GetNativeData(GLContext::NativeGLContext);
[(ChildView *)mView setGLContext:glContext];
[(ChildView *)mView setUsingOMTCompositor:true];
}
}
gfxASurface*
nsChildView::GetThebesSurface()
{
@ -2096,6 +2113,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (void)setGLContext:(NSOpenGLContext *)aGLContext
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
mGLContext = aGLContext;
[mGLContext retain];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (void)dealloc
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
@ -2546,13 +2573,18 @@ NSEvent* gLastDragMouseDownEvent = nil;
}
#endif
if (mGeckoChild->GetLayerManager(nsnull)->GetBackendType() == LayerManager::LAYERS_OPENGL) {
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(mGeckoChild->GetLayerManager(nsnull));
manager->SetClippingRegion(paintEvent.region);
LayerManager *layerManager = mGeckoChild->GetLayerManager(nsnull);
if (layerManager->GetBackendType() == LayerManager::LAYERS_OPENGL) {
NSOpenGLContext *glContext;
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(layerManager);
manager->SetClippingRegion(paintEvent.region);
glContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
if (!mGLContext) {
mGLContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
[mGLContext retain];
[self setGLContext:glContext];
}
mGeckoChild->DispatchWindowEvent(paintEvent);
// Force OpenGL to refresh the very first time we draw. This works around a
@ -2592,6 +2624,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
painted = mGeckoChild->DispatchWindowEvent(paintEvent);
}
// Force OpenGL to refresh the very first time we draw. This works around a
// Mac OS X bug that stops windows updating on OS X when we use OpenGL.
if (painted && !mDidForceRefreshOpenGL &&
layerManager->AsShadowManager() && mUsingOMTCompositor) {
if (!mDidForceRefreshOpenGL) {
[self performSelector:@selector(forceRefreshOpenGL) withObject:nil afterDelay:0];
mDidForceRefreshOpenGL = YES;
}
}
if (!painted && [self isOpaque]) {
// Gecko refused to draw, but we've claimed to be opaque, so we have to
// draw something--fill with white.
@ -3129,6 +3171,12 @@ NSEvent* gLastDragMouseDownEvent = nil;
}
#endif // #ifdef __LP64__
- (void)setUsingOMTCompositor:(BOOL)aUseOMTC
{
mUsingOMTCompositor = aUseOMTC;
}
// Returning NO from this method only disallows ordering on mousedown - in order
// to prevent it for mouseup too, we need to call [NSApp preventWindowOrdering]
// when handling the mousedown event.

View File

@ -38,6 +38,8 @@
#include "mozilla/Util.h"
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/CompositorParent.h"
#include "nsBaseWidget.h"
#include "nsDeviceContext.h"
#include "nsCOMPtr.h"
@ -55,6 +57,7 @@
#include "nsIXULRuntime.h"
#include "nsIGfxInfo.h"
#include "npapi.h"
#include "base/thread.h"
#ifdef DEBUG
#include "nsIObserver.h"
@ -70,6 +73,8 @@ static PRInt32 gNumWidgets;
using namespace mozilla::layers;
using namespace mozilla;
using base::Thread;
using mozilla::ipc::AsyncChannel;
nsIContent* nsBaseWidget::mLastRollup = nsnull;
@ -104,6 +109,7 @@ nsBaseWidget::nsBaseWidget()
, mEventCallback(nsnull)
, mViewCallback(nsnull)
, mContext(nsnull)
, mCompositorThread(nsnull)
, mCursor(eCursor_standard)
, mWindowType(eWindowType_child)
, mBorderStyle(eBorderStyle_none)
@ -142,6 +148,12 @@ nsBaseWidget::~nsBaseWidget()
if (mLayerManager) {
mLayerManager->Destroy();
mLayerManager = nsnull;
}
if (mCompositorChild) {
mCompositorChild->Destroy();
delete mCompositorThread;
}
#ifdef NOISY_WIDGET_LEAKS
@ -814,6 +826,38 @@ nsBaseWidget::GetShouldAccelerate()
return mUseAcceleratedRendering;
}
void nsBaseWidget::CreateCompositor()
{
mCompositorParent = new CompositorParent(this);
mCompositorThread = new Thread("CompositorThread");
if (mCompositorThread->Start()) {
LayerManager* lm = CreateBasicLayerManager();
MessageLoop *childMessageLoop = mCompositorThread->message_loop();
mCompositorChild = new CompositorChild(lm);
AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel();
AsyncChannel::Side childSide = mozilla::ipc::AsyncChannel::Child;
mCompositorChild->Open(parentChannel, childMessageLoop, childSide);
PLayersChild* shadowManager =
mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_OPENGL);
if (shadowManager) {
ShadowLayerForwarder* lf = lm->AsShadowForwarder();
if (!lf) {
delete lm;
mCompositorChild = nsnull;
}
lf->SetShadowManager(shadowManager);
lf->SetParentBackendType(LayerManager::LAYERS_OPENGL);
mLayerManager = lm;
} else {
NS_WARNING("fail to construct LayersChild");
delete lm;
mCompositorChild = nsnull;
}
}
}
LayerManager* nsBaseWidget::GetLayerManager(PLayersChild* aShadowManager,
LayersBackend aBackendHint,
LayerManagerPersistence aPersistence,
@ -824,16 +868,29 @@ LayerManager* nsBaseWidget::GetLayerManager(PLayersChild* aShadowManager,
mUseAcceleratedRendering = GetShouldAccelerate();
if (mUseAcceleratedRendering) {
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
/**
* XXX - On several OSes initialization is expected to fail for now.
* If we'd get a none-basic layer manager they'd crash. This is ok though
* since on those platforms it will fail. Anyone implementing new
* platforms on LayerManagerOGL should ensure their widget is able to
* deal with it though!
*/
if (layerManager->Initialize()) {
mLayerManager = layerManager;
// Try to use an async compositor first, if possible
bool useCompositor =
Preferences::GetBool("layers.offmainthreadcomposition.enabled", false);
if (useCompositor) {
// e10s uses the parameter to pass in the shadow manager from the TabChild
// so we don't expect to see it there since this doesn't support e10s.
NS_ASSERTION(aShadowManager == nsnull, "Async Compositor not supported with e10s");
CreateCompositor();
}
if (!mLayerManager) {
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
/**
* XXX - On several OSes initialization is expected to fail for now.
* If we'd get a non-basic layer manager they'd crash. This is ok though
* since on those platforms it will fail. Anyone implementing new
* platforms on LayerManagerOGL should ensure their widget is able to
* deal with it though!
*/
if (layerManager->Initialize()) {
mLayerManager = layerManager;
}
}
}
if (!mLayerManager) {

View File

@ -51,6 +51,17 @@ class nsIContent;
class nsAutoRollup;
class gfxContext;
namespace mozilla {
namespace layers {
class CompositorChild;
class CompositorParent;
}
}
namespace base {
class Thread;
}
/**
* Common widget implementation used as base class for native
* or crossplatform implementations of Widgets.
@ -66,6 +77,9 @@ class nsBaseWidget : public nsIWidget
protected:
typedef mozilla::layers::BasicLayerManager BasicLayerManager;
typedef mozilla::layers::CompositorChild CompositorChild;
typedef mozilla::layers::CompositorParent CompositorParent;
typedef base::Thread Thread;
public:
nsBaseWidget();
@ -117,6 +131,7 @@ public:
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
bool* aAllowRetaining = nsnull);
virtual void CreateCompositor();
virtual void DrawOver(LayerManager* aManager, nsIntRect aRect) {}
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
virtual gfxASurface* GetThebesSurface();
@ -268,6 +283,9 @@ protected:
nsDeviceContext* mContext;
nsRefPtr<LayerManager> mLayerManager;
nsRefPtr<LayerManager> mBasicLayerManager;
nsRefPtr<CompositorChild> mCompositorChild;
nsRefPtr<CompositorParent> mCompositorParent;
Thread* mCompositorThread;
nscolor mBackground;
nscolor mForeground;
nsCursor mCursor;

View File

@ -350,6 +350,22 @@ void* nsDeque::ObjectAt(PRInt32 aIndex) const {
return result;
}
void* nsDeque::RemoveObjectAt(PRInt32 aIndex) {
if ((aIndex<0) || (aIndex>=mSize)) {
return 0;
}
void* result=mData[modulus(mOrigin + aIndex, mCapacity)];
// "Shuffle down" all elements in the array by 1, overwritting the element
// being removed.
for (PRInt32 i=aIndex; i<mSize; i++) {
mData[modulus(mOrigin + i, mCapacity)] = mData[modulus(mOrigin + i + 1, mCapacity)];
}
mSize--;
return result;
}
/**
* Create and return an iterator pointing to
* the beginning of the queue. Note that this

View File

@ -152,6 +152,14 @@ class NS_COM_GLUE nsDeque {
*/
void* ObjectAt(int aIndex) const;
/**
* Removes and returns the i'th member from the deque.
*
* @param index of desired item
* @return the element which was removed
*/
void* RemoveObjectAt(int aIndex);
/**
* Remove all items from container without destroying them.
*

View File

@ -223,6 +223,39 @@ private:
nsCOMPtr<nsISupports> mSupports;
};
/**
* hashkey wrapper using refcounted * KeyType
*
* @see nsTHashtable::EntryType for specification
*/
template<class T>
class nsRefPtrHashKey : public PLDHashEntryHdr
{
public:
typedef T* KeyType;
typedef const T* KeyTypePointer;
nsRefPtrHashKey(const T* key) :
mKey(const_cast<T*>(key)) { }
nsRefPtrHashKey(const nsRefPtrHashKey& toCopy) :
mKey(toCopy.mKey) { }
~nsRefPtrHashKey() { }
KeyType GetKey() const { return mKey; }
bool KeyEquals(KeyTypePointer aKey) const { return aKey == mKey; }
static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey)
{
return NS_PTR_TO_INT32(aKey) >>2;
}
enum { ALLOW_MEMMOVE = true };
private:
nsRefPtr<T> mKey;
};
/**
* hashkey wrapper using T* KeyType
*

View File

@ -89,6 +89,7 @@ CPP_UNIT_TESTS = \
TestCOMArray.cpp \
TestCOMPtr.cpp \
TestCOMPtrEq.cpp \
TestDeque.cpp \
TestFile.cpp \
TestHashtables.cpp \
TestID.cpp \
@ -109,7 +110,6 @@ endif
#CPP_UNIT_TESTS += \
# TestArray.cpp \
# TestCRT.cpp \
# TestDeque.cpp \
# TestEncoding.cpp \
# TestExpirationTracker.cpp \
# TestPipes.cpp \

View File

@ -35,6 +35,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "TestHarness.h"
#include "nsDeque.h"
#include "nsCRT.h"
#include <stdio.h>
@ -44,13 +45,12 @@
**************************************************************/
class _TestDeque {
public:
_TestDeque() {
SelfTest();
}
int SelfTest();
nsresult OriginalTest();
nsresult OriginalFlaw();
nsresult AssignFlaw();
int Test();
private:
int OriginalTest();
int OriginalFlaw();
int AssignFlaw();
int TestRemove();
};
static _TestDeque sTestDeque;
@ -60,96 +60,214 @@ class _Dealloc: public nsDequeFunctor {
}
};
#define TEST(aCondition, aMsg) \
if (!(aCondition)) { fail("TestDeque: "#aMsg); return 1; }
/**
* conduct automated self test for this class
*
* @param
* @return
*/
int _TestDeque::SelfTest() {
int _TestDeque::Test() {
/* the old deque should have failed a bunch of these tests */
int results=0;
results+=OriginalTest();
results+=OriginalFlaw();
results+=AssignFlaw();
results+=TestRemove();
return results;
}
nsresult _TestDeque::OriginalTest() {
int ints[200];
int count=sizeof(ints)/sizeof(int);
int _TestDeque::OriginalTest() {
const int size = 200;
int ints[size];
int i=0;
int* temp;
int temp;
nsDeque theDeque(new _Dealloc); //construct a simple one...
for (i=0;i<count;i++) { //initialize'em
ints[i]=10*(1+i);
// ints = [0...199]
for (i=0;i<size;i++) { //initialize'em
ints[i]=i;
}
// queue = [0...69]
for (i=0;i<70;i++) {
theDeque.Push(&ints[i]);
temp=*(int*)theDeque.Peek();
TEST(temp == i, "Verify end after push #1");
TEST(theDeque.GetSize() == i + 1, "Verify size after push #1");
}
for (i=0;i<56;i++) {
temp=(int*)theDeque.Pop();
TEST(theDeque.GetSize() == 70, "Verify overall size after pushes #1");
// queue = [0...14]
for (i=1;i<=55;i++) {
temp=*(int*)theDeque.Pop();
TEST(temp == 70-i, "Verify end after pop # 1");
TEST(theDeque.GetSize() == 70 - i, "Verify size after pop # 1");
}
TEST(theDeque.GetSize() == 15, "Verify overall size after pops");
// queue = [0...14,0...54]
for (i=0;i<55;i++) {
theDeque.Push(&ints[i]);
temp=*(int*)theDeque.Peek();
TEST(temp == i, "Verify end after push #2");
TEST(theDeque.GetSize() == i + 15 + 1, "Verify size after push # 2");
}
for (i=0;i<35;i++) {
temp=(int*)theDeque.Pop();
TEST(theDeque.GetSize() == 70, "Verify size after end of all pushes #2");
// queue = [0...14,0...19]
for (i=1;i<=35;i++) {
temp=*(int*)theDeque.Pop();
TEST(temp == 55-i, "Verify end after pop # 2");
TEST(theDeque.GetSize() == 70 - i, "Verify size after pop #2");
}
TEST(theDeque.GetSize() == 35, "Verify overall size after end of all pops #2");
// queue = [0...14,0...19,0...34]
for (i=0;i<35;i++) {
theDeque.Push(&ints[i]);
temp = *(int*)theDeque.Peek();
TEST(temp == i, "Verify end after push # 3");
TEST(theDeque.GetSize() == 35 + 1 + i, "Verify size after push #3");
}
for (i=0;i<38;i++) {
temp=(int*)theDeque.Pop();
// queue = [0...14,0...19]
for (i=0;i<35;i++) {
temp=*(int*)theDeque.Pop();
TEST(temp == 34 - i, "Verify end after pop # 3");
}
return NS_OK;
// queue = [0...14]
for (i=0;i<20;i++) {
temp=*(int*)theDeque.Pop();
TEST(temp == 19 - i, "Verify end after pop # 4");
}
// queue = []
for (i=0;i<15;i++) {
temp=*(int*)theDeque.Pop();
TEST(temp == 14 - i, "Verify end after pop # 5");
}
TEST(theDeque.GetSize() == 0, "Deque should finish empty.");
return 0;
}
nsresult _TestDeque::OriginalFlaw() {
int _TestDeque::OriginalFlaw() {
int ints[200];
int i=0;
int* temp;
nsDeque secondDeque(new _Dealloc);
int temp;
nsDeque d(new _Dealloc);
/**
* Test 1. Origin near end, semi full, call Peek().
* you start, mCapacity is 8
*/
printf("fill array\n");
for (i=32; i; --i)
ints[i]=i*3+10;
printf("push 6 times\n");
for (i=0; i<6; i++)
secondDeque.Push(&ints[i]);
printf("popfront 4 times:\n");
for (i=4; i; --i) {
temp=(int*)secondDeque.PopFront();
printf("%d\t",*temp);
for (i=0; i<30; i++)
ints[i]=i;
for (i=0; i<6; i++) {
d.Push(&ints[i]);
temp = *(int*)d.Peek();
TEST(temp == i, "OriginalFlaw push #1");
}
printf("push 4 times\n");
for (int j=4; j; --j)
secondDeque.Push(&ints[++i]);
printf("origin should now be about 4\n");
printf("and size should be 6\n");
printf("origin+size>capacity\n");
TEST(d.GetSize() == 6, "OriginalFlaw size check #1");
/*<akk> Oh, I see ... it's a circular buffer */
printf("but the old code wasn't behaving accordingly.\n");
for (i=0; i<4; i++) {
temp=*(int*)d.PopFront();
TEST(temp == i, "PopFront test");
}
// d = [4,5]
TEST(d.GetSize() == 2, "OriginalFlaw size check #2");
/*right*/
printf("we shouldn't crash or anything interesting, ");
for (i=0; i<4; i++) {
d.Push(&ints[6 + i]);
}
// d = [4...9]
temp=(int*)secondDeque.Peek();
printf("peek: %d\n",*temp);
return NS_OK;
for (i=4; i<=9; i++) {
temp=*(int*)d.PopFront();
TEST(temp == i, "OriginalFlaw empty check");
}
return 0;
}
nsresult _TestDeque::AssignFlaw() {
int _TestDeque::AssignFlaw() {
nsDeque src(new _Dealloc),dest(new _Dealloc);
return NS_OK;
return 0;
}
static bool VerifyContents(const nsDeque& aDeque, const int* aContents, int aLength) {
for (int i=0; i<aLength; ++i) {
if (*(int*)aDeque.ObjectAt(i) != aContents[i]) {
return false;
}
}
return true;
}
int _TestDeque::TestRemove() {
nsDeque d;
const int count = 10;
int ints[count];
for (int i=0; i<count; i++) {
ints[i] = i;
}
for (int i=0; i<6; i++) {
d.Push(&ints[i]);
}
// d = [0...5]
d.PopFront();
d.PopFront();
// d = [2,5]
for (int i=2; i<=5; i++) {
int t = *(int*)d.ObjectAt(i-2);
TEST(t == i, "Verify ObjectAt()");
}
d.RemoveObjectAt(1);
// d == [2,4,5]
static const int t1[] = {2,4,5};
TEST(VerifyContents(d, t1, 3), "verify contents t1");
d.PushFront(&ints[1]);
d.PushFront(&ints[0]);
d.PushFront(&ints[7]);
d.PushFront(&ints[6]);
// d == [6,7,0,1,2,4,5] // (0==mOrigin)
static const int t2[] = {6,7,0,1,2,4,5};
TEST(VerifyContents(d, t2, 7), "verify contents t2");
d.RemoveObjectAt(1);
// d == [6,0,1,2,4,5] // (1==mOrigin)
static const int t3[] = {6,0,1,2,4,5};
TEST(VerifyContents(d, t3, 6), "verify contents t3");
d.RemoveObjectAt(5);
// d == [6,0,1,2,4] // (1==mOrigin)
static const int t4[] = {6,0,1,2,4};
TEST(VerifyContents(d, t4, 5), "verify contents t4");
d.RemoveObjectAt(0);
// d == [0,1,2,4] // (2==mOrigin)
static const int t5[] = {0,1,2,4};
TEST(VerifyContents(d, t5, 4), "verify contents t5");
return 0;
}
int main (void) {
ScopedXPCOM xpcom("TestTimers");
NS_ENSURE_FALSE(xpcom.failed(), 1);
_TestDeque test;
int result = test.Test();
TEST(result == 0, "All tests pass");
return 0;
}