Source code

Revision control

Other Tools

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 "nsDocShell.h"
8
9
#include <algorithm>
10
11
#ifdef XP_WIN
12
# include <process.h>
13
# define getpid _getpid
14
#else
15
# include <unistd.h> // for getpid()
16
#endif
17
18
#include "mozilla/ArrayUtils.h"
19
#include "mozilla/Attributes.h"
20
#include "mozilla/AutoRestore.h"
21
#include "mozilla/BasePrincipal.h"
22
#include "mozilla/Casting.h"
23
#include "mozilla/Components.h"
24
#include "mozilla/DebugOnly.h"
25
#include "mozilla/Encoding.h"
26
#include "mozilla/EventStateManager.h"
27
#include "mozilla/HTMLEditor.h"
28
#include "mozilla/LoadInfo.h"
29
#include "mozilla/Logging.h"
30
#include "mozilla/MediaFeatureChange.h"
31
#include "mozilla/Preferences.h"
32
#include "mozilla/PresShell.h"
33
#include "mozilla/ResultExtensions.h"
34
#include "mozilla/ScrollTypes.h"
35
#include "mozilla/Services.h"
36
#include "mozilla/StaticPrefs_browser.h"
37
#include "mozilla/StaticPrefs_dom.h"
38
#include "mozilla/StaticPrefs_extensions.h"
39
#include "mozilla/StaticPrefs_privacy.h"
40
#include "mozilla/StaticPrefs_security.h"
41
#include "mozilla/StaticPrefs_ui.h"
42
#include "mozilla/StaticPrefs_fission.h"
43
#include "mozilla/StartupTimeline.h"
44
#include "mozilla/StorageAccess.h"
45
#include "mozilla/Telemetry.h"
46
#include "mozilla/Unused.h"
47
#include "mozilla/WidgetUtils.h"
48
49
#include "mozilla/dom/ClientChannelHelper.h"
50
#include "mozilla/dom/ClientHandle.h"
51
#include "mozilla/dom/ClientInfo.h"
52
#include "mozilla/dom/ClientManager.h"
53
#include "mozilla/dom/ClientSource.h"
54
#include "mozilla/dom/ContentChild.h"
55
#include "mozilla/dom/ContentFrameMessageManager.h"
56
#include "mozilla/dom/DocGroup.h"
57
#include "mozilla/dom/Element.h"
58
#include "mozilla/dom/HTMLAnchorElement.h"
59
#include "mozilla/dom/PerformanceNavigation.h"
60
#include "mozilla/dom/PermissionMessageUtils.h"
61
#include "mozilla/dom/PopupBlocker.h"
62
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
63
#include "mozilla/dom/ScreenOrientation.h"
64
#include "mozilla/dom/ScriptSettings.h"
65
#include "mozilla/dom/ServiceWorkerInterceptController.h"
66
#include "mozilla/dom/ServiceWorkerUtils.h"
67
#include "mozilla/dom/SessionStorageManager.h"
68
#include "mozilla/dom/BrowserChild.h"
69
#include "mozilla/dom/TabGroup.h"
70
#include "mozilla/dom/ToJSValue.h"
71
#include "mozilla/dom/UserActivation.h"
72
#include "mozilla/dom/ChildSHistory.h"
73
#include "mozilla/dom/nsCSPContext.h"
74
#include "mozilla/dom/LoadURIOptionsBinding.h"
75
#include "mozilla/dom/JSWindowActorChild.h"
76
#include "mozilla/net/DocumentChannel.h"
77
#include "nsSHEntry.h"
78
#include "mozilla/net/DocumentChannelChild.h"
79
#include "mozilla/net/UrlClassifierFeatureFactory.h"
80
#include "ReferrerInfo.h"
81
82
#include "nsIApplicationCacheChannel.h"
83
#include "nsIApplicationCacheContainer.h"
84
#include "nsIAppShell.h"
85
#include "nsIAuthPrompt.h"
86
#include "nsIAuthPrompt2.h"
87
#include "nsICachingChannel.h"
88
#include "nsICaptivePortalService.h"
89
#include "nsIChannel.h"
90
#include "nsIChannelEventSink.h"
91
#include "nsIClassOfService.h"
92
#include "nsIConsoleReportCollector.h"
93
#include "nsIContent.h"
94
#include "nsIContentInlines.h"
95
#include "nsIContentSecurityPolicy.h"
96
#include "nsIContentViewer.h"
97
#include "nsIController.h"
98
#include "nsIDocShellTreeItem.h"
99
#include "nsIDocShellTreeOwner.h"
100
#include "mozilla/dom/Document.h"
101
#include "nsIDocumentLoaderFactory.h"
102
#include "nsIDOMWindow.h"
103
#include "nsIEditingSession.h"
104
#include "nsIExternalProtocolService.h"
105
#include "nsIFormPOSTActionChannel.h"
106
#include "nsIFrame.h"
107
#include "nsIGlobalObject.h"
108
#include "nsIHttpChannel.h"
109
#include "nsIHttpChannelInternal.h"
110
#include "nsIIDNService.h"
111
#include "nsIInputStreamChannel.h"
112
#include "nsIInterfaceRequestorUtils.h"
113
#include "nsILayoutHistoryState.h"
114
#include "nsILoadInfo.h"
115
#include "nsIMultiPartChannel.h"
116
#include "nsINestedURI.h"
117
#include "nsINetworkPredictor.h"
118
#include "nsINode.h"
119
#include "nsINSSErrorsService.h"
120
#include "nsIObserverService.h"
121
#include "nsIOService.h"
122
#include "nsIPrincipal.h"
123
#include "nsIPrivacyTransitionObserver.h"
124
#include "nsIPrompt.h"
125
#include "nsIPromptFactory.h"
126
#include "nsIReflowObserver.h"
127
#include "nsIScriptChannel.h"
128
#include "nsIScriptObjectPrincipal.h"
129
#include "nsIScriptSecurityManager.h"
130
#include "nsIScrollableFrame.h"
131
#include "nsIScrollObserver.h"
132
#include "nsISecureBrowserUI.h"
133
#include "nsISeekableStream.h"
134
#include "nsISelectionDisplay.h"
135
#include "nsISHEntry.h"
136
#include "nsISiteSecurityService.h"
137
#include "nsISocketProvider.h"
138
#include "nsIStringBundle.h"
139
#include "nsIStructuredCloneContainer.h"
140
#include "nsIBrowserChild.h"
141
#include "nsITextToSubURI.h"
142
#include "nsITimedChannel.h"
143
#include "nsITimer.h"
144
#include "nsITransportSecurityInfo.h"
145
#include "nsIUploadChannel.h"
146
#include "nsIURIFixup.h"
147
#include "nsIURILoader.h"
148
#include "nsIViewSourceChannel.h"
149
#include "nsIWebBrowserChrome.h"
150
#include "nsIWebBrowserChrome3.h"
151
#include "nsIWebBrowserChromeFocus.h"
152
#include "nsIWebBrowserFind.h"
153
#include "nsIWebProgress.h"
154
#include "nsIWidget.h"
155
#include "nsIWindowWatcher.h"
156
#include "nsIWritablePropertyBag2.h"
157
158
#include "nsCommandManager.h"
159
#include "nsPIDOMWindow.h"
160
#include "nsPIWindowRoot.h"
161
162
#include "IHistory.h"
163
#include "IUrlClassifierUITelemetry.h"
164
165
#include "nsArray.h"
166
#include "nsArrayUtils.h"
167
#include "nsCExternalHandlerService.h"
168
#include "nsContentDLF.h"
169
#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
170
#include "nsContentSecurityManager.h"
171
#include "nsContentUtils.h"
172
#include "nsCURILoader.h"
173
#include "nsDocShellCID.h"
174
#include "nsDocShellEditorData.h"
175
#include "nsDocShellEnumerator.h"
176
#include "nsDocShellLoadState.h"
177
#include "nsDocShellLoadTypes.h"
178
#include "nsDOMCID.h"
179
#include "nsDOMNavigationTiming.h"
180
#include "nsDSURIContentListener.h"
181
#include "nsEditingSession.h"
182
#include "nsError.h"
183
#include "nsEscape.h"
184
#include "nsFocusManager.h"
185
#include "nsGlobalWindow.h"
186
#include "nsISearchService.h"
187
#include "nsJSEnvironment.h"
188
#include "nsNetCID.h"
189
#include "nsNetUtil.h"
190
#include "nsObjectLoadingContent.h"
191
#include "nsPingListener.h"
192
#include "nsPoint.h"
193
#include "nsQueryObject.h"
194
#include "nsQueryActor.h"
195
#include "nsRect.h"
196
#include "nsRefreshTimer.h"
197
#include "nsSandboxFlags.h"
198
#include "nsSHistory.h"
199
#include "SHEntryChild.h"
200
#include "nsStructuredCloneContainer.h"
201
#include "nsSubDocumentFrame.h"
202
#include "nsView.h"
203
#include "nsViewManager.h"
204
#include "nsViewSourceHandler.h"
205
#include "nsWebBrowserFind.h"
206
#include "nsWhitespaceTokenizer.h"
207
#include "nsWidgetsCID.h"
208
#include "nsXULAppAPI.h"
209
210
#include "GeckoProfiler.h"
211
#include "mozilla/NullPrincipal.h"
212
#include "Navigator.h"
213
#include "prenv.h"
214
#include "URIUtils.h"
215
216
#include "timeline/JavascriptTimelineMarker.h"
217
218
#ifdef MOZ_PLACES
219
# include "nsIFaviconService.h"
220
# include "mozIPlacesPendingOperation.h"
221
#endif
222
223
#if NS_PRINT_PREVIEW
224
# include "nsIDocumentViewerPrint.h"
225
# include "nsIWebBrowserPrint.h"
226
#endif
227
228
#ifdef MOZ_GECKO_PROFILER
229
# include "ProfilerMarkerPayload.h"
230
#endif
231
232
using namespace mozilla;
233
using namespace mozilla::dom;
234
using namespace mozilla::net;
235
236
// Threshold value in ms for META refresh based redirects
237
#define REFRESH_REDIRECT_TIMER 15000
238
239
// Hint for native dispatch of events on how long to delay after
240
// all documents have loaded in milliseconds before favoring normal
241
// native event dispatch priorites over performance
242
// Can be overridden with docshell.event_starvation_delay_hint pref.
243
#define NS_EVENT_STARVATION_DELAY_HINT 2000
244
245
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
246
247
// Number of documents currently loading
248
static int32_t gNumberOfDocumentsLoading = 0;
249
250
// Global count of existing docshells.
251
static int32_t gDocShellCount = 0;
252
253
// Global count of docshells with the private attribute set
254
static uint32_t gNumberOfPrivateDocShells = 0;
255
256
#ifdef DEBUG
257
static mozilla::LazyLogModule gDocShellLog("nsDocShell");
258
static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging(
259
"DocShellAndDOMWindowLeak");
260
#endif
261
static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
262
extern mozilla::LazyLogModule gPageCacheLog;
263
264
const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties";
265
const char kAppstringsBundleURL[] =
267
268
// Global reference to the URI fixup service.
269
nsIURIFixup* nsDocShell::sURIFixup = nullptr;
270
271
static void FavorPerformanceHint(bool aPerfOverStarvation) {
272
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
273
if (appShell) {
274
appShell->FavorPerformanceHint(
275
aPerfOverStarvation,
276
Preferences::GetUint("docshell.event_starvation_delay_hint",
277
NS_EVENT_STARVATION_DELAY_HINT));
278
}
279
}
280
281
static void IncreasePrivateDocShellCount() {
282
gNumberOfPrivateDocShells++;
283
if (gNumberOfPrivateDocShells > 1 || !XRE_IsContentProcess()) {
284
return;
285
}
286
287
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
288
cc->SendPrivateDocShellsExist(true);
289
}
290
291
static void DecreasePrivateDocShellCount() {
292
MOZ_ASSERT(gNumberOfPrivateDocShells > 0);
293
gNumberOfPrivateDocShells--;
294
if (!gNumberOfPrivateDocShells) {
295
if (XRE_IsContentProcess()) {
296
dom::ContentChild* cc = dom::ContentChild::GetSingleton();
297
cc->SendPrivateDocShellsExist(false);
298
return;
299
}
300
301
nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService();
302
if (obsvc) {
303
obsvc->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
304
}
305
}
306
}
307
308
static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext,
309
nsILoadInfo* aLoadInfo) {
310
MOZ_ASSERT(aBrowsingContext);
311
MOZ_ASSERT(aLoadInfo);
312
313
if (aLoadInfo->GetExternalContentPolicyType() !=
314
nsIContentPolicy::TYPE_DOCUMENT) {
315
return false;
316
}
317
318
return aBrowsingContext->IsTopContent();
319
}
320
321
// True if loading for top level document loading in active tab.
322
static bool IsUrgentStart(BrowsingContext* aBrowsingContext,
323
nsILoadInfo* aLoadInfo, uint32_t aLoadType) {
324
MOZ_ASSERT(aBrowsingContext);
325
MOZ_ASSERT(aLoadInfo);
326
327
if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) {
328
return false;
329
}
330
331
if (aLoadType &
332
(nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) {
333
return true;
334
}
335
336
return aBrowsingContext->GetIsActive();
337
}
338
339
nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
340
uint64_t aContentWindowID)
341
: nsDocLoader(),
342
mHistoryID(aBrowsingContext->GetHistoryID()),
343
mContentWindowID(aContentWindowID),
344
mBrowsingContext(aBrowsingContext),
345
mForcedCharset(nullptr),
346
mParentCharset(nullptr),
347
mTreeOwner(nullptr),
348
mScrollbarPref(ScrollbarPreference::Auto),
349
mCharsetReloadState(eCharsetReloadInit),
350
mOrientationLock(hal::eScreenOrientation_None),
351
mParentCharsetSource(0),
352
mFrameMargins(-1, -1),
353
mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome),
354
mPreviousEntryIndex(-1),
355
mLoadedEntryIndex(-1),
356
mChildOffset(0),
357
mBusyFlags(BUSY_FLAGS_NONE),
358
mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
359
mLoadType(0),
360
mDefaultLoadFlags(nsIRequest::LOAD_NORMAL),
361
mFailedLoadType(0),
362
mFrameType(FRAME_TYPE_REGULAR),
363
mPrivateBrowsingId(0),
364
mDisplayMode(nsIDocShell::DISPLAY_MODE_BROWSER),
365
mJSRunToCompletionDepth(0),
366
mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE),
367
mMetaViewportOverride(nsIDocShell::META_VIEWPORT_OVERRIDE_NONE),
368
mFullscreenAllowed(CHECK_ATTRIBUTES),
369
mCreatingDocument(false),
370
#ifdef DEBUG
371
mInEnsureScriptEnv(false),
372
#endif
373
mCreated(false),
374
mAllowSubframes(true),
375
mAllowJavascript(true),
376
mAllowMetaRedirects(true),
377
mAllowImages(true),
378
mAllowMedia(true),
379
mAllowDNSPrefetch(true),
380
mAllowWindowControl(true),
381
mUseErrorPages(false),
382
mObserveErrorPages(true),
383
mCSSErrorReportingEnabled(false),
384
mAllowAuth(mItemType == typeContent),
385
mAllowKeywordFixup(false),
386
mIsOffScreenBrowser(false),
387
mDisableMetaRefreshWhenInactive(false),
388
mIsAppTab(false),
389
mUseGlobalHistory(false),
390
mUseRemoteTabs(false),
391
mUseRemoteSubframes(false),
392
mUseTrackingProtection(false),
393
mDeviceSizeIsPageSize(false),
394
mWindowDraggingAllowed(false),
395
mInFrameSwap(false),
396
mInheritPrivateBrowsingId(true),
397
mCanExecuteScripts(false),
398
mFiredUnloadEvent(false),
399
mEODForCurrentDocument(false),
400
mURIResultedInDocument(false),
401
mIsBeingDestroyed(false),
402
mIsExecutingOnLoadHandler(false),
403
mIsPrintingOrPP(false),
404
mSavingOldViewer(false),
405
mDynamicallyCreated(false),
406
mAffectPrivateSessionLifetime(true),
407
mInvisible(false),
408
mHasLoadedNonBlankURI(false),
409
mBlankTiming(false),
410
mTitleValidForCurrentURI(false),
411
mIsFrame(false),
412
mWillChangeProcess(false),
413
mWatchedByDevtools(false),
414
mIsNavigating(false) {
415
AssertOriginAttributesMatchPrivateBrowsing();
416
417
// If no outer window ID was provided, generate a new one.
418
if (aContentWindowID == 0) {
419
mContentWindowID = nsContentUtils::GenerateWindowId();
420
}
421
422
if (gDocShellCount++ == 0) {
423
NS_ASSERTION(sURIFixup == nullptr,
424
"Huh, sURIFixup not null in first nsDocShell ctor!");
425
426
nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
427
uriFixup.forget(&sURIFixup);
428
}
429
430
MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p created\n", this));
431
432
#ifdef DEBUG
433
// We're counting the number of |nsDocShells| to help find leaks
434
++gNumberOfDocShells;
435
MOZ_LOG(gDocShellAndDOMWindowLeakLogging, LogLevel::Info,
436
("++DOCSHELL %p == %ld [pid = %d] [id = %s]\n", (void*)this,
437
gNumberOfDocShells, getpid(), nsIDToCString(mHistoryID).get()));
438
#endif
439
}
440
441
nsDocShell::~nsDocShell() {
442
MOZ_ASSERT(!mObserved);
443
444
// Avoid notifying observers while we're in the dtor.
445
mIsBeingDestroyed = true;
446
447
Destroy();
448
449
if (mSessionHistory) {
450
mSessionHistory->LegacySHistory()->ClearRootBrowsingContext();
451
}
452
453
if (mContentViewer) {
454
mContentViewer->Close(nullptr);
455
mContentViewer->Destroy();
456
mContentViewer = nullptr;
457
}
458
459
if (--gDocShellCount == 0) {
460
NS_IF_RELEASE(sURIFixup);
461
}
462
463
MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p destroyed\n", this));
464
465
#ifdef DEBUG
466
if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)) {
467
nsAutoCString url;
468
if (mLastOpenedURI) {
469
url = mLastOpenedURI->GetSpecOrDefault();
470
471
// Data URLs can be very long, so truncate to avoid flooding the log.
472
const uint32_t maxURLLength = 1000;
473
if (url.Length() > maxURLLength) {
474
url.Truncate(maxURLLength);
475
}
476
}
477
478
// We're counting the number of |nsDocShells| to help find leaks
479
--gNumberOfDocShells;
480
MOZ_LOG(gDocShellAndDOMWindowLeakLogging, LogLevel::Info,
481
("--DOCSHELL %p == %ld [pid = %d] [id = %s] [url = %s]\n",
482
(void*)this, gNumberOfDocShells, getpid(),
483
nsIDToCString(mHistoryID).get(), url.get()));
484
}
485
#endif
486
}
487
488
/* static */
489
already_AddRefed<nsDocShell> nsDocShell::Create(
490
BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) {
491
MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!");
492
493
nsresult rv;
494
RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID);
495
496
// Initialize the underlying nsDocLoader.
497
rv = ds->nsDocLoader::Init();
498
if (NS_WARN_IF(NS_FAILED(rv))) {
499
return nullptr;
500
}
501
502
// Create our ContentListener
503
ds->mContentListener = new nsDSURIContentListener(ds);
504
505
// If parent intercept is not enabled then we must forward to
506
// the network controller from docshell. We also enable if we're
507
// in the parent process in order to support non-e10s configurations.
508
// Note: This check is duplicated in SharedWorkerInterfaceRequestor's
509
// constructor.
510
if (!ServiceWorkerParentInterceptEnabled() || XRE_IsParentProcess()) {
511
ds->mInterceptController = new ServiceWorkerInterceptController();
512
}
513
514
// We want to hold a strong ref to the loadgroup, so it better hold a weak
515
// ref to us... use an InterfaceRequestorProxy to do this.
516
nsCOMPtr<nsIInterfaceRequestor> proxy = new InterfaceRequestorProxy(ds);
517
ds->mLoadGroup->SetNotificationCallbacks(proxy);
518
519
// XXX(nika): We have our BrowsingContext, so we might be able to skip this.
520
// It could be nice to directly set up our DocLoader tree?
521
rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds);
522
if (NS_WARN_IF(NS_FAILED(rv))) {
523
return nullptr;
524
}
525
526
// Add |ds| as a progress listener to itself. A little weird, but simpler
527
// than reproducing all the listener-notification logic in overrides of the
528
// various methods via which nsDocLoader can be notified. Note that this
529
// holds an nsWeakPtr to |ds|, so it's ok.
530
rv = ds->AddProgressListener(ds, nsIWebProgress::NOTIFY_STATE_DOCUMENT |
531
nsIWebProgress::NOTIFY_STATE_NETWORK);
532
if (NS_WARN_IF(NS_FAILED(rv))) {
533
return nullptr;
534
}
535
536
// If our parent is present in this process, set up our parent now.
537
RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent();
538
if (parent && parent->GetDocShell()) {
539
parent->GetDocShell()->AddChild(ds);
540
}
541
542
// Make |ds| the primary DocShell for the given context.
543
aBrowsingContext->SetDocShell(ds);
544
545
return ds.forget();
546
}
547
548
void nsDocShell::DestroyChildren() {
549
nsCOMPtr<nsIDocShellTreeItem> shell;
550
nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
551
while (iter.HasMore()) {
552
shell = do_QueryObject(iter.GetNext());
553
NS_ASSERTION(shell, "docshell has null child");
554
555
if (shell) {
556
shell->SetTreeOwner(nullptr);
557
}
558
}
559
560
nsDocLoader::DestroyChildren();
561
}
562
563
NS_IMPL_CYCLE_COLLECTION_WEAK_PTR_INHERITED(nsDocShell, nsDocLoader,
564
mScriptGlobal, mInitialClientSource,
565
mSessionHistory, mBrowsingContext,
566
mChromeEventHandler)
567
568
NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)
569
NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)
570
571
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocShell)
572
NS_INTERFACE_MAP_ENTRY(nsIDocShell)
573
NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)
574
NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
575
NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
576
NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)
577
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
578
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
579
NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)
580
NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)
581
NS_INTERFACE_MAP_ENTRY(nsILoadContext)
582
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsINetworkInterceptController,
583
mInterceptController)
584
NS_INTERFACE_MAP_ENTRY(nsIDeprecationWarner)
585
NS_INTERFACE_MAP_END_INHERITING(nsDocLoader)
586
587
NS_IMETHODIMP
588
nsDocShell::GetInterface(const nsIID& aIID, void** aSink) {
589
MOZ_ASSERT(aSink, "null out param");
590
591
*aSink = nullptr;
592
593
if (aIID.Equals(NS_GET_IID(nsICommandManager))) {
594
NS_ENSURE_SUCCESS(EnsureCommandHandler(), NS_ERROR_FAILURE);
595
*aSink = static_cast<nsICommandManager*>(mCommandManager.get());
596
} else if (aIID.Equals(NS_GET_IID(nsIURIContentListener))) {
597
*aSink = mContentListener;
598
} else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)) ||
599
aIID.Equals(NS_GET_IID(nsIGlobalObject)) ||
600
aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)) ||
601
aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)) ||
602
aIID.Equals(NS_GET_IID(nsIDOMWindow))) &&
603
NS_SUCCEEDED(EnsureScriptEnvironment())) {
604
return mScriptGlobal->QueryInterface(aIID, aSink);
605
} else if (aIID.Equals(NS_GET_IID(Document)) &&
606
NS_SUCCEEDED(EnsureContentViewer())) {
607
RefPtr<Document> doc = mContentViewer->GetDocument();
608
doc.forget(aSink);
609
return *aSink ? NS_OK : NS_NOINTERFACE;
610
} else if (aIID.Equals(NS_GET_IID(nsIApplicationCacheContainer))) {
611
*aSink = nullptr;
612
613
// Return application cache associated with this docshell, if any
614
615
nsCOMPtr<nsIContentViewer> contentViewer;
616
GetContentViewer(getter_AddRefs(contentViewer));
617
if (!contentViewer) {
618
return NS_ERROR_NO_INTERFACE;
619
}
620
621
RefPtr<Document> doc = contentViewer->GetDocument();
622
NS_ASSERTION(doc, "Should have a document.");
623
if (!doc) {
624
return NS_ERROR_NO_INTERFACE;
625
}
626
627
#if defined(DEBUG)
628
MOZ_LOG(
629
gDocShellLog, LogLevel::Debug,
630
("nsDocShell[%p]: returning app cache container %p", this, doc.get()));
631
#endif
632
return doc->QueryInterface(aIID, aSink);
633
} else if (aIID.Equals(NS_GET_IID(nsIPrompt)) &&
634
NS_SUCCEEDED(EnsureScriptEnvironment())) {
635
nsresult rv;
636
nsCOMPtr<nsIWindowWatcher> wwatch =
637
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
638
NS_ENSURE_SUCCESS(rv, rv);
639
640
// Get the an auth prompter for our window so that the parenting
641
// of the dialogs works as it should when using tabs.
642
nsIPrompt* prompt;
643
rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt);
644
NS_ENSURE_SUCCESS(rv, rv);
645
646
*aSink = prompt;
647
return NS_OK;
648
} else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
649
aIID.Equals(NS_GET_IID(nsIAuthPrompt2))) {
650
return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))
651
? NS_OK
652
: NS_NOINTERFACE;
653
} else if (aIID.Equals(NS_GET_IID(nsISHistory))) {
654
RefPtr<ChildSHistory> shistory = GetSessionHistory();
655
if (shistory) {
656
// XXX(nika): Stop exposing nsISHistory through GetInterface.
657
nsCOMPtr<nsISHistory> legacy = shistory->LegacySHistory();
658
legacy.forget(aSink);
659
return NS_OK;
660
}
661
return NS_NOINTERFACE;
662
} else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind))) {
663
nsresult rv = EnsureFind();
664
if (NS_FAILED(rv)) {
665
return rv;
666
}
667
668
*aSink = mFind;
669
NS_ADDREF((nsISupports*)*aSink);
670
return NS_OK;
671
} else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay))) {
672
if (PresShell* presShell = GetPresShell()) {
673
return presShell->QueryInterface(aIID, aSink);
674
}
675
} else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner))) {
676
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
677
nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
678
if (NS_SUCCEEDED(rv) && treeOwner) {
679
return treeOwner->QueryInterface(aIID, aSink);
680
}
681
} else if (aIID.Equals(NS_GET_IID(nsIBrowserChild))) {
682
*aSink = GetBrowserChild().take();
683
return *aSink ? NS_OK : NS_ERROR_FAILURE;
684
} else {
685
return nsDocLoader::GetInterface(aIID, aSink);
686
}
687
688
NS_IF_ADDREF(((nsISupports*)*aSink));
689
return *aSink ? NS_OK : NS_NOINTERFACE;
690
}
691
692
NS_IMETHODIMP
693
nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) {
694
// Note: this gets called fairly early (before a pageload actually starts).
695
// We could probably defer this even longer.
696
nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
697
static_cast<BrowserChild*>(browserChild.get())
698
->SetCancelContentJSEpoch(aEpoch);
699
return NS_OK;
700
}
701
702
NS_IMETHODIMP
703
nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) {
704
MOZ_ASSERT(aLoadState, "Must have a valid load state!");
705
MOZ_ASSERT(
706
(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,
707
"Should not have these flags set");
708
709
if (!aLoadState->TriggeringPrincipal()) {
710
MOZ_ASSERT(false, "LoadURI must have a triggering principal");
711
return NS_ERROR_FAILURE;
712
}
713
714
bool oldIsNavigating = mIsNavigating;
715
auto cleanupIsNavigating =
716
MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; });
717
if (aSetNavigating) {
718
mIsNavigating = true;
719
}
720
721
PopupBlocker::PopupControlState popupState;
722
if (aLoadState->LoadFlags() & LOAD_FLAGS_ALLOW_POPUPS) {
723
popupState = PopupBlocker::openAllowed;
724
} else {
725
popupState = PopupBlocker::openOverridden;
726
}
727
AutoPopupStatePusher statePusher(popupState);
728
729
if (aLoadState->GetOriginalURIString().isSome()) {
730
// Save URI string in case it's needed later when
731
// sending to search engine service in EndPageLoad()
732
mOriginalUriString = *aLoadState->GetOriginalURIString();
733
}
734
735
if (aLoadState->GetCancelContentJSEpoch().isSome()) {
736
SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch());
737
}
738
739
// Note: we allow loads to get through here even if mFiredUnloadEvent is
740
// true; that case will get handled in LoadInternal or LoadHistoryEntry,
741
// so we pass false as the second parameter to IsNavigationAllowed.
742
// However, we don't allow the page to change location *in the middle of*
743
// firing beforeunload, so we do need to check if *beforeunload* is currently
744
// firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
745
if (!IsNavigationAllowed(true, false)) {
746
return NS_OK; // JS may not handle returning of an error code
747
}
748
749
if (aLoadState->LoadFlags() & LOAD_FLAGS_FORCE_TRR) {
750
mDefaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE;
751
} else if (aLoadState->LoadFlags() & LOAD_FLAGS_DISABLE_TRR) {
752
mDefaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE;
753
}
754
755
if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
756
mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) {
757
StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
758
}
759
760
// LoadType used to be set to a default value here, if no LoadInfo/LoadState
761
// object was passed in. That functionality has been removed as of bug
762
// 1492648. LoadType should now be set up by the caller at the time they
763
// create their nsDocShellLoadState object to pass into LoadURI.
764
765
MOZ_LOG(
766
gDocShellLeakLog, LogLevel::Debug,
767
("nsDocShell[%p]: loading %s with flags 0x%08x", this,
768
aLoadState->URI()->GetSpecOrDefault().get(), aLoadState->LoadFlags()));
769
770
if (!aLoadState->SHEntry() &&
771
!LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),
772
LOAD_FLAGS_REPLACE_HISTORY)) {
773
// This is possibly a subframe, so handle it accordingly.
774
//
775
// If history exists, it will be loaded into the aLoadState object, and the
776
// LoadType will be changed.
777
MaybeHandleSubframeHistory(aLoadState);
778
}
779
780
if (aLoadState->SHEntry()) {
781
#ifdef DEBUG
782
MOZ_LOG(gDocShellLog, LogLevel::Debug,
783
("nsDocShell[%p]: loading from session history", this));
784
#endif
785
786
return LoadHistoryEntry(aLoadState->SHEntry(), aLoadState->LoadType());
787
}
788
789
// On history navigation via Back/Forward buttons, don't execute
790
// automatic JavaScript redirection such as |location.href = ...| or
791
// |window.open()|
792
//
793
// LOAD_NORMAL: window.open(...) etc.
794
// LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
795
if ((aLoadState->LoadType() == LOAD_NORMAL ||
796
aLoadState->LoadType() == LOAD_STOP_CONTENT) &&
797
ShouldBlockLoadingForBackButton()) {
798
return NS_OK;
799
}
800
801
BrowsingContext::Type bcType = mBrowsingContext->GetType();
802
803
// Set up the inheriting principal in LoadState.
804
nsresult rv = aLoadState->SetupInheritingPrincipal(bcType, mOriginAttributes);
805
NS_ENSURE_SUCCESS(rv, rv);
806
807
rv = aLoadState->SetupTriggeringPrincipal(mOriginAttributes);
808
NS_ENSURE_SUCCESS(rv, rv);
809
810
aLoadState->CalculateLoadURIFlags();
811
812
MOZ_ASSERT(aLoadState->TypeHint().IsVoid(),
813
"Typehint should be null when calling InternalLoad from LoadURI");
814
MOZ_ASSERT(aLoadState->FileName().IsVoid(),
815
"FileName should be null when calling InternalLoad from LoadURI");
816
MOZ_ASSERT(aLoadState->SHEntry() == nullptr,
817
"SHEntry should be null when calling InternalLoad from LoadURI");
818
819
return InternalLoad(aLoadState,
820
nullptr, // no nsIDocShell
821
nullptr); // no nsIRequest
822
}
823
824
void nsDocShell::MaybeHandleSubframeHistory(nsDocShellLoadState* aLoadState) {
825
// First, verify if this is a subframe.
826
nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
827
GetInProcessSameTypeParent(getter_AddRefs(parentAsItem));
828
nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
829
830
if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) {
831
// This is the root docshell. If we got here while
832
// executing an onLoad Handler,this load will not go
833
// into session history.
834
bool inOnLoadHandler = false;
835
GetIsExecutingOnLoadHandler(&inOnLoadHandler);
836
if (inOnLoadHandler) {
837
aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
838
}
839
return;
840
}
841
842
/* OK. It is a subframe. Checkout the parent's loadtype. If the parent was
843
* loaded through a history mechanism, then get the SH entry for the child
844
* from the parent. This is done to restore frameset navigation while going
845
* back/forward. If the parent was loaded through any other loadType, set the
846
* child's loadType too accordingly, so that session history does not get
847
* confused.
848
*/
849
850
// Get the parent's load type
851
uint32_t parentLoadType;
852
parentDS->GetLoadType(&parentLoadType);
853
854
// Get the ShEntry for the child from the parent
855
nsCOMPtr<nsISHEntry> currentSH;
856
bool oshe = false;
857
parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
858
bool dynamicallyAddedChild = mDynamicallyCreated;
859
860
if (!dynamicallyAddedChild && !oshe && currentSH) {
861
// Only use the old SHEntry, if we're sure enough that
862
// it wasn't originally for some other frame.
863
nsCOMPtr<nsISHEntry> shEntry;
864
currentSH->GetChildSHEntryIfHasNoDynamicallyAddedChild(
865
mChildOffset, getter_AddRefs(shEntry));
866
if (shEntry) {
867
aLoadState->SetSHEntry(shEntry);
868
}
869
}
870
871
// Make some decisions on the child frame's loadType based on the
872
// parent's loadType, if the subframe hasn't loaded anything into it.
873
//
874
// In some cases privileged scripts may try to get the DOMWindow
875
// reference of this docshell before the loading starts, causing the
876
// initial about:blank content viewer being created and mCurrentURI being
877
// set. To handle this case we check if mCurrentURI is about:blank and
878
// currentSHEntry is null.
879
nsCOMPtr<nsISHEntry> currentChildEntry;
880
GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe);
881
882
if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry)) {
883
// This is a pre-existing subframe. If
884
// 1. The load of this frame was not originally initiated by session
885
// history directly (i.e. (!shEntry) condition succeeded, but it can
886
// still be a history load on parent which causes this frame being
887
// loaded), which we checked with the above assert, and
888
// 2. mCurrentURI is not null, nor the initial about:blank,
889
// it is possible that a parent's onLoadHandler or even self's
890
// onLoadHandler is loading a new page in this child. Check parent's and
891
// self's busy flag and if it is set, we don't want this onLoadHandler
892
// load to get in to session history.
893
BusyFlags parentBusy = parentDS->GetBusyFlags();
894
BusyFlags selfBusy = GetBusyFlags();
895
896
if (parentBusy & BUSY_FLAGS_BUSY || selfBusy & BUSY_FLAGS_BUSY) {
897
aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
898
aLoadState->SetSHEntry(nullptr);
899
}
900
return;
901
}
902
903
// This is a newly created frame. Check for exception cases first.
904
// By default the subframe will inherit the parent's loadType.
905
if (aLoadState->SHEntry() &&
906
(parentLoadType == LOAD_NORMAL || parentLoadType == LOAD_LINK ||
907
parentLoadType == LOAD_NORMAL_EXTERNAL)) {
908
// The parent was loaded normally. In this case, this *brand new*
909
// child really shouldn't have a SHEntry. If it does, it could be
910
// because the parent is replacing an existing frame with a new frame,
911
// in the onLoadHandler. We don't want this url to get into session
912
// history. Clear off shEntry, and set load type to
913
// LOAD_BYPASS_HISTORY.
914
bool inOnLoadHandler = false;
915
parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
916
if (inOnLoadHandler) {
917
aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
918
aLoadState->SetSHEntry(nullptr);
919
}
920
} else if (parentLoadType == LOAD_REFRESH) {
921
// Clear shEntry. For refresh loads, we have to load
922
// what comes through the pipe, not what's in history.
923
aLoadState->SetSHEntry(nullptr);
924
} else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
925
(aLoadState->SHEntry() &&
926
((parentLoadType & LOAD_CMD_HISTORY) ||
927
(parentLoadType == LOAD_RELOAD_NORMAL) ||
928
(parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
929
(parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
930
(parentLoadType ==
931
LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
932
// If the parent url, bypassed history or was loaded from
933
// history, pass on the parent's loadType to the new child
934
// frame too, so that the child frame will also
935
// avoid getting into history.
936
aLoadState->SetLoadType(parentLoadType);
937
} else if (parentLoadType == LOAD_ERROR_PAGE) {
938
// If the parent document is an error page, we don't
939
// want to update global/session history. However,
940
// this child frame is not an error page.
941
aLoadState->SetLoadType(LOAD_BYPASS_HISTORY);
942
} else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
943
(parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
944
(parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
945
// the new frame should inherit the parent's load type so that it also
946
// bypasses the cache and/or proxy
947
aLoadState->SetLoadType(parentLoadType);
948
}
949
}
950
951
/*
952
* Reset state to a new content model within the current document and the
953
* document viewer. Called by the document before initiating an out of band
954
* document.write().
955
*/
956
NS_IMETHODIMP
957
nsDocShell::PrepareForNewContentModel() {
958
// Clear out our form control state, because the state of controls
959
// in the pre-open() document should not affect the state of
960
// controls that are now going to be written.
961
SetLayoutHistoryState(nullptr);
962
mEODForCurrentDocument = false;
963
return NS_OK;
964
}
965
966
NS_IMETHODIMP
967
nsDocShell::FirePageHideNotification(bool aIsUnload) {
968
FirePageHideNotificationInternal(aIsUnload, false);
969
return NS_OK;
970
}
971
972
void nsDocShell::FirePageHideNotificationInternal(
973
bool aIsUnload, bool aSkipCheckingDynEntries) {
974
if (mContentViewer && !mFiredUnloadEvent) {
975
// Keep an explicit reference since calling PageHide could release
976
// mContentViewer
977
nsCOMPtr<nsIContentViewer> contentViewer(mContentViewer);
978
mFiredUnloadEvent = true;
979
980
if (mTiming) {
981
mTiming->NotifyUnloadEventStart();
982
}
983
984
contentViewer->PageHide(aIsUnload);
985
986
if (mTiming) {
987
mTiming->NotifyUnloadEventEnd();
988
}
989
990
AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids;
991
uint32_t n = mChildList.Length();
992
kids.SetCapacity(n);
993
for (uint32_t i = 0; i < n; i++) {
994
kids.AppendElement(do_QueryInterface(ChildAt(i)));
995
}
996
997
n = kids.Length();
998
for (uint32_t i = 0; i < n; ++i) {
999
RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get());
1000
if (child) {
1001
// Skip checking dynamic subframe entries in our children.
1002
child->FirePageHideNotificationInternal(aIsUnload, true);
1003
}
1004
}
1005
1006
// If the document is unloading, remove all dynamic subframe entries.
1007
if (aIsUnload && !aSkipCheckingDynEntries) {
1008
RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
1009
if (rootSH && mOSHE) {
1010
int32_t index = rootSH->Index();
1011
rootSH->LegacySHistory()->RemoveDynEntries(index, mOSHE);
1012
}
1013
}
1014
1015
// Now make sure our editor, if any, is detached before we go
1016
// any farther.
1017
DetachEditorFromWindow();
1018
}
1019
}
1020
1021
nsresult nsDocShell::DispatchToTabGroup(
1022
TaskCategory aCategory, already_AddRefed<nsIRunnable>&& aRunnable) {
1023
// Hold the ref so we won't forget to release it.
1024
nsCOMPtr<nsIRunnable> runnable(aRunnable);
1025
nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
1026
if (!win) {
1027
// Window should only be unavailable after destroyed.
1028
MOZ_ASSERT(mIsBeingDestroyed);
1029
return NS_ERROR_FAILURE;
1030
}
1031
1032
if (win->GetDocGroup()) {
1033
return win->GetDocGroup()->Dispatch(aCategory, runnable.forget());
1034
}
1035
1036
return SchedulerGroup::Dispatch(aCategory, runnable.forget());
1037
}
1038
1039
NS_IMETHODIMP
1040
nsDocShell::DispatchLocationChangeEvent() {
1041
return DispatchToTabGroup(
1042
TaskCategory::Other,
1043
NewRunnableMethod("nsDocShell::FireDummyOnLocationChange", this,
1044
&nsDocShell::FireDummyOnLocationChange));
1045
}
1046
1047
NS_IMETHODIMP
1048
nsDocShell::StartDelayedAutoplayMediaComponents() {
1049
RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow();
1050
if (outerWindow) {
1051
outerWindow->SetMediaSuspend(nsISuspendedTypes::NONE_SUSPENDED);
1052
}
1053
return NS_OK;
1054
}
1055
1056
bool nsDocShell::MaybeInitTiming() {
1057
if (mTiming && !mBlankTiming) {
1058
return false;
1059
}
1060
1061
bool canBeReset = false;
1062
1063
if (mScriptGlobal && mBlankTiming) {
1064
nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
1065
if (innerWin && innerWin->GetPerformance()) {
1066
mTiming = innerWin->GetPerformance()->GetDOMTiming();
1067
mBlankTiming = false;
1068
}
1069
}
1070
1071
if (!mTiming) {
1072
mTiming = new nsDOMNavigationTiming(this);
1073
canBeReset = true;
1074
}
1075
1076
mTiming->NotifyNavigationStart(
1077
mBrowsingContext->GetIsActive()
1078
? nsDOMNavigationTiming::DocShellState::eActive
1079
: nsDOMNavigationTiming::DocShellState::eInactive);
1080
1081
return canBeReset;
1082
}
1083
1084
void nsDocShell::MaybeResetInitTiming(bool aReset) {
1085
if (aReset) {
1086
mTiming = nullptr;
1087
}
1088
}
1089
1090
nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const {
1091
return mTiming;
1092
}
1093
1094
//
1095
// Bug 13871: Prevent frameset spoofing
1096
//
1097
// This routine answers: 'Is origin's document from same domain as
1098
// target's document?'
1099
//
1100
// file: uris are considered the same domain for the purpose of
1101
// frame navigation regardless of script accessibility (bug 420425)
1102
//
1103
/* static */
1104
bool nsDocShell::ValidateOrigin(BrowsingContext* aOrigin,
1105
BrowsingContext* aTarget) {
1106
nsIDocShell* originDocShell = aOrigin->GetDocShell();
1107
MOZ_ASSERT(originDocShell, "originDocShell must not be null");
1108
Document* originDocument = originDocShell->GetDocument();
1109
NS_ENSURE_TRUE(originDocument, false);
1110
1111
nsIDocShell* targetDocShell = aTarget->GetDocShell();
1112
MOZ_ASSERT(targetDocShell, "targetDocShell must not be null");
1113
Document* targetDocument = targetDocShell->GetDocument();
1114
NS_ENSURE_TRUE(targetDocument, false);
1115
1116
bool equal;
1117
nsresult rv = originDocument->NodePrincipal()->Equals(
1118
targetDocument->NodePrincipal(), &equal);
1119
if (NS_SUCCEEDED(rv) && equal) {
1120
return true;
1121
}
1122
1123
// Not strictly equal, special case if both are file: uris
1124
nsCOMPtr<nsIURI> originURI;
1125
nsCOMPtr<nsIURI> targetURI;
1126
nsCOMPtr<nsIURI> innerOriginURI;
1127
nsCOMPtr<nsIURI> innerTargetURI;
1128
1129
rv = originDocument->NodePrincipal()->GetURI(getter_AddRefs(originURI));
1130
if (NS_SUCCEEDED(rv) && originURI) {
1131
innerOriginURI = NS_GetInnermostURI(originURI);
1132
}
1133
1134
rv = targetDocument->NodePrincipal()->GetURI(getter_AddRefs(targetURI));
1135
if (NS_SUCCEEDED(rv) && targetURI) {
1136
innerTargetURI = NS_GetInnermostURI(targetURI);
1137
}
1138
1139
return innerOriginURI && innerTargetURI && SchemeIsFile(innerOriginURI) &&
1140
SchemeIsFile(innerTargetURI);
1141
}
1142
1143
nsPresContext* nsDocShell::GetEldestPresContext() {
1144
nsIContentViewer* viewer = mContentViewer;
1145
while (viewer) {
1146
nsIContentViewer* prevViewer = viewer->GetPreviousViewer();
1147
if (!prevViewer) {
1148
return viewer->GetPresContext();
1149
}
1150
viewer = prevViewer;
1151
}
1152
1153
return nullptr;
1154
}
1155
1156
nsPresContext* nsDocShell::GetPresContext() {
1157
if (!mContentViewer) {
1158
return nullptr;
1159
}
1160
1161
return mContentViewer->GetPresContext();
1162
}
1163
1164
PresShell* nsDocShell::GetPresShell() {
1165
nsPresContext* presContext = GetPresContext();
1166
return presContext ? presContext->GetPresShell() : nullptr;
1167
}
1168
1169
PresShell* nsDocShell::GetEldestPresShell() {
1170
nsPresContext* presContext = GetEldestPresContext();
1171
1172
if (presContext) {
1173
return presContext->GetPresShell();
1174
}
1175
1176
return nullptr;
1177
}
1178
1179
NS_IMETHODIMP
1180
nsDocShell::GetContentViewer(nsIContentViewer** aContentViewer) {
1181
NS_ENSURE_ARG_POINTER(aContentViewer);
1182
1183
*aContentViewer = mContentViewer;
1184
NS_IF_ADDREF(*aContentViewer);
1185
return NS_OK;
1186
}
1187
1188
NS_IMETHODIMP
1189
nsDocShell::GetOuterWindowID(uint64_t* aWindowID) {
1190
*aWindowID = mContentWindowID;
1191
return NS_OK;
1192
}
1193
1194
NS_IMETHODIMP
1195
nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) {
1196
mChromeEventHandler = aChromeEventHandler;
1197
1198
if (mScriptGlobal) {
1199
mScriptGlobal->SetChromeEventHandler(mChromeEventHandler);
1200
}
1201
1202
return NS_OK;
1203
}
1204
1205
NS_IMETHODIMP
1206
nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) {
1207
NS_ENSURE_ARG_POINTER(aChromeEventHandler);
1208
RefPtr<EventTarget> handler = mChromeEventHandler;
1209
handler.forget(aChromeEventHandler);
1210
return NS_OK;
1211
}
1212
1213
NS_IMETHODIMP
1214
nsDocShell::SetCurrentURI(nsIURI* aURI) {
1215
// Note that securityUI will set STATE_IS_INSECURE, even if
1216
// the scheme of |aURI| is "https".
1217
SetCurrentURI(aURI, nullptr, true, 0);
1218
return NS_OK;
1219
}
1220
1221
bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
1222
bool aFireOnLocationChange,
1223
uint32_t aLocationFlags) {
1224
MOZ_ASSERT(!mIsBeingDestroyed);
1225
1226
MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,
1227
("DOCSHELL %p SetCurrentURI %s\n", this,
1228
aURI ? aURI->GetSpecOrDefault().get() : ""));
1229
1230
// We don't want to send a location change when we're displaying an error
1231
// page, and we don't want to change our idea of "current URI" either
1232
if (mLoadType == LOAD_ERROR_PAGE) {
1233
return false;
1234
}
1235
1236
bool uriIsEqual = false;
1237
if (!mCurrentURI || !aURI ||
1238
NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual)) || !uriIsEqual) {
1239
mTitleValidForCurrentURI = false;
1240
}
1241
1242
mCurrentURI = aURI;
1243
1244
#ifdef DEBUG
1245
mLastOpenedURI = aURI;
1246
#endif
1247
1248
if (!NS_IsAboutBlank(mCurrentURI)) {
1249
mHasLoadedNonBlankURI = true;
1250
}
1251
1252
bool isRoot = mBrowsingContext->IsTop();
1253
bool isSubFrame = false; // Is this a subframe navigation?
1254
1255
if (mLSHE) {
1256
isSubFrame = mLSHE->GetIsSubFrame();
1257
}
1258
1259
if (!isSubFrame && !isRoot) {
1260
/*
1261
* We don't want to send OnLocationChange notifications when
1262
* a subframe is being loaded for the first time, while
1263
* visiting a frameset page
1264
*/
1265
return false;
1266
}
1267
1268
if (aFireOnLocationChange) {
1269
FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
1270
}
1271
return !aFireOnLocationChange;
1272
}
1273
1274
NS_IMETHODIMP
1275
nsDocShell::GetCharset(nsACString& aCharset) {
1276
aCharset.Truncate();
1277
1278
PresShell* presShell = GetPresShell();
1279
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
1280
Document* doc = presShell->GetDocument();
1281
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
1282
doc->GetDocumentCharacterSet()->Name(aCharset);
1283
return NS_OK;
1284
}
1285
1286
NS_IMETHODIMP
1287
nsDocShell::GatherCharsetMenuTelemetry() {
1288
nsCOMPtr<nsIContentViewer> viewer;
1289
GetContentViewer(getter_AddRefs(viewer));
1290
if (!viewer) {
1291
return NS_OK;
1292
}
1293
1294
Document* doc = viewer->GetDocument();
1295
if (!doc || doc->WillIgnoreCharsetOverride()) {
1296
return NS_OK;
1297
}
1298
1299
Telemetry::ScalarSet(Telemetry::ScalarID::ENCODING_OVERRIDE_USED, true);
1300
1301
nsIURI* url = doc->GetOriginalURI();
1302
bool isFileURL = url && SchemeIsFile(url);
1303
1304
int32_t charsetSource = doc->GetDocumentCharacterSetSource();
1305
switch (charsetSource) {
1306
case kCharsetFromTopLevelDomain:
1307
// Unlabeled doc on a domain that we map to a fallback encoding
1308
Telemetry::AccumulateCategorical(
1309
Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION::RemoteTld);
1310
break;
1311
case kCharsetFromFallback:
1312
case kCharsetFromDocTypeDefault:
1313
case kCharsetFromCache:
1314
case kCharsetFromParentFrame:
1315
// Changing charset on an unlabeled doc.
1316
if (isFileURL) {
1317
Telemetry::AccumulateCategorical(
1318
Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION::Local);
1319
} else {
1320
Telemetry::AccumulateCategorical(
1321
Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION::RemoteNonTld);
1322
}
1323
break;
1324
case kCharsetFromInitialAutoDetection:
1325
case kCharsetFromFinalAutoDetection:
1326
// Changing charset on unlabeled doc where chardet fired
1327
if (isFileURL) {
1328
Telemetry::AccumulateCategorical(
1329
Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION::LocalChardet);
1330
} else {
1331
Telemetry::AccumulateCategorical(
1332
Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION::RemoteChardet);
1333
}
1334
break;
1335
case kCharsetFromMetaPrescan:
1336
case kCharsetFromMetaTag:
1337
case kCharsetFromChannel:
1338
// Changing charset on a doc that had a charset label.
1339
Telemetry::AccumulateCategorical(
1340
Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION::Labeled);
1341
break;
1342
case kCharsetFromParentForced:
1343
case kCharsetFromUserForced:
1344
// Changing charset on a document that already had an override.
1345
Telemetry::AccumulateCategorical(
1346
Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION::AlreadyOverridden);
1347
break;
1348
case kCharsetFromIrreversibleAutoDetection:
1349
case kCharsetFromOtherComponent:
1350
case kCharsetFromByteOrderMark:
1351
case kCharsetUninitialized:
1352
default:
1353
// Bug. This isn't supposed to happen.
1354
Telemetry::AccumulateCategorical(
1355
Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION::Bug);
1356
break;
1357
}
1358
return NS_OK;
1359
}
1360
1361
NS_IMETHODIMP
1362
nsDocShell::SetCharset(const nsACString& aCharset) {
1363
// set the charset override
1364
return SetForcedCharset(aCharset);
1365
}
1366
1367
NS_IMETHODIMP
1368
nsDocShell::SetForcedCharset(const nsACString& aCharset) {
1369
if (aCharset.IsEmpty()) {
1370
mForcedCharset = nullptr;
1371
return NS_OK;
1372
}
1373
const Encoding* encoding = Encoding::ForLabel(aCharset);
1374
if (!encoding) {
1375
// Reject unknown labels
1376
return NS_ERROR_INVALID_ARG;
1377
}
1378
if (!encoding->IsAsciiCompatible() && encoding != ISO_2022_JP_ENCODING) {
1379
// Reject XSS hazards
1380
return NS_ERROR_INVALID_ARG;
1381
}
1382
mForcedCharset = encoding;
1383
return NS_OK;
1384
}
1385
1386
NS_IMETHODIMP
1387
nsDocShell::GetForcedCharset(nsACString& aResult) {
1388
if (mForcedCharset) {
1389
mForcedCharset->Name(aResult);
1390
} else {
1391
aResult.Truncate();
1392
}
1393
return NS_OK;
1394
}
1395
1396
void nsDocShell::SetParentCharset(const Encoding*& aCharset,
1397
int32_t aCharsetSource,
1398
nsIPrincipal* aPrincipal) {
1399
mParentCharset = aCharset;
1400
mParentCharsetSource = aCharsetSource;
1401
mParentCharsetPrincipal = aPrincipal;
1402
}
1403
1404
void nsDocShell::GetParentCharset(const Encoding*& aCharset,
1405
int32_t* aCharsetSource,
1406
nsIPrincipal** aPrincipal) {
1407
aCharset = mParentCharset;
1408
*aCharsetSource = mParentCharsetSource;
1409
NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal);
1410
}
1411
1412
NS_IMETHODIMP
1413
nsDocShell::GetHasMixedActiveContentLoaded(bool* aHasMixedActiveContentLoaded) {
1414
RefPtr<Document> doc(GetDocument());
1415
*aHasMixedActiveContentLoaded = doc && doc->GetHasMixedActiveContentLoaded();
1416
return NS_OK;
1417
}
1418
1419
NS_IMETHODIMP
1420
nsDocShell::GetHasMixedActiveContentBlocked(
1421
bool* aHasMixedActiveContentBlocked) {
1422
RefPtr<Document> doc(GetDocument());
1423
*aHasMixedActiveContentBlocked =
1424
doc && doc->GetHasMixedActiveContentBlocked();
1425
return NS_OK;
1426
}
1427
1428
NS_IMETHODIMP
1429
nsDocShell::GetHasMixedDisplayContentLoaded(
1430
bool* aHasMixedDisplayContentLoaded) {
1431
RefPtr<Document> doc(GetDocument());
1432
*aHasMixedDisplayContentLoaded =
1433
doc && doc->GetHasMixedDisplayContentLoaded();
1434
return NS_OK;
1435
}
1436
1437
NS_IMETHODIMP
1438
nsDocShell::GetHasMixedDisplayContentBlocked(
1439
bool* aHasMixedDisplayContentBlocked) {
1440
RefPtr<Document> doc(GetDocument());
1441
*aHasMixedDisplayContentBlocked =
1442
doc && doc->GetHasMixedDisplayContentBlocked();
1443
return NS_OK;
1444
}
1445
1446
NS_IMETHODIMP
1447
nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) {
1448
MOZ_ASSERT(aPromise);
1449
1450
ErrorResult rv;
1451
RefPtr<Document> doc(GetDocument());
1452
RefPtr<Promise> retPromise = Promise::Create(doc->GetOwnerGlobal(), rv);
1453
if (NS_WARN_IF(rv.Failed())) {
1454
return rv.StealNSResult();
1455
}
1456
1457
// Retrieve the document's content blocking events from the parent process.
1458
RefPtr<Document::GetContentBlockingEventsPromise> promise =
1459
doc->GetContentBlockingEvents();
1460
if (promise) {
1461
promise->Then(
1462
GetCurrentThreadSerialEventTarget(), __func__,
1463
[retPromise](const Document::GetContentBlockingEventsPromise::
1464
ResolveOrRejectValue& aValue) {
1465
if (aValue.IsResolve()) {
1466
bool has = aValue.ResolveValue() &
1467
nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT;
1468
retPromise->MaybeResolve(has);
1469
} else {
1470
retPromise->MaybeResolve(false);
1471
}
1472
});
1473
} else {
1474
retPromise->MaybeResolve(false);
1475
}
1476
1477
retPromise.forget(aPromise);
1478
return NS_OK;
1479
}
1480
1481
NS_IMETHODIMP
1482
nsDocShell::GetAllowPlugins(bool* aAllowPlugins) {
1483
NS_ENSURE_ARG_POINTER(aAllowPlugins);
1484
1485
*aAllowPlugins = mBrowsingContext->GetAllowPlugins();
1486
return NS_OK;
1487
}
1488
1489
NS_IMETHODIMP
1490
nsDocShell::SetAllowPlugins(bool aAllowPlugins) {
1491
mBrowsingContext->SetAllowPlugins(aAllowPlugins);
1492
// XXX should enable or disable a plugin host
1493
return NS_OK;
1494
}
1495
1496
NS_IMETHODIMP
1497
nsDocShell::GetAllowJavascript(bool* aAllowJavascript) {
1498
NS_ENSURE_ARG_POINTER(aAllowJavascript);
1499
1500
*aAllowJavascript = mAllowJavascript;
1501
return NS_OK;
1502
}
1503
1504
NS_IMETHODIMP
1505
nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) {
1506
MOZ_ASSERT(aEnabled);
1507
*aEnabled = mCSSErrorReportingEnabled;
1508
return NS_OK;
1509
}
1510
1511
NS_IMETHODIMP
1512
nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) {
1513
mCSSErrorReportingEnabled = aEnabled;
1514
return NS_OK;
1515
}
1516
1517
NS_IMETHODIMP
1518
nsDocShell::SetAllowJavascript(bool aAllowJavascript) {
1519
mAllowJavascript = aAllowJavascript;
1520
RecomputeCanExecuteScripts();
1521
return NS_OK;
1522
}
1523
1524
NS_IMETHODIMP
1525
nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
1526
NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing);
1527
AssertOriginAttributesMatchPrivateBrowsing();
1528
*aUsePrivateBrowsing = mPrivateBrowsingId > 0;
1529
return NS_OK;
1530
}
1531
1532
NS_IMETHODIMP
1533
nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) {
1534
if (!CanSetOriginAttributes()) {
1535
bool changed = aUsePrivateBrowsing != (mPrivateBrowsingId > 0);
1536
1537
return changed ? NS_ERROR_FAILURE : NS_OK;
1538
}
1539
1540
return SetPrivateBrowsing(aUsePrivateBrowsing);
1541
}
1542
1543
NS_IMETHODIMP
1544
nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) {
1545
MOZ_ASSERT(!mIsBeingDestroyed);
1546
1547
bool changed = aUsePrivateBrowsing != (mPrivateBrowsingId > 0);
1548
if (changed) {
1549
mPrivateBrowsingId = aUsePrivateBrowsing ? 1 : 0;
1550
1551
if (mItemType != typeChrome) {
1552
mOriginAttributes.SyncAttributesWithPrivateBrowsing(aUsePrivateBrowsing);
1553
}
1554
1555
if (mAffectPrivateSessionLifetime) {
1556
if (aUsePrivateBrowsing) {
1557
IncreasePrivateDocShellCount();
1558
} else {
1559
DecreasePrivateDocShellCount();
1560
}
1561
}
1562
}
1563
1564
nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
1565
while (iter.HasMore()) {
1566
nsCOMPtr<nsILoadContext> shell = do_QueryObject(iter.GetNext());
1567
if (shell) {
1568
shell->SetPrivateBrowsing(aUsePrivateBrowsing);
1569
}
1570
}
1571
1572
if (changed) {
1573
nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
1574
while (iter.HasMore()) {
1575
nsWeakPtr ref = iter.GetNext();
1576
nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
1577
if (!obs) {
1578
mPrivacyObservers.RemoveElement(ref);
1579
} else {
1580
obs->PrivateModeChanged(aUsePrivateBrowsing);
1581
}
1582
}
1583
}
1584
1585
AssertOriginAttributesMatchPrivateBrowsing();
1586
return NS_OK;
1587
}
1588
1589
NS_IMETHODIMP
1590
nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) {
1591
NS_ENSURE_ARG_POINTER(aResult);
1592
1593
*aResult = mHasLoadedNonBlankURI;
1594
return NS_OK;
1595
}
1596
1597
NS_IMETHODIMP
1598
nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) {
1599
NS_ENSURE_ARG_POINTER(aUseRemoteTabs);
1600
1601
*aUseRemoteTabs = mUseRemoteTabs;
1602
return NS_OK;
1603
}
1604
1605
NS_IMETHODIMP
1606
nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) {
1607
if (aUseRemoteTabs) {
1608
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::DOMIPCEnabled,
1609
true);
1610
}
1611
1612
// Don't allow non-remote tabs with remote subframes.
1613
if (NS_WARN_IF(!aUseRemoteTabs && mUseRemoteSubframes)) {
1614
return NS_ERROR_UNEXPECTED;
1615
}
1616
1617
mUseRemoteTabs = aUseRemoteTabs;
1618
return NS_OK;
1619
}
1620
1621
NS_IMETHODIMP
1622
nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
1623
NS_ENSURE_ARG_POINTER(aUseRemoteSubframes);
1624
1625
*aUseRemoteSubframes = mUseRemoteSubframes;
1626
return NS_OK;
1627
}
1628
1629
NS_IMETHODIMP
1630
nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) {
1631
static bool annotated = false;
1632
1633
if (aUseRemoteSubframes && !annotated) {
1634
annotated = true;
1635
CrashReporter::AnnotateCrashReport(
1636
CrashReporter::Annotation::DOMFissionEnabled, true);
1637
}
1638
1639
// Don't allow non-remote tabs with remote subframes.
1640
if (NS_WARN_IF(aUseRemoteSubframes && !mUseRemoteTabs)) {
1641
return NS_ERROR_UNEXPECTED;
1642
}
1643
1644
mUseRemoteSubframes = aUseRemoteSubframes;
1645
return NS_OK;
1646
}
1647
1648
NS_IMETHODIMP
1649
nsDocShell::SetAffectPrivateSessionLifetime(bool aAffectLifetime) {
1650
MOZ_ASSERT(!mIsBeingDestroyed);
1651
1652
bool change = aAffectLifetime != mAffectPrivateSessionLifetime;
1653
if (change && UsePrivateBrowsing()) {
1654
AssertOriginAttributesMatchPrivateBrowsing();
1655
if (aAffectLifetime) {
1656
IncreasePrivateDocShellCount();
1657
} else {
1658
DecreasePrivateDocShellCount();
1659
}
1660
}
1661
mAffectPrivateSessionLifetime = aAffectLifetime;
1662
1663
nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
1664
while (iter.HasMore()) {
1665
nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
1666
if (shell) {
1667
shell->SetAffectPrivateSessionLifetime(aAffectLifetime);
1668
}
1669
}
1670
return NS_OK;
1671
}
1672
1673
NS_IMETHODIMP
1674
nsDocShell::GetAffectPrivateSessionLifetime(bool* aAffectLifetime) {
1675
*aAffectLifetime = mAffectPrivateSessionLifetime;
1676
return NS_OK;
1677
}
1678
1679
NS_IMETHODIMP
1680
nsDocShell::AddWeakPrivacyTransitionObserver(
1681
nsIPrivacyTransitionObserver* aObserver) {
1682
nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1683
if (!weakObs) {
1684
return NS_ERROR_NOT_AVAILABLE;
1685
}
1686
mPrivacyObservers.AppendElement(weakObs);
1687
return NS_OK;
1688
}
1689
1690
NS_IMETHODIMP
1691
nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) {
1692
nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1693
if (!weakObs) {
1694
return NS_ERROR_FAILURE;
1695
}
1696
mReflowObservers.AppendElement(weakObs);
1697
return NS_OK;
1698
}
1699
1700
NS_IMETHODIMP
1701
nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) {
1702
nsWeakPtr obs = do_GetWeakReference(aObserver);
1703
return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
1704
}
1705
1706
NS_IMETHODIMP
1707
nsDocShell::NotifyReflowObservers(bool aInterruptible,
1708
DOMHighResTimeStamp aStart,
1709
DOMHighResTimeStamp aEnd) {
1710
nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers);
1711
while (iter.HasMore()) {
1712
nsWeakPtr ref = iter.GetNext();
1713
nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref);
1714
if (!obs) {
1715
mReflowObservers.RemoveElement(ref);
1716
} else if (aInterruptible) {
1717
obs->ReflowInterruptible(aStart, aEnd);
1718
} else {
1719
obs->Reflow(aStart, aEnd);
1720
}
1721
}
1722
return NS_OK;
1723
}
1724
1725
NS_IMETHODIMP
1726
nsDocShell::GetAllowMetaRedirects(bool* aReturn) {
1727
NS_ENSURE_ARG_POINTER(aReturn);
1728
1729
*aReturn = mAllowMetaRedirects;
1730
return NS_OK;
1731
}
1732
1733
NS_IMETHODIMP
1734
nsDocShell::SetAllowMetaRedirects(bool aValue) {
1735
mAllowMetaRedirects = aValue;
1736
return NS_OK;
1737
}
1738
1739
NS_IMETHODIMP
1740
nsDocShell::GetAllowSubframes(bool* aAllowSubframes) {
1741
NS_ENSURE_ARG_POINTER(aAllowSubframes);
1742
1743
*aAllowSubframes = mAllowSubframes;
1744
return NS_OK;
1745
}
1746
1747
NS_IMETHODIMP
1748
nsDocShell::SetAllowSubframes(bool aAllowSubframes) {
1749
mAllowSubframes = aAllowSubframes;
1750
return NS_OK;
1751
}
1752
1753
NS_IMETHODIMP
1754
nsDocShell::GetAllowImages(bool* aAllowImages) {
1755
NS_ENSURE_ARG_POINTER(aAllowImages);
1756
1757
*aAllowImages = mAllowImages;
1758
return NS_OK;
1759
}
1760
1761
NS_IMETHODIMP
1762
nsDocShell::SetAllowImages(bool aAllowImages) {
1763
mAllowImages = aAllowImages;
1764
return NS_OK;
1765
}
1766
1767
NS_IMETHODIMP
1768
nsDocShell::GetAllowMedia(bool* aAllowMedia) {
1769
*aAllowMedia = mAllowMedia;
1770
return NS_OK;
1771
}
1772
1773
NS_IMETHODIMP
1774
nsDocShell::SetAllowMedia(bool aAllowMedia) {
1775
mAllowMedia = aAllowMedia;
1776
1777
// Mute or unmute audio contexts attached to the inner window.
1778
if (mScriptGlobal) {
1779
if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) {
1780
if (aAllowMedia) {
1781
innerWin->UnmuteAudioContexts();
1782
} else {
1783
innerWin->MuteAudioContexts();
1784
}
1785
}
1786
}
1787
1788
return NS_OK;
1789
}
1790
1791
NS_IMETHODIMP
1792
nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) {
1793
*aAllowDNSPrefetch = mAllowDNSPrefetch;
1794
return NS_OK;
1795
}
1796
1797
NS_IMETHODIMP
1798
nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) {
1799
mAllowDNSPrefetch = aAllowDNSPrefetch;
1800
return NS_OK;
1801
}
1802
1803
NS_IMETHODIMP
1804
nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) {
1805
*aAllowWindowControl = mAllowWindowControl;
1806
return NS_OK;
1807
}
1808
1809
NS_IMETHODIMP
1810
nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) {
1811
mAllowWindowControl = aAllowWindowControl;
1812
return NS_OK;
1813
}
1814
1815
NS_IMETHODIMP
1816
nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) {
1817
*aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting();
1818
return NS_OK;
1819
}
1820
1821
NS_IMETHODIMP
1822
nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) {
1823
mBrowsingContext->SetAllowContentRetargeting(aAllowContentRetargeting);
1824
return NS_OK;
1825
}
1826
1827
NS_IMETHODIMP
1828
nsDocShell::GetAllowContentRetargetingOnChildren(
1829
bool* aAllowContentRetargetingOnChildren) {
1830
*aAllowContentRetargetingOnChildren =
1831
mBrowsingContext->GetAllowContentRetargetingOnChildren();
1832
return NS_OK;
1833
}
1834
1835
NS_IMETHODIMP
1836
nsDocShell::SetAllowContentRetargetingOnChildren(
1837
bool aAllowContentRetargetingOnChildren) {
1838
mBrowsingContext->SetAllowContentRetargetingOnChildren(
1839
aAllowContentRetargetingOnChildren);
1840
return NS_OK;
1841
}
1842
1843
NS_IMETHODIMP
1844
nsDocShell::GetInheritPrivateBrowsingId(bool* aInheritPrivateBrowsingId) {
1845
*aInheritPrivateBrowsingId = mInheritPrivateBrowsingId;
1846
return NS_OK;
1847
}
1848
1849
NS_IMETHODIMP
1850
nsDocShell::SetInheritPrivateBrowsingId(bool aInheritPrivateBrowsingId) {
1851
mInheritPrivateBrowsingId = aInheritPrivateBrowsingId;
1852
return NS_OK;
1853
}
1854
1855
NS_IMETHODIMP
1856
nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed) {
1857
NS_ENSURE_ARG_POINTER(aFullscreenAllowed);
1858
1859
// Browsers and apps have their mFullscreenAllowed retrieved from their
1860
// corresponding iframe in their parent upon creation.
1861
if (mFullscreenAllowed != CHECK_ATTRIBUTES) {
1862
*aFullscreenAllowed = (mFullscreenAllowed == PARENT_ALLOWS);
1863
return NS_OK;
1864
}
1865
1866
// Assume false until we determine otherwise...
1867
*aFullscreenAllowed = false;
1868
1869
nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
1870
if (!win) {
1871
return NS_OK;
1872
}
1873
if (nsCOMPtr<Element> frameElement = win->GetFrameElementInternal()) {
1874
if (frameElement->IsXULElement()) {
1875
if (frameElement->HasAttr(kNameSpaceID_None,
1876
nsGkAtoms::disablefullscreen)) {
1877
// Document inside this frame is explicitly disabled.
1878
return NS_OK;
1879
}
1880
} else {
1881
// We do not allow document inside any containing element other
1882
// than iframe to enter fullscreen.
1883
if (frameElement->IsHTMLElement(nsGkAtoms::iframe)) {
1884
// If any ancestor iframe does not have allowfullscreen attribute
1885
// set, then fullscreen is not allowed.
1886
if (!frameElement->HasAttr(kNameSpaceID_None,
1887
nsGkAtoms::allowfullscreen) &&
1888
!frameElement->HasAttr(kNameSpaceID_None,
1889
nsGkAtoms::mozallowfullscreen)) {
1890
return NS_OK;
1891
}
1892
} else if (frameElement->IsHTMLElement(nsGkAtoms::embed)) {
1893
// Respect allowfullscreen only if this is a rewritten YouTube embed.
1894
nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent =
1895
do_QueryInterface(frameElement);
1896
if (!objectLoadingContent) {
1897
return NS_OK;
1898
}
1899
nsObjectLoadingContent* olc =
1900
static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
1901
if (!olc->IsRewrittenYoutubeEmbed()) {
1902
return NS_OK;
1903
}
1904
// We don't have to check prefixed attributes because Flash does not
1905
// support them.
1906
if (!frameElement->HasAttr(kNameSpaceID_None,
1907
nsGkAtoms::allowfullscreen)) {
1908
return NS_OK;
1909
}
1910
} else {
1911
// neither iframe nor embed
1912
return NS_OK;
1913
}
1914
}
1915
}
1916
1917
// If we have no parent then we're the root docshell; no ancestor of the
1918
// original docshell doesn't have a allowfullscreen attribute, so
1919
// report fullscreen as allowed.
1920
RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
1921
if (!parent) {
1922
*aFullscreenAllowed = true;
1923
return NS_OK;
1924
}
1925
1926
// Otherwise, we have a parent, continue the checking for
1927
// mozFullscreenAllowed in the parent docshell's ancestors.
1928
return parent->GetFullscreenAllowed(aFullscreenAllowed);
1929
}
1930
1931
NS_IMETHODIMP
1932
nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed) {
1933
if (!nsIDocShell::GetIsMozBrowser()) {
1934
// Only allow setting of fullscreenAllowed on content/process boundaries.
1935
// At non-boundaries the fullscreenAllowed attribute is calculated based on
1936
// whether all enclosing frames have the "mozFullscreenAllowed" attribute
1937
// set to "true". fullscreenAllowed is set at the process boundaries to
1938
// propagate the value of the parent's "mozFullscreenAllowed" attribute
1939
// across process boundaries.
1940
return NS_ERROR_UNEXPECTED;