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