|  | // Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "content/renderer/web_ui_mojo.h" | 
|  |  | 
|  | #include "content/common/view_messages.h" | 
|  | #include "content/public/renderer/render_frame.h" | 
|  | #include "content/public/renderer/render_view.h" | 
|  | #include "content/renderer/web_ui_mojo_context_state.h" | 
|  | #include "gin/per_context_data.h" | 
|  | #include "third_party/WebKit/public/web/WebKit.h" | 
|  | #include "third_party/WebKit/public/web/WebLocalFrame.h" | 
|  | #include "third_party/WebKit/public/web/WebView.h" | 
|  | #include "v8/include/v8.h" | 
|  |  | 
|  | namespace content { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | const char kWebUIMojoContextStateKey[] = "WebUIMojoContextState"; | 
|  |  | 
|  | struct WebUIMojoContextStateData : public base::SupportsUserData::Data { | 
|  | scoped_ptr<WebUIMojoContextState> state; | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | WebUIMojo::MainFrameObserver::MainFrameObserver(WebUIMojo* web_ui_mojo) | 
|  | : RenderFrameObserver(RenderFrame::FromWebFrame( | 
|  | web_ui_mojo->render_view()->GetWebView()->mainFrame())), | 
|  | web_ui_mojo_(web_ui_mojo) { | 
|  | } | 
|  |  | 
|  | WebUIMojo::MainFrameObserver::~MainFrameObserver() { | 
|  | } | 
|  |  | 
|  | void WebUIMojo::MainFrameObserver::WillReleaseScriptContext( | 
|  | v8::Local<v8::Context> context, | 
|  | int world_id) { | 
|  | web_ui_mojo_->DestroyContextState(context); | 
|  | } | 
|  |  | 
|  | void WebUIMojo::MainFrameObserver::DidFinishDocumentLoad() { | 
|  | web_ui_mojo_->OnDidFinishDocumentLoad(); | 
|  | } | 
|  |  | 
|  | void WebUIMojo::MainFrameObserver::OnDestruct() { | 
|  | } | 
|  |  | 
|  | WebUIMojo::WebUIMojo(RenderView* render_view) | 
|  | : RenderViewObserver(render_view), | 
|  | RenderViewObserverTracker<WebUIMojo>(render_view), | 
|  | main_frame_observer_(this) { | 
|  | } | 
|  |  | 
|  | WebUIMojo::~WebUIMojo() { | 
|  | } | 
|  |  | 
|  | void WebUIMojo::CreateContextState() { | 
|  | v8::HandleScope handle_scope(blink::mainThreadIsolate()); | 
|  | blink::WebLocalFrame* frame = | 
|  | render_view()->GetWebView()->mainFrame()->toWebLocalFrame(); | 
|  | v8::Local<v8::Context> context = frame->mainWorldScriptContext(); | 
|  | gin::PerContextData* context_data = gin::PerContextData::From(context); | 
|  | WebUIMojoContextStateData* data = new WebUIMojoContextStateData; | 
|  | data->state.reset(new WebUIMojoContextState( | 
|  | render_view()->GetWebView()->mainFrame(), context)); | 
|  | context_data->SetUserData(kWebUIMojoContextStateKey, data); | 
|  | } | 
|  |  | 
|  | void WebUIMojo::DestroyContextState(v8::Local<v8::Context> context) { | 
|  | gin::PerContextData* context_data = gin::PerContextData::From(context); | 
|  | if (!context_data) | 
|  | return; | 
|  | context_data->RemoveUserData(kWebUIMojoContextStateKey); | 
|  | } | 
|  |  | 
|  | void WebUIMojo::OnDidFinishDocumentLoad() { | 
|  | v8::HandleScope handle_scope(blink::mainThreadIsolate()); | 
|  | WebUIMojoContextState* state = GetContextState(); | 
|  | if (state) | 
|  | state->Run(); | 
|  | } | 
|  |  | 
|  | WebUIMojoContextState* WebUIMojo::GetContextState() { | 
|  | blink::WebLocalFrame* frame = | 
|  | render_view()->GetWebView()->mainFrame()->toWebLocalFrame(); | 
|  | v8::HandleScope handle_scope(blink::mainThreadIsolate()); | 
|  | v8::Local<v8::Context> context = frame->mainWorldScriptContext(); | 
|  | gin::PerContextData* context_data = gin::PerContextData::From(context); | 
|  | if (!context_data) | 
|  | return NULL; | 
|  | WebUIMojoContextStateData* context_state = | 
|  | static_cast<WebUIMojoContextStateData*>( | 
|  | context_data->GetUserData(kWebUIMojoContextStateKey)); | 
|  | return context_state ? context_state->state.get() : NULL; | 
|  | } | 
|  |  | 
|  | void WebUIMojo::DidCreateDocumentElement(blink::WebLocalFrame* frame) { | 
|  | CreateContextState(); | 
|  | } | 
|  |  | 
|  | void WebUIMojo::DidClearWindowObject(blink::WebLocalFrame* frame) { | 
|  | if (frame != render_view()->GetWebView()->mainFrame()) | 
|  | return; | 
|  |  | 
|  | // NOTE: this function may be called early on twice. From the constructor | 
|  | // mainWorldScriptContext() may trigger this to be called. If we are created | 
|  | // before the page is loaded (which is very likely), then on first load this | 
|  | // is called. In the case of the latter we may have already supplied the | 
|  | // handle to the context state so that if we destroy now the handle is | 
|  | // lost. If this is the result of the first load then the contextstate should | 
|  | // be empty and we don't need to destroy it. | 
|  | WebUIMojoContextState* state = GetContextState(); | 
|  | if (state && !state->module_added()) | 
|  | return; | 
|  |  | 
|  | v8::HandleScope handle_scope(blink::mainThreadIsolate()); | 
|  | DestroyContextState(frame->mainWorldScriptContext()); | 
|  | } | 
|  |  | 
|  | }  // namespace content |