OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "content/renderer/web_ui_mojo_context_state.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/stl_util.h" | |
9 #include "content/public/renderer/render_frame.h" | |
10 #include "content/public/renderer/resource_fetcher.h" | |
11 #include "content/renderer/web_ui_runner.h" | |
12 #include "gin/converter.h" | |
13 #include "gin/modules/module_registry.h" | |
14 #include "gin/per_context_data.h" | |
15 #include "gin/public/context_holder.h" | |
16 #include "gin/try_catch.h" | |
17 #include "third_party/WebKit/public/platform/WebURLResponse.h" | |
18 #include "third_party/WebKit/public/web/WebFrame.h" | |
19 #include "third_party/WebKit/public/web/WebScriptSource.h" | |
20 | |
21 using v8::Context; | |
22 using v8::HandleScope; | |
23 using v8::Isolate; | |
24 using v8::Object; | |
25 using v8::ObjectTemplate; | |
26 using v8::Script; | |
27 | |
28 namespace content { | |
29 | |
30 namespace { | |
31 | |
32 // All modules have this prefixed to them when downloading. | |
33 // TODO(sky): move this into some common place. | |
34 const char kModulePrefix[] = "chrome://mojo/"; | |
35 | |
36 void RunMain(base::WeakPtr<gin::Runner> runner, | |
37 v8::Local<v8::Value> module) { | |
38 v8::Isolate* isolate = runner->GetContextHolder()->isolate(); | |
39 v8::Local<v8::Function> start; | |
40 CHECK(gin::ConvertFromV8(isolate, module, &start)); | |
41 runner->Call(start, runner->global(), 0, NULL); | |
42 } | |
43 | |
44 } // namespace | |
45 | |
46 // WebUIMojo ------------------------------------------------------------------- | |
47 | |
48 WebUIMojoContextState::WebUIMojoContextState(blink::WebFrame* frame, | |
49 v8::Local<v8::Context> context) | |
50 : frame_(frame), | |
51 module_added_(false) { | |
52 gin::PerContextData* context_data = gin::PerContextData::From(context); | |
53 gin::ContextHolder* context_holder = context_data->context_holder(); | |
54 runner_.reset(new WebUIRunner(frame_, context_holder)); | |
55 gin::Runner::Scope scoper(runner_.get()); | |
56 gin::ModuleRegistry::From(context)->AddObserver(this); | |
57 content::RenderFrame::FromWebFrame(frame) | |
58 ->EnsureMojoBuiltinsAreAvailable(context_holder->isolate(), context); | |
59 gin::ModuleRegistry::InstallGlobals(context->GetIsolate(), context->Global()); | |
60 // Warning |frame| may be destroyed. | |
61 // TODO(sky): add test for this. | |
62 } | |
63 | |
64 WebUIMojoContextState::~WebUIMojoContextState() { | |
65 gin::Runner::Scope scoper(runner_.get()); | |
66 gin::ModuleRegistry::From( | |
67 runner_->GetContextHolder()->context())->RemoveObserver(this); | |
68 } | |
69 | |
70 void WebUIMojoContextState::Run() { | |
71 gin::ContextHolder* context_holder = runner_->GetContextHolder(); | |
72 gin::ModuleRegistry::From(context_holder->context())->LoadModule( | |
73 context_holder->isolate(), | |
74 "main", | |
75 base::Bind(RunMain, runner_->GetWeakPtr())); | |
76 } | |
77 | |
78 void WebUIMojoContextState::FetchModules(const std::vector<std::string>& ids) { | |
79 gin::Runner::Scope scoper(runner_.get()); | |
80 gin::ContextHolder* context_holder = runner_->GetContextHolder(); | |
81 gin::ModuleRegistry* registry = gin::ModuleRegistry::From( | |
82 context_holder->context()); | |
83 for (size_t i = 0; i < ids.size(); ++i) { | |
84 if (fetched_modules_.find(ids[i]) == fetched_modules_.end() && | |
85 registry->available_modules().count(ids[i]) == 0) { | |
86 FetchModule(ids[i]); | |
87 } | |
88 } | |
89 } | |
90 | |
91 void WebUIMojoContextState::FetchModule(const std::string& id) { | |
92 const GURL url(kModulePrefix + id); | |
93 // TODO(sky): better error checks here? | |
94 DCHECK(url.is_valid() && !url.is_empty()); | |
95 DCHECK(fetched_modules_.find(id) == fetched_modules_.end()); | |
96 fetched_modules_.insert(id); | |
97 ResourceFetcher* fetcher = ResourceFetcher::Create(url); | |
98 module_fetchers_.push_back(fetcher); | |
99 fetcher->Start(frame_, | |
100 blink::WebURLRequest::RequestContextScript, | |
101 blink::WebURLRequest::FrameTypeNone, | |
102 ResourceFetcher::PLATFORM_LOADER, | |
103 base::Bind(&WebUIMojoContextState::OnFetchModuleComplete, | |
104 base::Unretained(this), | |
105 fetcher)); | |
106 } | |
107 | |
108 void WebUIMojoContextState::OnFetchModuleComplete( | |
109 ResourceFetcher* fetcher, | |
110 const blink::WebURLResponse& response, | |
111 const std::string& data) { | |
112 DCHECK_EQ(kModulePrefix, | |
113 response.url().string().utf8().substr(0, arraysize(kModulePrefix) - 1)); | |
114 const std::string module = | |
115 response.url().string().utf8().substr(arraysize(kModulePrefix) - 1); | |
116 // We can't delete fetch right now as the arguments to this function come from | |
117 // it and are used below. Instead use a scope_ptr to cleanup. | |
118 scoped_ptr<ResourceFetcher> deleter(fetcher); | |
119 module_fetchers_.weak_erase( | |
120 std::find(module_fetchers_.begin(), module_fetchers_.end(), fetcher)); | |
121 if (data.empty()) { | |
122 NOTREACHED(); | |
123 return; // TODO(sky): log something? | |
124 } | |
125 | |
126 runner_->Run(data, module); | |
127 } | |
128 | |
129 void WebUIMojoContextState::OnDidAddPendingModule( | |
130 const std::string& id, | |
131 const std::vector<std::string>& dependencies) { | |
132 FetchModules(dependencies); | |
133 | |
134 gin::ContextHolder* context_holder = runner_->GetContextHolder(); | |
135 gin::ModuleRegistry* registry = gin::ModuleRegistry::From( | |
136 context_holder->context()); | |
137 registry->AttemptToLoadMoreModules(context_holder->isolate()); | |
138 } | |
139 | |
140 } // namespace content | |
OLD | NEW |