Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/chrome/nsChromeProtocolHandler.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* vim:set ts=4 sw=4 sts=4 et cin: */
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
/*
8
9
  A protocol handler for ``chrome:''
10
11
*/
12
13
#include "nsChromeProtocolHandler.h"
14
#include "nsChromeRegistry.h"
15
#include "nsCOMPtr.h"
16
#include "nsContentUtils.h"
17
#include "nsThreadUtils.h"
18
#include "nsIChannel.h"
19
#include "nsIChromeRegistry.h"
20
#include "nsIFile.h"
21
#include "nsIFileChannel.h"
22
#include "nsIIOService.h"
23
#include "nsILoadGroup.h"
24
#include "nsIScriptSecurityManager.h"
25
#include "nsIStandardURL.h"
26
#include "nsNetUtil.h"
27
#include "nsNetCID.h"
28
#include "nsIURL.h"
29
#include "nsString.h"
30
#include "nsStandardURL.h"
31
32
////////////////////////////////////////////////////////////////////////////////
33
34
NS_IMPL_ISUPPORTS(nsChromeProtocolHandler,
35
                  nsIProtocolHandler,
36
                  nsISupportsWeakReference)
37
38
////////////////////////////////////////////////////////////////////////////////
39
// nsIProtocolHandler methods:
40
41
NS_IMETHODIMP
42
nsChromeProtocolHandler::GetScheme(nsACString &result)
43
0
{
44
0
    result.AssignLiteral("chrome");
45
0
    return NS_OK;
46
0
}
47
48
NS_IMETHODIMP
49
nsChromeProtocolHandler::GetDefaultPort(int32_t *result)
50
0
{
51
0
    *result = -1;        // no port for chrome: URLs
52
0
    return NS_OK;
53
0
}
54
55
NS_IMETHODIMP
56
nsChromeProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
57
0
{
58
0
    // don't override anything.
59
0
    *_retval = false;
60
0
    return NS_OK;
61
0
}
62
63
NS_IMETHODIMP
64
nsChromeProtocolHandler::GetProtocolFlags(uint32_t *result)
65
24
{
66
24
    *result = URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE;
67
24
    return NS_OK;
68
24
}
69
70
NS_IMETHODIMP
71
nsChromeProtocolHandler::NewURI(const nsACString &aSpec,
72
                                const char *aCharset,
73
                                nsIURI *aBaseURI,
74
                                nsIURI **result)
75
26.6k
{
76
26.6k
77
26.6k
    // Chrome: URLs (currently) have no additional structure beyond that provided
78
26.6k
    // by standard URLs, so there is no "outer" given to CreateInstance
79
26.6k
    nsresult rv;
80
26.6k
    nsCOMPtr<nsIURI> surl;
81
26.6k
    nsCOMPtr<nsIURI> base(aBaseURI);
82
26.6k
    rv = NS_MutateURI(new mozilla::net::nsStandardURL::Mutator())
83
26.6k
           .Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
84
26.6k
                                   nsIStandardURL::URLTYPE_STANDARD,
85
26.6k
                                   -1, nsCString(aSpec), aCharset,
86
26.6k
                                   base, nullptr))
87
26.6k
           .Finalize(surl);
88
26.6k
    if (NS_FAILED(rv)) {
89
442
        return rv;
90
442
    }
91
26.2k
92
26.2k
    // Canonify the "chrome:" URL; e.g., so that we collapse
93
26.2k
    // "chrome://navigator/content/" and "chrome://navigator/content"
94
26.2k
    // and "chrome://navigator/content/navigator.xul".
95
26.2k
96
26.2k
    rv = nsChromeRegistry::Canonify(surl);
97
26.2k
    if (NS_FAILED(rv))
98
26.2k
        return rv;
99
7.16k
100
7.16k
    surl.forget(result);
101
7.16k
    return NS_OK;
102
7.16k
}
103
104
NS_IMETHODIMP
105
nsChromeProtocolHandler::NewChannel2(nsIURI* aURI,
106
                                     nsILoadInfo* aLoadInfo,
107
                                     nsIChannel** aResult)
108
0
{
109
0
    nsresult rv;
110
0
111
0
    NS_ENSURE_ARG_POINTER(aURI);
112
0
    NS_ENSURE_ARG_POINTER(aLoadInfo);
113
0
114
0
    MOZ_ASSERT(aResult, "Null out param");
115
0
116
#ifdef DEBUG
117
    // Check that the uri we got is already canonified
118
    nsresult debug_rv;
119
    nsCOMPtr<nsIURI> debugURL = aURI;
120
    debug_rv = nsChromeRegistry::Canonify(debugURL);
121
    if (NS_SUCCEEDED(debug_rv)) {
122
        bool same;
123
        debug_rv = aURI->Equals(debugURL, &same);
124
        if (NS_SUCCEEDED(debug_rv)) {
125
            NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!");
126
        }
127
    }
128
#endif
129
130
0
    nsCOMPtr<nsIChannel> result;
131
0
132
0
    if (!nsChromeRegistry::gChromeRegistry) {
133
0
        // We don't actually want this ref, we just want the service to
134
0
        // initialize if it hasn't already.
135
0
        nsCOMPtr<nsIChromeRegistry> reg =
136
0
            mozilla::services::GetChromeRegistryService();
137
0
        NS_ENSURE_TRUE(nsChromeRegistry::gChromeRegistry, NS_ERROR_FAILURE);
138
0
    }
139
0
140
0
    nsCOMPtr<nsIURI> resolvedURI;
141
0
    rv = nsChromeRegistry::gChromeRegistry->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI));
142
0
    if (NS_FAILED(rv)) {
143
#ifdef DEBUG
144
        printf("Couldn't convert chrome URL: %s\n",
145
               aURI->GetSpecOrDefault().get());
146
#endif
147
        return rv;
148
0
    }
149
0
150
0
    // We don't want to allow the inner protocol handler modify the result principal URI
151
0
    // since we want either |aURI| or anything pre-set by upper layers to prevail.
152
0
    nsCOMPtr<nsIURI> savedResultPrincipalURI;
153
0
    rv = aLoadInfo->GetResultPrincipalURI(getter_AddRefs(savedResultPrincipalURI));
154
0
    NS_ENSURE_SUCCESS(rv, rv);
155
0
156
0
    rv = NS_NewChannelInternal(getter_AddRefs(result),
157
0
                               resolvedURI,
158
0
                               aLoadInfo);
159
0
    NS_ENSURE_SUCCESS(rv, rv);
160
0
161
#ifdef DEBUG
162
    nsCOMPtr<nsIFileChannel> fileChan(do_QueryInterface(result));
163
    if (fileChan) {
164
        nsCOMPtr<nsIFile> file;
165
        fileChan->GetFile(getter_AddRefs(file));
166
167
        bool exists = false;
168
        file->Exists(&exists);
169
        if (!exists) {
170
            printf("Chrome file doesn't exist: %s\n",
171
                   file->HumanReadablePath().get());
172
        }
173
    }
174
#endif
175
176
0
    // Make sure that the channel remembers where it was
177
0
    // originally loaded from.
178
0
    rv = aLoadInfo->SetResultPrincipalURI(savedResultPrincipalURI);
179
0
    NS_ENSURE_SUCCESS(rv, rv);
180
0
    rv = result->SetOriginalURI(aURI);
181
0
    if (NS_FAILED(rv)) return rv;
182
0
183
0
    // Get a system principal for content files and set the owner
184
0
    // property of the result
185
0
    nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
186
0
    nsAutoCString path;
187
0
    rv = url->GetPathQueryRef(path);
188
0
    if (StringBeginsWith(path, NS_LITERAL_CSTRING("/content/"))) {
189
0
        result->SetOwner(nsContentUtils::GetSystemPrincipal());
190
0
    }
191
0
192
0
    // XXX Removed dependency-tracking code from here, because we're not
193
0
    // tracking them anyways (with fastload we checked only in DEBUG
194
0
    // and with startupcache not at all), but this is where we would start
195
0
    // if we need to re-add.
196
0
    // See bug 531886, bug 533038.
197
0
    result->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
198
0
199
0
    *aResult = result;
200
0
    NS_ADDREF(*aResult);
201
0
    return NS_OK;
202
0
}
203
204
NS_IMETHODIMP
205
nsChromeProtocolHandler::NewChannel(nsIURI* aURI,
206
                                    nsIChannel* *aResult)
207
0
{
208
0
  return NewChannel2(aURI, nullptr, aResult);
209
0
}
210
211
////////////////////////////////////////////////////////////////////////////////