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 #ifndef nsFileControlFrame_h___
8 #define nsFileControlFrame_h___
9 
10 #include "mozilla/Attributes.h"
11 #include "nsBlockFrame.h"
12 #include "nsIFormControlFrame.h"
13 #include "nsIDOMEventListener.h"
14 #include "nsIAnonymousContentCreator.h"
15 #include "nsCOMPtr.h"
16 
17 namespace mozilla {
18 namespace dom {
19 class FileList;
20 class BlobImpl;
21 class DataTransfer;
22 }  // namespace dom
23 }  // namespace mozilla
24 
25 class nsFileControlFrame final : public nsBlockFrame,
26                                  public nsIFormControlFrame,
27                                  public nsIAnonymousContentCreator {
28   using Element = mozilla::dom::Element;
29 
30  public:
31   NS_DECL_QUERYFRAME
32   NS_DECL_FRAMEARENA_HELPERS(nsFileControlFrame)
33 
34   explicit nsFileControlFrame(ComputedStyle* aStyle,
35                               nsPresContext* aPresContext);
36 
37   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
38                     nsIFrame* aPrevInFlow) override;
39 
40   void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
41               const ReflowInput& aReflowInput,
42               nsReflowStatus& aStatus) override;
43 
44   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
45                                 const nsDisplayListSet& aLists) override;
46 
47   // nsIFormControlFrame
48   virtual nsresult SetFormProperty(nsAtom* aName,
49                                    const nsAString& aValue) override;
50   virtual void SetFocus(bool aOn, bool aRepaint) override;
51 
52   nscoord GetMinISize(gfxContext* aRenderingContext) override;
53   nscoord GetPrefISize(gfxContext* aRenderingContext) override;
54 
55   virtual void DestroyFrom(nsIFrame* aDestructRoot,
56                            PostDestroyData& aPostDestroyData) override;
57 
58 #ifdef DEBUG_FRAME_DUMP
59   virtual nsresult GetFrameName(nsAString& aResult) const override;
60 #endif
61 
62   virtual void ContentStatesChanged(mozilla::EventStates aStates) override;
63 
64   // nsIAnonymousContentCreator
65   virtual nsresult CreateAnonymousContent(
66       nsTArray<ContentInfo>& aElements) override;
67   virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
68                                         uint32_t aFilter) override;
69 
70 #ifdef ACCESSIBILITY
71   virtual mozilla::a11y::AccType AccessibleType() override;
72 #endif
73 
74   typedef bool (*AcceptAttrCallback)(const nsAString&, void*);
75 
76  protected:
77   class MouseListener;
78   friend class MouseListener;
79   class MouseListener : public nsIDOMEventListener {
80    public:
81     NS_DECL_ISUPPORTS
82 
MouseListener(nsFileControlFrame * aFrame)83     explicit MouseListener(nsFileControlFrame* aFrame) : mFrame(aFrame) {}
84 
ForgetFrame()85     void ForgetFrame() { mFrame = nullptr; }
86 
87    protected:
88     virtual ~MouseListener() = default;
89 
90     nsFileControlFrame* mFrame;
91   };
92 
93   class SyncDisabledStateEvent;
94   friend class SyncDisabledStateEvent;
95   class SyncDisabledStateEvent : public mozilla::Runnable {
96    public:
SyncDisabledStateEvent(nsFileControlFrame * aFrame)97     explicit SyncDisabledStateEvent(nsFileControlFrame* aFrame)
98         : mozilla::Runnable("nsFileControlFrame::SyncDisabledStateEvent"),
99           mFrame(aFrame) {}
100 
Run()101     NS_IMETHOD Run() override {
102       nsFileControlFrame* frame =
103           static_cast<nsFileControlFrame*>(mFrame.GetFrame());
104       NS_ENSURE_STATE(frame);
105 
106       frame->SyncDisabledState();
107       return NS_OK;
108     }
109 
110    private:
111     WeakFrame mFrame;
112   };
113 
114   class DnDListener : public MouseListener {
115    public:
DnDListener(nsFileControlFrame * aFrame)116     explicit DnDListener(nsFileControlFrame* aFrame) : MouseListener(aFrame) {}
117 
118     // nsIDOMEventListener
119     MOZ_CAN_RUN_SCRIPT_BOUNDARY
120     NS_IMETHOD HandleEvent(mozilla::dom::Event* aEvent) override;
121 
122     nsresult GetBlobImplForWebkitDirectory(mozilla::dom::FileList* aFileList,
123                                            mozilla::dom::BlobImpl** aBlobImpl);
124 
125     bool IsValidDropData(mozilla::dom::DataTransfer* aDataTransfer);
126     bool CanDropTheseFiles(mozilla::dom::DataTransfer* aDataTransfer,
127                            bool aSupportsMultiple);
128   };
129 
IsFrameOfType(uint32_t aFlags)130   virtual bool IsFrameOfType(uint32_t aFlags) const override {
131     return nsBlockFrame::IsFrameOfType(
132         aFlags & ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
133   }
134 
135   /**
136    * The text box input.
137    * @see nsFileControlFrame::CreateAnonymousContent
138    */
139   RefPtr<Element> mTextContent;
140   /**
141    * The button to open a file or directory picker.
142    * @see nsFileControlFrame::CreateAnonymousContent
143    */
144   RefPtr<Element> mBrowseFilesOrDirs;
145 
146   /**
147    * Drag and drop mouse listener.
148    * This makes sure we don't get used after destruction.
149    */
150   RefPtr<DnDListener> mMouseListener;
151 
152  protected:
153   /**
154    * Crop aText to fit inside aWidth using the styles of aFrame.
155    * @return true if aText was modified
156    */
157   static bool CropTextToWidth(gfxContext& aRenderingContext,
158                               const nsIFrame* aFrame, nscoord aWidth,
159                               nsString& aText);
160 
161   /**
162    * Sync the disabled state of the content with anonymous children.
163    */
164   void SyncDisabledState();
165 
166   /**
167    * Updates the displayed value by using aValue.
168    */
169   void UpdateDisplayedValue(const nsAString& aValue, bool aNotify);
170 };
171 
172 #endif  // nsFileControlFrame_h___
173