1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/search/iframe_source.h"
6
7#include "base/memory/ref_counted_memory.h"
8#include "base/strings/string_piece.h"
9#include "base/strings/string_util.h"
10#include "chrome/browser/search/instant_io_context.h"
11#include "chrome/common/url_constants.h"
12#include "content/public/browser/navigation_entry.h"
13#include "content/public/browser/render_frame_host.h"
14#include "content/public/browser/web_contents.h"
15#include "net/url_request/url_request.h"
16#include "ui/base/resource/resource_bundle.h"
17#include "url/gurl.h"
18
19IframeSource::IframeSource() {
20}
21
22IframeSource::~IframeSource() {
23}
24
25std::string IframeSource::GetMimeType(
26    const std::string& path_and_query) const {
27  std::string path(GURL("chrome-search://host/" + path_and_query).path());
28  if (EndsWith(path, ".js", false))
29    return "application/javascript";
30  if (EndsWith(path, ".png", false))
31    return "image/png";
32  if (EndsWith(path, ".css", false))
33    return "text/css";
34  if (EndsWith(path, ".html", false))
35    return "text/html";
36  return "";
37}
38
39bool IframeSource::ShouldServiceRequest(
40    const net::URLRequest* request) const {
41  const std::string& path = request->url().path();
42  return InstantIOContext::ShouldServiceRequest(request) &&
43      request->url().SchemeIs(chrome::kChromeSearchScheme) &&
44      request->url().host() == GetSource() &&
45      ServesPath(path);
46}
47
48bool IframeSource::ShouldDenyXFrameOptions() const {
49  return false;
50}
51
52bool IframeSource::GetOrigin(
53    int render_process_id,
54    int render_frame_id,
55    std::string* origin) const {
56  content::RenderFrameHost* rfh =
57      content::RenderFrameHost::FromID(render_process_id, render_frame_id);
58  content::WebContents* contents =
59      content::WebContents::FromRenderFrameHost(rfh);
60  if (contents == NULL)
61    return false;
62  const content::NavigationEntry* entry =
63      contents->GetController().GetVisibleEntry();
64  if (entry == NULL)
65    return false;
66
67  *origin = entry->GetURL().GetOrigin().spec();
68  // Origin should not include a trailing slash. That is part of the path.
69  base::TrimString(*origin, "/", origin);
70  return true;
71}
72
73void IframeSource::SendResource(
74    int resource_id,
75    const content::URLDataSource::GotDataCallback& callback) {
76  scoped_refptr<base::RefCountedStaticMemory> response(
77      ResourceBundle::GetSharedInstance().LoadDataResourceBytes(resource_id));
78  callback.Run(response.get());
79}
80
81void IframeSource::SendJSWithOrigin(
82    int resource_id,
83    int render_process_id,
84    int render_frame_id,
85    const content::URLDataSource::GotDataCallback& callback) {
86  std::string origin;
87  if (!GetOrigin(render_process_id, render_frame_id, &origin)) {
88    callback.Run(NULL);
89    return;
90  }
91
92  base::StringPiece template_js =
93      ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id);
94  std::string response(template_js.as_string());
95  ReplaceFirstSubstringAfterOffset(&response, 0, "{{ORIGIN}}", origin);
96  callback.Run(base::RefCountedString::TakeString(&response));
97}
98