summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/extensions/resource_request_policy.cc
blob: 116b218d1541e1e3319044924f177c73ac3c09ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/renderer/extensions/resource_request_policy.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/icons/icons_handler.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_set.h"
#include "chrome/common/extensions/manifest_url_handler.h"
#include "chrome/common/extensions/web_accessible_resources_handler.h"
#include "chrome/common/url_constants.h"
#include "content/public/common/page_transition_types.h"
#include "extensions/common/constants.h"
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"

namespace extensions {

// This method does a security check whether chrome-extension:// URLs can be
// requested by the renderer. Since this is in an untrusted process, the browser
// has a similar check to enforce the policy, in case this process is exploited.
// If you are changing this function, ensure equivalent checks are added to
// extension_protocols.cc's AllowExtensionResourceLoad.

// static
bool ResourceRequestPolicy::CanRequestResource(
    const GURL& resource_url,
    WebKit::WebFrame* frame,
    content::PageTransition transition_type,
    const ExtensionSet* loaded_extensions) {
  CHECK(resource_url.SchemeIs(extensions::kExtensionScheme));

  const Extension* extension =
      loaded_extensions->GetExtensionOrAppByURL(ExtensionURLInfo(resource_url));
  if (!extension) {
    // Allow the load in the case of a non-existent extension. We'll just get a
    // 404 from the browser process.
    return true;
  }

  // Disallow loading of packaged resources for hosted apps. We don't allow
  // hybrid hosted/packaged apps. The one exception is access to icons, since
  // some extensions want to be able to do things like create their own
  // launchers.
  std::string resource_root_relative_path =
      resource_url.path().empty() ? "" : resource_url.path().substr(1);
  if (extension->is_hosted_app() &&
      !IconsInfo::GetIcons(extension)
          .ContainsPath(resource_root_relative_path)) {
    LOG(ERROR) << "Denying load of " << resource_url.spec() << " from "
               << "hosted app.";
    return false;
  }

  // Disallow loading of extension resources which are not explicitly listed
  // as web accessible if the manifest version is 2 or greater.
  if (!WebAccessibleResourcesInfo::IsResourceWebAccessible(
          extension, resource_url.path()) &&
      !CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableExtensionsResourceWhitelist)) {
    GURL frame_url = frame->document().url();
    GURL page_url = frame->top()->document().url();

    // Exceptions are:
    // - empty origin (needed for some edge cases when we have empty origins)
    bool is_empty_origin = frame_url.is_empty();
    // - extensions requesting their own resources (frame_url check is for
    //     images, page_url check is for iframes)
    bool is_own_resource = frame_url.GetOrigin() == extension->url() ||
        page_url.GetOrigin() == extension->url();
    // - devtools (chrome-extension:// URLs are loaded into frames of devtools
    //     to support the devtools extension APIs)
    bool is_dev_tools = page_url.SchemeIs(chrome::kChromeDevToolsScheme) &&
                        !ManifestURL::GetDevToolsPage(extension).is_empty();
    bool transition_allowed =
        !content::PageTransitionIsWebTriggerable(transition_type);
    // - unreachable web page error page (to allow showing the icon of the
    //   unreachable app on this page)
    bool is_error_page = frame_url == GURL(content::kUnreachableWebDataURL);

    if (!is_empty_origin && !is_own_resource &&
        !is_dev_tools && !transition_allowed && !is_error_page) {
      std::string message = base::StringPrintf(
          "Denying load of %s. Resources must be listed in the "
          "web_accessible_resources manifest key in order to be loaded by "
          "pages outside the extension.",
          resource_url.spec().c_str());
      frame->addMessageToConsole(
          WebKit::WebConsoleMessage(WebKit::WebConsoleMessage::LevelError,
                                    WebKit::WebString::fromUTF8(message)));
      return false;
    }
  }

  return true;
}

// static
bool ResourceRequestPolicy::CanRequestExtensionResourceScheme(
    const GURL& resource_url,
    WebKit::WebFrame* frame) {
  CHECK(resource_url.SchemeIs(chrome::kExtensionResourceScheme));

  GURL frame_url = frame->document().url();
  if (!frame_url.is_empty() &&
      !frame_url.SchemeIs(extensions::kExtensionScheme)) {
    std::string message = base::StringPrintf(
        "Denying load of %s. chrome-extension-resources:// can only be "
        "loaded from extensions.",
      resource_url.spec().c_str());
    frame->addMessageToConsole(
        WebKit::WebConsoleMessage(WebKit::WebConsoleMessage::LevelError,
                                  WebKit::WebString::fromUTF8(message)));
    return false;
  }

  return true;
}

ResourceRequestPolicy::ResourceRequestPolicy() {
}

}  // namespace extensions