Merge the last PGO-green inbound changeset to m-c.

This commit is contained in:
Ryan VanderMeulen 2012-12-10 13:56:39 -05:00
commit 81ec2f7d25
143 changed files with 2435 additions and 935 deletions

View File

@ -74,7 +74,7 @@ private:
class EmbeddedObjCollector : public AccCollector
{
public:
virtual ~EmbeddedObjCollector() { };
virtual ~EmbeddedObjCollector() { }
public:
virtual int32_t GetIndexAt(Accessible* aAccessible);

View File

@ -213,7 +213,7 @@ public:
mNode = aTargetNode;
mParent = mAccessible->Parent();
}
virtual ~AccMutationEvent() { };
virtual ~AccMutationEvent() { }
// Event
static const EventGroup kEventGroup = eMutationEvent;
@ -291,7 +291,7 @@ public:
AccReorderEvent(Accessible* aTarget) :
AccEvent(::nsIAccessibleEvent::EVENT_REORDER, aTarget,
eAutoDetect, eCoalesceReorder) { }
virtual ~AccReorderEvent() { };
virtual ~AccReorderEvent() { }
// Event
static const EventGroup kEventGroup = eReorderEvent;

View File

@ -28,7 +28,7 @@ class DocAccessible;
class Notification
{
public:
virtual ~Notification() { };
virtual ~Notification() { }
NS_INLINE_DECL_REFCOUNTING(Notification)

View File

@ -17,7 +17,7 @@ class StyleInfo
{
public:
StyleInfo(dom::Element* aElement, nsIPresShell* aPresShell);
~StyleInfo() { };
~StyleInfo() { }
void Display(nsAString& aValue);
void TextAlign(nsAString& aValue);

View File

@ -304,8 +304,8 @@ public:
class nsAccessibleDOMStringList : public nsIDOMDOMStringList
{
public:
nsAccessibleDOMStringList() {};
virtual ~nsAccessibleDOMStringList() {};
nsAccessibleDOMStringList() {}
virtual ~nsAccessibleDOMStringList() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMDOMSTRINGLIST

View File

@ -950,7 +950,7 @@ public:
KeyBinding() : mKey(0), mModifierMask(0) {}
KeyBinding(uint32_t aKey, uint32_t aModifierMask) :
mKey(aKey), mModifierMask(aModifierMask) {};
mKey(aKey), mModifierMask(aModifierMask) {}
inline bool IsEmpty() const { return !mKey; }
inline uint32_t Key() const { return mKey; }

View File

@ -20,7 +20,7 @@ class HTMLHRAccessible : public LeafAccessible
public:
HTMLHRAccessible(nsIContent* aContent, DocAccessible* aDoc) :
LeafAccessible(aContent, aDoc) {};
LeafAccessible(aContent, aDoc) {}
// Accessible
virtual a11y::role NativeRole();
@ -33,7 +33,7 @@ class HTMLBRAccessible : public LeafAccessible
{
public:
HTMLBRAccessible(nsIContent* aContent, DocAccessible* aDoc) :
LeafAccessible(aContent, aDoc) {};
LeafAccessible(aContent, aDoc) {}
// Accessible
virtual a11y::role NativeRole();
@ -52,7 +52,7 @@ class HTMLLabelAccessible : public HyperTextAccessibleWrap
public:
HTMLLabelAccessible(nsIContent* aContent, DocAccessible* aDoc) :
HyperTextAccessibleWrap(aContent, aDoc) {};
HyperTextAccessibleWrap(aContent, aDoc) {}
NS_DECL_ISUPPORTS_INHERITED
@ -71,7 +71,7 @@ class HTMLOutputAccessible : public HyperTextAccessibleWrap
public:
HTMLOutputAccessible(nsIContent* aContent, DocAccessible* aDoc) :
HyperTextAccessibleWrap(aContent, aDoc) {};
HyperTextAccessibleWrap(aContent, aDoc) {}
NS_DECL_ISUPPORTS_INHERITED

View File

@ -123,7 +123,6 @@ _BROWSER_FILES = \
browser_bug556061.js \
browser_bug559991.js \
browser_bug561623.js \
browser_bug561636.js \
browser_bug562649.js \
browser_bug563588.js \
browser_bug565575.js \
@ -314,10 +313,15 @@ else
_BROWSER_FILES += \
browser_bug565667.js \
$(NULL)
# TODO: Activate after carbon test plugin lands, bug 628651
# browser_maconly_carbon_mismatch_plugin.js \
# browser_maconly_carbon_mismatch_plugin.js
endif
# bug 766546, disable browser_bug561636.js on Windows
ifneq ($(OS_ARCH),WINNT)
_BROWSER_FILES += \
browser_bug561636.js \
$(NULL)
endif
ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING

View File

@ -12,18 +12,21 @@ relativesrcdir = @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
MOCHITEST_BROWSER_FILES = \
browser_dbg_cmd_break.html \
browser_dbg_cmd_break.js \
browser_dbg_cmd.html \
browser_dbg_cmd.js \
browser_cmd_addon.js \
browser_cmd_calllog.js \
browser_cmd_calllog_chrome.js \
browser_cmd_commands.js \
browser_cmd_cookie.js \
browser_cmd_integrate.js \
browser_cmd_jsb.js \
browser_cmd_jsb_script.jsi \
browser_cmd_pagemod_export.html \
browser_cmd_pagemod_export.js \
browser_cmd_pref.js \
browser_cmd_restart.js \
browser_cmd_screenshot.html \
browser_cmd_settings.js \
browser_gcli_canon.js \
browser_gcli_cli.js \
@ -62,12 +65,14 @@ MOCHITEST_BROWSER_FILES += \
$(NULL)
endif
ifneq ($(OS_ARCH),WINNT)
MOCHITEST_BROWSER_FILES += \
browser_dbg_cmd_break.html \
browser_dbg_cmd.html \
browser_cmd_screenshot.html \
browser_cmd_pagemod_export.html \
browser_cmd_jsb_script.jsi \
browser_cmd_calllog.js \
browser_cmd_calllog_chrome.js \
$(NULL)
else
$(filter disabled-temporarily--bug-817304, browser_cmd_calllog.js)
$(filter disabled-temporarily--bug-819017, browser_cmd_calllog_chrome.js)
endif
include $(topsrcdir)/config/rules.mk

View File

@ -104,7 +104,7 @@ MOCHITEST_BROWSER_FILES = \
browser_webconsole_bug_622303_persistent_filters.js \
browser_webconsole_bug_770099_bad_policyuri.js \
browser_webconsole_bug_770099_violation.js \
browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js \
$(filter disabled-temporarily--bug-808264, browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js) \
browser_cached_messages.js \
browser_bug664688_sandbox_update_after_navigation.js \
browser_result_format_as_string.js \

View File

@ -329,14 +329,32 @@ ElfSection *Elf::getSectionAt(unsigned int offset)
return NULL;
}
ElfSegment *Elf::getSegmentByType(unsigned int type)
ElfSegment *Elf::getSegmentByType(unsigned int type, ElfSegment *last)
{
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
std::vector<ElfSegment *>::iterator seg;
if (last) {
seg = std::find(segments.begin(), segments.end(), last);
++seg;
} else
seg = segments.begin();
for (; seg != segments.end(); seg++)
if ((*seg)->getType() == type)
return *seg;
return NULL;
}
void Elf::removeSegment(ElfSegment *segment)
{
if (!segment)
return;
std::vector<ElfSegment *>::iterator seg;
seg = std::find(segments.begin(), segments.end(), segment);
if (seg == segments.end())
return;
segment->clear();
segments.erase(seg);
}
ElfDynamic_Section *Elf::getDynSection()
{
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
@ -359,20 +377,15 @@ void Elf::normalize()
section->getShdr().sh_name = eh_shstrndx->getStrIndex(section->getName());
}
ehdr->markDirty();
// Adjust PT_LOAD segments
// Check segments consistency
int i = 0;
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++, i++) {
if ((*seg)->getType() == PT_LOAD) {
std::list<ElfSection *>::iterator it = (*seg)->begin();
for (ElfSection *last = *(it++); it != (*seg)->end(); last = *(it++)) {
if (((*it)->getType() != SHT_NOBITS) &&
((*it)->getAddr() - last->getAddr()) != ((*it)->getOffset() - last->getOffset())) {
std::vector<ElfSegment *>::iterator next = seg;
segments.insert(++next, (*seg)->splitBefore(*it));
seg = segments.begin() + i;
break;
}
}
std::list<ElfSection *>::iterator it = (*seg)->begin();
for (ElfSection *last = *(it++); it != (*seg)->end(); last = *(it++)) {
if (((*it)->getType() != SHT_NOBITS) &&
((*it)->getAddr() - last->getAddr()) != ((*it)->getOffset() - last->getOffset())) {
throw std::runtime_error("Segments inconsistency");
}
}
}
// fixup ehdr before writing
@ -481,6 +494,15 @@ unsigned int ElfSection::getOffset()
return (shdr.sh_offset = 0);
unsigned int offset = previous->getOffset();
ElfSegment *ptload = getSegmentByType(PT_LOAD);
ElfSegment *prev_ptload = previous->getSegmentByType(PT_LOAD);
if (ptload && (ptload == prev_ptload)) {
offset += getAddr() - previous->getAddr();
return (shdr.sh_offset = offset);
}
if (previous->getType() != SHT_NOBITS)
offset += previous->getSize();
@ -555,6 +577,12 @@ void ElfSegment::addSection(ElfSection *section)
section->addToSegment(this);
}
void ElfSegment::removeSection(ElfSection *section)
{
sections.remove(section);
section->removeFromSegment(this);
}
unsigned int ElfSegment::getFileSize()
{
if (type == PT_GNU_RELRO)
@ -605,31 +633,11 @@ unsigned int ElfSegment::getAddr()
return sections.empty() ? 0 : sections.front()->getAddr();
}
ElfSegment *ElfSegment::splitBefore(ElfSection *section)
void ElfSegment::clear()
{
std::list<ElfSection *>::iterator i, rm;
for (i = sections.begin(); (*i != section) && (i != sections.end()); ++i);
if (i == sections.end())
return NULL;
// Probably very wrong.
Elf_Phdr phdr;
phdr.p_type = type;
phdr.p_vaddr = 0;
phdr.p_paddr = phdr.p_vaddr + v_p_diff;
phdr.p_flags = flags;
phdr.p_align = getAlign();
phdr.p_filesz = (unsigned int)-1;
phdr.p_memsz = (unsigned int)-1;
ElfSegment *segment = new ElfSegment(&phdr);
for (rm = i; i != sections.end(); ++i) {
for (std::list<ElfSection *>::iterator i = sections.begin(); i != sections.end(); ++i)
(*i)->removeFromSegment(this);
segment->addSection(*i);
}
sections.erase(rm, sections.end());
return segment;
sections.clear();
}
ElfValue *ElfDynamic_Section::getValueForType(unsigned int tag)

View File

@ -376,6 +376,37 @@ void set_relative_reloc(Elf_Rela *rel, Elf *elf, unsigned int value) {
rel->r_addend = value;
}
void maybe_split_segment(Elf *elf, ElfSegment *segment)
{
std::list<ElfSection *>::iterator it = segment->begin();
for (ElfSection *last = *(it++); it != segment->end(); last = *(it++)) {
// When two consecutive non-SHT_NOBITS sections are apart by more
// than the alignment of the section, the second can be moved closer
// to the first, but this requires the segment to be split.
if (((*it)->getType() != SHT_NOBITS) && (last->getType() != SHT_NOBITS) &&
((*it)->getOffset() - last->getOffset() - last->getSize() > segment->getAlign())) {
// Probably very wrong.
Elf_Phdr phdr;
phdr.p_type = PT_LOAD;
phdr.p_vaddr = 0;
phdr.p_paddr = phdr.p_vaddr + segment->getVPDiff();
phdr.p_flags = segment->getFlags();
phdr.p_align = segment->getAlign();
phdr.p_filesz = (unsigned int)-1;
phdr.p_memsz = (unsigned int)-1;
ElfSegment *newSegment = new ElfSegment(&phdr);
elf->insertSegmentAfter(segment, newSegment);
for (; it != segment->end(); ++it) {
newSegment->addSection(*it);
}
for (it = newSegment->begin(); it != newSegment->end(); it++) {
segment->removeSection(*it);
}
break;
}
}
}
template <typename Rel_Type>
int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type2, bool force)
{
@ -523,16 +554,23 @@ int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type
}
}
section->rels.assign(new_rels.begin(), new_rels.end());
section->shrink(new_rels.size() * section->getEntSize());
ElfRelHackCode_Section *relhackcode = new ElfRelHackCode_Section(relhackcode_section, *elf, original_init);
relhackcode->insertBefore(section);
relhack->insertAfter(relhackcode);
section->rels.assign(new_rels.begin(), new_rels.end());
section->shrink(new_rels.size() * section->getEntSize());
if (section->getOffset() + section->getSize() >= old_end) {
fprintf(stderr, "No gain. Skipping\n");
return -1;
}
// Adjust PT_LOAD segments
for (ElfSegment *segment = elf->getSegmentByType(PT_LOAD); segment;
segment = elf->getSegmentByType(PT_LOAD, segment)) {
maybe_split_segment(elf, segment);
}
// Ensure Elf sections will be at their final location.
elf->normalize();
ElfLocation *init = new ElfLocation(relhackcode, relhackcode->getEntryPoint());
@ -564,49 +602,100 @@ static inline int backup_file(const char *name)
void do_file(const char *name, bool backup = false, bool force = false)
{
std::ifstream file(name, std::ios::in|std::ios::binary);
Elf *elf = new Elf(file);
unsigned int size = elf->getSize();
Elf elf(file);
unsigned int size = elf.getSize();
fprintf(stderr, "%s: ", name);
if (elf->getType() != ET_DYN) {
if (elf.getType() != ET_DYN) {
fprintf(stderr, "Not a shared object. Skipping\n");
delete elf;
return;
}
for (ElfSection *section = elf->getSection(1); section != NULL;
for (ElfSection *section = elf.getSection(1); section != NULL;
section = section->getNext()) {
if (section->getName() &&
(strncmp(section->getName(), ".elfhack.", 9) == 0)) {
fprintf(stderr, "Already elfhacked. Skipping\n");
delete elf;
return;
}
}
int exit = -1;
switch (elf->getMachine()) {
switch (elf.getMachine()) {
case EM_386:
exit = do_relocation_section<Elf_Rel>(elf, R_386_RELATIVE, R_386_32, force);
exit = do_relocation_section<Elf_Rel>(&elf, R_386_RELATIVE, R_386_32, force);
break;
case EM_X86_64:
exit = do_relocation_section<Elf_Rela>(elf, R_X86_64_RELATIVE, R_X86_64_64, force);
exit = do_relocation_section<Elf_Rela>(&elf, R_X86_64_RELATIVE, R_X86_64_64, force);
break;
case EM_ARM:
exit = do_relocation_section<Elf_Rel>(elf, R_ARM_RELATIVE, R_ARM_ABS32, force);
exit = do_relocation_section<Elf_Rel>(&elf, R_ARM_RELATIVE, R_ARM_ABS32, force);
break;
}
if (exit == 0) {
if (!force && (elf->getSize() >= size)) {
if (!force && (elf.getSize() >= size)) {
fprintf(stderr, "No gain. Skipping\n");
} else if (backup && backup_file(name) != 0) {
fprintf(stderr, "Couln't create backup file\n");
} else {
std::ofstream ofile(name, std::ios::out|std::ios::binary|std::ios::trunc);
elf->write(ofile);
fprintf(stderr, "Reduced by %d bytes\n", size - elf->getSize());
elf.write(ofile);
fprintf(stderr, "Reduced by %d bytes\n", size - elf.getSize());
}
}
delete elf;
}
void undo_file(const char *name, bool backup = false)
{
std::ifstream file(name, std::ios::in|std::ios::binary);
Elf elf(file);
unsigned int size = elf.getSize();
fprintf(stderr, "%s: ", name);
if (elf.getType() != ET_DYN) {
fprintf(stderr, "Not a shared object. Skipping\n");
return;
}
ElfSection *data = NULL, *text = NULL;
for (ElfSection *section = elf.getSection(1); section != NULL;
section = section->getNext()) {
if (section->getName() &&
(strcmp(section->getName(), elfhack_data) == 0))
data = section;
if (section->getName() &&
(strcmp(section->getName(), elfhack_text) == 0))
text = section;
}
if (!data || !text) {
fprintf(stderr, "Not elfhacked. Skipping\n");
return;
}
if (data != text->getNext()) {
fprintf(stderr, elfhack_data " section not following " elfhack_text ". Skipping\n");
return;
}
ElfSegment *first = elf.getSegmentByType(PT_LOAD);
ElfSegment *second = elf.getSegmentByType(PT_LOAD, first);
if (second->getFlags() != first->getFlags()) {
fprintf(stderr, "First two PT_LOAD segments don't have the same flags. Skipping\n");
return;
}
// Move sections from the second PT_LOAD to the first, and remove the
// second PT_LOAD segment.
for (std::list<ElfSection *>::iterator section = second->begin();
section != second->end(); ++section)
first->addSection(*section);
elf.removeSegment(second);
if (backup && backup_file(name) != 0) {
fprintf(stderr, "Couln't create backup file\n");
} else {
std::ofstream ofile(name, std::ios::out|std::ios::binary|std::ios::trunc);
elf.write(ofile);
fprintf(stderr, "Grown by %d bytes\n", elf.getSize() - size);
}
}
int main(int argc, char *argv[])
@ -614,6 +703,7 @@ int main(int argc, char *argv[])
int arg;
bool backup = false;
bool force = false;
bool revert = false;
char *lastSlash = rindex(argv[0], '/');
if (lastSlash != NULL)
rundir = strndup(argv[0], lastSlash - argv[0]);
@ -622,6 +712,10 @@ int main(int argc, char *argv[])
force = true;
else if (strcmp(argv[arg], "-b") == 0)
backup = true;
else if (strcmp(argv[arg], "-r") == 0)
revert = true;
else if (revert)
undo_file(argv[arg], backup);
else
do_file(argv[arg], backup, force);
}

View File

@ -270,7 +270,7 @@ public:
ElfSection *getSectionAt(unsigned int offset);
ElfSegment *getSegmentByType(unsigned int type);
ElfSegment *getSegmentByType(unsigned int type, ElfSegment *last = NULL);
ElfDynamic_Section *getDynSection();
@ -282,6 +282,14 @@ public:
char getType();
char getMachine();
unsigned int getSize();
void insertSegmentAfter(ElfSegment *previous, ElfSegment *segment) {
std::vector<ElfSegment *>::iterator prev = std::find(segments.begin(), segments.end(), previous);
segments.insert(prev + 1, segment);
}
void removeSegment(ElfSegment *segment);
private:
Elf_Ehdr *ehdr;
ElfLocation eh_entry;
@ -319,11 +327,8 @@ public:
SectionInfo getInfo() { return info; }
void shrink(unsigned int newsize) {
if (newsize < shdr.sh_size) {
if (newsize < shdr.sh_size)
shdr.sh_size = newsize;
if (next)
next->markDirty();
}
}
unsigned int getOffset();
@ -345,7 +350,7 @@ public:
(getType() == SHT_GNU_verdef) ||
(getType() == SHT_GNU_verneed) ||
(getType() == SHT_GNU_versym) ||
isInSegmentType(PT_INTERP)) &&
getSegmentByType(PT_INTERP)) &&
(getFlags() & SHF_ALLOC);
}
@ -364,6 +369,7 @@ public:
next->previous = this;
if (dirty)
markDirty();
insertInSegments(section->segments);
}
void insertBefore(ElfSection *section, bool dirty = true) {
@ -381,6 +387,7 @@ public:
previous->next = this;
if (dirty)
markDirty();
insertInSegments(section->segments);
}
void markDirty() {
@ -415,7 +422,10 @@ private:
segments.erase(i, i + 1);
}
bool isInSegmentType(unsigned int type);
ElfSegment *getSegmentByType(unsigned int type);
void insertInSegments(std::vector<ElfSegment *> &segs);
protected:
Elf_Shdr shdr;
char *data;
@ -444,11 +454,12 @@ public:
unsigned int getAddr();
void addSection(ElfSection *section);
void removeSection(ElfSection *section);
std::list<ElfSection *>::iterator begin() { return sections.begin(); }
std::list<ElfSection *>::iterator end() { return sections.end(); }
ElfSegment *splitBefore(ElfSection *section);
void clear();
private:
unsigned int type;
int v_p_diff; // Difference between physical and virtual address
@ -643,11 +654,17 @@ inline unsigned int Elf::getSize() {
return section->getOffset() + section->getSize();
}
inline bool ElfSection::isInSegmentType(unsigned int type) {
inline ElfSegment *ElfSection::getSegmentByType(unsigned int type) {
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
if ((*seg)->getType() == type)
return true;
return false;
return *seg;
return NULL;
}
inline void ElfSection::insertInSegments(std::vector<ElfSegment *> &segs) {
for (std::vector<ElfSegment *>::iterator it = segs.begin(); it != segs.end(); ++it) {
(*it)->addSection(this);
}
}
inline ElfLocation::ElfLocation(ElfSection *section, unsigned int off, enum position pos)

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<script>
window.onload = function() {
setInterval(
function next_step() {
var style = document.createElement('style');
style.innerHTML = "{ }";
document.getElementsByTagName("*")[ 7 ].appendChild(style);
window.dump('.');
}, 10);
}
</script>
</head>
<body>
<div id="console"></div>
<div id="parentDiv">
<div id="left-to-right" dir="auto" class="testElement">
<input type="text" value="מקור השם עברית">Test test test
</div>
</div>
<script id="des">
var el = document.getElementById("left-to-right");
document.defaultView.getComputedStyle(el, null).getPropertyValue('border-right-color');
document.getElementById("parentDiv").style.display = "none";
</script>
</body>
</html>

View File

@ -116,3 +116,4 @@ load 752226-2.html
HTTP(..) load xhr_abortinprogress.html
load 786854.html
load xhr_empty_datauri.html
load 816253.html

View File

@ -732,6 +732,9 @@ void SetAncestorDirectionIfAuto(nsINode* aTextNode, Directionality aDir,
// we found the node that set the element's direction after our
// text node, so we need to reset the direction
resetDirection = true;
nsTextNodeDirectionalityMap::RemoveElementFromMap(
directionWasSetByTextNode, parent
);
break;
}

View File

@ -131,7 +131,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
* Used by pluginHost to know if we're loading with a channel, so it
* will not open its own.
*/
bool SrcStreamLoading() { return mSrcStreamLoading; };
bool SrcStreamLoading() { return mSrcStreamLoading; }
protected:
/**

View File

@ -5458,7 +5458,7 @@ nsEventStateManager::WheelPrefs::Init(
nsAutoCString prefNameAction(basePrefName);
prefNameAction.AppendLiteral("action");
int32_t action = Preferences::GetInt(prefNameAction.get(), ACTION_SCROLL);
if (action < ACTION_NONE || action > ACTION_LAST) {
if (action < int32_t(ACTION_NONE) || action > int32_t(ACTION_LAST)) {
NS_WARNING("Unsupported action pref value, replaced with 'Scroll'.");
action = ACTION_SCROLL;
}
@ -5469,7 +5469,7 @@ nsEventStateManager::WheelPrefs::Init(
// because this pref is introduced mainly for tilt wheels.
prefNameAction.AppendLiteral(".override_x");
int32_t actionOverrideX = Preferences::GetInt(prefNameAction.get(), -1);
if (actionOverrideX < -1 || actionOverrideX > ACTION_LAST) {
if (actionOverrideX < -1 || actionOverrideX > int32_t(ACTION_LAST)) {
NS_WARNING("Unsupported action override pref value, didn't override.");
actionOverrideX = -1;
}

View File

@ -31,7 +31,7 @@ enum MediaEngineState {
class MediaEngine
{
public:
virtual ~MediaEngine() {};
virtual ~MediaEngine() {}
/* Populate an array of video sources in the nsTArray. Also include devices
* that are currently unavailable. */
@ -48,7 +48,7 @@ public:
class MediaEngineSource : public nsISupports
{
public:
virtual ~MediaEngineSource() {};
virtual ~MediaEngineSource() {}
/* Populate the human readable name of this device in the nsAString */
virtual void GetName(nsAString&) = 0;
@ -114,7 +114,7 @@ struct MediaEngineVideoOptions {
class MediaEngineVideoSource : public MediaEngineSource
{
public:
virtual ~MediaEngineVideoSource() {};
virtual ~MediaEngineVideoSource() {}
/* Return a MediaEngineVideoOptions struct with appropriate values for all
* fields. */
@ -127,7 +127,7 @@ public:
class MediaEngineAudioSource : public MediaEngineSource
{
public:
virtual ~MediaEngineAudioSource() {};
virtual ~MediaEngineAudioSource() {}
};
}

View File

@ -95,7 +95,7 @@ public:
if (mList) {
mList->mItems[mListIndex] = nullptr;
}
};
}
/**
* Create an unowned copy of an owned length. The caller is responsible for

View File

@ -71,7 +71,7 @@ public:
if (mAList) {
( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nullptr;
}
};
}
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
bool *triedToWrap);

View File

@ -70,7 +70,7 @@ public:
if (mList) {
mList->mItems[mListIndex] = nullptr;
}
};
}
/**
* Create an unowned copy. The caller is responsible for the first AddRef().

View File

@ -81,7 +81,7 @@ public:
if (mList) {
mList->mItems[mListIndex] = nullptr;
}
};
}
/**
* Create an unowned copy of an owned transform. The caller is responsible for

View File

@ -5123,8 +5123,8 @@ nsSVGFELightingElement::Filter(nsSVGFilterInstance *instance,
S[2] = pointsAt[2] - lightPos[2];
NORMALIZE(S);
float dot = -DOT(L, S);
if (dot < cosConeAngle) dot = 0;
float tmp = pow(dot, specularExponent);
if (dot < cosConeAngle) tmp = 0;
color = NS_RGB(uint8_t(NS_GET_R(lightColor) * tmp),
uint8_t(NS_GET_G(lightColor) * tmp),
uint8_t(NS_GET_B(lightColor) * tmp));
@ -5983,7 +5983,7 @@ nsSVGFEDisplacementMapElement::Filter(nsSVGFilterInstance *instance,
uint8_t* targetData = aTarget->mImage->Data();
uint32_t stride = aTarget->mImage->Stride();
static uint8_t dummyData[4] = { 0, 0, 0, 0 };
static const uint8_t dummyData[4] = { 0, 0, 0, 0 };
static const uint16_t channelMap[5] = {
0,
@ -6010,7 +6010,7 @@ nsSVGFEDisplacementMapElement::Filter(nsSVGFilterInstance *instance,
bool outOfBounds = sourceX < 0 || sourceX >= width ||
sourceY < 0 || sourceY >= height;
uint8_t* data;
const uint8_t* data;
int32_t multiplier;
if (outOfBounds) {
data = dummyData;

View File

@ -231,34 +231,6 @@ nsSVGSVGElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight)
return mLengthAttributes[HEIGHT].ToDOMAnimatedLength(aHeight, this);
}
/* attribute DOMString contentScriptType; */
NS_IMETHODIMP
nsSVGSVGElement::GetContentScriptType(nsAString & aContentScriptType)
{
NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetContentScriptType");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsSVGSVGElement::SetContentScriptType(const nsAString & aContentScriptType)
{
NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetContentScriptType");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute DOMString contentStyleType; */
NS_IMETHODIMP
nsSVGSVGElement::GetContentStyleType(nsAString & aContentStyleType)
{
NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetContentStyleType");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsSVGSVGElement::SetContentStyleType(const nsAString & aContentStyleType)
{
NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetContentStyleType");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute nsIDOMSVGRect viewport; */
NS_IMETHODIMP
nsSVGSVGElement::GetViewport(nsIDOMSVGRect * *aViewport)

View File

@ -141,7 +141,7 @@ public:
NS_ADDREF(*aStyle);
return NS_OK;
}
NS_FORWARD_NSIFRAMELOADEROWNER(static_cast<nsXULElement*>(mElement.get())->);
NS_FORWARD_NSIFRAMELOADEROWNER(static_cast<nsXULElement*>(mElement.get())->)
private:
nsCOMPtr<nsIDOMXULElement> mElement;
};

View File

@ -47,7 +47,7 @@ this.PermissionsTable = { geolocation: {
},
camera: {
app: DENY_ACTION,
privileged: PROMPT_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
alarms: {
@ -235,6 +235,11 @@ this.PermissionsTable = { geolocation: {
channels: ["normal", "content", "notification",
"alarm", "telephony", "ringer", "publicnotification"]
},
"open-remote-window": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
};
/**

View File

@ -10,20 +10,16 @@ using namespace mozilla::dom;
NS_IMPL_ISUPPORTS1(AudioChannelAgent, nsIAudioChannelAgent)
static nsRefPtr<AudioChannelService> gAudioChannelService;
AudioChannelAgent::AudioChannelAgent()
: mCallback(nullptr)
, mAudioChannelType(AUDIO_AGENT_CHANNEL_ERROR)
, mIsRegToService(false)
, mVisible(true)
{
gAudioChannelService = AudioChannelService::GetAudioChannelService();
}
AudioChannelAgent::~AudioChannelAgent()
{
gAudioChannelService = nullptr;
}
/* readonly attribute long audioChannelType; */
@ -68,14 +64,15 @@ NS_IMETHODIMP AudioChannelAgent::Init(int32_t channelType, nsIAudioChannelAgentC
/* boolean startPlaying (); */
NS_IMETHODIMP AudioChannelAgent::StartPlaying(bool *_retval)
{
AudioChannelService *service = AudioChannelService::GetAudioChannelService();
if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
gAudioChannelService == nullptr) {
service == nullptr) {
return NS_ERROR_FAILURE;
}
gAudioChannelService->RegisterAudioChannelAgent(this,
service->RegisterAudioChannelAgent(this,
static_cast<AudioChannelType>(mAudioChannelType));
*_retval = !gAudioChannelService->GetMuted(static_cast<AudioChannelType>(mAudioChannelType), !mVisible);
*_retval = !service->GetMuted(static_cast<AudioChannelType>(mAudioChannelType), !mVisible);
mIsRegToService = true;
return NS_OK;
}
@ -88,7 +85,8 @@ NS_IMETHODIMP AudioChannelAgent::StopPlaying(void)
return NS_ERROR_FAILURE;
}
gAudioChannelService->UnregisterAudioChannelAgent(this);
AudioChannelService *service = AudioChannelService::GetAudioChannelService();
service->UnregisterAudioChannelAgent(this);
mIsRegToService = false;
return NS_OK;
}
@ -100,7 +98,8 @@ NS_IMETHODIMP AudioChannelAgent::SetVisibilityState(bool visible)
mVisible = visible;
if (mIsRegToService && oldVisibility != mVisible && mCallback != nullptr) {
mCallback->CanPlayChanged(!gAudioChannelService->GetMuted(static_cast<AudioChannelType>(mAudioChannelType),
AudioChannelService *service = AudioChannelService::GetAudioChannelService();
mCallback->CanPlayChanged(!service->GetMuted(static_cast<AudioChannelType>(mAudioChannelType),
!mVisible));
}
return NS_OK;
@ -109,7 +108,8 @@ NS_IMETHODIMP AudioChannelAgent::SetVisibilityState(bool visible)
void AudioChannelAgent::NotifyAudioChannelStateChanged()
{
if (mCallback != nullptr) {
mCallback->CanPlayChanged(!gAudioChannelService->GetMuted(static_cast<AudioChannelType>(mAudioChannelType),
AudioChannelService *service = AudioChannelService::GetAudioChannelService();
mCallback->CanPlayChanged(!service->GetMuted(static_cast<AudioChannelType>(mAudioChannelType),
!mVisible));
}
}

View File

@ -103,7 +103,7 @@ public:
JSObject** aFunctionObject);
virtual nsIScriptGlobalObject *GetGlobalObject();
inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; };
inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; }
virtual JSContext* GetNativeContext();
virtual JSObject* GetNativeGlobal();

View File

@ -427,7 +427,7 @@ DOMInterfaces = {
'WebGLBuffer': {
'nativeType': 'mozilla::WebGLBuffer',
'headerFile': 'WebGLContext.h'
'headerFile': 'WebGLBuffer.h'
},
'WebGLExtensionCompressedTextureATC': {
@ -477,17 +477,17 @@ DOMInterfaces = {
'WebGLFramebuffer': {
'nativeType': 'mozilla::WebGLFramebuffer',
'headerFile': 'WebGLContext.h'
'headerFile': 'WebGLFramebuffer.h'
},
'WebGLProgram': {
'nativeType': 'mozilla::WebGLProgram',
'headerFile': 'WebGLContext.h'
'headerFile': 'WebGLProgram.h'
},
'WebGLRenderbuffer': {
'nativeType': 'mozilla::WebGLRenderbuffer',
'headerFile': 'WebGLContext.h'
'headerFile': 'WebGLRenderbuffer.h'
},
'WebGLRenderingContext': {
@ -500,23 +500,23 @@ DOMInterfaces = {
'WebGLShader': {
'nativeType': 'mozilla::WebGLShader',
'headerFile': 'WebGLContext.h'
'headerFile': 'WebGLShader.h'
},
'WebGLShaderPrecisionFormat': {
'nativeType': 'mozilla::WebGLShaderPrecisionFormat',
'headerFile': 'WebGLContext.h',
'headerFile': 'WebGLShaderPrecisionFormat.h',
'wrapperCache': False
},
'WebGLTexture': {
'nativeType': 'mozilla::WebGLTexture',
'headerFile': 'WebGLContext.h'
'headerFile': 'WebGLTexture.h'
},
'WebGLUniformLocation': {
'nativeType': 'mozilla::WebGLUniformLocation',
'headerFile': 'WebGLContext.h',
'headerFile': 'WebGLUniformLocation.h',
'wrapperCache': False
},

View File

@ -318,6 +318,19 @@ dictionary MozStkPlayTone
boolean isVibrate;
};
dictionary MozStkProvideLocalInfo
{
/**
* Indicate which local information is required.
* It shall be one of following:
* - nsIDOMMozIccManager.STK_LOCAL_INFO_LOCATION_INFO
* - nsIDOMMozIccManager.STK_LOCAL_INFO_IMEI
* - nsIDOMMozIccManager.STK_LOCAL_INFO_DATE_TIME_ZONE
* - nsIDOMMozIccManager.STK_LOCAL_INFO_LANGUAGE
*/
unsigned short localInfoType;
};
dictionary MozStkLocationEvent
{
/**
@ -403,6 +416,10 @@ dictionary MozStkCommand
* options is MozStkDuration.
*
* When typeOfCommand is
* - STK_CMD_PROVIDE_LOCAL_INFO
* options is MozStkProvideLocalInfo.
*
* When typeOfCommand is
* - STK_CMD_POLL_OFF
* options is null.
*
@ -458,6 +475,13 @@ dictionary MozStkResponse
* false: Rejected by User.
*/
boolean hasConfirmed;
/**
* The response for STK_CMD_PROVIDE_LOCAL_INFO
*
* @see MozStkLocalInfo
*/
jsval localInfo;
};
dictionary MozStkCallEvent
@ -493,3 +517,32 @@ dictionary MozStkCallEvent
*/
DOMString error;
};
dictionary MozStkLocalInfo
{
/**
* IMEI information
*/
DOMString imei;
/**
* Location Information
*
* @see MozStkLocationInfo.
*/
jsval locationInfo;
/**
* Date information
*
* @see Date
*/
jsval date;
/**
* Language Information
*
* @see ISO 639-1, Alpha-2 code
*/
DOMString language;
};

View File

@ -45,6 +45,7 @@ interface nsIDOMMozIccManager : nsIDOMEventTarget
const unsigned short STK_CMD_GET_INPUT = 0x23;
const unsigned short STK_CMD_SELECT_ITEM = 0x24;
const unsigned short STK_CMD_SET_UP_MENU = 0x25;
const unsigned short STK_CMD_PROVIDE_LOCAL_INFO = 0x26;
const unsigned short STK_CMD_SET_UP_IDLE_MODE_TEXT = 0x28;
/**
@ -194,6 +195,16 @@ interface nsIDOMMozIccManager : nsIDOMEventTarget
const unsigned short STK_TIME_UNIT_SECOND = 0x01;
const unsigned short STK_TIME_UNIT_TENTH_SECOND = 0x02;
/**
* Local Information list
*
* @see TS 102.223, clause 8.6
*/
const unsigned short STK_LOCAL_INFO_LOCATION_INFO = 0x00;
const unsigned short STK_LOCAL_INFO_IMEI = 0x01;
const unsigned short STK_LOCAL_INFO_DATE_TIME_ZONE = 0x03;
const unsigned short STK_LOCAL_INFO_LANGUAGE = 0x04;
/**
* Send the response back to ICC after an attempt to execute STK Proactive
* Command.

View File

@ -17,9 +17,57 @@ function testDisplayTextGsm7BitEncoding(cmd) {
runNextTest();
}
function testLocalInfoLocation(cmd) {
log("STK CMD " + JSON.stringify(cmd));
is(cmd.typeOfCommand, icc.STK_CMD_PROVIDE_LOCAL_INFO);
is(cmd.commandNumber, 0x01);
is(cmd.commandQualifier, icc.STK_LOCAL_INFO_LOCATION_INFO);
is(cmd.options.localInfoType, icc.STK_LOCAL_INFO_LOCATION_INFO);
runNextTest();
}
function testLocalInfoImei(cmd) {
log("STK CMD " + JSON.stringify(cmd));
is(cmd.typeOfCommand, icc.STK_CMD_PROVIDE_LOCAL_INFO);
is(cmd.commandNumber, 0x01);
is(cmd.commandQualifier, icc.STK_LOCAL_INFO_IMEI);
is(cmd.options.localInfoType, icc.STK_LOCAL_INFO_IMEI);
runNextTest();
}
function testLocalInfoDate(cmd) {
log("STK CMD " + JSON.stringify(cmd));
is(cmd.typeOfCommand, icc.STK_CMD_PROVIDE_LOCAL_INFO);
is(cmd.commandNumber, 0x01);
is(cmd.commandQualifier, icc.STK_LOCAL_INFO_DATE_TIME_ZONE);
is(cmd.options.localInfoType, icc.STK_LOCAL_INFO_DATE_TIME_ZONE);
runNextTest();
}
function testLocalInfoLanguage(cmd) {
log("STK CMD " + JSON.stringify(cmd));
is(cmd.typeOfCommand, icc.STK_CMD_PROVIDE_LOCAL_INFO);
is(cmd.commandNumber, 0x01);
is(cmd.commandQualifier, icc.STK_LOCAL_INFO_LANGUAGE);
is(cmd.options.localInfoType, icc.STK_LOCAL_INFO_LANGUAGE);
runNextTest();
}
let tests = [
{command: "d0288103012180820281020d1d00d3309bfc06c95c301aa8e80259c3ec34b9ac07c9602f58ed159bb940",
func: testDisplayTextGsm7BitEncoding},
{command: "d009810301260082028182",
func: testLocalInfoLocation},
{command: "d009810301260182028182",
func: testLocalInfoImei},
{command: "d009810301260382028182",
func: testLocalInfoDate},
{command: "d009810301260482028182",
func: testLocalInfoLanguage},
];
let pendingEmulatorCmdCount = 0;

View File

@ -22,7 +22,7 @@ interface nsIDOMSVGTransform;
#endif
%}
[scriptable, uuid(BEC06C4F-3EF7-486E-A8F5-F375EE5CB5A8)]
[scriptable, uuid(4670a204-4ef1-455f-9595-9847b077c624)]
interface nsIDOMSVGSVGElement
: nsIDOMSVGElement
/*
@ -47,10 +47,6 @@ interface nsIDOMSVGSVGElement
readonly attribute nsIDOMSVGAnimatedLength y;
readonly attribute nsIDOMSVGAnimatedLength width;
readonly attribute nsIDOMSVGAnimatedLength height;
attribute DOMString contentScriptType;
// raises DOMException on setting
attribute DOMString contentStyleType;
// raises DOMException on setting
readonly attribute nsIDOMSVGRect viewport;
readonly attribute float pixelUnitToMillimeterX;
readonly attribute float pixelUnitToMillimeterY;

View File

@ -284,6 +284,9 @@ TabChild::OnLocationChange(nsIWebProgress* aWebProgress,
return NS_OK;
}
nsCOMPtr<nsIDOMWindowUtils> utils(do_GetInterface(window));
utils->SetIsFirstPaint(true);
nsCOMPtr<nsIDOMDocument> progressDoc;
window->GetDocument(getter_AddRefs(progressDoc));
if (!progressDoc) {
@ -463,20 +466,27 @@ TabChild::HandlePossibleViewportChange()
metrics.mScrollableRect = gfx::Rect(0.0f, 0.0f, pageWidth, pageHeight);
metrics.mCompositionBounds = nsIntRect(0, 0, mInnerSize.width, mInnerSize.height);
gfxSize intrinsicScale =
AsyncPanZoomController::CalculateIntrinsicScale(metrics);
// FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of
// 0.0 to mean "did not calculate a zoom". In that case, we default
// it to the intrinsic scale.
if (viewportInfo.defaultZoom < 0.01f) {
viewportInfo.defaultZoom = intrinsicScale.width;
// Changing the zoom when we're not doing a first paint will get ignored
// by AsyncPanZoomController and causes a blurry flash.
bool isFirstPaint;
nsresult rv = utils->GetIsFirstPaint(&isFirstPaint);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv) || isFirstPaint) {
gfxSize intrinsicScale =
AsyncPanZoomController::CalculateIntrinsicScale(metrics);
// FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of
// 0.0 to mean "did not calculate a zoom". In that case, we default
// it to the intrinsic scale.
if (viewportInfo.defaultZoom < 0.01f) {
viewportInfo.defaultZoom = intrinsicScale.width;
}
MOZ_ASSERT(viewportInfo.minZoom <= viewportInfo.defaultZoom &&
viewportInfo.defaultZoom <= viewportInfo.maxZoom);
// GetViewportInfo() returns a resolution-dependent scale factor.
// Convert that to a resolution-indepedent zoom.
metrics.mZoom = gfxSize(viewportInfo.defaultZoom / intrinsicScale.width,
viewportInfo.defaultZoom / intrinsicScale.height);
}
MOZ_ASSERT(viewportInfo.minZoom <= viewportInfo.defaultZoom &&
viewportInfo.defaultZoom <= viewportInfo.maxZoom);
// GetViewportInfo() returns a resolution-dependent scale factor.
// Convert that to a resolution-indepedent zoom.
metrics.mZoom = gfxSize(viewportInfo.defaultZoom / intrinsicScale.width,
viewportInfo.defaultZoom / intrinsicScale.height);
metrics.mDisplayPort = AsyncPanZoomController::CalculatePendingDisplayPort(
// The page must have been refreshed in some way such as a new document or

View File

@ -254,13 +254,13 @@ public:
mSource = aSource;
mType.Assign(NS_LITERAL_STRING("video"));
mSource->GetName(mName);
};
}
MediaDevice(MediaEngineAudioSource* aSource) {
mSource = aSource;
mType.Assign(NS_LITERAL_STRING("audio"));
mSource->GetName(mName);
};
virtual ~MediaDevice() {};
}
virtual ~MediaDevice() {}
MediaEngineSource* GetSource();
private:
@ -317,7 +317,7 @@ private:
WindowTable *GetActiveWindows() {
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
return &mActiveWindows;
};
}
// Make private because we want only one instance of this class
MediaManager()
@ -326,11 +326,11 @@ private:
, mBackend(nullptr) {
mActiveWindows.Init();
mActiveCallbacks.Init();
};
}
~MediaManager() {
delete mBackend;
};
}
// ONLY access from MainThread so we don't need to lock
WindowTable mActiveWindows;

View File

@ -0,0 +1,70 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=812785
-->
<head>
<meta charset="utf-8">
<title>Bug 812785 - WebRTC use-after-free crash</title>
<script type="application/javascript">
var pc1, pc2, pc1_offer, pc2_answer, localAudio, remoteAudio;
function onFailure(code) {
stop();
}
function stop() {
pc1.close(); pc1 = null;
pc2.close(); pc2 = null;
var index = localStorage.index || 0;
if (index < 5) {
localStorage.index = index + 1;
window.location.reload();
}
else {
finish();
}
}
function start() {
localAudio = document.getElementById("local");
remoteAudio = document.getElementById("remote");
var stream = localAudio.mozCaptureStreamUntilEnded();
pc1 = new mozRTCPeerConnection();
pc2 = new mozRTCPeerConnection();
pc1.addStream(stream);
pc1.createOffer(function (offer) {
pc1_offer = offer;
pc1.setLocalDescription(pc1_offer, function () {
pc2.setRemoteDescription(pc1_offer, function () {
pc2.createAnswer(function (answer) {
pc2_answer = answer;
pc2.setLocalDescription(pc2_answer, function () {
pc1.setRemoteDescription(pc2_answer, function step6() {
stop();
}, onFailure);
}, onFailure);
}, onFailure);
}, onFailure);
}, onFailure);
}, onFailure);
}
function finish() {
delete localStorage["index"];
document.documentElement.removeAttribute("class");
}
</script>
</head>
<body onload="start()">
<audio id="local" controls autoplay><source type="audio/wav" src="" /></audio>
<audio id="remote" controls></audio>
</body>
</html>

View File

@ -6,3 +6,4 @@ load 791278.html
load 791330.html
load 801227.html
load 802982.html
load 812785.html

View File

@ -186,12 +186,20 @@ enum eNPPStreamTypeInternal {
static NS_DEFINE_IID(kMemoryCID, NS_MEMORY_CID);
PRIntervalTime NS_NotifyBeginPluginCall()
{
nsNPAPIPluginInstance::BeginPluginCall();
return PR_IntervalNow();
}
// This function sends a notification using the observer service to any object
// registered to listen to the "experimental-notify-plugin-call" subject.
// Each "experimental-notify-plugin-call" notification carries with it the run
// time value in milliseconds that the call took to execute.
void NS_NotifyPluginCall(PRIntervalTime startTime)
{
nsNPAPIPluginInstance::EndPluginCall();
PRIntervalTime endTime = PR_IntervalNow() - startTime;
nsCOMPtr<nsIObserverService> notifyUIService =
mozilla::services::GetObserverService();

View File

@ -200,6 +200,8 @@ nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
}
}
uint32_t nsNPAPIPluginInstance::gInPluginCalls = 0;
void
nsNPAPIPluginInstance::Destroy()
{

View File

@ -270,6 +270,14 @@ public:
// Returns the contents scale factor of the screen the plugin is drawn on.
double GetContentsScaleFactor();
static bool InPluginCall() { return gInPluginCalls > 0; }
static void BeginPluginCall() { ++gInPluginCalls; }
static void EndPluginCall()
{
NS_ASSERTION(InPluginCall(), "Must be in plugin call");
--gInPluginCalls;
}
protected:
nsresult GetTagType(nsPluginTagType *result);
@ -364,6 +372,8 @@ private:
// is this instance Java and affected by bug 750480?
bool mHaveJavaC2PJSObjectQuirk;
static uint32_t gInPluginCalls;
};
#endif // nsNPAPIPluginInstance_h_

View File

@ -14,6 +14,7 @@
#define CALL_SAFETY_ON
#endif
PRIntervalTime NS_NotifyBeginPluginCall();
void NS_NotifyPluginCall(PRIntervalTime);
#ifdef CALL_SAFETY_ON
@ -31,7 +32,7 @@ PR_END_MACRO
#define NS_TRY_SAFE_CALL_RETURN(ret, fun, pluginInst) \
PR_BEGIN_MACRO \
PRIntervalTime startTime = PR_IntervalNow(); \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
if(gSkipPluginSafeCalls) \
ret = fun; \
else \
@ -40,7 +41,7 @@ PR_BEGIN_MACRO \
{ \
ret = fun; \
} \
MOZ_SEH_EXCEPT(true) \
MOZ_SEH_EXCEPT(true) \
{ \
nsresult res; \
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &res));\
@ -54,7 +55,7 @@ PR_END_MACRO
#define NS_TRY_SAFE_CALL_VOID(fun, pluginInst) \
PR_BEGIN_MACRO \
PRIntervalTime startTime = PR_IntervalNow(); \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
if(gSkipPluginSafeCalls) \
fun; \
else \
@ -63,7 +64,7 @@ PR_BEGIN_MACRO \
{ \
fun; \
} \
MOZ_SEH_EXCEPT(true) \
MOZ_SEH_EXCEPT(true) \
{ \
nsresult res; \
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &res));\
@ -78,16 +79,16 @@ PR_END_MACRO
#define NS_TRY_SAFE_CALL_RETURN(ret, fun, pluginInst) \
PR_BEGIN_MACRO \
PRIntervalTime startTime = PR_IntervalNow(); \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
ret = fun; \
NS_NotifyPluginCall(startTime); \
NS_NotifyPluginCall(startTime); \
PR_END_MACRO
#define NS_TRY_SAFE_CALL_VOID(fun, pluginInst) \
PR_BEGIN_MACRO \
PRIntervalTime startTime = PR_IntervalNow(); \
fun; \
NS_NotifyPluginCall(startTime); \
#define NS_TRY_SAFE_CALL_VOID(fun, pluginInst) \
PR_BEGIN_MACRO \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
fun; \
NS_NotifyPluginCall(startTime); \
PR_END_MACRO
#endif // CALL_SAFETY_ON

View File

@ -24,3 +24,4 @@ qemu = true
[test_number_of_messages.js]
[test_mark_msg_read.js]
[test_mark_msg_read_error.js]
[test_bug814761.js]

View File

@ -0,0 +1,70 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 20000;
SpecialPowers.setBoolPref("dom.sms.enabled", true);
SpecialPowers.addPermission("sms", true, document);
let sms = window.navigator.mozSms;
// Note: 378 chars and below is fine, but 379 and above will cause the issue.
// Sending first message works, but second one we get emulator callback but
// the actual SMS is never received, so script will timeout waiting for the
// sms.onreceived event. Also note that a single larger message (i.e. 1600
// characters) works; so it is not a compounded send limit.
let fromNumber = "5551110000";
let msgLength = 379;
let msgText = new Array(msgLength + 1).join('a');
let pendingEmulatorCmdCount = 0;
function sendSmsToEmulator(from, text) {
++pendingEmulatorCmdCount;
let cmd = "sms send " + from + " " + text;
runEmulatorCmd(cmd, function (result) {
--pendingEmulatorCmdCount;
is(result[0], "OK", "Emulator response");
});
}
function firstIncomingSms() {
simulateIncomingSms(secondIncomingSms);
}
function secondIncomingSms() {
simulateIncomingSms(cleanUp);
}
function simulateIncomingSms(nextFunction) {
log("Simulating incoming multipart SMS (" + msgText.length
+ " chars total).");
sms.onreceived = function onreceived(event) {
log("Received 'onreceived' smsmanager event.");
sms.onreceived = null;
let incomingSms = event.message;
ok(incomingSms, "incoming sms");
is(incomingSms.body, msgText, "msg body");
window.setTimeout(nextFunction, 0);
};
sendSmsToEmulator(fromNumber, msgText);
}
function cleanUp() {
if (pendingEmulatorCmdCount) {
window.setTimeout(cleanUp, 100);
return;
}
SpecialPowers.removePermission("sms", document);
SpecialPowers.clearUserPref("dom.sms.enabled");
finish();
}
// Start the test
firstIncomingSms();

View File

@ -555,7 +555,9 @@ this.COMPREHENSIONTLV_TAG_ITEM_ID = 0x10;
this.COMPREHENSIONTLV_TAG_RESPONSE_LENGTH = 0x11;
this.COMPREHENSIONTLV_TAG_FILE_LIST = 0x12;
this.COMPREHENSIONTLV_TAG_LOCATION_INFO = 0x13;
this.COMPREHENSIONTLV_TAG_IMEI = 0x14;
this.COMPREHENSIONTLV_TAG_HELP_REQUEST = 0x15;
this.COMPREHENSIONTLV_TAG_NMR = 0x16;
this.COMPREHENSIONTLV_TAG_DEFAULT_TEXT = 0x17;
this.COMPREHENSIONTLV_TAG_CAUSE = 0x1a;
this.COMPREHENSIONTLV_TAG_LOCATION_STATUS = 0x1b;
@ -563,8 +565,17 @@ this.COMPREHENSIONTLV_TAG_TRANSACTION_ID = 0x1c;
this.COMPREHENSIONTLV_TAG_EVENT_LIST = 0x19;
this.COMPREHENSIONTLV_TAG_ICON_ID = 0x1e;
this.COMPREHENSIONTLV_TAG_ICON_ID_LIST = 0x1f;
this.COMPREHENSIONTLV_TAG_DATE_TIME_ZONE = 0x26;
this.COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE = 0x2b;
this.COMPREHENSIONTLV_TAG_LANGUAGE = 0x2d;
this.COMPREHENSIONTLV_TAG_URL = 0x31;
this.COMPREHENSIONTLV_TAG_ACCESS_TECH = 0x3f;
this.COMPREHENSIONTLV_TAG_SERVICE_RECORD = 0x41;
this.COMPREHENSIONTLV_TAG_IMEISV = 0x62;
this.COMPREHENSIONTLV_TAG_BATTERY_STATE = 0x63;
this.COMPREHENSIONTLV_TAG_NETWORK_SEARCH_MODE = 0x65;
this.COMPREHENSIONTLV_TAG_MEID = 0x6d;
this.COMPREHENSIONTLV_TAG_BROADCAST_NETWORK_INFO = 0x7a;
// Tags for Service Provider Display Information TLV
this.SPDI_TAG_SPDI = 0xa3;
@ -596,6 +607,7 @@ this.STK_CMD_GET_INKEY = 0x22;
this.STK_CMD_GET_INPUT = 0x23;
this.STK_CMD_SELECT_ITEM = 0x24;
this.STK_CMD_SET_UP_MENU = 0x25;
this.STK_CMD_PROVIDE_LOCAL_INFO = 0x26;
this.STK_CMD_SET_UP_IDLE_MODE_TEXT = 0x28;
// STK Result code.
@ -781,6 +793,23 @@ this.STK_TIME_UNIT_MINUTE = 0x00;
this.STK_TIME_UNIT_SECOND = 0x01;
this.STK_TIME_UNIT_TENTH_SECOND = 0x02;
// Local Information type.
this.STK_LOCAL_INFO_NNA = 0x00;
this.STK_LOCAL_INFO_IMEI = 0x01;
this.STK_LOCAL_INFO_NMR_FOR_NNA = 0x02;
this.STK_LOCAL_INFO_DATE_TIME_ZONE = 0x03;
this.STK_LOCAL_INFO_LANGUAGE = 0x04;
this.STK_LOCAL_INFO_ACCESS_TECH = 0x06;
this.STK_LOCAL_INFO_ESN = 0x07;
this.STK_LOCAL_INFO_IMEISV = 0x08;
this.STK_LOCAL_INFO_SEARCH_MODE = 0x09;
this.STK_LOCAL_INFO_CHARGE_STATE = 0x0A;
this.STK_LOCAL_INFO_MEID = 0x0B;
this.STK_LOCAL_INFO_BROADCAST_NETWORK_INFO = 0x0D;
this.STK_LOCAL_INFO_MULTIPLE_ACCESS_TECH = 0x0E;
this.STK_LOCAL_INFO_INFO_FOR_MULTIPLE_ACCESS_TECH = 0x0F;
this.STK_LOCAL_INFO_NMR_FOR_MULTIPLE_ACCESS_TECH = 0x10;
/**
* Supported Terminal Facilities.
*
@ -820,7 +849,7 @@ this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SS = 1;
this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_USSD = 1;
this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_CALL = 1;
this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_MENU = 1;
this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO = 0;
this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO = 1;
this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR = 0;
this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_EVENT_LIST = 1;
@ -832,6 +861,24 @@ this.STK_TERMINAL_SUPPORT_EVENT_USER_ACTIVITY = 0;
this.STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE = 0;
this.STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS = 0;
this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP = 0;
this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT = 0;
this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE = 1;
this.STK_TERMINAL_SUPPORT_GET_INKEY = 1;
this.STK_TERMINAL_SUPPORT_SET_UP_IDLE_MODE_TEXT = 1;
this.STK_TERMINAL_SUPPORT_RUN_AT_COMMAND = 0;
this.STK_TERMINAL_SUPPORT_SET_UP_CALL = 1;
this.STK_TERMINAL_SUPPORT_CALL_CONTROL_BY_NNA = 0;
this.STK_TERMINAL_SUPPORT_DISPLAY_TEXT = 1;
this.STK_TERMINAL_SUPPORT_SEND_DTMF_COMMAND = 1;
this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR = 0;
this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_LANGUAGE = 1;
this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_TIME_ADVANCE = 0;
this.STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION = 0;
this.STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER = 1;
this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH = 0;
this.STK_TERMINAL_PROFILE_DOWNLOAD =
(STK_TERMINAL_SUPPORT_PROFILE_DOWNLOAD << 0) |
(STK_TERMINAL_SUPPORT_SMS_PP_DOWNLOAD << 1) |
@ -882,6 +929,26 @@ this.STK_TERMINAL_PROFILE_EVENT =
(STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE << 6) |
(STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS << 7);
this.STK_TERMINAL_PROFILE_PROACTIVE_3 =
(STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP << 0) |
(STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT << 1) |
(STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE << 2) |
(STK_TERMINAL_SUPPORT_GET_INKEY << 3) |
(STK_TERMINAL_SUPPORT_SET_UP_IDLE_MODE_TEXT << 4) |
(STK_TERMINAL_SUPPORT_RUN_AT_COMMAND << 5) |
(STK_TERMINAL_SUPPORT_SET_UP_CALL << 6) |
(STK_TERMINAL_SUPPORT_CALL_CONTROL_BY_NNA << 7);
this.STK_TERMINAL_PROFILE_PROACTIVE_4 =
(STK_TERMINAL_SUPPORT_DISPLAY_TEXT << 0) |
(STK_TERMINAL_SUPPORT_SEND_DTMF_COMMAND << 1) |
(STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR << 2) |
(STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_LANGUAGE << 3) |
(STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_TIME_ADVANCE << 4) |
(STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION << 5) |
(STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER << 6) |
(STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH << 7);
this.STK_SUPPORTED_TERMINAL_PROFILE = [
STK_TERMINAL_PROFILE_DOWNLOAD,
STK_TERMINAL_PROFILE_OTHER,
@ -890,8 +957,8 @@ this.STK_SUPPORTED_TERMINAL_PROFILE = [
STK_TERMINAL_PROFILE_EVENT,
0x00, // Event extension
0x00, // Multiple card proactive commands
0x00, // Proactive Commands
0x00, // Proactive Commands
STK_TERMINAL_PROFILE_PROACTIVE_3,
STK_TERMINAL_PROFILE_PROACTIVE_4,
0x00, // Softkey support
0x00, // Softkey information
0x00, // BIP proactive commands

View File

@ -60,6 +60,9 @@ const TLV_EVENT_LIST_SIZE = 3;
const TLV_LOCATION_STATUS_SIZE = 3;
const TLV_LOCATION_INFO_GSM_SIZE = 9;
const TLV_LOCATION_INFO_UMTS_SIZE = 11;
const TLV_IMEI_SIZE = 10;
const TLV_DATE_TIME_ZONE_SIZE = 9;
const TLV_LANGUAGE_SIZE = 4;
const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"];
@ -475,8 +478,9 @@ let Buf = {
// we process any backlog in parcels immediately, before writing
// new data to the buffer. So the only edge case we need to handle
// is when the incoming data is larger than the buffer size.
if (incoming.length > this.INCOMING_BUFFER_LENGTH) {
this.growIncomingBuffer(incoming.length);
let minMustAvailableSize = incoming.length + this.readIncoming;
if (minMustAvailableSize > this.INCOMING_BUFFER_LENGTH) {
this.growIncomingBuffer(minMustAvailableSize);
}
// We can let the typed arrays do the copying if the incoming data won't
@ -585,6 +589,13 @@ let Buf = {
let error = this.readUint32();
options = this.tokenRequestMap[token];
if (!options) {
if (DEBUG) {
debug("Suspicious uninvited request found: " + token + ". Ignored!");
}
return;
}
delete this.tokenRequestMap[token];
request_type = options.rilRequestType;
@ -3118,11 +3129,13 @@ let RIL = {
* Send STK terminal response.
*
* @param command
* @param deviceIdentities
* @param resultCode
* @param [optional] itemIdentifier
* @param [optional] input
* @param [optional] isYesNo
* @param [optional] hasConfirmed
* @param [optional] localInfo
*/
sendStkTerminalResponse: function sendStkTerminalResponse(response) {
if (response.hasConfirmed !== undefined) {
@ -3154,6 +3167,18 @@ let RIL = {
TLV_RESULT_SIZE +
(response.itemIdentifier ? TLV_ITEM_ID_SIZE : 0) +
(textLen ? textLen + 3 : 0)) * 2;
if (response.localInfo) {
let localInfo = response.localInfo;
size = size +
(((localInfo.locationInfo ?
(localInfo.locationInfo.gsmCellId > 0xffff ?
TLV_LOCATION_INFO_UMTS_SIZE :
TLV_LOCATION_INFO_GSM_SIZE) :
0) +
(localInfo.imei ? TLV_IMEI_SIZE : 0) +
(localInfo.date ? TLV_DATE_TIME_ZONE_SIZE : 0) +
(localInfo.language ? TLV_LANGUAGE_SIZE : 0)) * 2);
}
Buf.writeUint32(size);
// Command Details
@ -3238,6 +3263,40 @@ let RIL = {
}
}
// Local Information
if (response.localInfo) {
let localInfo = response.localInfo;
// Location Infomation
if (localInfo.locationInfo) {
ComprehensionTlvHelper.writeLocationInfoTlv(localInfo.locationInfo);
}
// IMEI
if (localInfo.imei) {
let imei = localInfo.imei;
if(imei.length == 15) {
imei = imei + "0";
}
GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_IMEI);
GsmPDUHelper.writeHexOctet(8);
for (let i = 0; i < imei.length / 2; i++) {
GsmPDUHelper.writeHexOctet(parseInt(imei.substr(i * 2, 2), 16));
}
}
// Date and Time Zone
if (localInfo.date) {
ComprehensionTlvHelper.writeDateTimeZoneTlv(localInfo.date);
}
// Language
if (localInfo.language) {
ComprehensionTlvHelper.writeLanguageTlv(localInfo.language);
}
}
Buf.writeUint32(0);
Buf.sendParcel();
},
@ -6120,6 +6179,20 @@ let GsmPDUHelper = {
((octet & 0x0f) <= 0x09) * (octet & 0x0f) * 10;
},
/**
* Convert a BCD number to an octet (number)
*
* Only take two digits with absolute value.
*
* @param bcd
*
* @return the corresponding octet.
*/
BCDToOctet: function BCDToOctet(bcd) {
bcd = Math.abs(bcd);
return ((bcd % 10) << 4) + (Math.floor(bcd / 10) % 10);
},
/**
* Convert a semi-octet (number) to a GSM BCD char.
*/
@ -6204,6 +6277,24 @@ let GsmPDUHelper = {
}
},
/**
* Write numerical data as swapped nibble BCD.
* If the number of digit of data is even, add '0' at the beginning.
*
* @param data
* Data to write (as a string or a number)
*/
writeSwappedNibbleBCDNum: function writeSwappedNibbleBCDNum(data) {
data = data.toString();
if (data.length % 2) {
data = "0" + data;
}
for (let i = 0; i < data.length; i += 2) {
Buf.writeUint16(data.charCodeAt(i + 1));
Buf.writeUint16(data.charCodeAt(i));
}
},
/**
* Read user data, convert to septets, look up relevant characters in a
* 7-bit alphabet, and construct string.
@ -7028,6 +7119,43 @@ let GsmPDUHelper = {
return timestamp;
},
/**
* Write GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
*
* @see 3GPP TS 23.040 9.2.3.11
*/
writeTimestamp: function writeTimestamp(date) {
this.writeSwappedNibbleBCDNum(date.getFullYear() - PDU_TIMESTAMP_YEAR_OFFSET);
// The value returned by getMonth() is an integer between 0 and 11.
// 0 is corresponds to January, 1 to February, and so on.
this.writeSwappedNibbleBCDNum(date.getMonth() + 1);
this.writeSwappedNibbleBCDNum(date.getDate());
this.writeSwappedNibbleBCDNum(date.getHours());
this.writeSwappedNibbleBCDNum(date.getMinutes());
this.writeSwappedNibbleBCDNum(date.getSeconds());
// the value returned by getTimezoneOffset() is the difference,
// in minutes, between UTC and local time.
// For example, if your time zone is UTC+10 (Australian Eastern Standard Time),
// -600 will be returned.
// In TS 23.040 9.2.3.11, the Time Zone field of TP-SCTS indicates
// the different between the local time and GMT.
// And expressed in quarters of an hours. (so need to divid by 15)
let zone = date.getTimezoneOffset() / 15;
let octet = this.BCDToOctet(zone);
// the bit3 of the Time Zone field represents the algebraic sign.
// (0: positive, 1: negative).
// For example, if the time zone is -0800 GMT,
// 480 will be returned by getTimezoneOffset().
// In this case, need to mark sign bit as 1. => 0x08
if (zone > 0) {
octet = octet | 0x08;
}
this.writeHexOctet(octet);
},
/**
* User data can be 7 bit (default alphabet) data, 8 bit data, or 16 bit
* (UCS2) data.
@ -7738,6 +7866,9 @@ let StkCommandParamsFactory = {
case STK_CMD_POLL_OFF:
param = this.processPollOff(cmdDetails, ctlvs);
break;
case STK_CMD_PROVIDE_LOCAL_INFO:
param = this.processProvideLocalInfo(cmdDetails, ctlvs);
break;
case STK_CMD_SET_UP_EVENT_LIST:
param = this.processSetUpEventList(cmdDetails, ctlvs);
break;
@ -8145,6 +8276,21 @@ let StkCommandParamsFactory = {
playTone.isVibrate = (cmdDetails.commandQualifier & 0x01) != 0x00;
return playTone;
},
/**
* Construct a param for Provide Local Information
*
* @param cmdDetails
* The value object of CommandDetails TLV.
* @param ctlvs
* The all TLVs in this proactive command.
*/
processProvideLocalInfo: function processProvideLocalInfo(cmdDetails, ctlvs) {
let provideLocalInfo = {
localInfoType: cmdDetails.commandQualifier
};
return provideLocalInfo;
}
};
@ -8664,6 +8810,24 @@ let ComprehensionTlvHelper = {
GsmPDUHelper.writeHexOctet(0x80 | cause);
},
writeDateTimeZoneTlv: function writeDataTimeZoneTlv(date) {
GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DATE_TIME_ZONE);
GsmPDUHelper.writeHexOctet(7);
GsmPDUHelper.writeTimestamp(date);
},
writeLanguageTlv: function writeLanguageTlv(language) {
GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LANGUAGE);
GsmPDUHelper.writeHexOctet(2);
// ISO 639-1, Alpha-2 code
// TS 123.038, clause 6.2.1, GSM 7 bit Default Alphabet
GsmPDUHelper.writeHexOctet(
PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT].indexOf(language[0]));
GsmPDUHelper.writeHexOctet(
PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT].indexOf(language[1]));
},
getSizeOfLengthOctets: function getSizeOfLengthOctets(length) {
if (length >= 0x10000) {
return 4; // 0x83, len_1, len_2, len_3

View File

@ -82,6 +82,81 @@ add_test_incoming_parcel(null,
}
);
// Test Bug 814761: buffer overwritten
add_test(function test_incoming_parcel_buffer_overwritten() {
let worker = newWorker({
postRILMessage: function fakePostRILMessage(data) {
// do nothing
},
postMessage: function fakePostMessage(message) {
// do nothing
}
});
// A convenient alias.
let buf = worker.Buf;
// Allocate an array of specified size and set each of its elements to value.
function calloc(length, value) {
let array = new Array(length);
for (let i = 0; i < length; i++) {
array[i] = value;
}
return array;
}
// Do nothing in handleParcel().
let request = worker.REQUEST_REGISTRATION_STATE;
worker.RIL[request] = null;
// Prepare two parcels, whose sizes are both smaller than the incoming buffer
// size but larger when combined, to trigger the bug.
let pA_dataLength = buf.INCOMING_BUFFER_LENGTH / 2;
let pA = newIncomingParcel(-1,
worker.RESPONSE_TYPE_UNSOLICITED,
request,
calloc(pA_dataLength, 1));
let pA_parcelSize = pA.length - worker.PARCEL_SIZE_SIZE;
let pB_dataLength = buf.INCOMING_BUFFER_LENGTH * 3 / 4;
let pB = newIncomingParcel(-1,
worker.RESPONSE_TYPE_UNSOLICITED,
request,
calloc(pB_dataLength, 1));
let pB_parcelSize = pB.length - worker.PARCEL_SIZE_SIZE;
// First, send an incomplete pA and verifies related data pointer:
let p1 = pA.subarray(0, pA.length - 1);
worker.onRILMessage(p1);
// The parcel should not have been processed.
do_check_eq(buf.readAvailable, 0);
// buf.currentParcelSize should have been set because incoming data has more
// than 4 octets.
do_check_eq(buf.currentParcelSize, pA_parcelSize);
// buf.readIncoming should contains remaining unconsumed octets count.
do_check_eq(buf.readIncoming, p1.length - worker.PARCEL_SIZE_SIZE);
// buf.incomingWriteIndex should be ready to accept the last octet.
do_check_eq(buf.incomingWriteIndex, p1.length);
// Second, send the last octet of pA and whole pB. The Buf should now expand
// to cover both pA & pB.
let p2 = new Uint8Array(1 + pB.length);
p2.set(pA.subarray(pA.length - 1), 0);
p2.set(pB, 1);
worker.onRILMessage(p2);
// The parcels should have been both consumed.
do_check_eq(buf.readAvailable, 0);
// No parcel data remains.
do_check_eq(buf.currentParcelSize, 0);
// No parcel data remains.
do_check_eq(buf.readIncoming, 0);
// The Buf should now expand to cover both pA & pB.
do_check_eq(buf.incomingWriteIndex, pA.length + pB.length);
// end of incoming parcel's trip, let's do next test.
run_next_test();
});
// Test Buf.readUint8Array.
add_test_incoming_parcel(null,
function test_buf_readUint8Array(worker) {

View File

@ -121,6 +121,75 @@ add_test(function test_write_dialling_number() {
run_next_test();
});
/**
* Verify GsmPDUHelper.writeTimestamp
*/
add_test(function test_write_timestamp() {
let worker = newUint8Worker();
let helper = worker.GsmPDUHelper;
// current date
let dateInput = new Date();
let dateOutput = new Date();
helper.writeTimestamp(dateInput);
dateOutput.setTime(helper.readTimestamp());
do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
do_check_eq(dateInput.getDate(), dateOutput.getDate());
do_check_eq(dateInput.getHours(), dateOutput.getHours());
do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
// 2034-01-23 12:34:56 -0800 GMT
let time = Date.UTC(2034, 1, 23, 12, 34, 56);
time = time - (8 * 60 * 60 * 1000);
dateInput.setTime(time);
helper.writeTimestamp(dateInput);
dateOutput.setTime(helper.readTimestamp());
do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
do_check_eq(dateInput.getDate(), dateOutput.getDate());
do_check_eq(dateInput.getHours(), dateOutput.getHours());
do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
run_next_test();
});
/**
* Verify GsmPDUHelper.octectToBCD and GsmPDUHelper.BCDToOctet
*/
add_test(function test_octect_BCD() {
let worker = newUint8Worker();
let helper = worker.GsmPDUHelper;
// 23
let number = 23;
let octet = helper.BCDToOctet(number);
do_check_eq(helper.octetToBCD(octet), number);
// 56
number = 56;
octet = helper.BCDToOctet(number);
do_check_eq(helper.octetToBCD(octet), number);
// 0x23
octet = 0x23;
number = helper.octetToBCD(octet);
do_check_eq(helper.BCDToOctet(number), octet);
// 0x56
octet = 0x56;
number = helper.octetToBCD(octet);
do_check_eq(helper.BCDToOctet(number), octet);
run_next_test();
});
/**
* Verify RIL.isICCServiceAvailable.
*/
@ -582,3 +651,51 @@ add_test(function test_stk_proactive_command_more_time() {
run_next_test();
});
/**
* Verify Proactive Command : Provide Local Information
*/
add_test(function test_stk_proactive_command_provide_local_information() {
let worker = newUint8Worker();
let pduHelper = worker.GsmPDUHelper;
let berHelper = worker.BerTlvHelper;
let stkHelper = worker.StkProactiveCmdHelper;
// Verify IMEI
let local_info_1 = [
0xD0,
0x09,
0x81, 0x03, 0x01, 0x26, 0x01,
0x82, 0x02, 0x81, 0x82];
for (let i = 0; i < local_info_1.length; i++) {
pduHelper.writeHexOctet(local_info_1[i]);
}
let berTlv = berHelper.decode(local_info_1.length);
let ctlvs = berTlv.value;
let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
do_check_eq(tlv.value.commandNumber, 0x01);
do_check_eq(tlv.value.typeOfCommand, STK_CMD_PROVIDE_LOCAL_INFO);
do_check_eq(tlv.value.commandQualifier, STK_LOCAL_INFO_IMEI);
// Verify Date and Time Zone
let local_info_2 = [
0xD0,
0x09,
0x81, 0x03, 0x01, 0x26, 0x03,
0x82, 0x02, 0x81, 0x82];
for (let i = 0; i < local_info_2.length; i++) {
pduHelper.writeHexOctet(local_info_2[i]);
}
berTlv = berHelper.decode(local_info_2.length);
ctlvs = berTlv.value;
tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
do_check_eq(tlv.value.commandNumber, 0x01);
do_check_eq(tlv.value.typeOfCommand, STK_CMD_PROVIDE_LOCAL_INFO);
do_check_eq(tlv.value.commandQualifier, STK_LOCAL_INFO_DATE_TIME_ZONE);
run_next_test();
});

View File

@ -84,7 +84,7 @@ public:
}
private:
uint16_t mEnum;
void bool_conversion_helper() {};
void bool_conversion_helper() {}
public:
// Allow boolean conversion with no numeric conversion
typedef void (WSType::*bool_type)();

View File

@ -39,6 +39,18 @@
#include <emmintrin.h> // ARCH_CPU_X86_FAMILY was defined in build/config.h
#endif
#if defined(SK_CPU_LENDIAN)
#define R_OFFSET_IDX 0
#define G_OFFSET_IDX 1
#define B_OFFSET_IDX 2
#define A_OFFSET_IDX 3
#else
#define R_OFFSET_IDX 3
#define G_OFFSET_IDX 2
#define B_OFFSET_IDX 1
#define A_OFFSET_IDX 0
#endif
namespace skia {
namespace {
@ -162,11 +174,11 @@ void ConvolveHorizontally(const unsigned char* src_data,
int accum[4] = {0};
for (int filter_x = 0; filter_x < filter_length; filter_x++) {
ConvolutionFilter1D::Fixed cur_filter = filter_values[filter_x];
accum[0] += cur_filter * row_to_filter[filter_x * 4 + 0];
accum[1] += cur_filter * row_to_filter[filter_x * 4 + 1];
accum[2] += cur_filter * row_to_filter[filter_x * 4 + 2];
accum[0] += cur_filter * row_to_filter[filter_x * 4 + R_OFFSET_IDX];
accum[1] += cur_filter * row_to_filter[filter_x * 4 + G_OFFSET_IDX];
accum[2] += cur_filter * row_to_filter[filter_x * 4 + B_OFFSET_IDX];
if (has_alpha)
accum[3] += cur_filter * row_to_filter[filter_x * 4 + 3];
accum[3] += cur_filter * row_to_filter[filter_x * 4 + A_OFFSET_IDX];
}
// Bring this value back in range. All of the filter scaling factors
@ -178,11 +190,11 @@ void ConvolveHorizontally(const unsigned char* src_data,
accum[3] >>= ConvolutionFilter1D::kShiftBits;
// Store the new pixel.
out_row[out_x * 4 + 0] = ClampTo8(accum[0]);
out_row[out_x * 4 + 1] = ClampTo8(accum[1]);
out_row[out_x * 4 + 2] = ClampTo8(accum[2]);
out_row[out_x * 4 + R_OFFSET_IDX] = ClampTo8(accum[0]);
out_row[out_x * 4 + G_OFFSET_IDX] = ClampTo8(accum[1]);
out_row[out_x * 4 + B_OFFSET_IDX] = ClampTo8(accum[2]);
if (has_alpha)
out_row[out_x * 4 + 3] = ClampTo8(accum[3]);
out_row[out_x * 4 + A_OFFSET_IDX] = ClampTo8(accum[3]);
}
}
@ -209,11 +221,15 @@ void ConvolveVertically(const ConvolutionFilter1D::Fixed* filter_values,
int accum[4] = {0};
for (int filter_y = 0; filter_y < filter_length; filter_y++) {
ConvolutionFilter1D::Fixed cur_filter = filter_values[filter_y];
accum[0] += cur_filter * source_data_rows[filter_y][byte_offset + 0];
accum[1] += cur_filter * source_data_rows[filter_y][byte_offset + 1];
accum[2] += cur_filter * source_data_rows[filter_y][byte_offset + 2];
accum[0] += cur_filter
* source_data_rows[filter_y][byte_offset + R_OFFSET_IDX];
accum[1] += cur_filter
* source_data_rows[filter_y][byte_offset + G_OFFSET_IDX];
accum[2] += cur_filter
* source_data_rows[filter_y][byte_offset + B_OFFSET_IDX];
if (has_alpha)
accum[3] += cur_filter * source_data_rows[filter_y][byte_offset + 3];
accum[3] += cur_filter
* source_data_rows[filter_y][byte_offset + A_OFFSET_IDX];
}
// Bring this value back in range. All of the filter scaling factors
@ -225,9 +241,9 @@ void ConvolveVertically(const ConvolutionFilter1D::Fixed* filter_values,
accum[3] >>= ConvolutionFilter1D::kShiftBits;
// Store the new pixel.
out_row[byte_offset + 0] = ClampTo8(accum[0]);
out_row[byte_offset + 1] = ClampTo8(accum[1]);
out_row[byte_offset + 2] = ClampTo8(accum[2]);
out_row[byte_offset + R_OFFSET_IDX] = ClampTo8(accum[0]);
out_row[byte_offset + G_OFFSET_IDX] = ClampTo8(accum[1]);
out_row[byte_offset + B_OFFSET_IDX] = ClampTo8(accum[2]);
if (has_alpha) {
unsigned char alpha = ClampTo8(accum[3]);
@ -238,15 +254,15 @@ void ConvolveVertically(const ConvolutionFilter1D::Fixed* filter_values,
// values) when the resulting bitmap is drawn to the screen.
//
// We only need to do this when generating the final output row (here).
int max_color_channel = NS_MAX(out_row[byte_offset + 0],
NS_MAX(out_row[byte_offset + 1], out_row[byte_offset + 2]));
int max_color_channel = NS_MAX(out_row[byte_offset + R_OFFSET_IDX],
NS_MAX(out_row[byte_offset + G_OFFSET_IDX], out_row[byte_offset + B_OFFSET_IDX]));
if (alpha < max_color_channel)
out_row[byte_offset + 3] = max_color_channel;
out_row[byte_offset + A_OFFSET_IDX] = max_color_channel;
else
out_row[byte_offset + 3] = alpha;
out_row[byte_offset + A_OFFSET_IDX] = alpha;
} else {
// No alpha channel, the image is opaque.
out_row[byte_offset + 3] = 0xff;
out_row[byte_offset + A_OFFSET_IDX] = 0xff;
}
}
}

View File

@ -142,6 +142,7 @@ EXPORTS_mozilla/layers =\
RenderTrace.h \
SharedImageUtils.h \
ShmemYCbCrImage.h \
TaskThrottler.h \
$(NULL)
CPPSRCS += \
@ -161,6 +162,7 @@ CPPSRCS += \
ShadowLayerParent.cpp \
ShadowLayersParent.cpp \
ShmemYCbCrImage.cpp \
TaskThrottler.cpp \
$(NULL)
ifdef MOZ_X11 #{

View File

@ -967,7 +967,11 @@ void AsyncPanZoomController::RequestContentRepaint() {
// This message is compressed, so fire whether or not we already have a paint
// queued up. We need to know whether or not a paint was requested anyways,
// for the purposes of content calling window.scrollTo().
mGeckoContentController->RequestContentRepaint(mFrameMetrics);
mPaintThrottler.PostTask(
FROM_HERE,
NewRunnableMethod(mGeckoContentController.get(),
&GeckoContentController::RequestContentRepaint,
mFrameMetrics));
mLastPaintRequestMetrics = mFrameMetrics;
mWaitingForContentToPaint = true;
@ -1081,6 +1085,8 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFrame, bool aIsFirstPaint) {
MonitorAutoLock monitor(mMonitor);
mPaintThrottler.TaskComplete();
mLastContentPaintMetrics = aViewportFrame;
if (mWaitingForContentToPaint) {

View File

@ -15,6 +15,7 @@
#include "InputData.h"
#include "Axis.h"
#include "nsContentUtils.h"
#include "TaskThrottler.h"
#include "base/message_loop.h"
@ -458,6 +459,7 @@ private:
void SetState(PanZoomState aState);
nsRefPtr<CompositorParent> mCompositorParent;
TaskThrottler mPaintThrottler;
nsRefPtr<GeckoContentController> mGeckoContentController;
nsRefPtr<GestureEventListener> mGestureEventListener;

View File

@ -39,12 +39,16 @@ public:
Transaction()
: mSwapRequired(false)
, mOpen(false)
, mRotationChanged(false)
{}
void Begin(const nsIntRect& aTargetBounds, ScreenRotation aRotation)
{
mOpen = true;
mTargetBounds = aTargetBounds;
if (aRotation != mTargetRotation) {
mRotationChanged = true;
}
mTargetRotation = aRotation;
}
@ -86,11 +90,15 @@ public:
mMutants.clear();
mOpen = false;
mSwapRequired = false;
mRotationChanged = false;
}
bool Empty() const {
return mCset.empty() && mPaints.empty() && mMutants.empty();
}
bool RotationChanged() const {
return mRotationChanged;
}
bool Finished() const { return !mOpen && Empty(); }
EditVector mCset;
@ -103,6 +111,7 @@ public:
private:
bool mOpen;
bool mRotationChanged;
// disabled
Transaction(const Transaction&);
@ -285,8 +294,8 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies)
AutoTxnEnd _(mTxn);
if (mTxn->Empty()) {
MOZ_LAYERS_LOG(("[LayersForwarder] 0-length cset (?), skipping Update()"));
if (mTxn->Empty() && !mTxn->RotationChanged()) {
MOZ_LAYERS_LOG(("[LayersForwarder] 0-length cset (?) and no rotation event, skipping Update()"));
return true;
}

View File

@ -0,0 +1,49 @@
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
/* vim: set sw=2 sts=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
#include "base/message_loop.h"
#include "TaskThrottler.h"
namespace mozilla {
namespace layers {
TaskThrottler::TaskThrottler()
: mOutstanding(false)
, mQueuedTask(nullptr)
{ }
void
TaskThrottler::PostTask(const tracked_objects::Location& aLocation,
CancelableTask* aTask)
{
aTask->SetBirthPlace(aLocation);
if (mOutstanding) {
if (mQueuedTask) {
mQueuedTask->Cancel();
}
mQueuedTask = aTask;
} else {
aTask->Run();
delete aTask;
mOutstanding = true;
}
}
void
TaskThrottler::TaskComplete()
{
if (mQueuedTask) {
mQueuedTask->Run();
mQueuedTask = nullptr;
} else {
mOutstanding = false;
}
}
}
}

View File

@ -0,0 +1,56 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_TaskThrottler_h
#define mozilla_dom_TaskThrottler_h
#include "nsAutoPtr.h"
class CancelableTask;
namespace tracked_objects {
class Location;
}
namespace mozilla {
namespace layers {
/** The TaskThrottler prevents update event overruns. It is used in cases where
* you're sending an async message and waiting for a reply. You need to call
* PostTask to queue a task and TaskComplete when you get a response.
*
* The call to TaskComplete will run the recent task posted since the last
* request was sent, if any. This means that at any time there can be at most 1
* outstanding request being processed and at most 1 queued behind it.
*
* This is used in the context of repainting a scrollable region. While another
* process is painting you might get several updates from the UI thread but when
* the paint is complete you want to send the most recent.
*/
class TaskThrottler {
public:
TaskThrottler();
/** Post a task to be run as soon as there are no outstanding tasks.
*
* @param aLocation Use the macro FROM_HERE
* @param aTask Ownership of this object is transferred to TaskThrottler
* which will delete it when it is either run or becomes
* obsolete or the TaskThrottler is destructed.
*/
void PostTask(const tracked_objects::Location& aLocation,
CancelableTask* aTask);
void TaskComplete();
private:
bool mOutstanding;
nsAutoPtr<CancelableTask> mQueuedTask;
};
}
}
#endif // mozilla_dom_TaskThrottler_h

View File

@ -94,7 +94,7 @@
//////////////////////////////////////////////////////////////////////
#if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN)
#if defined (__ppc__) || defined(__ppc64__)
#if defined (__ppc__) || defined(__PPC__) || defined(__ppc64__) || defined(__PPC64__)
#define SK_CPU_BENDIAN
#else
#define SK_CPU_LENDIAN

View File

@ -196,6 +196,7 @@ FT2FontEntry::CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
fe->mItalic = aProxyEntry.mItalic;
fe->mWeight = aProxyEntry.mWeight;
fe->mStretch = aProxyEntry.mStretch;
fe->mIsUserFont = true;
}
return fe;
}

View File

@ -82,8 +82,14 @@ gfxCharacterMap::NotifyReleased()
delete this;
}
gfxFontEntry::~gfxFontEntry()
gfxFontEntry::~gfxFontEntry()
{
// For downloaded fonts, we need to tell the user font cache that this
// entry is being deleted.
if (!mIsProxy && IsUserFont() && !IsLocalUserFont()) {
gfxUserFontSet::UserFontCache::ForgetFont(this);
}
if (mSVGGlyphs) {
delete mSVGGlyphs;
}
@ -1238,6 +1244,11 @@ gfxFontCache::gfxFontCache()
gfxFontCache::~gfxFontCache()
{
// Ensure the user font cache releases its references to font entries,
// so they aren't kept alive after the font instances and font-list
// have been shut down.
gfxUserFontSet::UserFontCache::Shutdown();
if (mWordCacheExpirationTimer) {
mWordCacheExpirationTimer->Cancel();
mWordCacheExpirationTimer = nullptr;

View File

@ -1504,6 +1504,15 @@ gfxFcFontSet::SortPreferredFonts(bool &aWaitForUserFont)
for (uint32_t f = 0; f < familyFonts->Length(); ++f) {
FcPattern *font = familyFonts->ElementAt(f);
// Fix up the family name of user-font patterns, as the same
// font entry may be used (via the UserFontCache) for multiple
// CSS family names
if (isUserFont) {
font = FcPatternDuplicate(font);
FcPatternDel(font, FC_FAMILY);
FcPatternAddString(font, FC_FAMILY, family);
}
// User fonts are already filtered by slant (but not size) in
// mUserFontSet->FindFontEntry().
if (!isUserFont && !SlantIsAcceptable(font, requestedSlant))
@ -1524,7 +1533,12 @@ gfxFcFontSet::SortPreferredFonts(bool &aWaitForUserFont)
// FcFontSetDestroy will remove a reference but FcFontSetAdd
// does _not_ take a reference!
if (FcFontSetAdd(fontSet, font)) {
FcPatternReference(font);
// We don't add a reference here for user fonts, because we're
// using a local clone of the pattern (see above) in order to
// override the family name
if (!isUserFont) {
FcPatternReference(font);
}
}
}
}

View File

@ -15,6 +15,8 @@
#include "prlong.h"
#include "nsNetUtil.h"
#include "nsIProtocolHandler.h"
#include "nsIPrincipal.h"
#include "mozilla/Telemetry.h"
#include "woff.h"
@ -406,6 +408,7 @@ StoreUserFontData(gfxFontEntry* aFontEntry, gfxProxyFontEntry* aProxy,
userFontData->mLocalName = src.mLocalName;
} else {
userFontData->mURI = src.mURI;
userFontData->mPrincipal = aProxy->mPrincipal;
}
userFontData->mFormat = src.mFormatFlags;
userFontData->mRealName = aOriginalName;
@ -559,48 +562,65 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry)
if (gfxPlatform::GetPlatform()->IsFontFormatSupported(currSrc.mURI,
currSrc.mFormatFlags)) {
nsresult rv;
bool loadDoesntSpin = false;
rv = NS_URIChainHasFlags(currSrc.mURI,
nsIProtocolHandler::URI_SYNC_LOAD_IS_OK,
&loadDoesntSpin);
nsIPrincipal *principal = nullptr;
nsresult rv = CheckFontLoad(&currSrc, &principal);
if (NS_SUCCEEDED(rv) && loadDoesntSpin) {
uint8_t *buffer = nullptr;
uint32_t bufferLength = 0;
// sync load font immediately
rv = SyncLoadFontData(aProxyEntry, &currSrc, buffer,
bufferLength);
if (NS_SUCCEEDED(rv) &&
LoadFont(aProxyEntry, buffer, bufferLength)) {
if (NS_SUCCEEDED(rv) && principal != nullptr) {
// see if we have an existing entry for this source
gfxFontEntry *fe =
UserFontCache::GetFont(currSrc.mURI, principal,
aProxyEntry);
if (fe) {
ReplaceFontEntry(aProxyEntry, fe);
return STATUS_LOADED;
} else {
LogMessage(aProxyEntry, "font load failed",
nsIScriptError::errorFlag, rv);
}
} else {
// otherwise load font async
rv = StartLoad(aProxyEntry, &currSrc);
bool loadOK = NS_SUCCEEDED(rv);
// record the principal returned by CheckFontLoad,
// for use when creating a channel
// and when caching the loaded entry
aProxyEntry->mPrincipal = principal;
if (loadOK) {
#ifdef PR_LOGGING
if (LOG_ENABLED()) {
nsAutoCString fontURI;
currSrc.mURI->GetSpec(fontURI);
LOG(("userfonts (%p) [src %d] loading uri: (%s) for (%s)\n",
this, aProxyEntry->mSrcIndex, fontURI.get(),
NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
bool loadDoesntSpin = false;
rv = NS_URIChainHasFlags(currSrc.mURI,
nsIProtocolHandler::URI_SYNC_LOAD_IS_OK,
&loadDoesntSpin);
if (NS_SUCCEEDED(rv) && loadDoesntSpin) {
uint8_t *buffer = nullptr;
uint32_t bufferLength = 0;
// sync load font immediately
rv = SyncLoadFontData(aProxyEntry, &currSrc,
buffer, bufferLength);
if (NS_SUCCEEDED(rv) &&
(fe = LoadFont(aProxyEntry, buffer, bufferLength))) {
UserFontCache::CacheFont(fe);
return STATUS_LOADED;
} else {
LogMessage(aProxyEntry, "font load failed",
nsIScriptError::errorFlag, rv);
}
#endif
return STATUS_LOADING;
} else {
LogMessage(aProxyEntry, "download failed",
nsIScriptError::errorFlag, rv);
// otherwise load font async
rv = StartLoad(aProxyEntry, &currSrc);
if (NS_SUCCEEDED(rv)) {
#ifdef PR_LOGGING
if (LOG_ENABLED()) {
nsAutoCString fontURI;
currSrc.mURI->GetSpec(fontURI);
LOG(("userfonts (%p) [src %d] loading uri: (%s) for (%s)\n",
this, aProxyEntry->mSrcIndex, fontURI.get(),
NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
}
#endif
return STATUS_LOADING;
} else {
LogMessage(aProxyEntry, "download failed",
nsIScriptError::errorFlag, rv);
}
}
} else {
LogMessage(aProxyEntry, "download not allowed",
nsIScriptError::errorFlag, rv);
}
} else {
// We don't log a warning to the web console yet,
@ -752,6 +772,7 @@ gfxUserFontSet::LoadFont(gfxProxyFontEntry *aProxy,
uint32_t(mGeneration)));
}
#endif
UserFontCache::CacheFont(fe);
ReplaceFontEntry(aProxy, fe);
} else {
#ifdef PR_LOGGING
@ -778,3 +799,94 @@ gfxUserFontSet::GetFamily(const nsAString& aFamilyName) const
return mFontFamilies.GetWeak(key);
}
///////////////////////////////////////////////////////////////////////////////
// gfxUserFontSet::UserFontCache - re-use platform font entries for user fonts
// across pages/fontsets rather than instantiating new platform fonts.
//
// Entries are added to this cache when a platform font is instantiated from
// downloaded data, and removed when the platform font entry is destroyed.
// We don't need to use a timed expiration scheme here because the gfxFontEntry
// for a downloaded font will be kept alive by its corresponding gfxFont
// instance(s) until they are deleted, and *that* happens using an expiration
// tracker (gfxFontCache). The result is that the downloaded font instances
// recorded here will persist between pages and can get reused (provided the
// source URI and principal match, of course).
///////////////////////////////////////////////////////////////////////////////
nsTHashtable<gfxUserFontSet::UserFontCache::Entry>*
gfxUserFontSet::UserFontCache::sUserFonts = nullptr;
bool
gfxUserFontSet::UserFontCache::Entry::KeyEquals(const KeyTypePointer aKey) const
{
bool equal;
if (NS_FAILED(mURI->Equals(aKey->mURI, &equal)) || !equal) {
return false;
}
if (NS_FAILED(mPrincipal->Equals(aKey->mPrincipal, &equal)) || !equal) {
return false;
}
const gfxFontEntry *fe = aKey->mFontEntry;
if (mFontEntry->mItalic != fe->mItalic ||
mFontEntry->mWeight != fe->mWeight ||
mFontEntry->mStretch != fe->mStretch ||
mFontEntry->mFeatureSettings != fe->mFeatureSettings ||
mFontEntry->mLanguageOverride != fe->mLanguageOverride) {
return false;
}
return true;
}
void
gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry *aFontEntry)
{
if (!sUserFonts) {
sUserFonts = new nsTHashtable<Entry>;
sUserFonts->Init();
}
gfxUserFontData *data = aFontEntry->mUserFontData;
sUserFonts->PutEntry(Key(data->mURI, data->mPrincipal, aFontEntry));
}
void
gfxUserFontSet::UserFontCache::ForgetFont(gfxFontEntry *aFontEntry)
{
if (!sUserFonts) {
// if we've already deleted the cache (i.e. during shutdown),
// just ignore this
return;
}
gfxUserFontData *data = aFontEntry->mUserFontData;
sUserFonts->RemoveEntry(Key(data->mURI, data->mPrincipal, aFontEntry));
}
gfxFontEntry*
gfxUserFontSet::UserFontCache::GetFont(nsIURI *aSrcURI,
nsIPrincipal *aPrincipal,
gfxProxyFontEntry *aProxy)
{
if (!sUserFonts) {
return nullptr;
}
Entry* entry = sUserFonts->GetEntry(Key(aSrcURI, aPrincipal, aProxy));
if (entry) {
return entry->GetFontEntry();
}
return nullptr;
}
void
gfxUserFontSet::UserFontCache::Shutdown()
{
if (sUserFonts) {
delete sUserFonts;
sUserFonts = nullptr;
}
}

View File

@ -14,10 +14,11 @@
#include "nsCOMPtr.h"
#include "nsIURI.h"
#include "nsIFile.h"
#include "nsIPrincipal.h"
#include "nsISupportsImpl.h"
#include "nsIScriptError.h"
#include "nsURIHashKey.h"
class nsIURI;
class gfxMixedFontFamily;
class nsFontFaceLoader;
@ -35,10 +36,9 @@ struct gfxFontFaceSrc {
uint32_t mFormatFlags;
nsString mLocalName; // full font name if local
nsCOMPtr<nsIURI> mURI; // uri if url
nsCOMPtr<nsIURI> mURI; // uri if url
nsCOMPtr<nsIURI> mReferrer; // referrer url if url
nsCOMPtr<nsISupports> mOriginPrincipal; // principal if url
nsCOMPtr<nsIPrincipal> mOriginPrincipal; // principal if url
};
// Subclassed to store platform-specific code cleaned out when font entry is
@ -56,6 +56,7 @@ public:
nsTArray<uint8_t> mMetadata; // woff metadata block (compressed), if any
nsCOMPtr<nsIURI> mURI; // URI of the source, if it was url()
nsCOMPtr<nsIPrincipal> mPrincipal; // principal for the download, if url()
nsString mLocalName; // font name used for the source, if local()
nsString mRealName; // original fullname from the font resource
uint32_t mSrcIndex; // index in the rule's source list
@ -202,10 +203,14 @@ public:
bool& aFoundFamily,
bool& aNeedsBold,
bool& aWaitForUserFont);
// check whether the given source is allowed to be loaded
virtual nsresult CheckFontLoad(const gfxFontFaceSrc *aFontFaceSrc,
nsIPrincipal **aPrincipal) = 0;
// initialize the process that loads external font data, which upon
// completion will call OnLoadComplete method
virtual nsresult StartLoad(gfxProxyFontEntry *aProxy,
virtual nsresult StartLoad(gfxProxyFontEntry *aProxy,
const gfxFontFaceSrc *aFontFaceSrc) = 0;
// when download has been completed, pass back data here
@ -231,6 +236,104 @@ public:
// increment the generation on font load
void IncrementGeneration();
class UserFontCache {
public:
// Record a loaded user-font in the cache. This requires that the
// font-entry's userFontData has been set up already, as it relies
// on the URI and Principal recorded there.
static void CacheFont(gfxFontEntry *aFontEntry);
// The given gfxFontEntry is being destroyed, so remove any record that
// refers to it.
static void ForgetFont(gfxFontEntry *aFontEntry);
// Return the gfxFontEntry corresponding to a given URI and principal,
// and the features of the given proxy, or nullptr if none is available
static gfxFontEntry* GetFont(nsIURI *aSrcURI,
nsIPrincipal *aPrincipal,
gfxProxyFontEntry *aProxy);
// Clear everything so that we don't leak URIs and Principals.
static void Shutdown();
private:
// Key used to look up entries in the user-font cache.
// Note that key comparison does *not* use the mFontEntry field
// as a whole; it only compares specific fields within the entry
// (weight/width/style/features) that could affect font selection
// or rendering, and that must match between a font-set's proxy
// entry and the corresponding "real" font entry.
struct Key {
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mPrincipal;
gfxFontEntry *mFontEntry;
Key(nsIURI* aURI, nsIPrincipal* aPrincipal,
gfxFontEntry* aFontEntry)
: mURI(aURI),
mPrincipal(aPrincipal),
mFontEntry(aFontEntry)
{ }
};
class Entry : public PLDHashEntryHdr {
public:
typedef const Key& KeyType;
typedef const Key* KeyTypePointer;
Entry(KeyTypePointer aKey)
: mURI(aKey->mURI),
mPrincipal(aKey->mPrincipal),
mFontEntry(aKey->mFontEntry)
{ }
Entry(const Entry& aOther)
: mURI(aOther.mURI),
mPrincipal(aOther.mPrincipal),
mFontEntry(aOther.mFontEntry)
{ }
~Entry() { }
bool KeyEquals(const KeyTypePointer aKey) const;
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(const KeyTypePointer aKey) {
uint32_t principalHash;
aKey->mPrincipal->GetHashValue(&principalHash);
return mozilla::HashGeneric(principalHash,
nsURIHashKey::HashKey(aKey->mURI),
HashFeatures(aKey->mFontEntry->mFeatureSettings),
( aKey->mFontEntry->mItalic |
(aKey->mFontEntry->mWeight << 1) |
(aKey->mFontEntry->mStretch << 10) ) ^
aKey->mFontEntry->mLanguageOverride);
}
enum { ALLOW_MEMMOVE = false };
gfxFontEntry* GetFontEntry() const { return mFontEntry; }
private:
static uint32_t
HashFeatures(const nsTArray<gfxFontFeature>& aFeatures) {
return mozilla::HashBytes(aFeatures.Elements(),
aFeatures.Length() * sizeof(gfxFontFeature));
}
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mPrincipal;
// The "real" font entry corresponding to this downloaded font.
// The font entry MUST notify the cache when it is destroyed
// (by calling Forget()).
gfxFontEntry *mFontEntry;
};
static nsTHashtable<Entry> *sUserFonts;
};
protected:
// for a given proxy font entry, attempt to load the next resource
// in the src list
@ -247,11 +350,7 @@ protected:
virtual nsresult SyncLoadFontData(gfxProxyFontEntry *aFontToLoad,
const gfxFontFaceSrc *aFontFaceSrc,
uint8_t* &aBuffer,
uint32_t &aBufferLength)
{
// implemented in nsUserFontSet
return NS_ERROR_NOT_IMPLEMENTED;
}
uint32_t &aBufferLength) = 0;
gfxMixedFontFamily *GetFamily(const nsAString& aName) const;
@ -320,6 +419,7 @@ public:
nsTArray<gfxFontFaceSrc> mSrcList;
uint32_t mSrcIndex; // index of loading src item
nsFontFaceLoader *mLoader; // current loader for this entry, if any
nsCOMPtr<nsIPrincipal> mPrincipal;
};

View File

@ -89,7 +89,7 @@ public:
// If we're doing a "size decode", we more or less pass through the image
// data, stopping only to scoop out the image dimensions. A size decode
// must be enabled by SetSizeDecode() _before_calling Init().
bool IsSizeDecode() { return mSizeDecode; };
bool IsSizeDecode() { return mSizeDecode; }
void SetSizeDecode(bool aSizeDecode)
{
NS_ABORT_IF_FALSE(!mInitialized, "Can't set size decode after Init()!");
@ -104,10 +104,10 @@ public:
uint32_t GetCompleteFrameCount() { return mInFrame ? mFrameCount - 1 : mFrameCount; }
// Error tracking
bool HasError() { return HasDataError() || HasDecoderError(); };
bool HasDataError() { return mDataError; };
bool HasDecoderError() { return NS_FAILED(mFailCode); };
nsresult GetDecoderError() { return mFailCode; };
bool HasError() { return HasDataError() || HasDecoderError(); }
bool HasDataError() { return mDataError; }
bool HasDecoderError() { return NS_FAILED(mFailCode); }
nsresult GetDecoderError() { return mFailCode; }
void PostResizeError() { PostDataError(); }
bool GetDecodeDone() const {
return mDecodeDone;

View File

@ -114,7 +114,7 @@ public:
imgStatusTracker& GetStatusTracker();
// Get the current principal of the image. No AddRefing.
inline nsIPrincipal* GetPrincipal() const { return mPrincipal.get(); };
inline nsIPrincipal* GetPrincipal() const { return mPrincipal.get(); }
// Resize the cache entry to 0 if it exists
void ResetCacheEntry();

View File

@ -114,7 +114,7 @@ public:
// with its status. Weak pointers.
void AddConsumer(imgRequestProxy* aConsumer);
bool RemoveConsumer(imgRequestProxy* aConsumer, nsresult aStatus);
size_t ConsumerCount() const { return mConsumers.Length(); };
size_t ConsumerCount() const { return mConsumers.Length(); }
// This is intentionally non-general because its sole purpose is to support an
// some obscure network priority logic in imgRequest. That stuff could probably
@ -190,8 +190,8 @@ public:
void ClearRequest();
// Weak pointer getters - no AddRefs.
inline mozilla::image::Image* GetImage() const { return mImage; };
inline imgRequest* GetRequest() const { return mRequest; };
inline mozilla::image::Image* GetImage() const { return mImage; }
inline imgRequest* GetRequest() const { return mRequest; }
inline imgIDecoderObserver* GetDecoderObserver() { return mTrackerObserver.get(); }

View File

@ -24,8 +24,6 @@
#include "nsIComponentManager.h"
#include "nsIMemory.h"
#include "nsIObserverService.h"
#include "pratom.h"
#include "prmem.h"
#include "nsCOMArray.h"
#include "nsTextFormatter.h"
#include "nsIErrorService.h"

View File

@ -231,29 +231,6 @@ public:
correctDeltas(4, 4);
}
uint32_t *getPoolSpace(uint32_t insn, uint32_t constant, bool isReusable = false)
{
flushIfNoSpaceFor(4, 4);
m_loadOffsets.append(AssemblerBuffer::size());
if (isReusable)
for (int i = 0; i < m_numConsts; ++i) {
if (m_mask[i] == ReusableConst && m_pool[i] == constant) {
AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, i));
correctDeltas(4);
return;
}
}
m_pool[m_numConsts] = constant;
m_mask[m_numConsts] = static_cast<char>(isReusable ? ReusableConst : UniqueConst);
AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, m_numConsts));
++m_numConsts;
correctDeltas(4, 4);
}
void putIntWithConstantDouble(uint32_t insn, double constant)
{
flushIfNoSpaceFor(4, 8);

View File

@ -304,7 +304,7 @@ struct ClosureInfo
ffi_closure_free(closure);
if (errResult)
js_free(errResult);
};
}
};
bool IsCTypesGlobal(JSObject* obj);

View File

@ -135,7 +135,7 @@ class BailoutClosure
void constructFrame() {
guards_.construct();
};
}
InvokeArgsGuard *argsGuard() {
return &guards_.ref().iag;
}

View File

@ -26,7 +26,7 @@ class BitSet : private TempObject
private:
BitSet(unsigned int max) :
max_(max),
bits_(NULL) {};
bits_(NULL) {}
unsigned int max_;
uint32_t *bits_;

View File

@ -53,7 +53,7 @@ class FixedList
const T &operator [](size_t index) const {
JS_ASSERT(index < length_);
return list_[index];
};
}
};
} // namespace ion

View File

@ -7,6 +7,7 @@
#include "IonAnalysis.h"
#include "IonBuilder.h"
#include "Lowering.h"
#include "MIRGraph.h"
#include "Ion.h"
#include "IonAnalysis.h"
@ -5243,7 +5244,7 @@ IonBuilder::jsop_getelem_dense()
MDefinition *obj = current->pop();
JSValueType knownType = JSVAL_TYPE_UNKNOWN;
if (!needsHoleCheck && !barrier) {
if (!barrier) {
knownType = types->getKnownTypeTag();
// Null and undefined have no payload so they can't be specialized.
@ -5253,6 +5254,11 @@ IonBuilder::jsop_getelem_dense()
// constant.
if (knownType == JSVAL_TYPE_UNDEFINED || knownType == JSVAL_TYPE_NULL)
knownType = JSVAL_TYPE_UNKNOWN;
// Different architectures may want typed element reads which require
// hole checks to be done as either value or typed reads.
if (needsHoleCheck && !LIRGenerator::allowTypedElementHoleCheck())
knownType = JSVAL_TYPE_UNKNOWN;
}
// Ensure id is an integer.

File diff suppressed because it is too large Load Diff

View File

@ -624,7 +624,7 @@ class LInstruction
virtual bool isCall() const {
return false;
};
}
uint32_t id() const {
return id_;
}

View File

@ -125,8 +125,8 @@ class LinearScanAllocator : public LiveRangeAllocator<LinearScanVirtualRegister>
void validateIntervals();
void validateAllocations();
#else
inline void validateIntervals() { };
inline void validateAllocations() { };
inline void validateIntervals() { }
inline void validateAllocations() { }
#endif
#ifdef JS_NUNBOX32

View File

@ -1488,9 +1488,13 @@ LIRGenerator::visitLoadElement(MLoadElement *ins)
return false;
default:
JS_ASSERT(!ins->fallible());
return define(new LLoadElementT(useRegister(ins->elements()),
useRegisterOrConstant(ins->index())), ins);
{
LLoadElementT *lir = new LLoadElementT(useRegister(ins->elements()),
useRegisterOrConstant(ins->index()));
if (ins->fallible() && !assignSnapshot(lir))
return false;
return define(lir, ins);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -343,31 +343,31 @@ struct FunctionInfo<R (*)(JSContext *)> : public VMFunction {
template <class R, class A1>
struct FunctionInfo<R (*)(JSContext *, A1)> : public VMFunction {
typedef R (*pf)(JSContext *, A1);
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_1);
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_1)
};
template <class R, class A1, class A2>
struct FunctionInfo<R (*)(JSContext *, A1, A2)> : public VMFunction {
typedef R (*pf)(JSContext *, A1, A2);
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_2);
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_2)
};
template <class R, class A1, class A2, class A3>
struct FunctionInfo<R (*)(JSContext *, A1, A2, A3)> : public VMFunction {
typedef R (*pf)(JSContext *, A1, A2, A3);
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_3);
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_3)
};
template <class R, class A1, class A2, class A3, class A4>
struct FunctionInfo<R (*)(JSContext *, A1, A2, A3, A4)> : public VMFunction {
typedef R (*pf)(JSContext *, A1, A2, A3, A4);
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_4);
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_4)
};
template <class R, class A1, class A2, class A3, class A4, class A5>
struct FunctionInfo<R (*)(JSContext *, A1, A2, A3, A4, A5)> : public VMFunction {
typedef R (*pf)(JSContext *, A1, A2, A3, A4, A5);
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_5);
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_5)
};
#undef FUNCTION_INFO_STRUCT_BODY

View File

@ -14,7 +14,7 @@ namespace ion {
class LDivI : public LBinaryMath<1>
{
public:
LIR_HEADER(DivI);
LIR_HEADER(DivI)
LDivI(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) {
setOperand(0, lhs);
@ -33,7 +33,7 @@ class LDivI : public LBinaryMath<1>
class LModI : public LBinaryMath<1>
{
public:
LIR_HEADER(ModI);
LIR_HEADER(ModI)
LModI(const LAllocation &lhs, const LAllocation &rhs) {
setOperand(0, lhs);
@ -50,7 +50,7 @@ class LModPowTwoI : public LInstructionHelper<1,1,0>
const int32_t shift_;
public:
LIR_HEADER(ModPowTwoI);
LIR_HEADER(ModPowTwoI)
LModPowTwoI(const LAllocation &lhs, int32_t shift)
: shift_(shift)
@ -70,7 +70,7 @@ class LModPowTwoI : public LInstructionHelper<1,1,0>
class LPowHalfD : public LInstructionHelper<1, 1, 1>
{
public:
LIR_HEADER(PowHalfD);
LIR_HEADER(PowHalfD)
LPowHalfD(const LAllocation &input, const LDefinition &temp) {
setOperand(0, input);
setTemp(0, temp);
@ -91,7 +91,7 @@ class LPowHalfD : public LInstructionHelper<1, 1, 1>
class LTableSwitch : public LInstructionHelper<0, 1, 2>
{
public:
LIR_HEADER(TableSwitch);
LIR_HEADER(TableSwitch)
LTableSwitch(const LAllocation &in, const LDefinition &inputCopy,
const LDefinition &jumpTablePointer, MTableSwitch *ins)
@ -121,7 +121,7 @@ class LTableSwitch : public LInstructionHelper<0, 1, 2>
class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
{
public:
LIR_HEADER(TableSwitchV);
LIR_HEADER(TableSwitchV)
LTableSwitchV(const LDefinition &inputCopy, const LDefinition &floatCopy,
const LDefinition &jumpTablePointer, MTableSwitch *ins)
@ -153,7 +153,7 @@ class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
class LGuardShape : public LInstructionHelper<0, 1, 0>
{
public:
LIR_HEADER(GuardShape);
LIR_HEADER(GuardShape)
LGuardShape(const LAllocation &in) {
setOperand(0, in);
@ -166,7 +166,7 @@ class LGuardShape : public LInstructionHelper<0, 1, 0>
class LRecompileCheck : public LInstructionHelper<0, 0, 0>
{
public:
LIR_HEADER(RecompileCheck);
LIR_HEADER(RecompileCheck)
const MRecompileCheck *mir() const {
return mir_->toRecompileCheck();
@ -176,13 +176,13 @@ class LRecompileCheck : public LInstructionHelper<0, 0, 0>
class LInterruptCheck : public LInstructionHelper<0, 0, 0>
{
public:
LIR_HEADER(InterruptCheck);
LIR_HEADER(InterruptCheck)
};
class LMulI : public LBinaryMath<0, 1>
{
public:
LIR_HEADER(MulI);
LIR_HEADER(MulI)
LMulI(const LAllocation &lhs, const LAllocation &rhs, const LAllocation &lhsCopy) {
setOperand(0, lhs);

View File

@ -166,6 +166,11 @@ class LIRGeneratorShared : public MInstructionVisitor
public:
bool visitConstant(MConstant *ins);
// Whether to generate typed reads for element accesses with hole checks.
static bool allowTypedElementHoleCheck() {
return false;
}
};
} // namespace ion

View File

@ -19,7 +19,7 @@ class LBox : public LInstructionHelper<1, 1, 0>
MIRType type_;
public:
LIR_HEADER(Box);
LIR_HEADER(Box)
LBox(MIRType type, const LAllocation &payload)
: type_(type)
@ -50,7 +50,7 @@ class LUnboxBase : public LInstructionHelper<1, 1, 0>
class LUnbox : public LUnboxBase {
public:
LIR_HEADER(Unbox);
LIR_HEADER(Unbox)
LUnbox(const LAllocation &input)
: LUnboxBase(input)
@ -59,7 +59,7 @@ class LUnbox : public LUnboxBase {
class LUnboxDouble : public LUnboxBase {
public:
LIR_HEADER(UnboxDouble);
LIR_HEADER(UnboxDouble)
LUnboxDouble(const LAllocation &input)
: LUnboxBase(input)
@ -72,7 +72,7 @@ class LDouble : public LInstructionHelper<1, 0, 0>
double d_;
public:
LIR_HEADER(Double);
LIR_HEADER(Double)
LDouble(double d)
: d_(d)

View File

@ -230,12 +230,17 @@ CodeGeneratorX86::visitLoadElementT(LLoadElementT *load)
{
Operand source = createArrayElementOperand(ToRegister(load->elements()), load->index());
if (load->mir()->needsHoleCheck()) {
Assembler::Condition cond = masm.testMagic(Assembler::Equal, source);
if (!bailoutIf(cond, load->snapshot()))
return false;
}
if (load->mir()->type() == MIRType_Double)
masm.loadInt32OrDouble(source, ToFloatRegister(load->output()));
else
masm.movl(masm.ToPayload(source), ToRegister(load->output()));
JS_ASSERT(!load->mir()->needsHoleCheck());
return true;
}

View File

@ -49,6 +49,10 @@ class LIRGeneratorX86 : public LIRGeneratorX86Shared
bool visitReturn(MReturn *ret);
bool visitStoreTypedArrayElement(MStoreTypedArrayElement *ins);
bool lowerPhi(MPhi *phi);
static bool allowTypedElementHoleCheck() {
return true;
}
};
typedef LIRGeneratorX86 LIRGeneratorSpecific;

View File

@ -272,6 +272,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
cmpl(tag, ImmTag(JSVAL_TAG_MAGIC));
return cond;
}
Condition testMagic(Condition cond, const Operand &operand) {
JS_ASSERT(cond == Equal || cond == NotEqual);
cmpl(ToType(operand), ImmTag(JSVAL_TAG_MAGIC));
return cond;
}
Condition testPrimitive(Condition cond, const Register &tag) {
JS_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));

View File

@ -51,7 +51,7 @@ class TaggedProto
template <>
struct RootKind<TaggedProto>
{
static ThingRootKind rootKind() { return THING_ROOT_OBJECT; };
static ThingRootKind rootKind() { return THING_ROOT_OBJECT; }
};
template <> struct RootMethods<const TaggedProto>

View File

@ -49,8 +49,8 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
* is not safe to unwrap, operations requiring full access to the underlying
* object (via UnwrapObjectChecked) will throw. Otherwise, they will succeed.
*/
void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; };
bool isSafeToUnwrap() { return mSafeToUnwrap; };
void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; }
bool isSafeToUnwrap() { return mSafeToUnwrap; }
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
JSObject *parent, Wrapper *handler);

View File

@ -826,7 +826,7 @@ class FrameState
#ifdef DEBUG
void assertValidRegisterState() const;
#else
inline void assertValidRegisterState() const {};
inline void assertValidRegisterState() const {}
#endif
// Return an address, relative to the StackFrame, that represents where

View File

@ -24,7 +24,7 @@ namespace xpc {
class ChromeObjectWrapper : public ChromeObjectWrapperBase
{
public:
ChromeObjectWrapper() : ChromeObjectWrapperBase(0) {};
ChromeObjectWrapper() : ChromeObjectWrapperBase(0) {}
/* Custom traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper,

View File

@ -49,6 +49,7 @@ FrameLayerBuilder::DisplayItemData::DisplayItemData(LayerManagerData* aParent, u
, mLayerState(aLayerState)
, mUsed(true)
, mIsInvalid(false)
, mIsVisible(true)
{
}
@ -66,6 +67,7 @@ FrameLayerBuilder::DisplayItemData::DisplayItemData(DisplayItemData &toCopy)
mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
mLayerState = toCopy.mLayerState;
mUsed = toCopy.mUsed;
mIsVisible = toCopy.mIsVisible;
}
void
@ -1100,13 +1102,15 @@ FrameLayerBuilder::GetDisplayItemDataForManager(nsDisplayItem* aItem,
}
bool
FrameLayerBuilder::HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
FrameLayerBuilder::HasVisibleRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
{
nsTArray<DisplayItemData*> *array =
reinterpret_cast<nsTArray<DisplayItemData*>*>(aFrame->Properties().Get(LayerManagerDataProperty()));
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
if (array->ElementAt(i)->mDisplayItemKey == aDisplayItemKey) {
DisplayItemData* data = array->ElementAt(i);
if (data->mDisplayItemKey == aDisplayItemKey &&
data->IsVisibleInLayer()) {
return true;
}
}
@ -1115,7 +1119,7 @@ FrameLayerBuilder::HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey
}
void
FrameLayerBuilder::IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback)
FrameLayerBuilder::IterateVisibleRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback)
{
nsTArray<DisplayItemData*> *array =
reinterpret_cast<nsTArray<DisplayItemData*>*>(aFrame->Properties().Get(LayerManagerDataProperty()));
@ -1125,7 +1129,8 @@ FrameLayerBuilder::IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallb
for (uint32_t i = 0; i < array->Length(); i++) {
DisplayItemData* data = array->ElementAt(i);
if (data->mDisplayItemKey != nsDisplayItem::TYPE_ZERO) {
if (data->mDisplayItemKey != nsDisplayItem::TYPE_ZERO &&
data->IsVisibleInLayer()) {
aCallback(aFrame, data);
}
}
@ -1841,7 +1846,7 @@ ContainerState::ThebesLayerData::Accumulate(ContainerState* aState,
nsRegion opaqueClipped;
nsRegionRectIterator iter(opaque);
for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
opaqueClipped.Or(opaqueClipped, aClip.ApproximateIntersect(*r));
opaqueClipped.Or(opaqueClipped, aClip.ApproximateIntersectInner(*r));
}
nsIntRegion opaquePixels = aState->ScaleRegionToInsidePixels(opaqueClipped, snap);
@ -2348,6 +2353,7 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem,
GetTranslationForThebesLayer(newThebesLayer));
}
}
aItem->NotifyRenderingChanged();
return;
}
if (!aNewLayer) {
@ -2410,6 +2416,7 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem,
#endif
}
if (!combined.IsEmpty()) {
aItem->NotifyRenderingChanged();
InvalidatePostTransformRegion(newThebesLayer,
combined.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
GetTranslationForThebesLayer(newThebesLayer));
@ -2454,7 +2461,8 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
}
}
AddLayerDisplayItem(aLayer, aItem, aClip, aLayerState, aTopLeft, tempManager, aGeometry);
DisplayItemData* displayItemData =
AddLayerDisplayItem(aLayer, aItem, aClip, aLayerState, aTopLeft, tempManager, aGeometry);
ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
if (entry) {
@ -2521,7 +2529,7 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
}
}
ClippedDisplayItem* cdi =
entry->mItems.AppendElement(ClippedDisplayItem(aItem, aClip,
entry->mItems.AppendElement(ClippedDisplayItem(aItem, displayItemData, aClip,
mContainerLayerGeneration));
cdi->mInactiveLayerManager = tempManager;
}
@ -2596,7 +2604,7 @@ FrameLayerBuilder::ClippedDisplayItem::~ClippedDisplayItem()
}
}
void
FrameLayerBuilder::DisplayItemData*
FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
nsDisplayItem* aItem,
const Clip& aClip,
@ -2606,7 +2614,7 @@ FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
nsAutoPtr<nsDisplayItemGeometry> aGeometry)
{
if (aLayer->Manager() != mRetainingManager)
return;
return nullptr;
DisplayItemData *data = StoreDataForFrame(aItem, aLayer, aLayerState);
ThebesLayer *t = aLayer->AsThebesLayer();
@ -2615,6 +2623,7 @@ FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
data->mClip = aClip;
}
data->mInactiveManager = aManager;
return data;
}
nsIntPoint
@ -3263,15 +3272,29 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
uint32_t i;
// Update visible regions. We need perform visibility analysis again
// because we may be asked to draw into part of a ThebesLayer that
// isn't actually visible in the window (e.g., because a ThebesLayer
// expanded its visible region to a rectangle internally), in which
// case the mVisibleRect stored in the display item may be wrong.
nsRegion visible = aRegionToDraw.ToAppUnits(appUnitsPerDevPixel);
// Update visible rects in display items to reflect visibility
// just considering items in this ThebesLayer. This is different from the
// original visible rects, which describe which part of each item
// is visible in the window. These can be larger than the original
// visible rect, because we may be asked to draw into part of a
// ThebesLayer that isn't actually visible in the window (e.g.,
// because a ThebesLayer expanded its visible region to a rectangle
// internally, or because we're caching prerendered content).
// We also compute the intersection of those visible rects with
// aRegionToDraw. These are the rectangles of each display item
// that actually need to be drawn now.
// Treat as visible everything this layer already contains or will
// contain.
nsIntRegion layerRegion;
layerRegion.Or(aLayer->GetValidRegion(), aRegionToDraw);
nsRegion visible = layerRegion.ToAppUnits(appUnitsPerDevPixel);
visible.MoveBy(NSIntPixelsToAppUnits(offset.x, appUnitsPerDevPixel),
NSIntPixelsToAppUnits(offset.y, appUnitsPerDevPixel));
visible.ScaleInverseRoundOut(userData->mXScale, userData->mYScale);
nsRegion toDraw = aRegionToDraw.ToAppUnits(appUnitsPerDevPixel);
toDraw.MoveBy(NSIntPixelsToAppUnits(offset.x, appUnitsPerDevPixel),
NSIntPixelsToAppUnits(offset.y, appUnitsPerDevPixel));
toDraw.ScaleInverseRoundOut(userData->mXScale, userData->mYScale);
for (i = items.Length(); i > 0; --i) {
ClippedDisplayItem* cdi = &items[i - 1];
@ -3287,29 +3310,28 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
(cdi->mClip.mRoundedClipRects.IsEmpty() &&
cdi->mClip.mClipRect.Contains(visible.GetBounds()))) {
cdi->mItem->RecomputeVisibility(builder, &visible);
continue;
}
// Do a little dance to account for the fact that we're clipping
// to cdi->mClipRect
nsRegion clipped;
clipped.And(visible, cdi->mClip.mClipRect);
nsRegion finalClipped = clipped;
cdi->mItem->RecomputeVisibility(builder, &finalClipped);
// If we have rounded clip rects, don't subtract from the visible
// region since we aren't displaying everything inside the rect.
if (cdi->mClip.mRoundedClipRects.IsEmpty()) {
nsRegion removed;
removed.Sub(clipped, finalClipped);
nsRegion newVisible;
newVisible.Sub(visible, removed);
// Don't let the visible region get too complex.
if (newVisible.GetNumRects() <= 15) {
visible = newVisible;
} else {
// Do a little dance to account for the fact that we're clipping
// to cdi->mClipRect
nsRegion clipped;
clipped.And(visible, cdi->mClip.mClipRect);
nsRegion finalClipped = clipped;
cdi->mItem->RecomputeVisibility(builder, &finalClipped);
// If we have rounded clip rects, don't subtract from the visible
// region since we aren't displaying everything inside the rect.
if (cdi->mClip.mRoundedClipRects.IsEmpty()) {
nsRegion removed;
removed.Sub(clipped, finalClipped);
nsRegion newVisible;
newVisible.Sub(visible, removed);
// Don't let the visible region get too complex.
if (newVisible.GetNumRects() <= 15) {
visible = newVisible;
}
}
if (!cdi->mClip.IsRectClippedByRoundedCorner(cdi->mItem->GetVisibleRect())) {
cdi->mClip.RemoveRoundedCorners();
}
}
if (!cdi->mClip.IsRectClippedByRoundedCorner(cdi->mItem->GetVisibleRect())) {
cdi->mClip.RemoveRoundedCorners();
}
}
@ -3322,8 +3344,13 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
for (i = 0; i < items.Length(); ++i) {
ClippedDisplayItem* cdi = &items[i];
if (cdi->mItem->GetVisibleRect().IsEmpty())
if (cdi->mData) {
cdi->mData->SetIsVisibleInLayer(!cdi->mItem->GetVisibleRect().IsEmpty());
}
if (!toDraw.Intersects(cdi->mItem->GetVisibleRect())) {
continue;
}
// If the new desired clip state is different from the current state,
// update the clip.
@ -3501,7 +3528,7 @@ FrameLayerBuilder::Clip::AddRoundedRectPathTo(gfxContext* aContext,
}
nsRect
FrameLayerBuilder::Clip::ApproximateIntersect(const nsRect& aRect) const
FrameLayerBuilder::Clip::ApproximateIntersectInner(const nsRect& aRect) const
{
nsRect r = aRect;
if (mHaveClipRect) {

View File

@ -96,6 +96,7 @@ public:
typedef layers::ThebesLayer ThebesLayer;
typedef layers::ImageLayer ImageLayer;
typedef layers::LayerManager LayerManager;
class DisplayItemData;
FrameLayerBuilder() :
mRetainingManager(nullptr),
@ -263,13 +264,13 @@ public:
* then this is the temporary layer manager to draw with.
*/
struct Clip;
void AddLayerDisplayItem(Layer* aLayer,
nsDisplayItem* aItem,
const Clip& aClip,
LayerState aLayerState,
const nsPoint& aTopLeft,
LayerManager* aManager,
nsAutoPtr<nsDisplayItemGeometry> aGeometry);
DisplayItemData* AddLayerDisplayItem(Layer* aLayer,
nsDisplayItem* aItem,
const Clip& aClip,
LayerState aLayerState,
const nsPoint& aTopLeft,
LayerManager* aManager,
nsAutoPtr<nsDisplayItemGeometry> aGeometry);
/**
* Record aItem as a display item that is rendered by the ThebesLayer
@ -314,15 +315,14 @@ public:
LayerManager* GetRetainingLayerManager() { return mRetainingManager; }
/**
* Returns true if the given display item was rendered during the previous
* paint. Returns false otherwise.
* Returns true if the given display item was visible in its layer during
* the previous paint. Returns false otherwise.
*/
static bool HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey);
static bool HasVisibleRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey);
class DisplayItemData;
typedef void (*DisplayItemDataCallback)(nsIFrame *aFrame, DisplayItemData* aItem);
static void IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback);
static void IterateVisibleRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback);
/**
* Save transform that was in aLayer when we last painted, and the position
@ -417,7 +417,7 @@ public:
// Return a rectangle contained in the intersection of aRect with this
// clip region. Tries to return the largest possible rectangle, but may
// not succeed.
nsRect ApproximateIntersect(const nsRect& aRect) const;
nsRect ApproximateIntersectInner(const nsRect& aRect) const;
// Returns false if aRect is definitely not clipped by a rounded corner in
// this clip. Returns true if aRect is clipped by a rounded corner in this
@ -477,6 +477,9 @@ public:
uint32_t GetDisplayItemKey() { return mDisplayItemKey; }
Layer* GetLayer() { return mLayer; }
void Invalidate() { mIsInvalid = true; }
bool IsVisibleInLayer() { return mIsVisible; }
void SetIsVisibleInLayer(bool aIsVisible) { mIsVisible = aIsVisible; }
protected:
DisplayItemData(LayerManagerData* aParent, uint32_t aKey, Layer* aLayer, LayerState aLayerState, uint32_t aGeneration);
@ -525,7 +528,15 @@ public:
* paint) has been updated in the current paint.
*/
bool mUsed;
/**
* True if the entire display item needs to be invalidated.
*/
bool mIsInvalid;
/**
* True if the display item is visible in its layer, otherwise
* it's completely covered by opaque content in its ThebesLayer.
*/
bool mIsVisible;
};
protected:
@ -592,14 +603,17 @@ protected:
* mItem always has an underlying frame.
*/
struct ClippedDisplayItem {
ClippedDisplayItem(nsDisplayItem* aItem, const Clip& aClip, uint32_t aGeneration)
: mItem(aItem), mClip(aClip), mContainerLayerGeneration(aGeneration)
ClippedDisplayItem(nsDisplayItem* aItem, DisplayItemData* aData,
const Clip& aClip, uint32_t aGeneration)
: mItem(aItem), mData(aData), mClip(aClip),
mContainerLayerGeneration(aGeneration)
{
}
~ClippedDisplayItem();
nsDisplayItem* mItem;
DisplayItemData* mData;
/**
* If the display item is being rendered as an inactive

View File

@ -109,7 +109,8 @@ CollectRestyles(nsISupports* aElement,
inline void
RestyleTracker::ProcessOneRestyle(Element* aElement,
nsRestyleHint aRestyleHint,
nsChangeHint aChangeHint)
nsChangeHint aChangeHint,
OverflowChangedTracker& aTracker)
{
NS_PRECONDITION((aRestyleHint & eRestyle_LaterSiblings) == 0,
"Someone should have handled this before calling us");
@ -121,14 +122,15 @@ RestyleTracker::ProcessOneRestyle(Element* aElement,
if (aRestyleHint & (eRestyle_Self | eRestyle_Subtree)) {
mFrameConstructor->RestyleElement(aElement, primaryFrame, aChangeHint,
*this,
(aRestyleHint & eRestyle_Subtree) != 0);
(aRestyleHint & eRestyle_Subtree) != 0,
aTracker);
} else if (aChangeHint &&
(primaryFrame ||
(aChangeHint & nsChangeHint_ReconstructFrame))) {
// Don't need to recompute style; just apply the hint
nsStyleChangeList changeList;
changeList.AppendChange(primaryFrame, aElement, aChangeHint);
mFrameConstructor->ProcessRestyledFrames(changeList);
mFrameConstructor->ProcessRestyledFrames(changeList, aTracker);
}
}
@ -142,6 +144,8 @@ RestyleTracker::DoProcessRestyles()
mFrameConstructor->mInStyleRefresh = true;
OverflowChangedTracker tracker;
// loop so that we process any restyle events generated by processing
while (mPendingRestyles.Count()) {
if (mHaveLaterSiblingRestyles) {
@ -206,7 +210,7 @@ RestyleTracker::DoProcessRestyles()
continue;
}
ProcessOneRestyle(element, data.mRestyleHint, data.mChangeHint);
ProcessOneRestyle(element, data.mRestyleHint, data.mChangeHint, tracker);
}
if (mHaveLaterSiblingRestyles) {
@ -235,11 +239,14 @@ RestyleTracker::DoProcessRestyles()
++currentRestyle) {
ProcessOneRestyle(currentRestyle->mElement,
currentRestyle->mRestyleHint,
currentRestyle->mChangeHint);
currentRestyle->mChangeHint,
tracker);
}
}
}
tracker.Flush();
// Set mInStyleRefresh to false now, since the EndUpdate call might
// add more restyles.
mFrameConstructor->mInStyleRefresh = false;

View File

@ -14,12 +14,136 @@
#include "mozilla/dom/Element.h"
#include "nsDataHashtable.h"
#include "nsIFrame.h"
#include "nsTPriorityQueue.h"
class nsCSSFrameConstructor;
namespace mozilla {
namespace css {
/**
* Helper class that collects a list of frames that need
* UpdateOverflow() called on them, and coalesces them
* to avoid walking up the same ancestor tree multiple times.
*/
class OverflowChangedTracker
{
public:
/**
* Add a frame that has had a style change, and needs its
* overflow updated.
*
* If there are pre-transform overflow areas stored for this
* frame, then we will call FinishAndStoreOverflow with those
* areas instead of UpdateOverflow().
*
* If the overflow area changes, then UpdateOverflow will also
* be called on the parent.
*/
void AddFrame(nsIFrame* aFrame) {
mEntryList.Push(Entry(aFrame, true));
}
/**
* Update the overflow of all added frames, and clear the entry list.
*
* Start from those deepest in the frame tree and works upwards. This stops
* us from processing the same frame twice.
*/
void Flush() {
while (!mEntryList.IsEmpty()) {
Entry entry = mEntryList.Pop();
// Pop off any duplicate entries and copy back mInitial
// if any have it set.
while (!mEntryList.IsEmpty() &&
mEntryList.Top().mFrame == entry.mFrame) {
Entry next = mEntryList.Pop();
if (next.mInitial) {
entry.mInitial = true;
}
}
nsIFrame *frame = entry.mFrame;
bool updateParent = false;
if (entry.mInitial) {
nsOverflowAreas* pre = static_cast<nsOverflowAreas*>
(frame->Properties().Get(frame->PreTransformOverflowAreasProperty()));
if (pre) {
// FinishAndStoreOverflow will change the overflow areas passed in,
// so make a copy.
nsOverflowAreas overflowAreas = *pre;
frame->FinishAndStoreOverflow(overflowAreas, frame->GetSize());
// We can't tell if the overflow changed, so update the parent regardless
updateParent = true;
}
}
// If the overflow changed, then we want to also update the parent's
// overflow. We always update the parent for initial frames.
if (!updateParent) {
updateParent = frame->UpdateOverflow() || entry.mInitial;
}
if (updateParent) {
nsIFrame *parent = frame->GetParent();
if (parent) {
mEntryList.Push(Entry(parent, entry.mDepth - 1, false));
}
}
}
}
private:
struct Entry
{
Entry(nsIFrame* aFrame, bool aInitial)
: mFrame(aFrame)
, mDepth(aFrame->GetDepthInFrameTree())
, mInitial(aInitial)
{}
Entry(nsIFrame* aFrame, uint32_t aDepth, bool aInitial)
: mFrame(aFrame)
, mDepth(aDepth)
, mInitial(aInitial)
{}
bool operator==(const Entry& aOther) const
{
return mFrame == aOther.mFrame;
}
/**
* Sort by the depth in the frame tree, and then
* the frame pointer.
*/
bool operator<(const Entry& aOther) const
{
if (mDepth != aOther.mDepth) {
// nsTPriorityQueue implements a min-heap and we
// want the highest depth first, so reverse this check.
return mDepth > aOther.mDepth;
}
return mFrame < aOther.mFrame;
}
nsIFrame* mFrame;
/* Depth in the frame tree */
uint32_t mDepth;
/**
* True if the frame had the actual style change, and we
* want to check for pre-transform overflow areas.
*/
bool mInitial;
};
/* A list of frames to process, sorted by their depth in the frame tree */
nsTPriorityQueue<Entry> mEntryList;
};
class RestyleTracker {
public:
typedef mozilla::dom::Element Element;
@ -114,7 +238,8 @@ private:
*/
inline void ProcessOneRestyle(Element* aElement,
nsRestyleHint aRestyleHint,
nsChangeHint aChangeHint);
nsChangeHint aChangeHint,
OverflowChangedTracker& aTracker);
/**
* The guts of our restyle processing.

View File

@ -7764,7 +7764,6 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
}
if (aChange & nsChangeHint_UpdateTransformLayer) {
aFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
aFrame->AddStateBits(NS_FRAME_TRANSFORM_CHANGED);
// If we're not already going to do an invalidating paint, see
// if we can get away with only updating the transform on a
// layer for this frame, and not scheduling an invalidating
@ -8057,7 +8056,8 @@ NeedToReframeForAddingOrRemovingTransform(nsIFrame* aFrame)
}
nsresult
nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList,
OverflowChangedTracker& aTracker)
{
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
"Someone forgot a script blocker");
@ -8209,30 +8209,10 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
if (!(frame->GetStateBits() &
(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
while (frame) {
nsOverflowAreas* pre = static_cast<nsOverflowAreas*>
(frame->Properties().Get(frame->PreTransformOverflowAreasProperty()));
if (pre) {
// FinishAndStoreOverflow will change the overflow areas passed in,
// so make a copy.
nsOverflowAreas overflowAreas = *pre;
frame->FinishAndStoreOverflow(overflowAreas, frame->GetSize());
} else {
frame->UpdateOverflow();
}
aTracker.AddFrame(frame);
nsIFrame* next =
frame =
nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame);
// Update the ancestors' overflow after we have updated the overflow
// for all the continuations with the same parent.
if (!next || frame->GetParent() != next->GetParent()) {
for (nsIFrame* ancestor = frame->GetParent(); ancestor;
ancestor = ancestor->GetParent()) {
if (!ancestor->UpdateOverflow()) {
break;
}
}
}
frame = next;
}
}
}
@ -8277,7 +8257,8 @@ nsCSSFrameConstructor::RestyleElement(Element *aElement,
nsIFrame *aPrimaryFrame,
nsChangeHint aMinHint,
RestyleTracker& aRestyleTracker,
bool aRestyleDescendants)
bool aRestyleDescendants,
OverflowChangedTracker& aTracker)
{
NS_ASSERTION(aPrimaryFrame == aElement->GetPrimaryFrame(),
"frame/content mismatch");
@ -8314,7 +8295,7 @@ nsCSSFrameConstructor::RestyleElement(Element *aElement,
nsStyleChangeList changeList;
ComputeStyleChangeFor(aPrimaryFrame, &changeList, aMinHint,
aRestyleTracker, aRestyleDescendants);
ProcessRestyledFrames(changeList);
ProcessRestyledFrames(changeList, aTracker);
} else {
// no frames, reconstruct for content
MaybeRecreateFramesForElement(aElement);
@ -12069,7 +12050,9 @@ nsCSSFrameConstructor::DoRebuildAllStyleData(RestyleTracker& aRestyleTracker,
&changeList, aExtraHint,
aRestyleTracker, true);
// Process the required changes
ProcessRestyledFrames(changeList);
OverflowChangedTracker tracker;
ProcessRestyledFrames(changeList, tracker);
tracker.Flush();
// Tell the style set it's safe to destroy the old rule tree. We
// must do this after the ProcessRestyledFrames call in case the

View File

@ -53,6 +53,7 @@ class nsCSSFrameConstructor : public nsFrameManager
public:
typedef mozilla::dom::Element Element;
typedef mozilla::css::RestyleTracker RestyleTracker;
typedef mozilla::css::OverflowChangedTracker OverflowChangedTracker;
nsCSSFrameConstructor(nsIDocument *aDocument, nsIPresShell* aPresShell);
~nsCSSFrameConstructor(void) {
@ -236,7 +237,8 @@ public:
// This function does not call ProcessAttachedQueue() on the binding manager.
// If the caller wants that to happen synchronously, it needs to handle that
// itself.
nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray);
nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray,
OverflowChangedTracker& aTracker);
private:
@ -390,7 +392,8 @@ private:
nsIFrame* aPrimaryFrame,
nsChangeHint aMinHint,
RestyleTracker& aRestyleTracker,
bool aRestyleDescendants);
bool aRestyleDescendants,
OverflowChangedTracker& aTracker);
nsresult InitAndRestoreFrame (const nsFrameConstructorState& aState,
nsIContent* aContent,

View File

@ -2845,7 +2845,8 @@ nsCSSRendering::ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
}
nsIFrame* attachedToFrame = aForFrame;
if (NS_STYLE_BG_ATTACHMENT_FIXED == aLayer.mAttachment) {
if (NS_STYLE_BG_ATTACHMENT_FIXED == aLayer.mAttachment &&
!aLayer.mImage.IsEmpty()) {
// If it's a fixed background attachment, then the image is placed
// relative to the viewport, which is the area of the root frame
// in a screen context or the page content frame in a print context.
@ -4689,26 +4690,19 @@ nsImageRenderer::Draw(nsPresContext* aPresContext,
bool
nsImageRenderer::IsRasterImage()
{
if (mType != eStyleImageType_Image)
if (mType != eStyleImageType_Image || !mImageContainer)
return false;
nsCOMPtr<imgIContainer> img;
if (NS_FAILED(mImage->GetImageData()->GetImage(getter_AddRefs(img))))
return false;
return img->GetType() == imgIContainer::TYPE_RASTER;
return mImageContainer->GetType() == imgIContainer::TYPE_RASTER;
}
already_AddRefed<mozilla::layers::ImageContainer>
nsImageRenderer::GetContainer(LayerManager* aManager)
{
if (mType != eStyleImageType_Image)
return nullptr;
nsCOMPtr<imgIContainer> img;
nsresult rv = mImage->GetImageData()->GetImage(getter_AddRefs(img));
if (NS_FAILED(rv))
if (mType != eStyleImageType_Image || !mImageContainer)
return nullptr;
nsRefPtr<ImageContainer> container;
rv = img->GetImageContainer(aManager, getter_AddRefs(container));
nsresult rv = mImageContainer->GetImageContainer(aManager, getter_AddRefs(container));
NS_ENSURE_SUCCESS(rv, nullptr);
return container.forget();
}

View File

@ -855,7 +855,17 @@ public:
aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
}
}
/**
* Called when the area rendered by this display item has changed (been
* invalidated or changed geometry) since the last paint. This includes
* when the display item was not rendered at all in the last paint.
* It does NOT get called when a display item was being rendered and no
* longer is, because generally that means there is no display item to
* call this method on.
*/
virtual void NotifyRenderingChanged() {}
/**
* @param aSnap set to true if the edges of the rectangles of the opaque
* region would be snapped to device pixels when drawing

View File

@ -2725,7 +2725,9 @@ PresShell::RecreateFramesFor(nsIContent* aContent)
// Mark ourselves as not safe to flush while we're doing frame construction.
++mChangeNestCount;
nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList);
css::OverflowChangedTracker tracker;
nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList, tracker);
tracker.Flush();
--mChangeNestCount;
return rv;
@ -7840,7 +7842,9 @@ PresShell::Observe(nsISupports* aSubject,
{
nsAutoScriptBlocker scriptBlocker;
++mChangeNestCount;
mFrameConstructor->ProcessRestyledFrames(changeList);
css::OverflowChangedTracker tracker;
mFrameConstructor->ProcessRestyledFrames(changeList, tracker);
tracker.Flush();
--mChangeNestCount;
}
}

View File

@ -25,9 +25,7 @@
#include "mozilla/Preferences.h"
#include "nsIViewManager.h"
#include "sampler.h"
using mozilla::TimeStamp;
using mozilla::TimeDuration;
#include "nsNPAPIPluginInstance.h"
using namespace mozilla;
@ -310,6 +308,11 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
NS_PRECONDITION(mPresContext, "Why are we notified after disconnection?");
NS_PRECONDITION(!nsContentUtils::GetCurrentJSContext(),
"Shouldn't have a JSContext on the stack");
if (nsNPAPIPluginInstance::InPluginCall()) {
NS_ERROR("Refresh driver should not run during plugin call!");
// Try to survive this by just ignoring the refresh tick.
return NS_OK;
}
if (mTestControllingRefreshes && aTimer) {
// Ignore real refreshes from our timer (but honor the others).

View File

@ -239,7 +239,6 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
BlitSurface(dest, destRect, surf);
GetUnderlyingFrame()->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().get());
GetUnderlyingFrame()->AddStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);
}
}

View File

@ -181,6 +181,10 @@ public:
mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
!mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty();
}
virtual void NotifyRenderingChanged() MOZ_OVERRIDE
{
mFrame->Properties().Delete(nsIFrame::CachedBackgroundImage());
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;

Some files were not shown because too many files have changed in this diff Show More