Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "MediaDocument.h"
7 #include "nsIPluginDocument.h"
8 #include "nsGkAtoms.h"
9 #include "nsIPresShell.h"
10 #include "nsIObjectFrame.h"
11 #include "nsNPAPIPluginInstance.h"
12 #include "nsIDocumentInlines.h"
13 #include "nsIDocShellTreeItem.h"
14 #include "nsNodeInfoManager.h"
15 #include "nsContentCreatorFunctions.h"
16 #include "nsContentPolicyUtils.h"
17 #include "nsIPropertyBag2.h"
18 #include "mozilla/dom/Element.h"
19 #include "nsObjectLoadingContent.h"
20 #include "GeckoProfiler.h"
22 namespace mozilla {
23 namespace dom {
25 class PluginDocument MOZ_FINAL : public MediaDocument
26 , public nsIPluginDocument
27 {
28 public:
29 PluginDocument();
30 virtual ~PluginDocument();
32 NS_DECL_ISUPPORTS_INHERITED
33 NS_DECL_NSIPLUGINDOCUMENT
35 virtual nsresult StartDocumentLoad(const char* aCommand,
36 nsIChannel* aChannel,
37 nsILoadGroup* aLoadGroup,
38 nsISupports* aContainer,
39 nsIStreamListener** aDocListener,
40 bool aReset = true,
41 nsIContentSink* aSink = nullptr);
43 virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject);
44 virtual bool CanSavePresentation(nsIRequest *aNewRequest);
46 const nsCString& GetType() const { return mMimeType; }
47 Element* GetPluginContent() { return mPluginContent; }
49 void StartLayout() { MediaDocument::StartLayout(); }
51 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PluginDocument, MediaDocument)
52 protected:
53 nsresult CreateSyntheticPluginDocument();
55 nsCOMPtr<Element> mPluginContent;
56 nsRefPtr<MediaDocumentStreamListener> mStreamListener;
57 nsCString mMimeType;
58 };
60 class PluginStreamListener : public MediaDocumentStreamListener
61 {
62 public:
63 PluginStreamListener(PluginDocument* doc)
64 : MediaDocumentStreamListener(doc)
65 , mPluginDoc(doc)
66 {}
67 NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt);
68 private:
69 nsRefPtr<PluginDocument> mPluginDoc;
70 };
73 NS_IMETHODIMP
74 PluginStreamListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
75 {
76 PROFILER_LABEL("PluginStreamListener", "OnStartRequest");
78 nsCOMPtr<nsIContent> embed = mPluginDoc->GetPluginContent();
79 nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(embed);
80 nsCOMPtr<nsIStreamListener> objListener = do_QueryInterface(objlc);
82 if (!objListener) {
83 NS_NOTREACHED("PluginStreamListener without appropriate content node");
84 return NS_BINDING_ABORTED;
85 }
87 SetStreamListener(objListener);
89 // Sets up the ObjectLoadingContent tag as if it is waiting for a
90 // channel, so it can proceed with a load normally once it gets OnStartRequest
91 nsresult rv = objlc->InitializeFromChannel(request);
92 if (NS_FAILED(rv)) {
93 NS_NOTREACHED("InitializeFromChannel failed");
94 return rv;
95 }
97 // Note that because we're now hooked up to a plugin listener, this will
98 // likely spawn a plugin, which may re-enter.
99 return MediaDocumentStreamListener::OnStartRequest(request, ctxt);
100 }
102 // NOTE! nsDocument::operator new() zeroes out all members, so don't
103 // bother initializing members to 0.
105 PluginDocument::PluginDocument()
106 {}
108 PluginDocument::~PluginDocument()
109 {}
112 NS_IMPL_CYCLE_COLLECTION_INHERITED(PluginDocument, MediaDocument,
113 mPluginContent)
115 NS_IMPL_ADDREF_INHERITED(PluginDocument, MediaDocument)
116 NS_IMPL_RELEASE_INHERITED(PluginDocument, MediaDocument)
118 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(PluginDocument)
119 NS_INTERFACE_TABLE_INHERITED(PluginDocument, nsIPluginDocument)
120 NS_INTERFACE_TABLE_TAIL_INHERITING(MediaDocument)
122 void
123 PluginDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject)
124 {
125 // Set the script global object on the superclass before doing
126 // anything that might require it....
127 MediaDocument::SetScriptGlobalObject(aScriptGlobalObject);
129 if (aScriptGlobalObject) {
130 if (!mPluginContent) {
131 // Create synthetic document
132 #ifdef DEBUG
133 nsresult rv =
134 #endif
135 CreateSyntheticPluginDocument();
136 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic document");
137 }
138 BecomeInteractive();
139 } else {
140 mStreamListener = nullptr;
141 }
142 }
145 bool
146 PluginDocument::CanSavePresentation(nsIRequest *aNewRequest)
147 {
148 // Full-page plugins cannot be cached, currently, because we don't have
149 // the stream listener data to feed to the plugin instance.
150 return false;
151 }
154 nsresult
155 PluginDocument::StartDocumentLoad(const char* aCommand,
156 nsIChannel* aChannel,
157 nsILoadGroup* aLoadGroup,
158 nsISupports* aContainer,
159 nsIStreamListener** aDocListener,
160 bool aReset,
161 nsIContentSink* aSink)
162 {
163 // do not allow message panes to host full-page plugins
164 // returning an error causes helper apps to take over
165 nsCOMPtr<nsIDocShellTreeItem> dsti (do_QueryInterface(aContainer));
166 if (dsti) {
167 bool isMsgPane = false;
168 dsti->NameEquals(MOZ_UTF16("messagepane"), &isMsgPane);
169 if (isMsgPane) {
170 return NS_ERROR_FAILURE;
171 }
172 }
174 nsresult rv =
175 MediaDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer,
176 aDocListener, aReset, aSink);
177 if (NS_FAILED(rv)) {
178 return rv;
179 }
181 rv = aChannel->GetContentType(mMimeType);
182 if (NS_FAILED(rv)) {
183 return rv;
184 }
186 MediaDocument::UpdateTitleAndCharset(mMimeType);
188 mStreamListener = new PluginStreamListener(this);
189 NS_ASSERTION(aDocListener, "null aDocListener");
190 NS_ADDREF(*aDocListener = mStreamListener);
192 return rv;
193 }
195 nsresult
196 PluginDocument::CreateSyntheticPluginDocument()
197 {
198 NS_ASSERTION(!GetShell() || !GetShell()->DidInitialize(),
199 "Creating synthetic plugin document content too late");
201 // make our generic document
202 nsresult rv = MediaDocument::CreateSyntheticDocument();
203 NS_ENSURE_SUCCESS(rv, rv);
204 // then attach our plugin
206 Element* body = GetBodyElement();
207 if (!body) {
208 NS_WARNING("no body on plugin document!");
209 return NS_ERROR_FAILURE;
210 }
212 // remove margins from body
213 NS_NAMED_LITERAL_STRING(zero, "0");
214 body->SetAttr(kNameSpaceID_None, nsGkAtoms::marginwidth, zero, false);
215 body->SetAttr(kNameSpaceID_None, nsGkAtoms::marginheight, zero, false);
218 // make plugin content
219 nsCOMPtr<nsINodeInfo> nodeInfo;
220 nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::embed, nullptr,
221 kNameSpaceID_XHTML,
222 nsIDOMNode::ELEMENT_NODE);
223 rv = NS_NewHTMLElement(getter_AddRefs(mPluginContent), nodeInfo.forget(),
224 NOT_FROM_PARSER);
225 NS_ENSURE_SUCCESS(rv, rv);
227 // make it a named element
228 mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::name,
229 NS_LITERAL_STRING("plugin"), false);
231 // fill viewport and auto-resize
232 NS_NAMED_LITERAL_STRING(percent100, "100%");
233 mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::width, percent100,
234 false);
235 mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::height, percent100,
236 false);
238 // set URL
239 nsAutoCString src;
240 mDocumentURI->GetSpec(src);
241 mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::src,
242 NS_ConvertUTF8toUTF16(src), false);
244 // set mime type
245 mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
246 NS_ConvertUTF8toUTF16(mMimeType), false);
248 // nsHTML(Shared)ObjectElement does not kick off a load on BindToTree if it is
249 // to a PluginDocument
250 body->AppendChildTo(mPluginContent, false);
252 return NS_OK;
255 }
257 NS_IMETHODIMP
258 PluginDocument::Print()
259 {
260 NS_ENSURE_TRUE(mPluginContent, NS_ERROR_FAILURE);
262 nsIObjectFrame* objectFrame =
263 do_QueryFrame(mPluginContent->GetPrimaryFrame());
264 if (objectFrame) {
265 nsRefPtr<nsNPAPIPluginInstance> pi;
266 objectFrame->GetPluginInstance(getter_AddRefs(pi));
267 if (pi) {
268 NPPrint npprint;
269 npprint.mode = NP_FULL;
270 npprint.print.fullPrint.pluginPrinted = false;
271 npprint.print.fullPrint.printOne = false;
272 npprint.print.fullPrint.platformPrint = nullptr;
274 pi->Print(&npprint);
275 }
276 }
278 return NS_OK;
279 }
281 } // namespace dom
282 } // namespace mozilla
284 nsresult
285 NS_NewPluginDocument(nsIDocument** aResult)
286 {
287 mozilla::dom::PluginDocument* doc = new mozilla::dom::PluginDocument();
289 NS_ADDREF(doc);
290 nsresult rv = doc->Init();
292 if (NS_FAILED(rv)) {
293 NS_RELEASE(doc);
294 }
296 *aResult = doc;
298 return rv;
299 }