Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/html/HTMLOptGroupElement.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
#include "mozilla/EventDispatcher.h"
8
#include "mozilla/EventStates.h"
9
#include "mozilla/dom/HTMLOptGroupElement.h"
10
#include "mozilla/dom/HTMLOptGroupElementBinding.h"
11
#include "mozilla/dom/HTMLSelectElement.h" // SafeOptionListMutation
12
#include "nsGkAtoms.h"
13
#include "nsStyleConsts.h"
14
#include "nsIFrame.h"
15
#include "nsIFormControlFrame.h"
16
17
NS_IMPL_NS_NEW_HTML_ELEMENT(OptGroup)
18
19
namespace mozilla {
20
namespace dom {
21
22
/**
23
 * The implementation of <optgroup>
24
 */
25
26
27
28
HTMLOptGroupElement::HTMLOptGroupElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
29
  : nsGenericHTMLElement(std::move(aNodeInfo))
30
0
{
31
0
  // We start off enabled
32
0
  AddStatesSilently(NS_EVENT_STATE_ENABLED);
33
0
}
34
35
HTMLOptGroupElement::~HTMLOptGroupElement()
36
0
{
37
0
}
38
39
40
NS_IMPL_ELEMENT_CLONE(HTMLOptGroupElement)
41
42
43
void
44
HTMLOptGroupElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
45
0
{
46
0
  aVisitor.mCanHandle = false;
47
0
  // Do not process any DOM events if the element is disabled
48
0
  // XXXsmaug This is not the right thing to do. But what is?
49
0
  if (IsDisabled()) {
50
0
    return;
51
0
  }
52
0
53
0
  if (nsIFrame* frame = GetPrimaryFrame()) {
54
0
    // FIXME(emilio): This poking at the style of the frame is broken unless we
55
0
    // flush before every event handling, which we don't really want to.
56
0
    if (frame->StyleUI()->mUserInput == StyleUserInput::None) {
57
0
      return;
58
0
    }
59
0
  }
60
0
61
0
  nsGenericHTMLElement::GetEventTargetParent(aVisitor);
62
0
}
63
64
Element*
65
HTMLOptGroupElement::GetSelect()
66
0
{
67
0
  Element* parent = nsINode::GetParentElement();
68
0
  if (!parent || !parent->IsHTMLElement(nsGkAtoms::select)) {
69
0
    return nullptr;
70
0
  }
71
0
  return parent;
72
0
}
73
74
nsresult
75
HTMLOptGroupElement::InsertChildBefore(nsIContent* aKid,
76
                                       nsIContent* aBeforeThis,
77
                                       bool aNotify)
78
0
{
79
0
  int32_t index = aBeforeThis ? ComputeIndexOf(aBeforeThis) : GetChildCount();
80
0
  SafeOptionListMutation safeMutation(GetSelect(), this, aKid, index, aNotify);
81
0
  nsresult rv =
82
0
    nsGenericHTMLElement::InsertChildBefore(aKid, aBeforeThis, aNotify);
83
0
  if (NS_FAILED(rv)) {
84
0
    safeMutation.MutationFailed();
85
0
  }
86
0
  return rv;
87
0
}
88
89
void
90
HTMLOptGroupElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
91
0
{
92
0
  SafeOptionListMutation safeMutation(GetSelect(), this, nullptr,
93
0
                                      ComputeIndexOf(aKid), aNotify);
94
0
  nsGenericHTMLElement::RemoveChildNode(aKid, aNotify);
95
0
}
96
97
nsresult
98
HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
99
                                  const nsAttrValue* aValue,
100
                                  const nsAttrValue* aOldValue,
101
                                  nsIPrincipal* aSubjectPrincipal,
102
                                  bool aNotify)
103
0
{
104
0
  if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled) {
105
0
106
0
    EventStates disabledStates;
107
0
    if (aValue) {
108
0
      disabledStates |= NS_EVENT_STATE_DISABLED;
109
0
    } else {
110
0
      disabledStates |= NS_EVENT_STATE_ENABLED;
111
0
    }
112
0
113
0
    EventStates oldDisabledStates = State() & DISABLED_STATES;
114
0
    EventStates changedStates = disabledStates ^ oldDisabledStates;
115
0
116
0
    if (!changedStates.IsEmpty()) {
117
0
      ToggleStates(changedStates, aNotify);
118
0
119
0
      // All our children <option> have their :disabled state depending on our
120
0
      // disabled attribute. We should make sure their state is updated.
121
0
      for (nsIContent* child = nsINode::GetFirstChild(); child;
122
0
           child = child->GetNextSibling()) {
123
0
        if (auto optElement = HTMLOptionElement::FromNode(child)) {
124
0
          optElement->OptGroupDisabledChanged(true);
125
0
        }
126
0
      }
127
0
    }
128
0
  }
129
0
130
0
  return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
131
0
                                            aOldValue, aSubjectPrincipal, aNotify);
132
0
}
133
134
JSObject*
135
HTMLOptGroupElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
136
0
{
137
0
  return HTMLOptGroupElement_Binding::Wrap(aCx, this, aGivenProto);
138
0
}
139
140
} // namespace dom
141
} // namespace mozilla