Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/style/nsDOMCSSAttrDeclaration.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/* DOM object for element.style */
8
9
#include "nsDOMCSSAttrDeclaration.h"
10
11
#include "mozilla/DeclarationBlock.h"
12
#include "mozilla/dom/Element.h"
13
#include "mozilla/dom/MutationEventBinding.h"
14
#include "mozilla/InternalMutationEvent.h"
15
#include "mozAutoDocUpdate.h"
16
#include "nsIDocument.h"
17
#include "nsIURI.h"
18
#include "nsNodeUtils.h"
19
#include "nsSMILCSSValueType.h"
20
#include "nsWrapperCacheInlines.h"
21
#include "nsIFrame.h"
22
#include "ActiveLayerTracker.h"
23
24
using namespace mozilla;
25
26
nsDOMCSSAttributeDeclaration::nsDOMCSSAttributeDeclaration(dom::Element* aElement,
27
                                                           bool aIsSMILOverride)
28
  : mElement(aElement)
29
  , mIsSMILOverride(aIsSMILOverride)
30
0
{
31
0
  NS_ASSERTION(aElement, "Inline style for a NULL element?");
32
0
}
33
34
nsDOMCSSAttributeDeclaration::~nsDOMCSSAttributeDeclaration()
35
0
{
36
0
}
37
38
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsDOMCSSAttributeDeclaration, mElement)
39
40
// mElement holds a strong ref to us, so if it's going to be
41
// skipped, the attribute declaration can't be part of a garbage
42
// cycle.
43
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDOMCSSAttributeDeclaration)
44
0
  if (tmp->mElement && Element::CanSkip(tmp->mElement, true)) {
45
0
    if (tmp->PreservingWrapper()) {
46
0
      tmp->MarkWrapperLive();
47
0
    }
48
0
    return true;
49
0
  }
50
0
  return tmp->HasKnownLiveWrapper();
51
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
52
53
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsDOMCSSAttributeDeclaration)
54
0
  return tmp->HasKnownLiveWrapper() ||
55
0
    (tmp->mElement && Element::CanSkipInCC(tmp->mElement));
56
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
57
58
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDOMCSSAttributeDeclaration)
59
0
  return tmp->HasKnownLiveWrapper() ||
60
0
    (tmp->mElement && Element::CanSkipThis(tmp->mElement));
61
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
62
63
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCSSAttributeDeclaration)
64
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
65
0
NS_IMPL_QUERY_TAIL_INHERITING(nsDOMCSSDeclaration)
66
67
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCSSAttributeDeclaration)
68
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCSSAttributeDeclaration)
69
70
nsresult
71
nsDOMCSSAttributeDeclaration::SetCSSDeclaration(DeclarationBlock* aDecl,
72
                                                MutationClosureData* aClosureData)
73
0
{
74
0
  NS_ASSERTION(mElement, "Must have Element to set the declaration!");
75
0
76
0
  // Whenever changing element.style values, aClosureData must be non-null.
77
0
  // SMIL doesn't update Element's attribute values, so closure data isn't
78
0
  // needed.
79
0
  MOZ_ASSERT_IF(!mIsSMILOverride, aClosureData);
80
0
81
0
  // If the closure hasn't been called because the declaration wasn't changed,
82
0
  // we need to explicitly call it now to get InlineStyleDeclarationWillChange
83
0
  // notification before SetInlineStyleDeclaration.
84
0
  if (aClosureData && aClosureData->mClosure) {
85
0
    aClosureData->mClosure(aClosureData);
86
0
  }
87
0
88
0
  aDecl->SetDirty();
89
0
  return mIsSMILOverride
90
0
    ? mElement->SetSMILOverrideStyleDeclaration(aDecl, true)
91
0
    : mElement->SetInlineStyleDeclaration(*aDecl, *aClosureData);
92
0
}
93
94
nsIDocument*
95
nsDOMCSSAttributeDeclaration::DocToUpdate()
96
0
{
97
0
  // We need OwnerDoc() rather than GetUncomposedDoc() because it might
98
0
  // be the BeginUpdate call that inserts mElement into the document.
99
0
  return mElement->OwnerDoc();
100
0
}
101
102
DeclarationBlock*
103
nsDOMCSSAttributeDeclaration::GetOrCreateCSSDeclaration(Operation aOperation,
104
                                                        DeclarationBlock** aCreated)
105
0
{
106
0
  MOZ_ASSERT(aOperation != eOperation_Modify || aCreated);
107
0
108
0
  if (!mElement)
109
0
    return nullptr;
110
0
111
0
  DeclarationBlock* declaration;
112
0
  if (mIsSMILOverride) {
113
0
    declaration = mElement->GetSMILOverrideStyleDeclaration();
114
0
  } else {
115
0
    declaration = mElement->GetInlineStyleDeclaration();
116
0
  }
117
0
118
0
  if (declaration) {
119
0
    return declaration;
120
0
  }
121
0
122
0
  if (aOperation != eOperation_Modify) {
123
0
    return nullptr;
124
0
  }
125
0
126
0
  // cannot fail
127
0
  RefPtr<DeclarationBlock> decl = new DeclarationBlock();
128
0
  // Mark the declaration dirty so that it can be reused by the caller.
129
0
  // Normally SetDirty is called later in SetCSSDeclaration.
130
0
  decl->SetDirty();
131
#ifdef DEBUG
132
  RefPtr<DeclarationBlock> mutableDecl = decl->EnsureMutable();
133
  MOZ_ASSERT(mutableDecl == decl);
134
#endif
135
  decl.swap(*aCreated);
136
0
  return *aCreated;
137
0
}
138
139
nsDOMCSSDeclaration::ParsingEnvironment
140
nsDOMCSSAttributeDeclaration::GetParsingEnvironment(
141
    nsIPrincipal* aSubjectPrincipal) const
142
0
{
143
0
  return {
144
0
    mElement->GetURLDataForStyleAttr(aSubjectPrincipal),
145
0
    mElement->OwnerDoc()->GetCompatibilityMode(),
146
0
    mElement->OwnerDoc()->CSSLoader(),
147
0
  };
148
0
}
149
150
nsresult
151
nsDOMCSSAttributeDeclaration::SetSMILValue(const nsCSSPropertyID aPropID,
152
                                           const nsSMILValue& aValue)
153
0
{
154
0
  MOZ_ASSERT(mIsSMILOverride);
155
0
  // No need to do the ActiveLayerTracker / ScrollLinkedEffectDetector bits,
156
0
  // since we're in a SMIL animation anyway, no need to try to detect we're a
157
0
  // scripted animation.
158
0
  RefPtr<DeclarationBlock> created;
159
0
  DeclarationBlock* olddecl =
160
0
    GetOrCreateCSSDeclaration(eOperation_Modify, getter_AddRefs(created));
161
0
  if (!olddecl) {
162
0
    return NS_ERROR_NOT_AVAILABLE;
163
0
  }
164
0
  mozAutoDocUpdate autoUpdate(DocToUpdate(), true);
165
0
  RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
166
0
  bool changed = nsSMILCSSValueType::SetPropertyValues(aValue, *decl);
167
0
  if (changed) {
168
0
    // We can pass nullptr as the latter param, since this is
169
0
    // mIsSMILOverride == true case.
170
0
    SetCSSDeclaration(decl, nullptr);
171
0
  }
172
0
  return NS_OK;
173
0
}
174
175
nsresult
176
nsDOMCSSAttributeDeclaration::SetPropertyValue(const nsCSSPropertyID aPropID,
177
                                               const nsAString& aValue,
178
                                               nsIPrincipal* aSubjectPrincipal)
179
0
{
180
0
  // Scripted modifications to style.opacity or style.transform
181
0
  // could immediately force us into the animated state if heuristics suggest
182
0
  // this is scripted animation.
183
0
  // FIXME: This is missing the margin shorthand and the logical versions of
184
0
  // the margin properties, see bug 1266287.
185
0
  if (aPropID == eCSSProperty_opacity || aPropID == eCSSProperty_transform ||
186
0
      aPropID == eCSSProperty_left || aPropID == eCSSProperty_top ||
187
0
      aPropID == eCSSProperty_right || aPropID == eCSSProperty_bottom ||
188
0
      aPropID == eCSSProperty_background_position_x ||
189
0
      aPropID == eCSSProperty_background_position_y ||
190
0
      aPropID == eCSSProperty_background_position) {
191
0
    nsIFrame* frame = mElement->GetPrimaryFrame();
192
0
    if (frame) {
193
0
      ActiveLayerTracker::NotifyInlineStyleRuleModified(frame, aPropID, aValue, this);
194
0
    }
195
0
  }
196
0
  return nsDOMCSSDeclaration::SetPropertyValue(aPropID, aValue, aSubjectPrincipal);
197
0
}
198
199
void
200
nsDOMCSSAttributeDeclaration::MutationClosureFunction(void* aData)
201
0
{
202
0
  MutationClosureData* data = static_cast<MutationClosureData*>(aData);
203
0
  // Clear mClosure pointer so that it doesn't get called again.
204
0
  data->mClosure = nullptr;
205
0
  data->mElement->InlineStyleDeclarationWillChange(*data);
206
0
}