web_ui_mojo.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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.h" 6 7#include "content/common/view_messages.h" 8#include "content/public/common/service_registry.h" 9#include "content/public/renderer/render_frame.h" 10#include "content/public/renderer/render_view.h" 11#include "content/renderer/web_ui_mojo_context_state.h" 12#include "gin/per_context_data.h" 13#include "third_party/WebKit/public/web/WebKit.h" 14#include "third_party/WebKit/public/web/WebLocalFrame.h" 15#include "third_party/WebKit/public/web/WebView.h" 16#include "v8/include/v8.h" 17 18namespace content { 19 20namespace { 21 22const char kWebUIMojoContextStateKey[] = "WebUIMojoContextState"; 23 24struct WebUIMojoContextStateData : public base::SupportsUserData::Data { 25 scoped_ptr<WebUIMojoContextState> state; 26}; 27 28} // namespace 29 30WebUIMojo::MainFrameObserver::MainFrameObserver(WebUIMojo* web_ui_mojo) 31 : RenderFrameObserver(RenderFrame::FromWebFrame( 32 web_ui_mojo->render_view()->GetWebView()->mainFrame())), 33 web_ui_mojo_(web_ui_mojo) { 34} 35 36WebUIMojo::MainFrameObserver::~MainFrameObserver() { 37} 38 39void WebUIMojo::MainFrameObserver::WillReleaseScriptContext( 40 v8::Handle<v8::Context> context, 41 int world_id) { 42 web_ui_mojo_->DestroyContextState(context); 43} 44 45void WebUIMojo::MainFrameObserver::DidFinishDocumentLoad() { 46 web_ui_mojo_->OnDidFinishDocumentLoad(); 47} 48 49WebUIMojo::WebUIMojo(RenderView* render_view) 50 : RenderViewObserver(render_view), 51 RenderViewObserverTracker<WebUIMojo>(render_view), 52 main_frame_observer_(this), 53 did_finish_document_load_(false) { 54 CreateContextState(); 55} 56 57void WebUIMojo::SetBrowserHandle(mojo::ScopedMessagePipeHandle handle) { 58 if (did_finish_document_load_) 59 SetHandleOnContextState(handle.Pass()); 60 else 61 pending_handle_ = handle.Pass(); 62} 63 64WebUIMojo::~WebUIMojo() { 65} 66 67void WebUIMojo::CreateContextState() { 68 v8::HandleScope handle_scope(blink::mainThreadIsolate()); 69 blink::WebLocalFrame* frame = 70 render_view()->GetWebView()->mainFrame()->toWebLocalFrame(); 71 v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); 72 gin::PerContextData* context_data = gin::PerContextData::From(context); 73 WebUIMojoContextStateData* data = new WebUIMojoContextStateData; 74 data->state.reset(new WebUIMojoContextState( 75 render_view()->GetWebView()->mainFrame(), context)); 76 context_data->SetUserData(kWebUIMojoContextStateKey, data); 77} 78 79void WebUIMojo::DestroyContextState(v8::Handle<v8::Context> context) { 80 gin::PerContextData* context_data = gin::PerContextData::From(context); 81 if (!context_data) 82 return; 83 context_data->RemoveUserData(kWebUIMojoContextStateKey); 84} 85 86void WebUIMojo::OnDidFinishDocumentLoad() { 87 did_finish_document_load_ = true; 88 mojo::MessagePipe pipe; 89 SetHandleOnContextState(pipe.handle0.Pass()); 90 RenderFrame::FromWebFrame(render_view()->GetWebView()->mainFrame())-> 91 GetServiceRegistry()-> 92 ConnectToRemoteService("webui_controller", pipe.handle1.Pass()); 93} 94 95void WebUIMojo::SetHandleOnContextState(mojo::ScopedMessagePipeHandle handle) { 96 DCHECK(did_finish_document_load_); 97 v8::HandleScope handle_scope(blink::mainThreadIsolate()); 98 WebUIMojoContextState* state = GetContextState(); 99 if (state) 100 state->SetHandle(handle.Pass()); 101} 102 103WebUIMojoContextState* WebUIMojo::GetContextState() { 104 blink::WebLocalFrame* frame = 105 render_view()->GetWebView()->mainFrame()->toWebLocalFrame(); 106 v8::HandleScope handle_scope(blink::mainThreadIsolate()); 107 v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); 108 gin::PerContextData* context_data = gin::PerContextData::From(context); 109 if (!context_data) 110 return NULL; 111 WebUIMojoContextStateData* context_state = 112 static_cast<WebUIMojoContextStateData*>( 113 context_data->GetUserData(kWebUIMojoContextStateKey)); 114 return context_state ? context_state->state.get() : NULL; 115} 116 117void WebUIMojo::DidClearWindowObject(blink::WebLocalFrame* frame) { 118 if (frame != render_view()->GetWebView()->mainFrame()) 119 return; 120 121 // NOTE: this function may be called early on twice. From the constructor 122 // mainWorldScriptContext() may trigger this to be called. If we are created 123 // before the page is loaded (which is very likely), then on first load this 124 // is called. In the case of the latter we may have already supplied the 125 // handle to the context state so that if we destroy now the handle is 126 // lost. If this is the result of the first load then the contextstate should 127 // be empty and we don't need to destroy it. 128 WebUIMojoContextState* state = GetContextState(); 129 if (state && !state->module_added()) 130 return; 131 132 v8::HandleScope handle_scope(blink::mainThreadIsolate()); 133 DestroyContextState(frame->mainWorldScriptContext()); 134 CreateContextState(); 135} 136 137} // namespace content 138