Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / extensions / browser / web_ui_user_script_loader.cc
blobc1519c8099bc8452fc15b674119b389f4f03bee8
1 // Copyright 2015 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.
5 #include "extensions/browser/web_ui_user_script_loader.h"
7 #include "base/bind.h"
8 #include "base/strings/string_util.h"
9 #include "content/public/browser/browser_context.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/render_process_host.h"
12 #include "extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.h"
14 namespace {
16 void SerializeOnFileThread(
17 scoped_ptr<extensions::UserScriptList> user_scripts,
18 extensions::UserScriptLoader::LoadScriptsCallback callback) {
19 scoped_ptr<base::SharedMemory> memory =
20 extensions::UserScriptLoader::Serialize(*user_scripts);
21 content::BrowserThread::PostTask(
22 content::BrowserThread::UI, FROM_HERE,
23 base::Bind(callback, base::Passed(&user_scripts), base::Passed(&memory)));
26 } // namespace
28 struct WebUIUserScriptLoader::UserScriptRenderInfo {
29 int render_process_id;
30 int render_view_id;
32 UserScriptRenderInfo() : render_process_id(-1), render_view_id(-1) {}
34 UserScriptRenderInfo(int render_process_id, int render_view_id)
35 : render_process_id(render_process_id), render_view_id(render_view_id) {}
38 WebUIUserScriptLoader::WebUIUserScriptLoader(
39 content::BrowserContext* browser_context,
40 const HostID& host_id)
41 : UserScriptLoader(browser_context, host_id), complete_fetchers_(0) {
42 SetReady(true);
45 WebUIUserScriptLoader::~WebUIUserScriptLoader() {
48 void WebUIUserScriptLoader::AddScripts(
49 const std::set<extensions::UserScript>& scripts,
50 int render_process_id,
51 int render_view_id) {
52 UserScriptRenderInfo info(render_process_id, render_view_id);
53 for (const extensions::UserScript& script : scripts) {
54 script_render_info_map_.insert(
55 std::pair<int, UserScriptRenderInfo>(script.id(), info));
58 extensions::UserScriptLoader::AddScripts(scripts);
61 void WebUIUserScriptLoader::LoadScripts(
62 scoped_ptr<extensions::UserScriptList> user_scripts,
63 const std::set<HostID>& changed_hosts,
64 const std::set<int>& added_script_ids,
65 LoadScriptsCallback callback) {
66 user_scripts_cache_.swap(user_scripts);
67 scripts_loaded_callback_ = callback;
69 // The total number of the tasks is used to trace whether all the fetches
70 // are complete. Therefore, we store all the fetcher pointers in |fetchers_|
71 // before we get theis number. Once we get the total number, start each
72 // fetch tasks.
73 DCHECK_EQ(0u, complete_fetchers_);
75 for (extensions::UserScript& script : *user_scripts_cache_) {
76 if (added_script_ids.count(script.id()) == 0)
77 continue;
79 auto iter = script_render_info_map_.find(script.id());
80 DCHECK(iter != script_render_info_map_.end());
81 int render_process_id = iter->second.render_process_id;
82 int render_view_id = iter->second.render_view_id;
84 content::BrowserContext* browser_context =
85 content::RenderProcessHost::FromID(render_process_id)
86 ->GetBrowserContext();
88 CreateWebUIURLFetchers(&script.js_scripts(), browser_context,
89 render_process_id, render_view_id);
90 CreateWebUIURLFetchers(&script.css_scripts(), browser_context,
91 render_process_id, render_view_id);
93 script_render_info_map_.erase(script.id());
96 // If no fetch is needed, call OnWebUIURLFetchComplete directly.
97 if (fetchers_.empty()) {
98 OnWebUIURLFetchComplete();
99 return;
101 for (auto fetcher : fetchers_)
102 fetcher->Start();
105 void WebUIUserScriptLoader::CreateWebUIURLFetchers(
106 extensions::UserScript::FileList* script_files,
107 content::BrowserContext* browser_context,
108 int render_process_id,
109 int render_view_id) {
110 for (extensions::UserScript::File& file : *script_files) {
111 if (file.GetContent().empty()) {
112 // The WebUIUserScriptLoader owns these WebUIURLFetchers. Once the
113 // loader is destroyed, all the fetchers will be destroyed. Therefore,
114 // we are sure it is safe to use base::Unretained(this) here.
115 scoped_ptr<WebUIURLFetcher> fetcher(new WebUIURLFetcher(
116 browser_context, render_process_id, render_view_id, file.url(),
117 base::Bind(&WebUIUserScriptLoader::OnSingleWebUIURLFetchComplete,
118 base::Unretained(this), &file)));
119 fetchers_.push_back(fetcher.Pass());
124 void WebUIUserScriptLoader::OnSingleWebUIURLFetchComplete(
125 extensions::UserScript::File* script_file,
126 bool success,
127 const std::string& data) {
128 if (success) {
129 // Remove BOM from the content.
130 std::string::size_type index = data.find(base::kUtf8ByteOrderMark);
131 if (index == 0)
132 script_file->set_content(data.substr(strlen(base::kUtf8ByteOrderMark)));
133 else
134 script_file->set_content(data);
137 ++complete_fetchers_;
138 if (complete_fetchers_ == fetchers_.size()) {
139 complete_fetchers_ = 0;
140 OnWebUIURLFetchComplete();
141 fetchers_.clear();
145 void WebUIUserScriptLoader::OnWebUIURLFetchComplete() {
146 content::BrowserThread::PostTask(
147 content::BrowserThread::FILE, FROM_HERE,
148 base::Bind(&SerializeOnFileThread, base::Passed(&user_scripts_cache_),
149 scripts_loaded_callback_));
150 scripts_loaded_callback_.Reset();