Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: Source/web/WebFrameImpl.cpp

Issue 23506013: Make the embedder responsible for creating the WebFrame (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Fix lifetime on frame detach Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/web/WebFrameImpl.h ('k') | Source/web/WebHelperPluginImpl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved. 2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 // 43 //
44 // FrameLoader and Frame are formerly one object that was split apart because 44 // FrameLoader and Frame are formerly one object that was split apart because
45 // it got too big. They basically have the same lifetime, hence the double line. 45 // it got too big. They basically have the same lifetime, hence the double line.
46 // 46 //
47 // WebFrame is refcounted and has one ref on behalf of the FrameLoader/Frame. 47 // WebFrame is refcounted and has one ref on behalf of the FrameLoader/Frame.
48 // This is not a normal reference counted pointer because that would require 48 // This is not a normal reference counted pointer because that would require
49 // changing WebKit code that we don't control. Instead, it is created with this 49 // changing WebKit code that we don't control. Instead, it is created with this
50 // ref initially and it is removed when the FrameLoader is getting destroyed. 50 // ref initially and it is removed when the FrameLoader is getting destroyed.
51 // 51 //
52 // WebFrames are created in two places, first in WebViewImpl when the root 52 // WebFrames are created in two places, first in WebViewImpl when the root
53 // frame is created, and second in WebFrame::CreateChildFrame when sub-frames 53 // frame is created, and second in WebFrame::createChildFrame when sub-frames
54 // are created. WebKit will hook up this object to the FrameLoader/Frame 54 // are created. WebKit will hook up this object to the FrameLoader/Frame
55 // and the refcount will be correct. 55 // and the refcount will be correct.
56 // 56 //
57 // How frames are destroyed 57 // How frames are destroyed
58 // ------------------------ 58 // ------------------------
59 // 59 //
60 // The main frame is never destroyed and is re-used. The FrameLoader is re-used 60 // The main frame is never destroyed and is re-used. The FrameLoader is re-used
61 // and a reference to the main frame is kept by the Page. 61 // and a reference to the main frame is kept by the Page.
62 // 62 //
63 // When frame content is replaced, all subframes are destroyed. This happens 63 // When frame content is replaced, all subframes are destroyed. This happens
64 // in FrameLoader::detachFromParent for each subframe. 64 // in FrameLoader::detachFromParent for each subframe.
65 // 65 //
66 // Frame going away causes the FrameLoader to get deleted. In FrameLoader's 66 // Frame going away causes the FrameLoader to get deleted. In FrameLoader's
67 // destructor, it notifies its client with frameLoaderDestroyed. This calls 67 // destructor, it notifies its client with frameLoaderDestroyed. This derefs
68 // WebFrame::Closing and then derefs the WebFrame and will cause it to be 68 // the WebFrame and will cause it to be deleted (unless an external someone
69 // deleted (unless an external someone is also holding a reference). 69 // is also holding a reference).
70 //
71 // Thie client is expected to be set whenever the WebFrameImpl is attached to
72 // the DOM.
70 73
71 #include "config.h" 74 #include "config.h"
72 #include "WebFrameImpl.h" 75 #include "WebFrameImpl.h"
73 76
74 #include "AssociatedURLLoader.h" 77 #include "AssociatedURLLoader.h"
75 #include "DOMUtilitiesPrivate.h" 78 #include "DOMUtilitiesPrivate.h"
76 #include "EventListenerWrapper.h" 79 #include "EventListenerWrapper.h"
77 #include "FindInPageCoordinates.h" 80 #include "FindInPageCoordinates.h"
78 #include "HTMLNames.h" 81 #include "HTMLNames.h"
79 #include "PageOverlay.h" 82 #include "PageOverlay.h"
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 if (output.length() >= maxChars - frameSeparatorLength) 262 if (output.length() >= maxChars - frameSeparatorLength)
260 return; 263 return;
261 264
262 output.append(frameSeparator, frameSeparatorLength); 265 output.append(frameSeparator, frameSeparatorLength);
263 frameContentAsPlainText(maxChars, curChild, output); 266 frameContentAsPlainText(maxChars, curChild, output);
264 if (output.length() >= maxChars) 267 if (output.length() >= maxChars)
265 return; // Filled up the buffer. 268 return; // Filled up the buffer.
266 } 269 }
267 } 270 }
268 271
269 static long long generateFrameIdentifier()
270 {
271 static long long next = 0;
272 return ++next;
273 }
274
275 WebPluginContainerImpl* WebFrameImpl::pluginContainerFromFrame(Frame* frame) 272 WebPluginContainerImpl* WebFrameImpl::pluginContainerFromFrame(Frame* frame)
276 { 273 {
277 if (!frame) 274 if (!frame)
278 return 0; 275 return 0;
279 if (!frame->document() || !frame->document()->isPluginDocument()) 276 if (!frame->document() || !frame->document()->isPluginDocument())
280 return 0; 277 return 0;
281 PluginDocument* pluginDocument = toPluginDocument(frame->document()); 278 PluginDocument* pluginDocument = toPluginDocument(frame->document());
282 return toPluginContainerImpl(pluginDocument->pluginWidget()); 279 return toPluginContainerImpl(pluginDocument->pluginWidget());
283 } 280 }
284 281
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 WebFrame* WebFrame::frameForContext(v8::Handle<v8::Context> context) 516 WebFrame* WebFrame::frameForContext(v8::Handle<v8::Context> context)
520 { 517 {
521 return WebFrameImpl::fromFrame(toFrameIfNotDetached(context)); 518 return WebFrameImpl::fromFrame(toFrameIfNotDetached(context));
522 } 519 }
523 520
524 WebFrame* WebFrame::fromFrameOwnerElement(const WebElement& element) 521 WebFrame* WebFrame::fromFrameOwnerElement(const WebElement& element)
525 { 522 {
526 return WebFrameImpl::fromFrameOwnerElement(PassRefPtr<Element>(element).get( )); 523 return WebFrameImpl::fromFrameOwnerElement(PassRefPtr<Element>(element).get( ));
527 } 524 }
528 525
526 void WebFrameImpl::close()
527 {
528 m_client = 0;
529 deref(); // Balances ref() acquired in WebFrame::create
530 }
531
529 WebString WebFrameImpl::uniqueName() const 532 WebString WebFrameImpl::uniqueName() const
530 { 533 {
531 return frame()->tree()->uniqueName(); 534 return frame()->tree()->uniqueName();
532 } 535 }
533 536
534 WebString WebFrameImpl::assignedName() const 537 WebString WebFrameImpl::assignedName() const
535 { 538 {
536 return frame()->tree()->name(); 539 return frame()->tree()->name();
537 } 540 }
538 541
539 void WebFrameImpl::setName(const WebString& name) 542 void WebFrameImpl::setName(const WebString& name)
540 { 543 {
541 frame()->tree()->setName(name); 544 frame()->tree()->setName(name);
542 } 545 }
543 546
544 long long WebFrameImpl::identifier() const 547 long long WebFrameImpl::embedderIdentifier() const
545 { 548 {
546 return m_identifier; 549 return m_embedderIdentifier;
547 } 550 }
548 551
549 WebVector<WebIconURL> WebFrameImpl::iconURLs(int iconTypesMask) const 552 WebVector<WebIconURL> WebFrameImpl::iconURLs(int iconTypesMask) const
550 { 553 {
551 // The URL to the icon may be in the header. As such, only 554 // The URL to the icon may be in the header. As such, only
552 // ask the loader for the icon if it's finished loading. 555 // ask the loader for the icon if it's finished loading.
553 if (frame()->loader()->state() == FrameStateComplete) 556 if (frame()->loader()->state() == FrameStateComplete)
554 return frame()->loader()->icon()->urlsForTypes(iconTypesMask); 557 return frame()->loader()->icon()->urlsForTypes(iconTypesMask);
555 return WebVector<WebIconURL>(); 558 return WebVector<WebIconURL>();
556 } 559 }
(...skipping 1497 matching lines...) Expand 10 before | Expand all | Expand 10 after
2054 WebString WebFrameImpl::layerTreeAsText(bool showDebugInfo) const 2057 WebString WebFrameImpl::layerTreeAsText(bool showDebugInfo) const
2055 { 2058 {
2056 if (!frame()) 2059 if (!frame())
2057 return WebString(); 2060 return WebString();
2058 2061
2059 return WebString(frame()->layerTreeAsText(showDebugInfo ? LayerTreeIncludesD ebugInfo : LayerTreeNormal)); 2062 return WebString(frame()->layerTreeAsText(showDebugInfo ? LayerTreeIncludesD ebugInfo : LayerTreeNormal));
2060 } 2063 }
2061 2064
2062 // WebFrameImpl public --------------------------------------------------------- 2065 // WebFrameImpl public ---------------------------------------------------------
2063 2066
2064 PassRefPtr<WebFrameImpl> WebFrameImpl::create(WebFrameClient* client) 2067 WebFrame* WebFrame::create(WebFrameClient* client)
2065 { 2068 {
2066 return adoptRef(new WebFrameImpl(client)); 2069 return WebFrameImpl::create(client);
2067 } 2070 }
2068 2071
2069 WebFrameImpl::WebFrameImpl(WebFrameClient* client) 2072 WebFrame* WebFrame::create(WebFrameClient* client, long long embedderIdentifier)
2073 {
2074 return WebFrameImpl::create(client, embedderIdentifier);
2075 }
2076
2077 long long WebFrame::generateEmbedderIdentifier()
2078 {
2079 static long long next = 0;
2080 // Assume that 64-bit will not wrap to -1.
2081 return ++next;
2082 }
2083
2084 WebFrameImpl* WebFrameImpl::create(WebFrameClient* client)
2085 {
2086 return WebFrameImpl::create(client, generateEmbedderIdentifier());
2087 }
2088
2089 WebFrameImpl* WebFrameImpl::create(WebFrameClient* client, long long embedderIde ntifier)
2090 {
2091 return adoptRef(new WebFrameImpl(client, embedderIdentifier)).leakRef();
2092 }
2093
2094 WebFrameImpl::WebFrameImpl(WebFrameClient* client, long long embedderIdentifier)
2070 : FrameDestructionObserver(0) 2095 : FrameDestructionObserver(0)
2071 , m_frameLoaderClient(this) 2096 , m_frameLoaderClient(this)
2072 , m_client(client) 2097 , m_client(client)
2073 , m_currentActiveMatchFrame(0) 2098 , m_currentActiveMatchFrame(0)
2074 , m_activeMatchIndexInCurrentFrame(-1) 2099 , m_activeMatchIndexInCurrentFrame(-1)
2075 , m_locatingActiveRect(false) 2100 , m_locatingActiveRect(false)
2076 , m_resumeScopingFromRange(0) 2101 , m_resumeScopingFromRange(0)
2077 , m_lastMatchCount(-1) 2102 , m_lastMatchCount(-1)
2078 , m_totalMatchCount(-1) 2103 , m_totalMatchCount(-1)
2079 , m_framesScopingCount(-1) 2104 , m_framesScopingCount(-1)
2080 , m_findRequestIdentifier(-1) 2105 , m_findRequestIdentifier(-1)
2081 , m_scopingInProgress(false) 2106 , m_scopingInProgress(false)
2082 , m_lastFindRequestCompletedWithNoMatches(false) 2107 , m_lastFindRequestCompletedWithNoMatches(false)
2083 , m_nextInvalidateAfter(0) 2108 , m_nextInvalidateAfter(0)
2084 , m_findMatchMarkersVersion(0) 2109 , m_findMatchMarkersVersion(0)
2085 , m_findMatchRectsAreValid(false) 2110 , m_findMatchRectsAreValid(false)
2086 , m_identifier(generateFrameIdentifier()) 2111 , m_embedderIdentifier(embedderIdentifier)
2087 , m_inSameDocumentHistoryLoad(false) 2112 , m_inSameDocumentHistoryLoad(false)
2088 { 2113 {
2089 WebKit::Platform::current()->incrementStatsCounter(webFrameActiveCount); 2114 WebKit::Platform::current()->incrementStatsCounter(webFrameActiveCount);
2090 frameCount++; 2115 frameCount++;
2091 } 2116 }
2092 2117
2093 WebFrameImpl::~WebFrameImpl() 2118 WebFrameImpl::~WebFrameImpl()
2094 { 2119 {
2095 WebKit::Platform::current()->decrementStatsCounter(webFrameActiveCount); 2120 WebKit::Platform::current()->decrementStatsCounter(webFrameActiveCount);
2096 frameCount--; 2121 frameCount--;
2097 2122
2098 cancelPendingScopingEffort(); 2123 cancelPendingScopingEffort();
2099 } 2124 }
2100 2125
2101 void WebFrameImpl::setWebCoreFrame(WebCore::Frame* frame) 2126 void WebFrameImpl::setWebCoreFrame(WebCore::Frame* frame)
2102 { 2127 {
2103 ASSERT(frame); 2128 ASSERT(frame);
2104 observeFrame(frame); 2129 observeFrame(frame);
2105 } 2130 }
2106 2131
2107 void WebFrameImpl::initializeAsMainFrame(WebCore::Page* page) 2132 void WebFrameImpl::initializeAsMainFrame(WebCore::Page* page)
2108 { 2133 {
2109 RefPtr<Frame> mainFrame = Frame::create(page, 0, &m_frameLoaderClient); 2134 RefPtr<Frame> mainFrame = Frame::create(page, 0, &m_frameLoaderClient);
2110 setWebCoreFrame(mainFrame.get()); 2135 setWebCoreFrame(mainFrame.get());
2111 2136
2112 // Add reference on behalf of FrameLoader. See comments in 2137 // Add reference on behalf of FrameLoader. See comments in
2113 // WebFrameLoaderClient::frameLoaderDestroyed for more info. 2138 // WebFrameLoaderClient::frameLoaderDestroyed for more info.
2114 ref(); 2139 ref();
2115 2140
2116 // We must call init() after m_frame is assigned because it is referenced 2141 // We must call init() after m_frame is assigned because it is referenced
2117 // during init(). 2142 // during init().
2118 frame()->init(); 2143 frame()->init();
2119 } 2144 }
2120 2145
2121 PassRefPtr<Frame> WebFrameImpl::createChildFrame(const FrameLoadRequest& request , HTMLFrameOwnerElement* ownerElement) 2146 PassRefPtr<Frame> WebFrameImpl::createChildFrame(const FrameLoadRequest& request , HTMLFrameOwnerElement* ownerElement)
2122 { 2147 {
2123 RefPtr<WebFrameImpl> webframe(adoptRef(new WebFrameImpl(m_client))); 2148 ASSERT(m_client);
2149 WebFrameImpl* webframe = toWebFrameImpl(m_client->createChildFrame(this, req uest.frameName()));
2150
2151 // If the embedder is returning 0 from createChildFrame(), it has not been
2152 // updated to the new ownership semantics where the embedder creates the
2153 // WebFrame. In that case, fall back to the old logic where the
2154 // WebFrameImpl is created here and published back to the embedder. To
2155 // bridge between the two ownership semantics, webframeLifetimeHack is
2156 // needeed to balance out the refcounting.
2157 //
2158 // FIXME: Remove once all embedders return non-null from createChildFrame().
2159 RefPtr<WebFrameImpl> webframeLifetimeHack;
2160 bool mustCallDidCreateFrame = false;
2161 if (!webframe) {
2162 mustCallDidCreateFrame = true;
2163 webframeLifetimeHack = adoptRef(WebFrameImpl::create(m_client));
2164 webframe = webframeLifetimeHack.get();
2165 }
2124 2166
2125 // Add an extra ref on behalf of the Frame/FrameLoader, which references the 2167 // Add an extra ref on behalf of the Frame/FrameLoader, which references the
2126 // WebFrame via the FrameLoaderClient interface. See the comment at the top 2168 // WebFrame via the FrameLoaderClient interface. See the comment at the top
2127 // of this file for more info. 2169 // of this file for more info.
2128 webframe->ref(); 2170 webframe->ref();
2129 2171
2130 RefPtr<Frame> childFrame = Frame::create(frame()->page(), ownerElement, &web frame->m_frameLoaderClient); 2172 RefPtr<Frame> childFrame = Frame::create(frame()->page(), ownerElement, &web frame->m_frameLoaderClient);
2131 webframe->setWebCoreFrame(childFrame.get()); 2173 webframe->setWebCoreFrame(childFrame.get());
2132 2174
2133 childFrame->tree()->setName(request.frameName()); 2175 childFrame->tree()->setName(request.frameName());
2134 2176
2135 frame()->tree()->appendChild(childFrame); 2177 frame()->tree()->appendChild(childFrame);
2136 2178
2179 // FIXME: Remove once all embedders return non-null from createChildFrame().
2180 if (mustCallDidCreateFrame)
2181 m_client->didCreateFrame(this, webframe);
2182
2137 // Frame::init() can trigger onload event in the parent frame, 2183 // Frame::init() can trigger onload event in the parent frame,
2138 // which may detach this frame and trigger a null-pointer access 2184 // which may detach this frame and trigger a null-pointer access
2139 // in FrameTree::removeChild. Move init() after appendChild call 2185 // in FrameTree::removeChild. Move init() after appendChild call
2140 // so that webframe->mFrame is in the tree before triggering 2186 // so that webframe->mFrame is in the tree before triggering
2141 // onload event handler. 2187 // onload event handler.
2142 // Because the event handler may set webframe->mFrame to null, 2188 // Because the event handler may set webframe->mFrame to null,
2143 // it is necessary to check the value after calling init() and 2189 // it is necessary to check the value after calling init() and
2144 // return without loading URL. 2190 // return without loading URL.
2191 // NOTE: m_client will be null if this frame has been detached.
2145 // (b:791612) 2192 // (b:791612)
2146 childFrame->init(); // create an empty document 2193 childFrame->init(); // create an empty document
2147 if (!childFrame->tree()->parent()) 2194 if (!childFrame->tree()->parent())
2148 return 0; 2195 return 0;
2149 2196
2150 HistoryItem* parentItem = frame()->loader()->history()->currentItem(); 2197 HistoryItem* parentItem = frame()->loader()->history()->currentItem();
2151 HistoryItem* childItem = 0; 2198 HistoryItem* childItem = 0;
2152 // If we're moving in the back/forward list, we might want to replace the co ntent 2199 // If we're moving in the back/forward list, we might want to replace the co ntent
2153 // of this child frame with whatever was there at that point. 2200 // of this child frame with whatever was there at that point.
2154 if (parentItem && parentItem->children().size() && isBackForwardLoadType(fra me()->loader()->loadType()) && !frame()->document()->loadEventFinished()) 2201 if (parentItem && parentItem->children().size() && isBackForwardLoadType(fra me()->loader()->loadType()) && !frame()->document()->loadEventFinished())
2155 childItem = parentItem->childItemWithTarget(childFrame->tree()->uniqueNa me()); 2202 childItem = parentItem->childItemWithTarget(childFrame->tree()->uniqueNa me());
2156 2203
2157 if (childItem) 2204 if (childItem)
2158 childFrame->loader()->loadHistoryItem(childItem); 2205 childFrame->loader()->loadHistoryItem(childItem);
2159 else 2206 else
2160 childFrame->loader()->load(FrameLoadRequest(0, request.resourceRequest() , "_self")); 2207 childFrame->loader()->load(FrameLoadRequest(0, request.resourceRequest() , "_self"));
2161 2208
2162 // A synchronous navigation (about:blank) would have already processed 2209 // A synchronous navigation (about:blank) would have already processed
2163 // onload, so it is possible for the frame to have already been destroyed by 2210 // onload, so it is possible for the frame to have already been destroyed by
2164 // script in the page. 2211 // script in the page.
2212 // NOTE: m_client will be null if this frame has been detached.
2165 if (!childFrame->tree()->parent()) 2213 if (!childFrame->tree()->parent())
2166 return 0; 2214 return 0;
2167 2215
2168 if (m_client)
2169 m_client->didCreateFrame(this, webframe.get());
2170
2171 return childFrame.release(); 2216 return childFrame.release();
2172 } 2217 }
2173 2218
2174 void WebFrameImpl::didChangeContentsSize(const IntSize& size) 2219 void WebFrameImpl::didChangeContentsSize(const IntSize& size)
2175 { 2220 {
2176 // This is only possible on the main frame. 2221 // This is only possible on the main frame.
2177 if (m_totalMatchCount > 0) { 2222 if (m_totalMatchCount > 0) {
2178 ASSERT(!parent()); 2223 ASSERT(!parent());
2179 ++m_findMatchMarkersVersion; 2224 ++m_findMatchMarkersVersion;
2180 } 2225 }
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
2464 2509
2465 // There is a possibility that the frame being detached was the only 2510 // There is a possibility that the frame being detached was the only
2466 // pending one. We need to make sure final replies can be sent. 2511 // pending one. We need to make sure final replies can be sent.
2467 flushCurrentScopingEffort(m_findRequestIdentifier); 2512 flushCurrentScopingEffort(m_findRequestIdentifier);
2468 2513
2469 cancelPendingScopingEffort(); 2514 cancelPendingScopingEffort();
2470 } 2515 }
2471 } 2516 }
2472 2517
2473 } // namespace WebKit 2518 } // namespace WebKit
OLDNEW
« no previous file with comments | « Source/web/WebFrameImpl.h ('k') | Source/web/WebHelperPluginImpl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698