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