| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) | 2 * Copyright (C) 2009 Google Inc. All rights reserved. |
| 3 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. | |
| 4 * | 3 * |
| 5 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions are |
| 7 * are met: | 6 * met: |
| 8 * 1. Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | |
| 11 * notice, this list of conditions and the following disclaimer in the | |
| 12 * documentation and/or other materials provided with the distribution. | |
| 13 * | 7 * |
| 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 8 * * Redistributions of source code must retain the above copyright |
| 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 9 * notice, this list of conditions and the following disclaimer. |
| 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 10 * * Redistributions in binary form must reproduce the above |
| 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 11 * copyright notice, this list of conditions and the following disclaimer |
| 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 12 * in the documentation and/or other materials provided with the |
| 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 13 * distribution. |
| 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 14 * * Neither the name of Google Inc. nor the names of its |
| 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 15 * contributors may be used to endorse or promote products derived from |
| 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 16 * this software without specific prior written permission. |
| 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 */ | 29 */ |
| 26 | 30 |
| 27 // How ownership works | 31 // How ownership works |
| 28 // ------------------- | 32 // ------------------- |
| 29 // | 33 // |
| 30 // Big oh represents a refcounted relationship: owner O--- ownee | 34 // Big oh represents a refcounted relationship: owner O--- ownee |
| 31 // | 35 // |
| 32 // WebView (for the toplevel frame only) | 36 // WebView (for the toplevel frame only) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 58 // | 62 // |
| 59 // When frame content is replaced, all subframes are destroyed. This happens | 63 // When frame content is replaced, all subframes are destroyed. This happens |
| 60 // in FrameLoader::detachFromParent for each subframe. | 64 // in FrameLoader::detachFromParent for each subframe. |
| 61 // | 65 // |
| 62 // 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 |
| 63 // destructor, it notifies its client with frameLoaderDestroyed. This calls | 67 // destructor, it notifies its client with frameLoaderDestroyed. This calls |
| 64 // WebFrame::Closing and then derefs the WebFrame and will cause it to be | 68 // WebFrame::Closing and then derefs the WebFrame and will cause it to be |
| 65 // deleted (unless an external someone is also holding a reference). | 69 // deleted (unless an external someone is also holding a reference). |
| 66 | 70 |
| 67 #include "config.h" | 71 #include "config.h" |
| 72 #include "WebFrameImpl.h" |
| 68 | 73 |
| 69 #include <algorithm> | 74 #include <algorithm> |
| 70 #include <string> | |
| 71 | 75 |
| 72 #include "HTMLFormElement.h" // need this before Document.h | |
| 73 #include "Chrome.h" | 76 #include "Chrome.h" |
| 74 #include "ChromiumBridge.h" | 77 #include "ChromiumBridge.h" |
| 75 #include "ClipboardUtilitiesChromium.h" | 78 #include "ClipboardUtilitiesChromium.h" |
| 76 #include "Console.h" | 79 #include "Console.h" |
| 77 #include "Document.h" | 80 #include "Document.h" |
| 78 #include "DocumentFragment.h" // Only needed for ReplaceSelectionCommand.h :( | 81 #include "DocumentFragment.h" // Only needed for ReplaceSelectionCommand.h :( |
| 79 #include "DocumentLoader.h" | 82 #include "DocumentLoader.h" |
| 80 #include "DocumentMarker.h" | 83 #include "DocumentMarker.h" |
| 81 #include "DOMWindow.h" | 84 #include "DOMWindow.h" |
| 85 #include "DOMUtilitiesPrivate.h" |
| 82 #include "Editor.h" | 86 #include "Editor.h" |
| 83 #include "EventHandler.h" | 87 #include "EventHandler.h" |
| 84 #include "FormState.h" | 88 #include "FormState.h" |
| 85 #include "FrameChromium.h" | 89 #include "FrameChromium.h" |
| 86 #include "FrameLoader.h" | 90 #include "FrameLoader.h" |
| 87 #include "FrameLoadRequest.h" | 91 #include "FrameLoadRequest.h" |
| 88 #include "FrameTree.h" | 92 #include "FrameTree.h" |
| 89 #include "FrameView.h" | 93 #include "FrameView.h" |
| 90 #include "GraphicsContext.h" | 94 #include "GraphicsContext.h" |
| 91 #include "HTMLCollection.h" | 95 #include "HTMLCollection.h" |
| 92 #include "HTMLHeadElement.h" | 96 #include "HTMLHeadElement.h" |
| 93 #include "HTMLInputElement.h" | 97 #include "HTMLInputElement.h" |
| 98 #include "HTMLFormElement.h" |
| 94 #include "HTMLFrameOwnerElement.h" | 99 #include "HTMLFrameOwnerElement.h" |
| 95 #include "HTMLLinkElement.h" | 100 #include "HTMLLinkElement.h" |
| 96 #include "HTMLNames.h" | 101 #include "HTMLNames.h" |
| 97 #include "HistoryItem.h" | 102 #include "HistoryItem.h" |
| 98 #include "InspectorController.h" | 103 #include "InspectorController.h" |
| 99 #if PLATFORM(DARWIN) | |
| 100 #include "LocalCurrentGraphicsContext.h" | |
| 101 #endif | |
| 102 #include "markup.h" | 104 #include "markup.h" |
| 103 #include "Page.h" | 105 #include "Page.h" |
| 106 #include "PasswordAutocompleteListener.h" |
| 104 #include "PlatformContextSkia.h" | 107 #include "PlatformContextSkia.h" |
| 105 #include "PrintContext.h" | 108 #include "PrintContext.h" |
| 106 #include "RenderFrame.h" | 109 #include "RenderFrame.h" |
| 107 #if PLATFORM(WIN_OS) | |
| 108 #include "RenderThemeChromiumWin.h" | |
| 109 #endif | |
| 110 #include "RenderView.h" | 110 #include "RenderView.h" |
| 111 #include "RenderWidget.h" | 111 #include "RenderWidget.h" |
| 112 #include "ReplaceSelectionCommand.h" | 112 #include "ReplaceSelectionCommand.h" |
| 113 #include "ResourceHandle.h" | 113 #include "ResourceHandle.h" |
| 114 #include "ResourceRequest.h" | 114 #include "ResourceRequest.h" |
| 115 #include "ScriptController.h" | 115 #include "ScriptController.h" |
| 116 #include "ScriptSourceCode.h" | 116 #include "ScriptSourceCode.h" |
| 117 #include "ScriptValue.h" | 117 #include "ScriptValue.h" |
| 118 #include "ScrollbarTheme.h" | 118 #include "ScrollbarTheme.h" |
| 119 #include "ScrollTypes.h" | 119 #include "ScrollTypes.h" |
| 120 #include "SelectionController.h" | 120 #include "SelectionController.h" |
| 121 #include "Settings.h" | 121 #include "Settings.h" |
| 122 #include "SkiaUtils.h" | 122 #include "SkiaUtils.h" |
| 123 #include "SubstituteData.h" | 123 #include "SubstituteData.h" |
| 124 #include "TextIterator.h" | 124 #include "TextIterator.h" |
| 125 #include "TextAffinity.h" | 125 #include "TextAffinity.h" |
| 126 #include "XPathResult.h" | 126 #include "XPathResult.h" |
| 127 #include "WebConsoleMessage.h" |
| 128 #include "WebDataSourceImpl.h" |
| 129 #include "WebFindOptions.h" |
| 130 #include "WebForm.h" |
| 131 #include "WebFrameClient.h" |
| 132 #include "WebHistoryItem.h" |
| 133 #include "WebRange.h" |
| 134 #include "WebRect.h" |
| 135 #include "WebScriptSource.h" |
| 136 #include "WebSecurityOrigin.h" |
| 137 #include "WebSize.h" |
| 138 #include "WebURLError.h" |
| 139 #include "WebVector.h" |
| 140 #include "WebViewImpl.h" |
| 127 #include <wtf/CurrentTime.h> | 141 #include <wtf/CurrentTime.h> |
| 128 #undef LOG | 142 |
| 129 | 143 #if PLATFORM(DARWIN) |
| 130 #include "webkit/api/public/WebConsoleMessage.h" | 144 #include "LocalCurrentGraphicsContext.h" |
| 131 #include "webkit/api/public/WebFindOptions.h" | 145 #endif |
| 132 #include "webkit/api/public/WebForm.h" | |
| 133 #include "webkit/api/public/WebFrameClient.h" | |
| 134 #include "webkit/api/public/WebHistoryItem.h" | |
| 135 #include "webkit/api/public/WebRange.h" | |
| 136 #include "webkit/api/public/WebRect.h" | |
| 137 #include "webkit/api/public/WebScriptSource.h" | |
| 138 #include "webkit/api/public/WebSecurityOrigin.h" | |
| 139 #include "webkit/api/public/WebSize.h" | |
| 140 #include "webkit/api/public/WebURLError.h" | |
| 141 #include "webkit/api/public/WebVector.h" | |
| 142 #include "webkit/api/src/DOMUtilitiesPrivate.h" | |
| 143 #include "webkit/api/src/PasswordAutocompleteListener.h" | |
| 144 #include "webkit/api/src/WebDataSourceImpl.h" | |
| 145 #include "webkit/glue/glue_util.h" | |
| 146 #include "webkit/glue/webframe_impl.h" | |
| 147 #include "webkit/glue/webview_impl.h" | |
| 148 | 146 |
| 149 #if PLATFORM(LINUX) | 147 #if PLATFORM(LINUX) |
| 150 #include <gdk/gdk.h> | 148 #include <gdk/gdk.h> |
| 151 #endif | 149 #endif |
| 152 | 150 |
| 153 using WebCore::AtomicString; | 151 using namespace WebCore; |
| 154 using WebCore::ChromiumBridge; | 152 |
| 155 using WebCore::Color; | 153 namespace WebKit { |
| 156 using WebCore::Document; | |
| 157 using WebCore::DocumentFragment; | |
| 158 using WebCore::DocumentLoader; | |
| 159 using WebCore::ExceptionCode; | |
| 160 using WebCore::GraphicsContext; | |
| 161 using WebCore::HTMLFrameOwnerElement; | |
| 162 using WebCore::HTMLInputElement; | |
| 163 using WebCore::Frame; | |
| 164 using WebCore::FrameLoader; | |
| 165 using WebCore::FrameLoadRequest; | |
| 166 using WebCore::FrameLoadType; | |
| 167 using WebCore::FrameTree; | |
| 168 using WebCore::FrameView; | |
| 169 using WebCore::HistoryItem; | |
| 170 using WebCore::HTMLFormElement; | |
| 171 using WebCore::IntRect; | |
| 172 using WebCore::KURL; | |
| 173 using WebCore::Node; | |
| 174 using WebCore::Range; | |
| 175 using WebCore::ReloadIgnoringCacheData; | |
| 176 using WebCore::RenderObject; | |
| 177 using WebCore::ResourceError; | |
| 178 using WebCore::ResourceHandle; | |
| 179 using WebCore::ResourceRequest; | |
| 180 using WebCore::ResourceResponse; | |
| 181 using WebCore::VisibleSelection; | |
| 182 using WebCore::ScriptValue; | |
| 183 using WebCore::SecurityOrigin; | |
| 184 using WebCore::SharedBuffer; | |
| 185 using WebCore::String; | |
| 186 using WebCore::SubstituteData; | |
| 187 using WebCore::TextIterator; | |
| 188 using WebCore::Timer; | |
| 189 using WebCore::VisiblePosition; | |
| 190 using WebCore::XPathResult; | |
| 191 | |
| 192 using WebKit::PasswordAutocompleteListener; | |
| 193 using WebKit::WebCanvas; | |
| 194 using WebKit::WebConsoleMessage; | |
| 195 using WebKit::WebData; | |
| 196 using WebKit::WebDataSource; | |
| 197 using WebKit::WebDataSourceImpl; | |
| 198 using WebKit::WebFindOptions; | |
| 199 using WebKit::WebFrame; | |
| 200 using WebKit::WebFrameClient; | |
| 201 using WebKit::WebHistoryItem; | |
| 202 using WebKit::WebForm; | |
| 203 using WebKit::WebRange; | |
| 204 using WebKit::WebRect; | |
| 205 using WebKit::WebScriptSource; | |
| 206 using WebKit::WebSecurityOrigin; | |
| 207 using WebKit::WebSize; | |
| 208 using WebKit::WebString; | |
| 209 using WebKit::WebURL; | |
| 210 using WebKit::WebURLError; | |
| 211 using WebKit::WebURLRequest; | |
| 212 using WebKit::WebURLResponse; | |
| 213 using WebKit::WebVector; | |
| 214 using WebKit::WebView; | |
| 215 | 154 |
| 216 // Key for a StatsCounter tracking how many WebFrames are active. | 155 // Key for a StatsCounter tracking how many WebFrames are active. |
| 217 static const char* const kWebFrameActiveCount = "WebFrameActiveCount"; | 156 static const char* const webFrameActiveCount = "WebFrameActiveCount"; |
| 218 | 157 |
| 219 static const char* const kOSDType = "application/opensearchdescription+xml"; | 158 static const char* const osdType = "application/opensearchdescription+xml"; |
| 220 static const char* const kOSDRel = "search"; | 159 static const char* const osdRel = "search"; |
| 221 | |
| 222 // The separator between frames when the frames are converted to plain text. | |
| 223 static const wchar_t kFrameSeparator[] = L"\n\n"; | |
| 224 static const size_t kFrameSeparatorLen = arraysize(kFrameSeparator) - 1; | |
| 225 | 160 |
| 226 // Backend for contentAsPlainText, this is a recursive function that gets | 161 // Backend for contentAsPlainText, this is a recursive function that gets |
| 227 // the text for the current frame and all of its subframes. It will append | 162 // the text for the current frame and all of its subframes. It will append |
| 228 // the text of each frame in turn to the |output| up to |max_chars| length. | 163 // the text of each frame in turn to the |output| up to |maxChars| length. |
| 229 // | 164 // |
| 230 // The |frame| must be non-NULL. | 165 // The |frame| must be non-null. |
| 231 static void FrameContentAsPlainText(size_t max_chars, Frame* frame, | 166 static void frameContentAsPlainText(size_t maxChars, Frame* frame, |
| 232 Vector<UChar>* output) { | 167 Vector<UChar>* output) |
| 233 Document* doc = frame->document(); | 168 { |
| 234 if (!doc) | 169 Document* doc = frame->document(); |
| 235 return; | 170 if (!doc) |
| 236 | 171 return; |
| 237 if (!frame->view()) | 172 |
| 238 return; | 173 if (!frame->view()) |
| 239 | 174 return; |
| 240 // TextIterator iterates over the visual representation of the DOM. As such, | 175 |
| 241 // it requires you to do a layout before using it (otherwise it'll crash). | 176 // TextIterator iterates over the visual representation of the DOM. As such, |
| 242 if (frame->view()->needsLayout()) | 177 // it requires you to do a layout before using it (otherwise it'll crash). |
| 243 frame->view()->layout(); | 178 if (frame->view()->needsLayout()) |
| 244 | 179 frame->view()->layout(); |
| 245 // Select the document body. | 180 |
| 246 RefPtr<Range> range(doc->createRange()); | 181 // Select the document body. |
| 247 ExceptionCode exception = 0; | 182 RefPtr<Range> range(doc->createRange()); |
| 248 range->selectNodeContents(doc->body(), exception); | 183 ExceptionCode exception = 0; |
| 249 | 184 range->selectNodeContents(doc->body(), exception); |
| 250 if (exception == 0) { | 185 |
| 251 // The text iterator will walk nodes giving us text. This is similar to | 186 if (exception == 0) { |
| 252 // the plainText() function in TextIterator.h, but we implement the maximum | 187 // The text iterator will walk nodes giving us text. This is similar to |
| 253 // size and also copy the results directly into a wstring, avoiding the | 188 // the plainText() function in TextIterator.h, but we implement the maximum |
| 254 // string conversion. | 189 // size and also copy the results directly into a wstring, avoiding the |
| 255 for (TextIterator it(range.get()); !it.atEnd(); it.advance()) { | 190 // string conversion. |
| 256 const UChar* chars = it.characters(); | 191 for (TextIterator it(range.get()); !it.atEnd(); it.advance()) { |
| 257 if (!chars) { | 192 const UChar* chars = it.characters(); |
| 258 if (it.length() != 0) { | 193 if (!chars) { |
| 259 // It appears from crash reports that an iterator can get into a state | 194 if (it.length() != 0) { |
| 260 // where the character count is nonempty but the character pointer is | 195 // It appears from crash reports that an iterator can get into a state |
| 261 // NULL. advance()ing it will then just add that many to the NULL | 196 // where the character count is nonempty but the character pointer is |
| 262 // pointer which won't be caught in a NULL check but will crash. | 197 // null. advance()ing it will then just add that many to the null |
| 263 // | 198 // pointer which won't be caught in a null check but will crash. |
| 264 // A NULL pointer and 0 length is common for some nodes. | 199 // |
| 265 // | 200 // A null pointer and 0 length is common for some nodes. |
| 266 // IF YOU CATCH THIS IN A DEBUGGER please let brettw know. We don't | 201 // |
| 267 // currently understand the conditions for this to occur. Ideally, the | 202 // IF YOU CATCH THIS IN A DEBUGGER please let brettw know. We don't |
| 268 // iterators would never get into the condition so we should fix them | 203 // currently understand the conditions for this to occur. Ideally, the |
| 269 // if we can. | 204 // iterators would never get into the condition so we should fix them |
| 270 ASSERT_NOT_REACHED(); | 205 // if we can. |
| 271 break; | 206 ASSERT_NOT_REACHED(); |
| 207 break; |
| 208 } |
| 209 |
| 210 // Just got a null node, we can forge ahead! |
| 211 continue; |
| 212 } |
| 213 size_t toAppend = |
| 214 std::min(static_cast<size_t>(it.length()), maxChars - output->size()); |
| 215 output->append(chars, toAppend); |
| 216 if (output->size() >= maxChars) |
| 217 return; // Filled up the buffer. |
| 272 } | 218 } |
| 273 | 219 } |
| 274 // Just got a NULL node, we can forge ahead! | 220 |
| 275 continue; | 221 // The separator between frames when the frames are converted to plain text. |
| 276 } | 222 const UChar frameSeparator[] = { '\n', '\n' }; |
| 277 size_t to_append = std::min(static_cast<size_t>(it.length()), | 223 const size_t frameSeparatorLen = 2; |
| 278 max_chars - output->size()); | 224 |
| 279 output->append(chars, to_append); | 225 // Recursively walk the children. |
| 280 if (output->size() >= max_chars) | 226 FrameTree* frameTree = frame->tree(); |
| 281 return; // Filled up the buffer. | 227 for (Frame* curChild = frameTree->firstChild(); curChild; curChild = curChild->tree()->nextSibling()) { |
| 282 } | 228 // Make sure the frame separator won't fill up the buffer, and give up if |
| 283 } | 229 // it will. The danger is if the separator will make the buffer longer than |
| 284 | 230 // maxChars. This will cause the computation above: |
| 285 // Recursively walk the children. | 231 // maxChars - output->size() |
| 286 FrameTree* frame_tree = frame->tree(); | 232 // to be a negative number which will crash when the subframe is added. |
| 287 for (Frame* cur_child = frame_tree->firstChild(); cur_child; | 233 if (output->size() >= maxChars - frameSeparatorLen) |
| 288 cur_child = cur_child->tree()->nextSibling()) { | 234 return; |
| 289 // Make sure the frame separator won't fill up the buffer, and give up if | 235 |
| 290 // it will. The danger is if the separator will make the buffer longer than | 236 output->append(frameSeparator, frameSeparatorLen); |
| 291 // max_chars. This will cause the computation above: | 237 frameContentAsPlainText(maxChars, curChild, output); |
| 292 // max_chars - output->size() | 238 if (output->size() >= maxChars) |
| 293 // to be a negative number which will crash when the subframe is added. | 239 return; // Filled up the buffer. |
| 294 if (output->size() >= max_chars - kFrameSeparatorLen) | 240 } |
| 295 return; | |
| 296 | |
| 297 output->append(kFrameSeparator, kFrameSeparatorLen); | |
| 298 FrameContentAsPlainText(max_chars, cur_child, output); | |
| 299 if (output->size() >= max_chars) | |
| 300 return; // Filled up the buffer. | |
| 301 } | |
| 302 } | 241 } |
| 303 | 242 |
| 304 // Simple class to override some of PrintContext behavior. | 243 // Simple class to override some of PrintContext behavior. |
| 305 class ChromePrintContext : public WebCore::PrintContext { | 244 class ChromePrintContext : public PrintContext, public Noncopyable { |
| 306 public: | 245 public: |
| 307 ChromePrintContext(Frame* frame) | 246 ChromePrintContext(Frame* frame) |
| 308 : PrintContext(frame), | 247 : PrintContext(frame) |
| 309 printed_page_width_(0) { | 248 , m_printedPageWidth(0) |
| 310 } | 249 { |
| 311 void begin(float width) { | 250 } |
| 312 ASSERT(!printed_page_width_); | 251 |
| 313 printed_page_width_ = width; | 252 void begin(float width) |
| 314 WebCore::PrintContext::begin(printed_page_width_); | 253 { |
| 315 } | 254 ASSERT(!m_printedPageWidth); |
| 316 float getPageShrink(int pageNumber) const { | 255 m_printedPageWidth = width; |
| 317 IntRect pageRect = m_pageRects[pageNumber]; | 256 PrintContext::begin(m_printedPageWidth); |
| 318 return printed_page_width_ / pageRect.width(); | 257 } |
| 319 } | 258 |
| 320 // Spools the printed page, a subrect of m_frame. | 259 float getPageShrink(int pageNumber) const |
| 321 // Skip the scale step. NativeTheme doesn't play well with scaling. Scaling | 260 { |
| 322 // is done browser side instead. | 261 IntRect pageRect = m_pageRects[pageNumber]; |
| 323 // Returns the scale to be applied. | 262 return m_printedPageWidth / pageRect.width(); |
| 324 float spoolPage(GraphicsContext& ctx, int pageNumber) { | 263 } |
| 325 IntRect pageRect = m_pageRects[pageNumber]; | 264 |
| 326 float scale = printed_page_width_ / pageRect.width(); | 265 // Spools the printed page, a subrect of m_frame. Skip the scale step. |
| 327 | 266 // NativeTheme doesn't play well with scaling. Scaling is done browser side |
| 328 ctx.save(); | 267 // instead. Returns the scale to be applied. |
| 329 ctx.translate(static_cast<float>(-pageRect.x()), | 268 float spoolPage(GraphicsContext& ctx, int pageNumber) |
| 330 static_cast<float>(-pageRect.y())); | 269 { |
| 331 ctx.clip(pageRect); | 270 IntRect pageRect = m_pageRects[pageNumber]; |
| 332 m_frame->view()->paintContents(&ctx, pageRect); | 271 float scale = m_printedPageWidth / pageRect.width(); |
| 333 ctx.restore(); | 272 |
| 334 return scale; | 273 ctx.save(); |
| 335 } | 274 ctx.translate(static_cast<float>(-pageRect.x()), |
| 336 protected: | 275 static_cast<float>(-pageRect.y())); |
| 337 // Set when printing. | 276 ctx.clip(pageRect); |
| 338 float printed_page_width_; | 277 m_frame->view()->paintContents(&ctx, pageRect); |
| 339 | 278 ctx.restore(); |
| 340 private: | 279 return scale; |
| 341 DISALLOW_COPY_AND_ASSIGN(ChromePrintContext); | 280 } |
| 281 |
| 282 private: |
| 283 // Set when printing. |
| 284 float m_printedPageWidth; |
| 342 }; | 285 }; |
| 343 | 286 |
| 344 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader) { | 287 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader) |
| 345 return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : NULL; | 288 { |
| 289 return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0; |
| 346 } | 290 } |
| 347 | 291 |
| 348 | 292 |
| 349 // WebFrame ------------------------------------------------------------------- | 293 // WebFrame ------------------------------------------------------------------- |
| 350 | 294 |
| 351 class WebFrameImpl::DeferredScopeStringMatches { | 295 class WebFrameImpl::DeferredScopeStringMatches { |
| 352 public: | 296 public: |
| 353 DeferredScopeStringMatches(WebFrameImpl* webframe, | 297 DeferredScopeStringMatches(WebFrameImpl* webFrame, |
| 354 int identifier, | 298 int identifier, |
| 355 const WebString& search_text, | 299 const WebString& searchText, |
| 356 const WebFindOptions& options, | 300 const WebFindOptions& options, |
| 357 bool reset) | 301 bool reset) |
| 358 : ALLOW_THIS_IN_INITIALIZER_LIST( | 302 : m_timer(this, &DeferredScopeStringMatches::doTimeout) |
| 359 timer_(this, &DeferredScopeStringMatches::DoTimeout)), | 303 , m_webFrame(webFrame) |
| 360 webframe_(webframe), | 304 , m_identifier(identifier) |
| 361 identifier_(identifier), | 305 , m_searchText(searchText) |
| 362 search_text_(search_text), | 306 , m_options(options) |
| 363 options_(options), | 307 , m_reset(reset) |
| 364 reset_(reset) { | 308 { |
| 365 timer_.startOneShot(0.0); | 309 m_timer.startOneShot(0.0); |
| 366 } | 310 } |
| 367 | 311 |
| 368 private: | 312 private: |
| 369 void DoTimeout(Timer<DeferredScopeStringMatches>*) { | 313 void doTimeout(Timer<DeferredScopeStringMatches>*) |
| 370 webframe_->CallScopeStringMatches( | 314 { |
| 371 this, identifier_, search_text_, options_, reset_); | 315 m_webFrame->callScopeStringMatches( |
| 372 } | 316 this, m_identifier, m_searchText, m_options, m_reset); |
| 373 | 317 } |
| 374 Timer<DeferredScopeStringMatches> timer_; | 318 |
| 375 RefPtr<WebFrameImpl> webframe_; | 319 Timer<DeferredScopeStringMatches> m_timer; |
| 376 int identifier_; | 320 RefPtr<WebFrameImpl> m_webFrame; |
| 377 WebString search_text_; | 321 int m_identifier; |
| 378 WebFindOptions options_; | 322 WebString m_searchText; |
| 379 bool reset_; | 323 WebFindOptions m_options; |
| 324 bool m_reset; |
| 380 }; | 325 }; |
| 381 | 326 |
| 382 | 327 |
| 383 // WebFrame ------------------------------------------------------------------- | 328 // WebFrame ------------------------------------------------------------------- |
| 384 | 329 |
| 385 // static | 330 WebFrame* WebFrame::frameForEnteredContext() |
| 386 WebFrame* WebFrame::frameForEnteredContext() { | 331 { |
| 387 Frame* frame = | 332 Frame* frame = |
| 388 WebCore::ScriptController::retrieveFrameForEnteredContext(); | 333 ScriptController::retrieveFrameForEnteredContext(); |
| 389 return WebFrameImpl::FromFrame(frame); | 334 return WebFrameImpl::fromFrame(frame); |
| 390 } | 335 } |
| 391 | 336 |
| 392 // static | 337 WebFrame* WebFrame::frameForCurrentContext() |
| 393 WebFrame* WebFrame::frameForCurrentContext() { | 338 { |
| 394 Frame* frame = | 339 Frame* frame = |
| 395 WebCore::ScriptController::retrieveFrameForCurrentContext(); | 340 ScriptController::retrieveFrameForCurrentContext(); |
| 396 return WebFrameImpl::FromFrame(frame); | 341 return WebFrameImpl::fromFrame(frame); |
| 397 } | 342 } |
| 398 | 343 |
| 399 WebString WebFrameImpl::name() const { | 344 WebString WebFrameImpl::name() const |
| 400 return webkit_glue::StringToWebString(frame_->tree()->name()); | 345 { |
| 401 } | 346 return m_frame->tree()->name(); |
| 402 | 347 } |
| 403 WebURL WebFrameImpl::url() const { | 348 |
| 404 const WebDataSource* ds = dataSource(); | 349 WebURL WebFrameImpl::url() const |
| 405 if (!ds) | 350 { |
| 351 const WebDataSource* ds = dataSource(); |
| 352 if (!ds) |
| 353 return WebURL(); |
| 354 return ds->request().url(); |
| 355 } |
| 356 |
| 357 WebURL WebFrameImpl::favIconURL() const |
| 358 { |
| 359 FrameLoader* frameLoader = m_frame->loader(); |
| 360 // The URL to the favicon may be in the header. As such, only |
| 361 // ask the loader for the favicon if it's finished loading. |
| 362 if (frameLoader->state() == FrameStateComplete) { |
| 363 const KURL& url = frameLoader->iconURL(); |
| 364 if (!url.isEmpty()) |
| 365 return url; |
| 366 } |
| 406 return WebURL(); | 367 return WebURL(); |
| 407 return ds->request().url(); | 368 } |
| 408 } | 369 |
| 409 | 370 WebURL WebFrameImpl::openSearchDescriptionURL() const |
| 410 WebURL WebFrameImpl::favIconURL() const { | 371 { |
| 411 WebCore::FrameLoader* frame_loader = frame_->loader(); | 372 FrameLoader* frameLoader = m_frame->loader(); |
| 412 // The URL to the favicon may be in the header. As such, only | 373 if (frameLoader->state() == FrameStateComplete |
| 413 // ask the loader for the favicon if it's finished loading. | 374 && m_frame->document() && m_frame->document()->head() |
| 414 if (frame_loader->state() == WebCore::FrameStateComplete) { | 375 && !m_frame->tree()->parent()) { |
| 415 const KURL& url = frame_loader->iconURL(); | 376 HTMLHeadElement* head = m_frame->document()->head(); |
| 416 if (!url.isEmpty()) { | 377 if (head) { |
| 417 return webkit_glue::KURLToWebURL(url); | 378 RefPtr<HTMLCollection> children = head->children(); |
| 418 } | 379 for (Node* child = children->firstItem(); child != 0; child = children->nextItem()) { |
| 419 } | 380 HTMLLinkElement* linkElement = toHTMLLinkElement(child); |
| 420 return WebURL(); | 381 if (linkElement |
| 421 } | 382 && linkElement->type() == osdType |
| 422 | 383 && linkElement->rel() == osdRel |
| 423 WebURL WebFrameImpl::openSearchDescriptionURL() const { | 384 && !linkElement->href().isEmpty()) |
| 424 WebCore::FrameLoader* frame_loader = frame_->loader(); | 385 return linkElement->href(); |
| 425 if (frame_loader->state() == WebCore::FrameStateComplete && | 386 } |
| 426 frame_->document() && frame_->document()->head() && | |
| 427 !frame_->tree()->parent()) { | |
| 428 WebCore::HTMLHeadElement* head = frame_->document()->head(); | |
| 429 if (head) { | |
| 430 RefPtr<WebCore::HTMLCollection> children = head->children(); | |
| 431 for (Node* child = children->firstItem(); child != NULL; | |
| 432 child = children->nextItem()) { | |
| 433 WebCore::HTMLLinkElement* link_element = | |
| 434 WebKit::toHTMLLinkElement(child); | |
| 435 if (link_element && link_element->type() == kOSDType && | |
| 436 link_element->rel() == kOSDRel && !link_element->href().isEmpty()) { | |
| 437 return webkit_glue::KURLToWebURL(link_element->href()); | |
| 438 } | 387 } |
| 439 } | 388 } |
| 440 } | 389 return WebURL(); |
| 441 } | 390 } |
| 442 return WebURL(); | 391 |
| 443 } | 392 WebSize WebFrameImpl::scrollOffset() const |
| 444 | 393 { |
| 445 WebSize WebFrameImpl::scrollOffset() const { | 394 FrameView* view = frameView(); |
| 446 WebCore::FrameView* view = frameview(); | 395 if (view) |
| 447 if (view) | 396 return view->scrollOffset(); |
| 448 return webkit_glue::IntSizeToWebSize(view->scrollOffset()); | 397 |
| 449 | 398 return WebSize(); |
| 450 return WebSize(); | 399 } |
| 451 } | 400 |
| 452 | 401 WebSize WebFrameImpl::contentsSize() const |
| 453 WebSize WebFrameImpl::contentsSize() const { | 402 { |
| 454 return webkit_glue::IntSizeToWebSize(frame()->view()->contentsSize()); | 403 return frame()->view()->contentsSize(); |
| 455 } | 404 } |
| 456 | 405 |
| 457 int WebFrameImpl::contentsPreferredWidth() const { | 406 int WebFrameImpl::contentsPreferredWidth() const |
| 458 if ((frame_->document() != NULL) && | 407 { |
| 459 (frame_->document()->renderView() != NULL)) { | 408 if ((m_frame->document() != 0) && (m_frame->document()->renderView() != 0)) |
| 460 return frame_->document()->renderView()->minPrefWidth(); | 409 return m_frame->document()->renderView()->minPrefWidth(); |
| 461 } else { | 410 |
| 462 return 0; | 411 return 0; |
| 463 } | 412 } |
| 464 } | 413 |
| 465 | 414 bool WebFrameImpl::hasVisibleContent() const |
| 466 bool WebFrameImpl::hasVisibleContent() const { | 415 { |
| 467 return frame()->view()->visibleWidth() > 0 && | 416 return frame()->view()->visibleWidth() > 0 && frame()->view()->visibleHeight() > 0; |
| 468 frame()->view()->visibleHeight() > 0; | 417 } |
| 469 } | 418 |
| 470 | 419 WebView* WebFrameImpl::view() const |
| 471 WebView* WebFrameImpl::view() const { | 420 { |
| 472 return GetWebViewImpl(); | 421 return viewImpl(); |
| 473 } | 422 } |
| 474 | 423 |
| 475 WebFrame* WebFrameImpl::opener() const { | 424 WebFrame* WebFrameImpl::opener() const |
| 476 Frame* opener = NULL; | 425 { |
| 477 if (frame_) | 426 Frame* opener = 0; |
| 478 opener = frame_->loader()->opener(); | 427 if (m_frame) |
| 479 return FromFrame(opener); | 428 opener = m_frame->loader()->opener(); |
| 480 } | 429 return fromFrame(opener); |
| 481 | 430 } |
| 482 WebFrame* WebFrameImpl::parent() const { | 431 |
| 483 Frame *parent = NULL; | 432 WebFrame* WebFrameImpl::parent() const |
| 484 if (frame_) | 433 { |
| 485 parent = frame_->tree()->parent(); | 434 Frame *parent = 0; |
| 486 return FromFrame(parent); | 435 if (m_frame) |
| 487 } | 436 parent = m_frame->tree()->parent(); |
| 488 | 437 return fromFrame(parent); |
| 489 WebFrame* WebFrameImpl::top() const { | 438 } |
| 490 if (frame_) | 439 |
| 491 return FromFrame(frame_->tree()->top()); | 440 WebFrame* WebFrameImpl::top() const |
| 492 | 441 { |
| 493 return NULL; | 442 if (m_frame) |
| 494 } | 443 return fromFrame(m_frame->tree()->top()); |
| 495 | 444 |
| 496 WebFrame* WebFrameImpl::firstChild() const { | 445 return 0; |
| 497 return FromFrame(frame()->tree()->firstChild()); | 446 } |
| 498 } | 447 |
| 499 | 448 WebFrame* WebFrameImpl::firstChild() const |
| 500 WebFrame* WebFrameImpl::lastChild() const { | 449 { |
| 501 return FromFrame(frame()->tree()->lastChild()); | 450 return fromFrame(frame()->tree()->firstChild()); |
| 502 } | 451 } |
| 503 | 452 |
| 504 WebFrame* WebFrameImpl::nextSibling() const { | 453 WebFrame* WebFrameImpl::lastChild() const |
| 505 return FromFrame(frame()->tree()->nextSibling()); | 454 { |
| 506 } | 455 return fromFrame(frame()->tree()->lastChild()); |
| 507 | 456 } |
| 508 WebFrame* WebFrameImpl::previousSibling() const { | 457 |
| 509 return FromFrame(frame()->tree()->previousSibling()); | 458 WebFrame* WebFrameImpl::nextSibling() const |
| 510 } | 459 { |
| 511 | 460 return fromFrame(frame()->tree()->nextSibling()); |
| 512 WebFrame* WebFrameImpl::traverseNext(bool wrap) const { | 461 } |
| 513 return FromFrame(frame()->tree()->traverseNextWithWrap(wrap)); | 462 |
| 514 } | 463 WebFrame* WebFrameImpl::previousSibling() const |
| 515 | 464 { |
| 516 WebFrame* WebFrameImpl::traversePrevious(bool wrap) const { | 465 return fromFrame(frame()->tree()->previousSibling()); |
| 517 return FromFrame(frame()->tree()->traversePreviousWithWrap(wrap)); | 466 } |
| 518 } | 467 |
| 519 | 468 WebFrame* WebFrameImpl::traverseNext(bool wrap) const |
| 520 WebFrame* WebFrameImpl::findChildByName(const WebKit::WebString& name) const { | 469 { |
| 521 return FromFrame(frame()->tree()->child( | 470 return fromFrame(frame()->tree()->traverseNextWithWrap(wrap)); |
| 522 webkit_glue::WebStringToString(name))); | 471 } |
| 523 } | 472 |
| 524 | 473 WebFrame* WebFrameImpl::traversePrevious(bool wrap) const |
| 525 WebFrame* WebFrameImpl::findChildByExpression( | 474 { |
| 526 const WebKit::WebString& xpath) const { | 475 return fromFrame(frame()->tree()->traversePreviousWithWrap(wrap)); |
| 527 if (xpath.isEmpty()) | 476 } |
| 528 return NULL; | 477 |
| 529 | 478 WebFrame* WebFrameImpl::findChildByName(const WebString& name) const |
| 530 Document* document = frame_->document(); | 479 { |
| 531 | 480 return fromFrame(frame()->tree()->child(name)); |
| 532 ExceptionCode ec = 0; | 481 } |
| 533 PassRefPtr<XPathResult> xpath_result = | 482 |
| 534 document->evaluate(webkit_glue::WebStringToString(xpath), | 483 WebFrame* WebFrameImpl::findChildByExpression(const WebString& xpath) const |
| 535 document, | 484 { |
| 536 NULL, /* namespace */ | 485 if (xpath.isEmpty()) |
| 537 XPathResult::ORDERED_NODE_ITERATOR_TYPE, | 486 return 0; |
| 538 NULL, /* XPathResult object */ | 487 |
| 539 ec); | 488 Document* document = m_frame->document(); |
| 540 if (!xpath_result.get()) | 489 |
| 541 return NULL; | 490 ExceptionCode ec = 0; |
| 542 | 491 PassRefPtr<XPathResult> xpathResult = |
| 543 Node* node = xpath_result->iterateNext(ec); | 492 document->evaluate(xpath, |
| 544 | 493 document, |
| 545 if (!node || !node->isFrameOwnerElement()) | 494 0, // namespace |
| 546 return NULL; | 495 XPathResult::ORDERED_NODE_ITERATOR_TYPE, |
| 547 HTMLFrameOwnerElement* frame_element = | 496 0, // XPathResult object |
| 548 static_cast<HTMLFrameOwnerElement*>(node); | 497 ec); |
| 549 return FromFrame(frame_element->contentFrame()); | 498 if (!xpathResult.get()) |
| 550 } | 499 return 0; |
| 551 | 500 |
| 552 void WebFrameImpl::forms(WebVector<WebForm>& results) const { | 501 Node* node = xpathResult->iterateNext(ec); |
| 553 if (!frame_) | 502 |
| 554 return; | 503 if (!node || !node->isFrameOwnerElement()) |
| 555 | 504 return 0; |
| 556 RefPtr<WebCore::HTMLCollection> forms = frame_->document()->forms(); | 505 HTMLFrameOwnerElement* frameElement = |
| 557 size_t form_count = forms->length(); | 506 static_cast<HTMLFrameOwnerElement*>(node); |
| 558 | 507 return fromFrame(frameElement->contentFrame()); |
| 559 WebVector<WebForm> temp(form_count); | 508 } |
| 560 for (size_t i = 0; i < form_count; ++i) { | 509 |
| 561 Node* node = forms->item(i); | 510 void WebFrameImpl::forms(WebVector<WebForm>& results) const |
| 562 // Strange but true, sometimes item can be NULL. | 511 { |
| 563 if (node) { | 512 if (!m_frame) |
| 564 temp[i] = webkit_glue::HTMLFormElementToWebForm( | 513 return; |
| 565 static_cast<HTMLFormElement*>(node)); | 514 |
| 566 } | 515 RefPtr<HTMLCollection> forms = m_frame->document()->forms(); |
| 567 } | 516 size_t formCount = forms->length(); |
| 568 results.swap(temp); | 517 |
| 569 } | 518 WebVector<WebForm> temp(formCount); |
| 570 | 519 for (size_t i = 0; i < formCount; ++i) { |
| 571 WebSecurityOrigin WebFrameImpl::securityOrigin() const { | 520 Node* node = forms->item(i); |
| 572 if (!frame_ || !frame_->document()) | 521 // Strange but true, sometimes item can be 0. |
| 573 return WebSecurityOrigin(); | 522 if (node) |
| 574 | 523 temp[i] = static_cast<HTMLFormElement*>(node); |
| 575 return webkit_glue::SecurityOriginToWebSecurityOrigin( | 524 } |
| 576 frame_->document()->securityOrigin()); | 525 results.swap(temp); |
| 577 } | 526 } |
| 578 | 527 |
| 579 void WebFrameImpl::grantUniversalAccess() { | 528 WebSecurityOrigin WebFrameImpl::securityOrigin() const |
| 580 ASSERT(frame_ && frame_->document()); | 529 { |
| 581 if (frame_ && frame_->document()) { | 530 if (!m_frame || !m_frame->document()) |
| 582 frame_->document()->securityOrigin()->grantUniversalAccess(); | 531 return WebSecurityOrigin(); |
| 583 } | 532 |
| 584 } | 533 return WebSecurityOrigin(m_frame->document()->securityOrigin()); |
| 585 | 534 } |
| 586 NPObject* WebFrameImpl::windowObject() const { | 535 |
| 587 if (!frame_) | 536 void WebFrameImpl::grantUniversalAccess() |
| 588 return NULL; | 537 { |
| 589 | 538 ASSERT(m_frame && m_frame->document()); |
| 590 return frame_->script()->windowScriptNPObject(); | 539 if (m_frame && m_frame->document()) |
| 591 } | 540 m_frame->document()->securityOrigin()->grantUniversalAccess(); |
| 592 | 541 } |
| 593 void WebFrameImpl::bindToWindowObject(const WebString& name, | 542 |
| 594 NPObject* object) { | 543 NPObject* WebFrameImpl::windowObject() const |
| 595 ASSERT(frame_); | 544 { |
| 596 if (!frame_ || !frame_->script()->isEnabled()) | 545 if (!m_frame) |
| 597 return; | 546 return 0; |
| 598 | 547 |
| 599 String key = webkit_glue::WebStringToString(name); | 548 return m_frame->script()->windowScriptNPObject(); |
| 549 } |
| 550 |
| 551 void WebFrameImpl::bindToWindowObject(const WebString& name, NPObject* object) |
| 552 { |
| 553 ASSERT(m_frame); |
| 554 if (!m_frame || !m_frame->script()->isEnabled()) |
| 555 return; |
| 556 |
| 557 String key = name; |
| 600 #if USE(V8) | 558 #if USE(V8) |
| 601 frame_->script()->bindToWindowObject(frame_, key, object); | 559 m_frame->script()->bindToWindowObject(m_frame, key, object); |
| 602 #else | 560 #else |
| 603 notImplemented(); | 561 notImplemented(); |
| 604 #endif | 562 #endif |
| 605 } | 563 } |
| 606 | 564 |
| 607 void WebFrameImpl::executeScript(const WebScriptSource& source) { | 565 void WebFrameImpl::executeScript(const WebScriptSource& source) |
| 608 frame_->script()->executeScript( | 566 { |
| 609 WebCore::ScriptSourceCode( | 567 m_frame->script()->executeScript( |
| 610 webkit_glue::WebStringToString(source.code), | 568 ScriptSourceCode(source.code, source.url, source.startLine)); |
| 611 webkit_glue::WebURLToKURL(source.url), | |
| 612 source.startLine)); | |
| 613 } | 569 } |
| 614 | 570 |
| 615 void WebFrameImpl::executeScriptInNewContext( | 571 void WebFrameImpl::executeScriptInNewContext( |
| 616 const WebScriptSource* sources_in, unsigned num_sources, | 572 const WebScriptSource* sourcesIn, unsigned numSources, int extensionGroup) |
| 617 int extension_group) { | 573 { |
| 618 Vector<WebCore::ScriptSourceCode> sources; | 574 Vector<ScriptSourceCode> sources; |
| 619 | 575 |
| 620 for (unsigned i = 0; i < num_sources; ++i) { | 576 for (unsigned i = 0; i < numSources; ++i) { |
| 621 sources.append(WebCore::ScriptSourceCode( | 577 sources.append(ScriptSourceCode( |
| 622 webkit_glue::WebStringToString(sources_in[i].code), | 578 sourcesIn[i].code, sourcesIn[i].url, sourcesIn[i].startLine)); |
| 623 webkit_glue::WebURLToKURL(sources_in[i].url), | 579 } |
| 624 sources_in[i].startLine)); | 580 |
| 625 } | 581 m_frame->script()->evaluateInNewContext(sources, extensionGroup); |
| 626 | |
| 627 frame_->script()->evaluateInNewContext(sources, extension_group); | |
| 628 } | 582 } |
| 629 | 583 |
| 630 void WebFrameImpl::executeScriptInIsolatedWorld( | 584 void WebFrameImpl::executeScriptInIsolatedWorld( |
| 631 int world_id, const WebScriptSource* sources_in, unsigned num_sources, | 585 int worldId, const WebScriptSource* sourcesIn, unsigned numSources, |
| 632 int extension_group) { | 586 int extensionGroup) |
| 633 Vector<WebCore::ScriptSourceCode> sources; | 587 { |
| 634 | 588 Vector<ScriptSourceCode> sources; |
| 635 for (unsigned i = 0; i < num_sources; ++i) { | 589 |
| 636 sources.append(WebCore::ScriptSourceCode( | 590 for (unsigned i = 0; i < numSources; ++i) { |
| 637 webkit_glue::WebStringToString(sources_in[i].code), | 591 sources.append(ScriptSourceCode( |
| 638 webkit_glue::WebURLToKURL(sources_in[i].url), | 592 sourcesIn[i].code, sourcesIn[i].url, sourcesIn[i].startLine)); |
| 639 sources_in[i].startLine)); | 593 } |
| 640 } | 594 |
| 641 | 595 m_frame->script()->evaluateInIsolatedWorld(worldId, sources, extensionGroup); |
| 642 frame_->script()->evaluateInIsolatedWorld(world_id, sources, extension_group); | 596 } |
| 643 } | 597 |
| 644 | 598 void WebFrameImpl::addMessageToConsole(const WebConsoleMessage& message) |
| 645 void WebFrameImpl::addMessageToConsole(const WebConsoleMessage& message) { | 599 { |
| 646 ASSERT(frame()); | 600 ASSERT(frame()); |
| 647 | 601 |
| 648 WebCore::MessageLevel webcore_message_level; | 602 MessageLevel webCoreMessageLevel; |
| 649 switch (message.level) { | 603 switch (message.level) { |
| 650 case WebConsoleMessage::LevelTip: | 604 case WebConsoleMessage::LevelTip: |
| 651 webcore_message_level = WebCore::TipMessageLevel; | 605 webCoreMessageLevel = TipMessageLevel; |
| 652 break; | 606 break; |
| 653 case WebConsoleMessage::LevelLog: | 607 case WebConsoleMessage::LevelLog: |
| 654 webcore_message_level = WebCore::LogMessageLevel; | 608 webCoreMessageLevel = LogMessageLevel; |
| 655 break; | 609 break; |
| 656 case WebConsoleMessage::LevelWarning: | 610 case WebConsoleMessage::LevelWarning: |
| 657 webcore_message_level = WebCore::WarningMessageLevel; | 611 webCoreMessageLevel = WarningMessageLevel; |
| 658 break; | 612 break; |
| 659 case WebConsoleMessage::LevelError: | 613 case WebConsoleMessage::LevelError: |
| 660 webcore_message_level = WebCore::ErrorMessageLevel; | 614 webCoreMessageLevel = ErrorMessageLevel; |
| 661 break; | 615 break; |
| 662 default: | 616 default: |
| 663 ASSERT_NOT_REACHED(); | 617 ASSERT_NOT_REACHED(); |
| 664 return; | 618 return; |
| 665 } | 619 } |
| 666 | 620 |
| 667 frame()->domWindow()->console()->addMessage( | 621 frame()->domWindow()->console()->addMessage( |
| 668 WebCore::OtherMessageSource, WebCore::LogMessageType, | 622 OtherMessageSource, LogMessageType, webCoreMessageLevel, message.text, |
| 669 webcore_message_level, webkit_glue::WebStringToString(message.text), | 623 1, String()); |
| 670 1, String()); | 624 } |
| 671 } | 625 |
| 672 | 626 void WebFrameImpl::collectGarbage() |
| 673 void WebFrameImpl::collectGarbage() { | 627 { |
| 674 if (!frame_) | 628 if (!m_frame) |
| 675 return; | 629 return; |
| 676 if (!frame_->settings()->isJavaScriptEnabled()) | 630 if (!m_frame->settings()->isJavaScriptEnabled()) |
| 677 return; | 631 return; |
| 678 // TODO(mbelshe): Move this to the ScriptController and make it JS neutral. | 632 // FIXME: Move this to the ScriptController and make it JS neutral. |
| 679 #if USE(V8) | 633 #if USE(V8) |
| 680 frame_->script()->collectGarbage(); | 634 m_frame->script()->collectGarbage(); |
| 681 #else | 635 #else |
| 682 notImplemented(); | 636 notImplemented(); |
| 683 #endif | 637 #endif |
| 684 } | 638 } |
| 685 | 639 |
| 686 #if USE(V8) | 640 #if USE(V8) |
| 687 // Returns the V8 context for this frame, or an empty handle if there is none. | 641 // Returns the V8 context for this frame, or an empty handle if there is none. |
| 688 v8::Local<v8::Context> WebFrameImpl::mainWorldScriptContext() const { | 642 v8::Local<v8::Context> WebFrameImpl::mainWorldScriptContext() const |
| 689 if (!frame_) | 643 { |
| 690 return v8::Local<v8::Context>(); | 644 if (!m_frame) |
| 691 | 645 return v8::Local<v8::Context>(); |
| 692 return WebCore::V8Proxy::mainWorldContext(frame_); | 646 |
| 647 return V8Proxy::mainWorldContext(m_frame); |
| 693 } | 648 } |
| 694 #endif | 649 #endif |
| 695 | 650 |
| 696 bool WebFrameImpl::insertStyleText( | 651 bool WebFrameImpl::insertStyleText( |
| 697 const WebString& css, const WebString& id) { | 652 const WebString& css, const WebString& id) { |
| 698 Document* document = frame()->document(); | 653 Document* document = frame()->document(); |
| 699 if (!document) | 654 if (!document) |
| 655 return false; |
| 656 Element* documentElement = document->documentElement(); |
| 657 if (!documentElement) |
| 658 return false; |
| 659 |
| 660 ExceptionCode err = 0; |
| 661 |
| 662 if (!id.isEmpty()) { |
| 663 Element* oldElement = document->getElementById(id); |
| 664 if (oldElement) { |
| 665 Node* parent = oldElement->parent(); |
| 666 if (!parent) |
| 667 return false; |
| 668 parent->removeChild(oldElement, err); |
| 669 } |
| 670 } |
| 671 |
| 672 RefPtr<Element> stylesheet = document->createElement( |
| 673 HTMLNames::styleTag, false); |
| 674 if (!id.isEmpty()) |
| 675 stylesheet->setAttribute(HTMLNames::idAttr, id); |
| 676 stylesheet->setTextContent(css, err); |
| 677 ASSERT(!err); |
| 678 Node* first = documentElement->firstChild(); |
| 679 bool success = documentElement->insertBefore(stylesheet, first, err); |
| 680 ASSERT(success); |
| 681 return success; |
| 682 } |
| 683 |
| 684 void WebFrameImpl::reload() |
| 685 { |
| 686 m_frame->loader()->history()->saveDocumentAndScrollState(); |
| 687 |
| 688 stopLoading(); // Make sure existing activity stops. |
| 689 m_frame->loader()->reload(); |
| 690 } |
| 691 |
| 692 void WebFrameImpl::loadRequest(const WebURLRequest& request) |
| 693 { |
| 694 ASSERT(!request.isNull()); |
| 695 const ResourceRequest& resourceRequest = request.toResourceRequest(); |
| 696 |
| 697 if (resourceRequest.url().protocolIs("javascript")) { |
| 698 loadJavaScriptURL(resourceRequest.url()); |
| 699 return; |
| 700 } |
| 701 |
| 702 stopLoading(); // Make sure existing activity stops. |
| 703 m_frame->loader()->load(resourceRequest, false); |
| 704 } |
| 705 |
| 706 void WebFrameImpl::loadHistoryItem(const WebHistoryItem& item) |
| 707 { |
| 708 RefPtr<HistoryItem> historyItem = PassRefPtr<HistoryItem>(item); |
| 709 ASSERT(historyItem.get()); |
| 710 |
| 711 stopLoading(); // Make sure existing activity stops. |
| 712 |
| 713 // If there is no currentItem, which happens when we are navigating in |
| 714 // session history after a crash, we need to manufacture one otherwise WebKit |
| 715 // hoarks. This is probably the wrong thing to do, but it seems to work. |
| 716 RefPtr<HistoryItem> currentItem = m_frame->loader()->history()->currentItem(); |
| 717 if (!currentItem) { |
| 718 currentItem = HistoryItem::create(); |
| 719 currentItem->setLastVisitWasFailure(true); |
| 720 m_frame->loader()->history()->setCurrentItem(currentItem.get()); |
| 721 viewImpl()->setCurrentHistoryItem(currentItem.get()); |
| 722 } |
| 723 |
| 724 m_frame->loader()->history()->goToItem( |
| 725 historyItem.get(), FrameLoadTypeIndexedBackForward); |
| 726 } |
| 727 |
| 728 void WebFrameImpl::loadData(const WebData& data, |
| 729 const WebString& mimeType, |
| 730 const WebString& textEncoding, |
| 731 const WebURL& baseURL, |
| 732 const WebURL& unreachableURL, |
| 733 bool replace) |
| 734 { |
| 735 SubstituteData substData(data, mimeType, textEncoding, unreachableURL); |
| 736 ASSERT(substData.isValid()); |
| 737 |
| 738 stopLoading(); // Make sure existing activity stops. |
| 739 m_frame->loader()->load(ResourceRequest(baseURL), substData, false); |
| 740 if (replace) { |
| 741 // Do this to force WebKit to treat the load as replacing the currently |
| 742 // loaded page. |
| 743 m_frame->loader()->setReplacing(); |
| 744 } |
| 745 } |
| 746 |
| 747 void WebFrameImpl::loadHTMLString(const WebData& data, |
| 748 const WebURL& baseURL, |
| 749 const WebURL& unreachableURL, |
| 750 bool replace) |
| 751 { |
| 752 loadData(data, |
| 753 WebString::fromUTF8("text/html"), |
| 754 WebString::fromUTF8("UTF-8"), |
| 755 baseURL, |
| 756 unreachableURL, |
| 757 replace); |
| 758 } |
| 759 |
| 760 bool WebFrameImpl::isLoading() const |
| 761 { |
| 762 if (!m_frame) |
| 763 return false; |
| 764 return m_frame->loader()->isLoading(); |
| 765 } |
| 766 |
| 767 void WebFrameImpl::stopLoading() |
| 768 { |
| 769 if (!m_frame) |
| 770 return; |
| 771 |
| 772 // FIXME: Figure out what we should really do here. It seems like a bug |
| 773 // that FrameLoader::stopLoading doesn't call stopAllLoaders. |
| 774 m_frame->loader()->stopAllLoaders(); |
| 775 m_frame->loader()->stopLoading(UnloadEventPolicyNone); |
| 776 } |
| 777 |
| 778 WebDataSource* WebFrameImpl::provisionalDataSource() const |
| 779 { |
| 780 FrameLoader* frameLoader = m_frame->loader(); |
| 781 |
| 782 // We regard the policy document loader as still provisional. |
| 783 DocumentLoader* docLoader = frameLoader->provisionalDocumentLoader(); |
| 784 if (!docLoader) |
| 785 docLoader = frameLoader->policyDocumentLoader(); |
| 786 |
| 787 return DataSourceForDocLoader(docLoader); |
| 788 } |
| 789 |
| 790 WebDataSource* WebFrameImpl::dataSource() const |
| 791 { |
| 792 return DataSourceForDocLoader(m_frame->loader()->documentLoader()); |
| 793 } |
| 794 |
| 795 WebHistoryItem WebFrameImpl::previousHistoryItem() const |
| 796 { |
| 797 // We use the previous item here because documentState (filled-out forms) |
| 798 // only get saved to history when it becomes the previous item. The caller |
| 799 // is expected to query the history item after a navigation occurs, after |
| 800 // the desired history item has become the previous entry. |
| 801 return WebHistoryItem(viewImpl()->previousHistoryItem()); |
| 802 } |
| 803 |
| 804 WebHistoryItem WebFrameImpl::currentHistoryItem() const |
| 805 { |
| 806 m_frame->loader()->history()->saveDocumentAndScrollState(); |
| 807 |
| 808 return WebHistoryItem(m_frame->page()->backForwardList()->currentItem()); |
| 809 } |
| 810 |
| 811 void WebFrameImpl::enableViewSourceMode(bool enable) |
| 812 { |
| 813 if (m_frame) |
| 814 m_frame->setInViewSourceMode(enable); |
| 815 } |
| 816 |
| 817 bool WebFrameImpl::isViewSourceModeEnabled() const |
| 818 { |
| 819 if (m_frame) |
| 820 return m_frame->inViewSourceMode(); |
| 821 |
| 700 return false; | 822 return false; |
| 701 WebCore::Element* document_element = document->documentElement(); | 823 } |
| 702 if (!document_element) | 824 |
| 703 return false; | 825 void WebFrameImpl::setReferrerForRequest( |
| 704 | 826 WebURLRequest& request, const WebURL& referrerURL) { |
| 705 ExceptionCode err = 0; | 827 String referrer; |
| 706 | 828 if (referrerURL.isEmpty()) |
| 707 if (!id.isEmpty()) { | 829 referrer = m_frame->loader()->outgoingReferrer(); |
| 708 WebCore::Element* old_element = | 830 else |
| 709 document->getElementById(webkit_glue::WebStringToString(id)); | 831 referrer = referrerURL.spec().utf16(); |
| 710 if (old_element) { | 832 if (SecurityOrigin::shouldHideReferrer(request.url(), referrer)) |
| 711 Node* parent = old_element->parent(); | 833 return; |
| 712 if (!parent) | 834 request.setHTTPHeaderField(WebString::fromUTF8("Referer"), referrer); |
| 835 } |
| 836 |
| 837 void WebFrameImpl::dispatchWillSendRequest(WebURLRequest& request) |
| 838 { |
| 839 ResourceResponse response; |
| 840 m_frame->loader()->client()->dispatchWillSendRequest( |
| 841 0, 0, request.toMutableResourceRequest(), response); |
| 842 } |
| 843 |
| 844 void WebFrameImpl::commitDocumentData(const char* data, size_t dataLen) |
| 845 { |
| 846 DocumentLoader* documentLoader = m_frame->loader()->documentLoader(); |
| 847 |
| 848 // Set the text encoding. This calls begin() for us. It is safe to call |
| 849 // this multiple times (Mac does: page/mac/WebCoreFrameBridge.mm). |
| 850 bool userChosen = true; |
| 851 String encoding = documentLoader->overrideEncoding(); |
| 852 if (encoding.isNull()) { |
| 853 userChosen = false; |
| 854 encoding = documentLoader->response().textEncodingName(); |
| 855 } |
| 856 m_frame->loader()->setEncoding(encoding, userChosen); |
| 857 |
| 858 // NOTE: mac only does this if there is a document |
| 859 m_frame->loader()->addData(data, dataLen); |
| 860 } |
| 861 |
| 862 unsigned WebFrameImpl::unloadListenerCount() const |
| 863 { |
| 864 return frame()->domWindow()->pendingUnloadEventListeners(); |
| 865 } |
| 866 |
| 867 bool WebFrameImpl::isProcessingUserGesture() const |
| 868 { |
| 869 return frame()->loader()->isProcessingUserGesture(); |
| 870 } |
| 871 |
| 872 bool WebFrameImpl::willSuppressOpenerInNewFrame() const |
| 873 { |
| 874 return frame()->loader()->suppressOpenerInNewFrame(); |
| 875 } |
| 876 |
| 877 void WebFrameImpl::replaceSelection(const WebString& text) |
| 878 { |
| 879 RefPtr<DocumentFragment> fragment = createFragmentFromText( |
| 880 frame()->selection()->toNormalizedRange().get(), text); |
| 881 applyCommand(ReplaceSelectionCommand::create( |
| 882 frame()->document(), fragment.get(), false, true, true)); |
| 883 } |
| 884 |
| 885 void WebFrameImpl::insertText(const WebString& text) |
| 886 { |
| 887 frame()->editor()->insertText(text, 0); |
| 888 } |
| 889 |
| 890 void WebFrameImpl::setMarkedText( |
| 891 const WebString& text, unsigned location, unsigned length) |
| 892 { |
| 893 Editor* editor = frame()->editor(); |
| 894 |
| 895 editor->confirmComposition(text); |
| 896 |
| 897 Vector<CompositionUnderline> decorations; |
| 898 editor->setComposition(text, decorations, location, length); |
| 899 } |
| 900 |
| 901 void WebFrameImpl::unmarkText() |
| 902 { |
| 903 frame()->editor()->confirmCompositionWithoutDisturbingSelection(); |
| 904 } |
| 905 |
| 906 bool WebFrameImpl::hasMarkedText() const |
| 907 { |
| 908 return frame()->editor()->hasComposition(); |
| 909 } |
| 910 |
| 911 WebRange WebFrameImpl::markedRange() const |
| 912 { |
| 913 return frame()->editor()->compositionRange(); |
| 914 } |
| 915 |
| 916 bool WebFrameImpl::executeCommand(const WebString& name) |
| 917 { |
| 918 ASSERT(frame()); |
| 919 |
| 920 if (name.length() <= 2) |
| 713 return false; | 921 return false; |
| 714 parent->removeChild(old_element, err); | 922 |
| 715 } | 923 // Since we don't have NSControl, we will convert the format of command |
| 716 } | 924 // string and call the function on Editor directly. |
| 717 | 925 String command = name; |
| 718 RefPtr<WebCore::Element> stylesheet = document->createElement( | 926 |
| 719 WebCore::HTMLNames::styleTag, false); | 927 // Make sure the first letter is upper case. |
| 720 if (!id.isEmpty()) | 928 command.replace(0, 1, command.substring(0, 1).upper()); |
| 721 stylesheet->setAttribute(WebCore::HTMLNames::idAttr, | 929 |
| 722 webkit_glue::WebStringToString(id)); | 930 // Remove the trailing ':' if existing. |
| 723 stylesheet->setTextContent(webkit_glue::WebStringToString(css), err); | 931 if (command[command.length() - 1] == UChar(':')) |
| 724 ASSERT(!err); | 932 command = command.substring(0, command.length() - 1); |
| 725 WebCore::Node* first = document_element->firstChild(); | 933 |
| 726 bool success = document_element->insertBefore(stylesheet, first, err); | 934 bool rv = true; |
| 727 ASSERT(success); | 935 |
| 728 return success; | 936 // Specially handling commands that Editor::execCommand does not directly |
| 729 } | 937 // support. |
| 730 | 938 if (command == "DeleteToEndOfParagraph") { |
| 731 void WebFrameImpl::reload() { | 939 Editor* editor = frame()->editor(); |
| 732 frame_->loader()->history()->saveDocumentAndScrollState(); | 940 if (!editor->deleteWithDirection(SelectionController::FORWARD, |
| 733 | 941 ParagraphBoundary, |
| 734 stopLoading(); // Make sure existing activity stops. | 942 true, |
| 735 frame_->loader()->reload(); | 943 false)) { |
| 736 } | 944 editor->deleteWithDirection(SelectionController::FORWARD, |
| 737 | 945 CharacterGranularity, |
| 738 void WebFrameImpl::loadRequest(const WebURLRequest& request) { | 946 true, |
| 739 const ResourceRequest* resource_request = | 947 false); |
| 740 webkit_glue::WebURLRequestToResourceRequest(&request); | 948 } |
| 741 ASSERT(resource_request); | 949 } else if (command == "Indent") |
| 742 | 950 frame()->editor()->indent(); |
| 743 if (resource_request->url().protocolIs("javascript")) { | 951 else if (command == "Outdent") |
| 744 LoadJavaScriptURL(resource_request->url()); | 952 frame()->editor()->outdent(); |
| 745 return; | 953 else if (command == "DeleteBackward") |
| 746 } | 954 rv = frame()->editor()->command(AtomicString("BackwardDelete")).execute(); |
| 747 | 955 else if (command == "DeleteForward") |
| 748 stopLoading(); // Make sure existing activity stops. | 956 rv = frame()->editor()->command(AtomicString("ForwardDelete")).execute(); |
| 749 frame_->loader()->load(*resource_request, false); | 957 else if (command == "AdvanceToNextMisspelling") { |
| 750 } | 958 // False must be passed here, or the currently selected word will never be |
| 751 | 959 // skipped. |
| 752 void WebFrameImpl::loadHistoryItem(const WebHistoryItem& item) { | 960 frame()->editor()->advanceToNextMisspelling(false); |
| 753 RefPtr<HistoryItem> history_item = | 961 } else if (command == "ToggleSpellPanel") |
| 754 webkit_glue::WebHistoryItemToHistoryItem(item); | 962 frame()->editor()->showSpellingGuessPanel(); |
| 755 ASSERT(history_item.get()); | 963 else |
| 756 | 964 rv = frame()->editor()->command(command).execute(); |
| 757 stopLoading(); // Make sure existing activity stops. | 965 return rv; |
| 758 | 966 } |
| 759 // If there is no current_item, which happens when we are navigating in | 967 |
| 760 // session history after a crash, we need to manufacture one otherwise WebKit | 968 bool WebFrameImpl::executeCommand(const WebString& name, const WebString& value) |
| 761 // hoarks. This is probably the wrong thing to do, but it seems to work. | 969 { |
| 762 RefPtr<HistoryItem> current_item = frame_->loader()->history()->currentItem(); | 970 ASSERT(frame()); |
| 763 if (!current_item) { | 971 String webName = name; |
| 764 current_item = HistoryItem::create(); | 972 |
| 765 current_item->setLastVisitWasFailure(true); | 973 // moveToBeginningOfDocument and moveToEndfDocument are only handled by WebKit |
| 766 frame_->loader()->history()->setCurrentItem(current_item.get()); | 974 // for editable nodes. |
| 767 GetWebViewImpl()->SetCurrentHistoryItem(current_item.get()); | 975 if (!frame()->editor()->canEdit() && webName == "moveToBeginningOfDocument") |
| 768 } | 976 return viewImpl()->propagateScroll(ScrollUp, ScrollByDocument); |
| 769 | 977 |
| 770 frame_->loader()->history()->goToItem(history_item.get(), | 978 if (!frame()->editor()->canEdit() && webName == "moveToEndOfDocument") |
| 771 WebCore::FrameLoadTypeIndexedBackForward); | 979 return viewImpl()->propagateScroll(ScrollDown, ScrollByDocument); |
| 772 } | 980 |
| 773 | 981 return frame()->editor()->command(webName).execute(value); |
| 774 void WebFrameImpl::loadData(const WebData& data, | 982 } |
| 775 const WebString& mime_type, | 983 |
| 776 const WebString& text_encoding, | 984 bool WebFrameImpl::isCommandEnabled(const WebString& name) const |
| 777 const WebURL& base_url, | 985 { |
| 778 const WebURL& unreachable_url, | 986 ASSERT(frame()); |
| 779 bool replace) { | 987 return frame()->editor()->command(name).isEnabled(); |
| 780 SubstituteData subst_data( | 988 } |
| 781 webkit_glue::WebDataToSharedBuffer(data), | 989 |
| 782 webkit_glue::WebStringToString(mime_type), | 990 void WebFrameImpl::enableContinuousSpellChecking(bool enable) |
| 783 webkit_glue::WebStringToString(text_encoding), | 991 { |
| 784 webkit_glue::WebURLToKURL(unreachable_url)); | 992 if (enable == isContinuousSpellCheckingEnabled()) |
| 785 ASSERT(subst_data.isValid()); | 993 return; |
| 786 | 994 frame()->editor()->toggleContinuousSpellChecking(); |
| 787 stopLoading(); // Make sure existing activity stops. | 995 } |
| 788 frame_->loader()->load(ResourceRequest(webkit_glue::WebURLToKURL(base_url)), | 996 |
| 789 subst_data, false); | 997 bool WebFrameImpl::isContinuousSpellCheckingEnabled() const |
| 790 if (replace) { | 998 { |
| 791 // Do this to force WebKit to treat the load as replacing the currently | 999 return frame()->editor()->isContinuousSpellCheckingEnabled(); |
| 792 // loaded page. | 1000 } |
| 793 frame_->loader()->setReplacing(); | 1001 |
| 794 } | 1002 bool WebFrameImpl::hasSelection() const |
| 795 } | 1003 { |
| 796 | 1004 // frame()->selection()->isNone() never returns true. |
| 797 void WebFrameImpl::loadHTMLString(const WebData& data, | 1005 return (frame()->selection()->start() != frame()->selection()->end()); |
| 798 const WebURL& base_url, | 1006 } |
| 799 const WebURL& unreachable_url, | 1007 |
| 800 bool replace) { | 1008 WebRange WebFrameImpl::selectionRange() const |
| 801 loadData(data, | 1009 { |
| 802 WebString::fromUTF8("text/html"), | 1010 return frame()->selection()->toNormalizedRange(); |
| 803 WebString::fromUTF8("UTF-8"), | 1011 } |
| 804 base_url, | 1012 |
| 805 unreachable_url, | 1013 WebString WebFrameImpl::selectionAsText() const |
| 806 replace); | 1014 { |
| 807 } | 1015 RefPtr<Range> range = frame()->selection()->toNormalizedRange(); |
| 808 | 1016 if (!range.get()) |
| 809 bool WebFrameImpl::isLoading() const { | 1017 return WebString(); |
| 810 if (!frame_) | 1018 |
| 811 return false; | 1019 String text = range->text(); |
| 812 return frame_->loader()->isLoading(); | |
| 813 } | |
| 814 | |
| 815 void WebFrameImpl::stopLoading() { | |
| 816 if (!frame_) | |
| 817 return; | |
| 818 | |
| 819 // TODO(darin): Figure out what we should really do here. It seems like a | |
| 820 // bug that FrameLoader::stopLoading doesn't call stopAllLoaders. | |
| 821 frame_->loader()->stopAllLoaders(); | |
| 822 frame_->loader()->stopLoading(WebCore::UnloadEventPolicyNone); | |
| 823 } | |
| 824 | |
| 825 WebDataSource* WebFrameImpl::provisionalDataSource() const { | |
| 826 FrameLoader* frame_loader = frame_->loader(); | |
| 827 | |
| 828 // We regard the policy document loader as still provisional. | |
| 829 DocumentLoader* doc_loader = frame_loader->provisionalDocumentLoader(); | |
| 830 if (!doc_loader) | |
| 831 doc_loader = frame_loader->policyDocumentLoader(); | |
| 832 | |
| 833 return DataSourceForDocLoader(doc_loader); | |
| 834 } | |
| 835 | |
| 836 WebDataSource* WebFrameImpl::dataSource() const { | |
| 837 return DataSourceForDocLoader(frame_->loader()->documentLoader()); | |
| 838 } | |
| 839 | |
| 840 WebHistoryItem WebFrameImpl::previousHistoryItem() const { | |
| 841 // We use the previous item here because documentState (filled-out forms) | |
| 842 // only get saved to history when it becomes the previous item. The caller | |
| 843 // is expected to query the history item after a navigation occurs, after | |
| 844 // the desired history item has become the previous entry. | |
| 845 return webkit_glue::HistoryItemToWebHistoryItem( | |
| 846 GetWebViewImpl()->GetPreviousHistoryItem()); | |
| 847 } | |
| 848 | |
| 849 WebHistoryItem WebFrameImpl::currentHistoryItem() const { | |
| 850 frame_->loader()->history()->saveDocumentAndScrollState(); | |
| 851 | |
| 852 return webkit_glue::HistoryItemToWebHistoryItem( | |
| 853 frame_->page()->backForwardList()->currentItem()); | |
| 854 } | |
| 855 | |
| 856 void WebFrameImpl::enableViewSourceMode(bool enable) { | |
| 857 if (frame_) | |
| 858 frame_->setInViewSourceMode(enable); | |
| 859 } | |
| 860 | |
| 861 bool WebFrameImpl::isViewSourceModeEnabled() const { | |
| 862 if (frame_) | |
| 863 return frame_->inViewSourceMode(); | |
| 864 | |
| 865 return false; | |
| 866 } | |
| 867 | |
| 868 void WebFrameImpl::setReferrerForRequest( | |
| 869 WebURLRequest& request, const WebURL& referrer_url) { | |
| 870 String referrer; | |
| 871 if (referrer_url.isEmpty()) { | |
| 872 referrer = frame_->loader()->outgoingReferrer(); | |
| 873 } else { | |
| 874 referrer = webkit_glue::WebStringToString(referrer_url.spec().utf16()); | |
| 875 } | |
| 876 if (SecurityOrigin::shouldHideReferrer( | |
| 877 webkit_glue::WebURLToKURL(request.url()), referrer)) | |
| 878 return; | |
| 879 request.setHTTPHeaderField(WebString::fromUTF8("Referer"), | |
| 880 webkit_glue::StringToWebString(referrer)); | |
| 881 } | |
| 882 | |
| 883 void WebFrameImpl::dispatchWillSendRequest(WebURLRequest& request) { | |
| 884 ResourceResponse response; | |
| 885 frame_->loader()->client()->dispatchWillSendRequest(NULL, 0, | |
| 886 *webkit_glue::WebURLRequestToMutableResourceRequest(&request), | |
| 887 response); | |
| 888 } | |
| 889 | |
| 890 void WebFrameImpl::commitDocumentData(const char* data, size_t data_len) { | |
| 891 DocumentLoader* document_loader = frame_->loader()->documentLoader(); | |
| 892 | |
| 893 // Set the text encoding. This calls begin() for us. It is safe to call | |
| 894 // this multiple times (Mac does: page/mac/WebCoreFrameBridge.mm). | |
| 895 bool user_chosen = true; | |
| 896 String encoding = document_loader->overrideEncoding(); | |
| 897 if (encoding.isNull()) { | |
| 898 user_chosen = false; | |
| 899 encoding = document_loader->response().textEncodingName(); | |
| 900 } | |
| 901 frame_->loader()->setEncoding(encoding, user_chosen); | |
| 902 | |
| 903 // NOTE: mac only does this if there is a document | |
| 904 frame_->loader()->addData(data, data_len); | |
| 905 } | |
| 906 | |
| 907 unsigned WebFrameImpl::unloadListenerCount() const { | |
| 908 return frame()->domWindow()->pendingUnloadEventListeners(); | |
| 909 } | |
| 910 | |
| 911 bool WebFrameImpl::isProcessingUserGesture() const { | |
| 912 return frame()->loader()->isProcessingUserGesture(); | |
| 913 } | |
| 914 | |
| 915 bool WebFrameImpl::willSuppressOpenerInNewFrame() const { | |
| 916 return frame()->loader()->suppressOpenerInNewFrame(); | |
| 917 } | |
| 918 | |
| 919 void WebFrameImpl::replaceSelection(const WebString& wtext) { | |
| 920 String text = webkit_glue::WebStringToString(wtext); | |
| 921 RefPtr<DocumentFragment> fragment = createFragmentFromText( | |
| 922 frame()->selection()->toNormalizedRange().get(), text); | |
| 923 WebCore::applyCommand(WebCore::ReplaceSelectionCommand::create( | |
| 924 frame()->document(), fragment.get(), false, true, true)); | |
| 925 } | |
| 926 | |
| 927 void WebFrameImpl::insertText(const WebString& text) { | |
| 928 frame()->editor()->insertText(webkit_glue::WebStringToString(text), NULL); | |
| 929 } | |
| 930 | |
| 931 void WebFrameImpl::setMarkedText( | |
| 932 const WebString& text, unsigned location, unsigned length) { | |
| 933 WebCore::Editor* editor = frame()->editor(); | |
| 934 WebCore::String str = webkit_glue::WebStringToString(text); | |
| 935 | |
| 936 editor->confirmComposition(str); | |
| 937 | |
| 938 WTF::Vector<WebCore::CompositionUnderline> decorations; | |
| 939 editor->setComposition(str, decorations, location, length); | |
| 940 } | |
| 941 | |
| 942 void WebFrameImpl::unmarkText() { | |
| 943 frame()->editor()->confirmCompositionWithoutDisturbingSelection(); | |
| 944 } | |
| 945 | |
| 946 bool WebFrameImpl::hasMarkedText() const { | |
| 947 return frame()->editor()->hasComposition(); | |
| 948 } | |
| 949 | |
| 950 WebRange WebFrameImpl::markedRange() const { | |
| 951 return webkit_glue::RangeToWebRange(frame()->editor()->compositionRange()); | |
| 952 } | |
| 953 | |
| 954 bool WebFrameImpl::executeCommand(const WebString& name) { | |
| 955 ASSERT(frame()); | |
| 956 | |
| 957 if (name.length() <= 2) | |
| 958 return false; | |
| 959 | |
| 960 // Since we don't have NSControl, we will convert the format of command | |
| 961 // string and call the function on Editor directly. | |
| 962 String command = webkit_glue::WebStringToString(name); | |
| 963 | |
| 964 // Make sure the first letter is upper case. | |
| 965 command.replace(0, 1, command.substring(0, 1).upper()); | |
| 966 | |
| 967 // Remove the trailing ':' if existing. | |
| 968 if (command[command.length() - 1] == UChar(':')) | |
| 969 command = command.substring(0, command.length() - 1); | |
| 970 | |
| 971 bool rv = true; | |
| 972 | |
| 973 // Specially handling commands that Editor::execCommand does not directly | |
| 974 // support. | |
| 975 if (command == "DeleteToEndOfParagraph") { | |
| 976 WebCore::Editor* editor = frame()->editor(); | |
| 977 if (!editor->deleteWithDirection(WebCore::SelectionController::FORWARD, | |
| 978 WebCore::ParagraphBoundary, | |
| 979 true, | |
| 980 false)) { | |
| 981 editor->deleteWithDirection(WebCore::SelectionController::FORWARD, | |
| 982 WebCore::CharacterGranularity, | |
| 983 true, | |
| 984 false); | |
| 985 } | |
| 986 } else if (command == "Indent") { | |
| 987 frame()->editor()->indent(); | |
| 988 } else if (command == "Outdent") { | |
| 989 frame()->editor()->outdent(); | |
| 990 } else if (command == "DeleteBackward") { | |
| 991 rv = frame()->editor()->command(AtomicString("BackwardDelete")).execute(); | |
| 992 } else if (command == "DeleteForward") { | |
| 993 rv = frame()->editor()->command(AtomicString("ForwardDelete")).execute(); | |
| 994 } else if (command == "AdvanceToNextMisspelling") { | |
| 995 // False must be passed here, or the currently selected word will never be | |
| 996 // skipped. | |
| 997 frame()->editor()->advanceToNextMisspelling(false); | |
| 998 } else if (command == "ToggleSpellPanel") { | |
| 999 frame()->editor()->showSpellingGuessPanel(); | |
| 1000 } else { | |
| 1001 rv = frame()->editor()->command(command).execute(); | |
| 1002 } | |
| 1003 return rv; | |
| 1004 } | |
| 1005 | |
| 1006 bool WebFrameImpl::executeCommand(const WebString& name, | |
| 1007 const WebString& value) { | |
| 1008 ASSERT(frame()); | |
| 1009 WebCore::String web_name = webkit_glue::WebStringToString(name); | |
| 1010 | |
| 1011 // moveToBeginningOfDocument and moveToEndfDocument are only handled by WebKit | |
| 1012 // for editable nodes. | |
| 1013 if (!frame()->editor()->canEdit() && | |
| 1014 web_name == "moveToBeginningOfDocument") { | |
| 1015 return GetWebViewImpl()->PropagateScroll(WebCore::ScrollUp, | |
| 1016 WebCore::ScrollByDocument); | |
| 1017 } else if (!frame()->editor()->canEdit() && | |
| 1018 web_name == "moveToEndOfDocument") { | |
| 1019 return GetWebViewImpl()->PropagateScroll(WebCore::ScrollDown, | |
| 1020 WebCore::ScrollByDocument); | |
| 1021 } else { | |
| 1022 return frame()->editor()->command(web_name). | |
| 1023 execute(webkit_glue::WebStringToString(value)); | |
| 1024 } | |
| 1025 } | |
| 1026 | |
| 1027 bool WebFrameImpl::isCommandEnabled(const WebString& name) const { | |
| 1028 ASSERT(frame()); | |
| 1029 return frame()->editor()->command(webkit_glue::WebStringToString(name)). | |
| 1030 isEnabled(); | |
| 1031 } | |
| 1032 | |
| 1033 void WebFrameImpl::enableContinuousSpellChecking(bool enable) { | |
| 1034 if (enable == isContinuousSpellCheckingEnabled()) | |
| 1035 return; | |
| 1036 frame()->editor()->toggleContinuousSpellChecking(); | |
| 1037 } | |
| 1038 | |
| 1039 bool WebFrameImpl::isContinuousSpellCheckingEnabled() const { | |
| 1040 return frame()->editor()->isContinuousSpellCheckingEnabled(); | |
| 1041 } | |
| 1042 | |
| 1043 bool WebFrameImpl::hasSelection() const { | |
| 1044 // frame()->selection()->isNone() never returns true. | |
| 1045 return (frame()->selection()->start() != frame()->selection()->end()); | |
| 1046 } | |
| 1047 | |
| 1048 WebRange WebFrameImpl::selectionRange() const { | |
| 1049 return webkit_glue::RangeToWebRange( | |
| 1050 frame()->selection()->toNormalizedRange()); | |
| 1051 } | |
| 1052 | |
| 1053 WebString WebFrameImpl::selectionAsText() const { | |
| 1054 RefPtr<Range> range = frame()->selection()->toNormalizedRange(); | |
| 1055 if (!range.get()) | |
| 1056 return WebString(); | |
| 1057 | |
| 1058 String text = range->text(); | |
| 1059 #if PLATFORM(WIN_OS) | 1020 #if PLATFORM(WIN_OS) |
| 1060 WebCore::replaceNewlinesWithWindowsStyleNewlines(text); | 1021 replaceNewlinesWithWindowsStyleNewlines(text); |
| 1061 #endif | 1022 #endif |
| 1062 WebCore::replaceNBSPWithSpace(text); | 1023 replaceNBSPWithSpace(text); |
| 1063 return webkit_glue::StringToWebString(text); | 1024 return text; |
| 1064 } | 1025 } |
| 1065 | 1026 |
| 1066 WebString WebFrameImpl::selectionAsMarkup() const { | 1027 WebString WebFrameImpl::selectionAsMarkup() const |
| 1067 RefPtr<Range> range = frame()->selection()->toNormalizedRange(); | 1028 { |
| 1068 if (!range.get()) | 1029 RefPtr<Range> range = frame()->selection()->toNormalizedRange(); |
| 1069 return WebString(); | 1030 if (!range.get()) |
| 1070 | 1031 return WebString(); |
| 1071 String markup = WebCore::createMarkup(range.get(), 0); | 1032 |
| 1072 return webkit_glue::StringToWebString(markup); | 1033 return createMarkup(range.get(), 0); |
| 1073 } | 1034 } |
| 1074 | 1035 |
| 1075 int WebFrameImpl::printBegin(const WebSize& page_size) { | 1036 int WebFrameImpl::printBegin(const WebSize& pageSize) |
| 1076 ASSERT(!frame()->document()->isFrameSet()); | 1037 { |
| 1077 | 1038 ASSERT(!frame()->document()->isFrameSet()); |
| 1078 print_context_.set(new ChromePrintContext(frame())); | 1039 |
| 1079 WebCore::FloatRect rect(0, 0, | 1040 m_printContext.set(new ChromePrintContext(frame())); |
| 1080 static_cast<float>(page_size.width), | 1041 FloatRect rect(0, 0, static_cast<float>(pageSize.width), |
| 1081 static_cast<float>(page_size.height)); | 1042 static_cast<float>(pageSize.height)); |
| 1082 print_context_->begin(rect.width()); | 1043 m_printContext->begin(rect.width()); |
| 1083 float page_height; | 1044 float pageHeight; |
| 1084 // We ignore the overlays calculation for now since they are generated in the | 1045 // We ignore the overlays calculation for now since they are generated in the |
| 1085 // browser. page_height is actually an output parameter. | 1046 // browser. pageHeight is actually an output parameter. |
| 1086 print_context_->computePageRects(rect, 0, 0, 1.0, page_height); | 1047 m_printContext->computePageRects(rect, 0, 0, 1.0, pageHeight); |
| 1087 return print_context_->pageCount(); | 1048 return m_printContext->pageCount(); |
| 1088 } | 1049 } |
| 1089 | 1050 |
| 1090 float WebFrameImpl::getPrintPageShrink(int page) { | 1051 float WebFrameImpl::getPrintPageShrink(int page) |
| 1091 // Ensure correct state. | 1052 { |
| 1092 if (!print_context_.get() || page < 0) { | 1053 // Ensure correct state. |
| 1093 ASSERT_NOT_REACHED(); | 1054 if (!m_printContext.get() || page < 0) { |
| 1094 return 0; | 1055 ASSERT_NOT_REACHED(); |
| 1095 } | 1056 return 0; |
| 1096 | 1057 } |
| 1097 return print_context_->getPageShrink(page); | 1058 |
| 1098 } | 1059 return m_printContext->getPageShrink(page); |
| 1099 | 1060 } |
| 1100 float WebFrameImpl::printPage(int page, WebCanvas* canvas) { | 1061 |
| 1101 // Ensure correct state. | 1062 float WebFrameImpl::printPage(int page, WebCanvas* canvas) |
| 1102 if (!print_context_.get() || page < 0 || !frame() || !frame()->document()) { | 1063 { |
| 1103 ASSERT_NOT_REACHED(); | 1064 // Ensure correct state. |
| 1104 return 0; | 1065 if (!m_printContext.get() || page < 0 || !frame() || !frame()->document()) { |
| 1105 } | 1066 ASSERT_NOT_REACHED(); |
| 1067 return 0; |
| 1068 } |
| 1106 | 1069 |
| 1107 #if PLATFORM(WIN_OS) || PLATFORM(LINUX) || PLATFORM(FREEBSD) | 1070 #if PLATFORM(WIN_OS) || PLATFORM(LINUX) || PLATFORM(FREEBSD) |
| 1108 PlatformContextSkia context(canvas); | 1071 PlatformContextSkia context(canvas); |
| 1109 GraphicsContext spool(&context); | 1072 GraphicsContext spool(&context); |
| 1110 #elif PLATFORM(DARWIN) | 1073 #elif PLATFORM(DARWIN) |
| 1111 GraphicsContext spool(canvas); | 1074 GraphicsContext spool(canvas); |
| 1112 WebCore::LocalCurrentGraphicsContext localContext(&spool); | 1075 LocalCurrentGraphicsContext localContext(&spool); |
| 1113 #endif | 1076 #endif |
| 1114 | 1077 |
| 1115 return print_context_->spoolPage(spool, page); | 1078 return m_printContext->spoolPage(spool, page); |
| 1116 } | 1079 } |
| 1117 | 1080 |
| 1118 void WebFrameImpl::printEnd() { | 1081 void WebFrameImpl::printEnd() |
| 1119 ASSERT(print_context_.get()); | 1082 { |
| 1120 if (print_context_.get()) | 1083 ASSERT(m_printContext.get()); |
| 1121 print_context_->end(); | 1084 if (m_printContext.get()) |
| 1122 print_context_.clear(); | 1085 m_printContext->end(); |
| 1123 } | 1086 m_printContext.clear(); |
| 1124 | 1087 } |
| 1125 bool WebFrameImpl::find(int request_id, | 1088 |
| 1126 const WebString& search_text, | 1089 bool WebFrameImpl::find(int identifier, |
| 1090 const WebString& searchText, |
| 1127 const WebFindOptions& options, | 1091 const WebFindOptions& options, |
| 1128 bool wrap_within_frame, | 1092 bool wrapWithinFrame, |
| 1129 WebRect* selection_rect) { | 1093 WebRect* selectionRect) |
| 1130 WebCore::String webcore_string = webkit_glue::WebStringToString(search_text); | 1094 { |
| 1131 | 1095 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl(); |
| 1132 WebFrameImpl* const main_frame_impl = GetWebViewImpl()->main_frame(); | 1096 |
| 1133 | 1097 if (!options.findNext) |
| 1134 if (!options.findNext) | 1098 frame()->page()->unmarkAllTextMatches(); |
| 1135 frame()->page()->unmarkAllTextMatches(); | 1099 else |
| 1136 else | 1100 setMarkerActive(m_activeMatch.get(), false); // Active match is changing. |
| 1137 SetMarkerActive(active_match_.get(), false); // Active match is changing. | 1101 |
| 1138 | 1102 // Starts the search from the current selection. |
| 1139 // Starts the search from the current selection. | 1103 bool startInSelection = true; |
| 1140 bool start_in_selection = true; | 1104 |
| 1141 | 1105 // If the user has selected something since the last Find operation we want |
| 1142 // If the user has selected something since the last Find operation we want | 1106 // to start from there. Otherwise, we start searching from where the last Find |
| 1143 // to start from there. Otherwise, we start searching from where the last Find | 1107 // operation left off (either a Find or a FindNext operation). |
| 1144 // operation left off (either a Find or a FindNext operation). | 1108 VisibleSelection selection(frame()->selection()->selection()); |
| 1145 VisibleSelection selection(frame()->selection()->selection()); | 1109 if (selection.isNone() && m_activeMatch) { |
| 1146 if (selection.isNone() && active_match_) { | 1110 selection = VisibleSelection(m_activeMatch.get()); |
| 1147 selection = VisibleSelection(active_match_.get()); | 1111 frame()->selection()->setSelection(selection); |
| 1148 frame()->selection()->setSelection(selection); | 1112 } |
| 1149 } | 1113 |
| 1150 | 1114 ASSERT(frame() && frame()->view()); |
| 1151 ASSERT(frame() && frame()->view()); | 1115 bool found = frame()->findString( |
| 1152 bool found = frame()->findString(webcore_string, options.forward, | 1116 searchText, options.forward, options.matchCase, wrapWithinFrame, |
| 1153 options.matchCase, wrap_within_frame, | 1117 startInSelection); |
| 1154 start_in_selection); | 1118 if (found) { |
| 1155 if (found) { | 1119 // Store which frame was active. This will come in handy later when we |
| 1156 // Store which frame was active. This will come in handy later when we | 1120 // change the active match ordinal below. |
| 1157 // change the active match ordinal below. | 1121 WebFrameImpl* oldActiveFrame = mainFrameImpl->m_activeMatchFrame; |
| 1158 WebFrameImpl* old_active_frame = main_frame_impl->active_match_frame_; | 1122 // Set this frame as the active frame (the one with the active highlight). |
| 1159 // Set this frame as the active frame (the one with the active highlight). | 1123 mainFrameImpl->m_activeMatchFrame = this; |
| 1160 main_frame_impl->active_match_frame_ = this; | 1124 |
| 1161 | 1125 // We found something, so we can now query the selection for its position. |
| 1162 // We found something, so we can now query the selection for its position. | 1126 VisibleSelection newSelection(frame()->selection()->selection()); |
| 1163 VisibleSelection new_selection(frame()->selection()->selection()); | 1127 IntRect currSelectionRect; |
| 1164 IntRect curr_selection_rect; | 1128 |
| 1165 | 1129 // If we thought we found something, but it couldn't be selected (perhaps |
| 1166 // If we thought we found something, but it couldn't be selected (perhaps | 1130 // because it was marked -webkit-user-select: none), we can't set it to |
| 1167 // because it was marked -webkit-user-select: none), we can't set it to | 1131 // be active but we still continue searching. This matches Safari's |
| 1168 // be active but we still continue searching. This matches Safari's | 1132 // behavior, including some oddities when selectable and un-selectable text |
| 1169 // behavior, including some oddities when selectable and un-selectable text | 1133 // are mixed on a page: see https://bugs.webkit.org/show_bug.cgi?id=19127. |
| 1170 // are mixed on a page: see https://bugs.webkit.org/show_bug.cgi?id=19127. | 1134 if (newSelection.isNone() || (newSelection.start() == newSelection.end())) |
| 1171 if (new_selection.isNone() || | 1135 m_activeMatch = 0; |
| 1172 (new_selection.start() == new_selection.end())) { | 1136 else { |
| 1173 active_match_ = NULL; | 1137 m_activeMatch = newSelection.toNormalizedRange(); |
| 1138 currSelectionRect = m_activeMatch->boundingBox(); |
| 1139 setMarkerActive(m_activeMatch.get(), true); // Active. |
| 1140 // WebKit draws the highlighting for all matches. |
| 1141 executeCommand(WebString::fromUTF8("Unselect")); |
| 1142 } |
| 1143 |
| 1144 if (!options.findNext) { |
| 1145 // This is a Find operation, so we set the flag to ask the scoping effort |
| 1146 // to find the active rect for us so we can update the ordinal (n of m). |
| 1147 m_locatingActiveRect = true; |
| 1148 } else { |
| 1149 if (oldActiveFrame != this) { |
| 1150 // If the active frame has changed it means that we have a multi-frame |
| 1151 // page and we just switch to searching in a new frame. Then we just |
| 1152 // want to reset the index. |
| 1153 if (options.forward) |
| 1154 m_activeMatchIndex = 0; |
| 1155 else |
| 1156 m_activeMatchIndex = m_lastMatchCount - 1; |
| 1157 } else { |
| 1158 // We are still the active frame, so increment (or decrement) the |
| 1159 // |m_activeMatchIndex|, wrapping if needed (on single frame pages). |
| 1160 options.forward ? ++m_activeMatchIndex : --m_activeMatchIndex; |
| 1161 if (m_activeMatchIndex + 1 > m_lastMatchCount) |
| 1162 m_activeMatchIndex = 0; |
| 1163 if (m_activeMatchIndex + 1 == 0) |
| 1164 m_activeMatchIndex = m_lastMatchCount - 1; |
| 1165 } |
| 1166 if (selectionRect) { |
| 1167 WebRect rect = frame()->view()->convertToContainingWindow(currSelectionRect); |
| 1168 rect.x -= frameView()->scrollOffset().width(); |
| 1169 rect.y -= frameView()->scrollOffset().height(); |
| 1170 *selectionRect = rect; |
| 1171 |
| 1172 reportFindInPageSelection(rect, m_activeMatchIndex + 1, identifier); |
| 1173 } |
| 1174 } |
| 1174 } else { | 1175 } else { |
| 1175 active_match_ = new_selection.toNormalizedRange(); | 1176 // Nothing was found in this frame. |
| 1176 curr_selection_rect = active_match_->boundingBox(); | 1177 m_activeMatch = 0; |
| 1177 SetMarkerActive(active_match_.get(), true); // Active. | 1178 |
| 1178 // WebKit draws the highlighting for all matches. | 1179 // Erase all previous tickmarks and highlighting. |
| 1179 executeCommand(WebString::fromUTF8("Unselect")); | 1180 invalidateArea(InvalidateAll); |
| 1180 } | 1181 } |
| 1181 | 1182 |
| 1182 if (!options.findNext) { | 1183 return found; |
| 1183 // This is a Find operation, so we set the flag to ask the scoping effort | 1184 } |
| 1184 // to find the active rect for us so we can update the ordinal (n of m). | 1185 |
| 1185 locating_active_rect_ = true; | 1186 void WebFrameImpl::stopFinding(bool clearSelection) |
| 1186 } else { | 1187 { |
| 1187 if (old_active_frame != this) { | 1188 if (!clearSelection) |
| 1188 // If the active frame has changed it means that we have a multi-frame | 1189 setFindEndstateFocusAndSelection(); |
| 1189 // page and we just switch to searching in a new frame. Then we just | 1190 cancelPendingScopingEffort(); |
| 1190 // want to reset the index. | 1191 |
| 1191 if (options.forward) | 1192 // Remove all markers for matches found and turn off the highlighting. |
| 1192 active_match_index_ = 0; | 1193 if (!parent()) |
| 1193 else | 1194 frame()->document()->removeMarkers(DocumentMarker::TextMatch); |
| 1194 active_match_index_ = last_match_count_ - 1; | 1195 frame()->setMarkedTextMatchesAreHighlighted(false); |
| 1195 } else { | 1196 |
| 1196 // We are still the active frame, so increment (or decrement) the | 1197 // Let the frame know that we don't want tickmarks or highlighting anymore. |
| 1197 // |active_match_index|, wrapping if needed (on single frame pages). | 1198 invalidateArea(InvalidateAll); |
| 1198 options.forward ? ++active_match_index_ : --active_match_index_; | 1199 } |
| 1199 if (active_match_index_ + 1 > last_match_count_) | 1200 |
| 1200 active_match_index_ = 0; | 1201 void WebFrameImpl::scopeStringMatches(int identifier, |
| 1201 if (active_match_index_ + 1 == 0) | 1202 const WebString& searchText, |
| 1202 active_match_index_ = last_match_count_ - 1; | |
| 1203 } | |
| 1204 if (selection_rect) { | |
| 1205 WebRect rect = webkit_glue::IntRectToWebRect( | |
| 1206 frame()->view()->convertToContainingWindow(curr_selection_rect)); | |
| 1207 rect.x -= frameview()->scrollOffset().width(); | |
| 1208 rect.y -= frameview()->scrollOffset().height(); | |
| 1209 *selection_rect = rect; | |
| 1210 | |
| 1211 ReportFindInPageSelection(rect, | |
| 1212 active_match_index_ + 1, | |
| 1213 request_id); | |
| 1214 } | |
| 1215 } | |
| 1216 } else { | |
| 1217 // Nothing was found in this frame. | |
| 1218 active_match_ = NULL; | |
| 1219 | |
| 1220 // Erase all previous tickmarks and highlighting. | |
| 1221 InvalidateArea(INVALIDATE_ALL); | |
| 1222 } | |
| 1223 | |
| 1224 return found; | |
| 1225 } | |
| 1226 | |
| 1227 void WebFrameImpl::stopFinding(bool clear_selection) { | |
| 1228 if (!clear_selection) | |
| 1229 SetFindEndstateFocusAndSelection(); | |
| 1230 cancelPendingScopingEffort(); | |
| 1231 | |
| 1232 // Remove all markers for matches found and turn off the highlighting. | |
| 1233 if (!parent()) | |
| 1234 frame()->document()->removeMarkers(WebCore::DocumentMarker::TextMatch); | |
| 1235 frame()->setMarkedTextMatchesAreHighlighted(false); | |
| 1236 | |
| 1237 // Let the frame know that we don't want tickmarks or highlighting anymore. | |
| 1238 InvalidateArea(INVALIDATE_ALL); | |
| 1239 } | |
| 1240 | |
| 1241 void WebFrameImpl::scopeStringMatches(int request_id, | |
| 1242 const WebString& search_text, | |
| 1243 const WebFindOptions& options, | 1203 const WebFindOptions& options, |
| 1244 bool reset) { | 1204 bool reset) |
| 1245 if (!ShouldScopeMatches(search_text)) | 1205 { |
| 1246 return; | 1206 if (!shouldScopeMatches(searchText)) |
| 1247 | 1207 return; |
| 1248 WebFrameImpl* main_frame_impl = GetWebViewImpl()->main_frame(); | 1208 |
| 1249 | 1209 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl(); |
| 1250 if (reset) { | 1210 |
| 1251 // This is a brand new search, so we need to reset everything. | 1211 if (reset) { |
| 1252 // Scoping is just about to begin. | 1212 // This is a brand new search, so we need to reset everything. |
| 1253 scoping_complete_ = false; | 1213 // Scoping is just about to begin. |
| 1254 // Clear highlighting for this frame. | 1214 m_scopingComplete = false; |
| 1255 if (frame()->markedTextMatchesAreHighlighted()) | 1215 // Clear highlighting for this frame. |
| 1256 frame()->page()->unmarkAllTextMatches(); | 1216 if (frame()->markedTextMatchesAreHighlighted()) |
| 1257 // Clear the counters from last operation. | 1217 frame()->page()->unmarkAllTextMatches(); |
| 1258 last_match_count_ = 0; | 1218 // Clear the counters from last operation. |
| 1259 next_invalidate_after_ = 0; | 1219 m_lastMatchCount = 0; |
| 1260 | 1220 m_nextInvalidateAfter = 0; |
| 1261 resume_scoping_from_range_ = NULL; | 1221 |
| 1262 | 1222 m_resumeScopingFromRange = 0; |
| 1263 main_frame_impl->frames_scoping_count_++; | 1223 |
| 1264 | 1224 mainFrameImpl->m_framesScopingCount++; |
| 1265 // Now, defer scoping until later to allow find operation to finish quickly. | 1225 |
| 1266 ScopeStringMatchesSoon( | 1226 // Now, defer scoping until later to allow find operation to finish quickly. |
| 1267 request_id, | 1227 scopeStringMatchesSoon( |
| 1268 search_text, | 1228 identifier, |
| 1269 options, | 1229 searchText, |
| 1270 false); // false=we just reset, so don't do it again. | 1230 options, |
| 1271 return; | 1231 false); // false=we just reset, so don't do it again. |
| 1272 } | 1232 return; |
| 1273 | 1233 } |
| 1274 WebCore::String webcore_string = webkit_glue::String16ToString(search_text); | 1234 |
| 1275 | 1235 RefPtr<Range> searchRange(rangeOfContents(frame()->document())); |
| 1276 RefPtr<Range> search_range(rangeOfContents(frame()->document())); | 1236 |
| 1277 | 1237 ExceptionCode ec = 0, ec2 = 0; |
| 1278 ExceptionCode ec = 0, ec2 = 0; | 1238 if (m_resumeScopingFromRange.get()) { |
| 1279 if (resume_scoping_from_range_.get()) { | 1239 // This is a continuation of a scoping operation that timed out and didn't |
| 1280 // This is a continuation of a scoping operation that timed out and didn't | 1240 // complete last time around, so we should start from where we left off. |
| 1281 // complete last time around, so we should start from where we left off. | 1241 searchRange->setStart(m_resumeScopingFromRange->startContainer(), |
| 1282 search_range->setStart(resume_scoping_from_range_->startContainer(), | 1242 m_resumeScopingFromRange->startOffset(ec2) + 1, |
| 1283 resume_scoping_from_range_->startOffset(ec2) + 1, | 1243 ec); |
| 1284 ec); | 1244 if (ec != 0 || ec2 != 0) { |
| 1285 if (ec != 0 || ec2 != 0) { | 1245 if (ec2 != 0) // A non-zero |ec| happens when navigating during search. |
| 1286 if (ec2 != 0) // A non-zero |ec| happens when navigating during search. | 1246 ASSERT_NOT_REACHED(); |
| 1287 ASSERT_NOT_REACHED(); | 1247 return; |
| 1288 return; | 1248 } |
| 1289 } | 1249 } |
| 1290 } | 1250 |
| 1291 | 1251 // This timeout controls how long we scope before releasing control. This |
| 1292 // This timeout controls how long we scope before releasing control. This | 1252 // value does not prevent us from running for longer than this, but it is |
| 1293 // value does not prevent us from running for longer than this, but it is | 1253 // periodically checked to see if we have exceeded our allocated time. |
| 1294 // periodically checked to see if we have exceeded our allocated time. | 1254 const double maxScopingDuration = 0.1; // seconds |
| 1295 const double kTimeout = 0.1; // seconds | 1255 |
| 1296 | 1256 int matchCount = 0; |
| 1297 int match_count = 0; | 1257 bool timedOut = false; |
| 1298 bool timeout = false; | 1258 double startTime = currentTime(); |
| 1299 double start_time = currentTime(); | 1259 do { |
| 1300 do { | 1260 // Find next occurrence of the search string. |
| 1301 // Find next occurrence of the search string. | 1261 // FIXME: (http://b/1088245) This WebKit operation may run for longer |
| 1302 // TODO(finnur): (http://b/1088245) This WebKit operation may run | 1262 // than the timeout value, and is not interruptible as it is currently |
| 1303 // for longer than the timeout value, and is not interruptible as it is | 1263 // written. We may need to rewrite it with interruptibility in mind, or |
| 1304 // currently written. We may need to rewrite it with interruptibility in | 1264 // find an alternative. |
| 1305 // mind, or find an alternative. | 1265 RefPtr<Range> resultRange(findPlainText(searchRange.get(), |
| 1306 RefPtr<Range> result_range(findPlainText(search_range.get(), | 1266 searchText, |
| 1307 webcore_string, | 1267 true, |
| 1308 true, | 1268 options.matchCase)); |
| 1309 options.matchCase)); | 1269 if (resultRange->collapsed(ec)) { |
| 1310 if (result_range->collapsed(ec)) { | 1270 if (!resultRange->startContainer()->isInShadowTree()) |
| 1311 if (!result_range->startContainer()->isInShadowTree()) | 1271 break; |
| 1312 break; | 1272 |
| 1313 | 1273 searchRange = rangeOfContents(frame()->document()); |
| 1314 search_range = rangeOfContents(frame()->document()); | 1274 searchRange->setStartAfter( |
| 1315 search_range->setStartAfter( | 1275 resultRange->startContainer()->shadowAncestorNode(), ec); |
| 1316 result_range->startContainer()->shadowAncestorNode(), ec); | 1276 continue; |
| 1317 continue; | 1277 } |
| 1318 } | 1278 |
| 1319 | 1279 // A non-collapsed result range can in some funky whitespace cases still not |
| 1320 // A non-collapsed result range can in some funky whitespace cases still not | 1280 // advance the range's start position (4509328). Break to avoid infinite |
| 1321 // advance the range's start position (4509328). Break to avoid infinite | 1281 // loop. (This function is based on the implementation of |
| 1322 // loop. (This function is based on the implementation of | 1282 // Frame::markAllMatchesForText, which is where this safeguard comes from). |
| 1323 // Frame::markAllMatchesForText, which is where this safeguard comes from). | 1283 VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM); |
| 1324 VisiblePosition new_start = endVisiblePosition(result_range.get(), | 1284 if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) |
| 1325 WebCore::DOWNSTREAM); | 1285 break; |
| 1326 if (new_start == startVisiblePosition(search_range.get(), | 1286 |
| 1327 WebCore::DOWNSTREAM)) | 1287 // Only treat the result as a match if it is visible |
| 1328 break; | 1288 if (frame()->editor()->insideVisibleArea(resultRange.get())) { |
| 1329 | 1289 ++matchCount; |
| 1330 // Only treat the result as a match if it is visible | 1290 |
| 1331 if (frame()->editor()->insideVisibleArea(result_range.get())) { | 1291 setStart(searchRange.get(), newStart); |
| 1332 ++match_count; | 1292 Node* shadowTreeRoot = searchRange->shadowTreeRootNode(); |
| 1333 | 1293 if (searchRange->collapsed(ec) && shadowTreeRoot) |
| 1334 setStart(search_range.get(), new_start); | 1294 searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec); |
| 1335 Node* shadow_tree_root = search_range->shadowTreeRootNode(); | 1295 |
| 1336 if (search_range->collapsed(ec) && shadow_tree_root) | 1296 // Catch a special case where Find found something but doesn't know what |
| 1337 search_range->setEnd(shadow_tree_root, | 1297 // the bounding box for it is. In this case we set the first match we find |
| 1338 shadow_tree_root->childNodeCount(), ec); | 1298 // as the active rect. |
| 1339 | 1299 IntRect resultBounds = resultRange->boundingBox(); |
| 1340 // Catch a special case where Find found something but doesn't know what | 1300 IntRect activeSelectionRect; |
| 1341 // the bounding box for it is. In this case we set the first match we find | 1301 if (m_locatingActiveRect) { |
| 1342 // as the active rect. | 1302 activeSelectionRect = m_activeMatch.get() ? |
| 1343 IntRect result_bounds = result_range->boundingBox(); | 1303 m_activeMatch->boundingBox() : resultBounds; |
| 1344 IntRect active_selection_rect; | 1304 } |
| 1345 if (locating_active_rect_) { | 1305 |
| 1346 active_selection_rect = active_match_.get() ? | 1306 // If the Find function found a match it will have stored where the |
| 1347 active_match_->boundingBox() : result_bounds; | 1307 // match was found in m_activeSelectionRect on the current frame. If we |
| 1348 } | 1308 // find this rect during scoping it means we have found the active |
| 1349 | 1309 // tickmark. |
| 1350 // If the Find function found a match it will have stored where the | 1310 bool foundActiveMatch = false; |
| 1351 // match was found in active_selection_rect_ on the current frame. If we | 1311 if (m_locatingActiveRect && (activeSelectionRect == resultBounds)) { |
| 1352 // find this rect during scoping it means we have found the active | 1312 // We have found the active tickmark frame. |
| 1353 // tickmark. | 1313 mainFrameImpl->m_activeMatchFrame = this; |
| 1354 bool found_active_match = false; | 1314 foundActiveMatch = true; |
| 1355 if (locating_active_rect_ && (active_selection_rect == result_bounds)) { | 1315 // We also know which tickmark is active now. |
| 1356 // We have found the active tickmark frame. | 1316 m_activeMatchIndex = matchCount - 1; |
| 1357 main_frame_impl->active_match_frame_ = this; | 1317 // To stop looking for the active tickmark, we set this flag. |
| 1358 found_active_match = true; | 1318 m_locatingActiveRect = false; |
| 1359 // We also know which tickmark is active now. | 1319 |
| 1360 active_match_index_ = match_count - 1; | 1320 // Notify browser of new location for the selected rectangle. |
| 1361 // To stop looking for the active tickmark, we set this flag. | 1321 resultBounds.move(-frameView()->scrollOffset().width(), |
| 1362 locating_active_rect_ = false; | 1322 -frameView()->scrollOffset().height()); |
| 1363 | 1323 reportFindInPageSelection( |
| 1364 // Notify browser of new location for the selected rectangle. | 1324 frame()->view()->convertToContainingWindow(resultBounds), |
| 1365 result_bounds.move(-frameview()->scrollOffset().width(), | 1325 m_activeMatchIndex + 1, |
| 1366 -frameview()->scrollOffset().height()); | 1326 identifier); |
| 1367 ReportFindInPageSelection( | 1327 } |
| 1368 webkit_glue::IntRectToWebRect( | 1328 |
| 1369 frame()->view()->convertToContainingWindow(result_bounds)), | 1329 addMarker(resultRange.get(), foundActiveMatch); |
| 1370 active_match_index_ + 1, | 1330 } |
| 1371 request_id); | 1331 |
| 1372 } | 1332 m_resumeScopingFromRange = resultRange; |
| 1373 | 1333 timedOut = (currentTime() - startTime) >= maxScopingDuration; |
| 1374 AddMarker(result_range.get(), found_active_match); | 1334 } while (!timedOut); |
| 1375 } | 1335 |
| 1376 | 1336 // Remember what we search for last time, so we can skip searching if more |
| 1377 resume_scoping_from_range_ = result_range; | 1337 // letters are added to the search string (and last outcome was 0). |
| 1378 timeout = (currentTime() - start_time) >= kTimeout; | 1338 m_lastSearchString = searchText; |
| 1379 } while (!timeout); | 1339 |
| 1380 | 1340 if (matchCount > 0) { |
| 1381 // Remember what we search for last time, so we can skip searching if more | 1341 frame()->setMarkedTextMatchesAreHighlighted(true); |
| 1382 // letters are added to the search string (and last outcome was 0). | 1342 |
| 1383 last_search_string_ = search_text; | 1343 m_lastMatchCount += matchCount; |
| 1384 | 1344 |
| 1385 if (match_count > 0) { | 1345 // Let the mainframe know how much we found during this pass. |
| 1386 frame()->setMarkedTextMatchesAreHighlighted(true); | 1346 mainFrameImpl->increaseMatchCount(matchCount, identifier); |
| 1387 | 1347 } |
| 1388 last_match_count_ += match_count; | 1348 |
| 1389 | 1349 if (timedOut) { |
| 1390 // Let the mainframe know how much we found during this pass. | 1350 // If we found anything during this pass, we should redraw. However, we |
| 1391 main_frame_impl->increaseMatchCount(match_count, request_id); | 1351 // don't want to spam too much if the page is extremely long, so if we |
| 1392 } | 1352 // reach a certain point we start throttling the redraw requests. |
| 1393 | 1353 if (matchCount > 0) |
| 1394 if (timeout) { | 1354 invalidateIfNecessary(); |
| 1395 // If we found anything during this pass, we should redraw. However, we | 1355 |
| 1396 // don't want to spam too much if the page is extremely long, so if we | 1356 // Scoping effort ran out of time, lets ask for another time-slice. |
| 1397 // reach a certain point we start throttling the redraw requests. | 1357 scopeStringMatchesSoon( |
| 1398 if (match_count > 0) | 1358 identifier, |
| 1399 InvalidateIfNecessary(); | 1359 searchText, |
| 1400 | 1360 options, |
| 1401 // Scoping effort ran out of time, lets ask for another time-slice. | 1361 false); // don't reset. |
| 1402 ScopeStringMatchesSoon( | 1362 return; // Done for now, resume work later. |
| 1403 request_id, | 1363 } |
| 1404 search_text, | 1364 |
| 1405 options, | 1365 // This frame has no further scoping left, so it is done. Other frames might, |
| 1406 false); // don't reset. | 1366 // of course, continue to scope matches. |
| 1407 return; // Done for now, resume work later. | 1367 m_scopingComplete = true; |
| 1408 } | 1368 mainFrameImpl->m_framesScopingCount--; |
| 1409 | 1369 |
| 1410 // This frame has no further scoping left, so it is done. Other frames might, | 1370 // If this is the last frame to finish scoping we need to trigger the final |
| 1411 // of course, continue to scope matches. | 1371 // update to be sent. |
| 1412 scoping_complete_ = true; | 1372 if (mainFrameImpl->m_framesScopingCount == 0) |
| 1413 main_frame_impl->frames_scoping_count_--; | 1373 mainFrameImpl->increaseMatchCount(0, identifier); |
| 1414 | 1374 |
| 1415 // If this is the last frame to finish scoping we need to trigger the final | 1375 // This frame is done, so show any scrollbar tickmarks we haven't drawn yet. |
| 1416 // update to be sent. | 1376 invalidateArea(InvalidateScrollbar); |
| 1417 if (main_frame_impl->frames_scoping_count_ == 0) | 1377 } |
| 1418 main_frame_impl->increaseMatchCount(0, request_id); | 1378 |
| 1419 | 1379 void WebFrameImpl::cancelPendingScopingEffort() |
| 1420 // This frame is done, so show any scrollbar tickmarks we haven't drawn yet. | 1380 { |
| 1421 InvalidateArea(INVALIDATE_SCROLLBAR); | 1381 deleteAllValues(m_deferredScopingWork); |
| 1422 } | 1382 m_deferredScopingWork.clear(); |
| 1423 | 1383 |
| 1424 void WebFrameImpl::cancelPendingScopingEffort() { | 1384 m_activeMatchIndex = -1; |
| 1425 deleteAllValues(deferred_scoping_work_); | 1385 } |
| 1426 deferred_scoping_work_.clear(); | 1386 |
| 1427 | 1387 void WebFrameImpl::increaseMatchCount(int count, int identifier) |
| 1428 active_match_index_ = -1; | 1388 { |
| 1429 } | 1389 // This function should only be called on the mainframe. |
| 1430 | 1390 ASSERT(!parent()); |
| 1431 void WebFrameImpl::increaseMatchCount(int count, int request_id) { | 1391 |
| 1432 // This function should only be called on the mainframe. | 1392 m_totalMatchCount += count; |
| 1433 ASSERT(!parent()); | 1393 |
| 1434 | 1394 // Update the UI with the latest findings. |
| 1435 total_matchcount_ += count; | 1395 if (client()) { |
| 1436 | 1396 client()->reportFindInPageMatchCount(identifier, m_totalMatchCount, |
| 1437 // Update the UI with the latest findings. | 1397 m_framesScopingCount == 0); |
| 1438 if (client()) { | 1398 } |
| 1439 client()->reportFindInPageMatchCount( | 1399 } |
| 1440 request_id, total_matchcount_, frames_scoping_count_ == 0); | 1400 |
| 1441 } | 1401 void WebFrameImpl::reportFindInPageSelection(const WebRect& selectionRect, |
| 1442 } | 1402 int activeMatchOrdinal, |
| 1443 | 1403 int identifier) |
| 1444 void WebFrameImpl::ReportFindInPageSelection(const WebRect& selection_rect, | 1404 { |
| 1445 int active_match_ordinal, | 1405 // Update the UI with the latest selection rect. |
| 1446 int request_id) { | 1406 if (client()) { |
| 1447 // Update the UI with the latest selection rect. | 1407 client()->reportFindInPageSelection( |
| 1448 if (client()) { | 1408 identifier, ordinalOfFirstMatchForFrame(this) + activeMatchOrdinal, |
| 1449 client()->reportFindInPageSelection( | 1409 selectionRect); |
| 1450 request_id, OrdinalOfFirstMatchForFrame(this) + active_match_ordinal, | 1410 } |
| 1451 selection_rect); | 1411 } |
| 1452 } | 1412 |
| 1453 } | 1413 void WebFrameImpl::resetMatchCount() |
| 1454 | 1414 { |
| 1455 void WebFrameImpl::resetMatchCount() { | 1415 m_totalMatchCount = 0; |
| 1456 total_matchcount_ = 0; | 1416 m_framesScopingCount = 0; |
| 1457 frames_scoping_count_ = 0; | 1417 } |
| 1458 } | 1418 |
| 1459 | 1419 WebURL WebFrameImpl::completeURL(const WebString& url) const |
| 1460 WebURL WebFrameImpl::completeURL(const WebString& url) const { | 1420 { |
| 1461 if (!frame_ || !frame_->document()) | 1421 if (!m_frame || !m_frame->document()) |
| 1462 return WebURL(); | 1422 return WebURL(); |
| 1463 | 1423 |
| 1464 return webkit_glue::KURLToWebURL( | 1424 return m_frame->document()->completeURL(url); |
| 1465 frame_->document()->completeURL(webkit_glue::WebStringToString(url))); | 1425 } |
| 1466 } | 1426 |
| 1467 | 1427 WebString WebFrameImpl::contentAsText(size_t maxChars) const |
| 1468 WebString WebFrameImpl::contentAsText(size_t max_chars) const { | 1428 { |
| 1469 if (!frame_) | 1429 if (!m_frame) |
| 1470 return WebString(); | 1430 return WebString(); |
| 1471 | 1431 |
| 1472 Vector<UChar> text; | 1432 Vector<UChar> text; |
| 1473 FrameContentAsPlainText(max_chars, frame_, &text); | 1433 frameContentAsPlainText(maxChars, m_frame, &text); |
| 1474 return webkit_glue::StringToWebString(String::adopt(text)); | 1434 return String::adopt(text); |
| 1475 } | 1435 } |
| 1476 | 1436 |
| 1477 WebString WebFrameImpl::contentAsMarkup() const { | 1437 WebString WebFrameImpl::contentAsMarkup() const |
| 1478 return webkit_glue::StringToWebString(createFullMarkup(frame_->document())); | 1438 { |
| 1439 return createFullMarkup(m_frame->document()); |
| 1479 } | 1440 } |
| 1480 | 1441 |
| 1481 // WebFrameImpl public --------------------------------------------------------- | 1442 // WebFrameImpl public --------------------------------------------------------- |
| 1482 | 1443 |
| 1483 int WebFrameImpl::live_object_count_ = 0; | 1444 int WebFrameImpl::m_liveObjectCount = 0; |
| 1484 | 1445 |
| 1485 PassRefPtr<WebFrameImpl> WebFrameImpl::create(WebFrameClient* client) { | 1446 PassRefPtr<WebFrameImpl> WebFrameImpl::create(WebFrameClient* client) |
| 1486 return adoptRef(new WebFrameImpl(ClientHandle::create(client))); | 1447 { |
| 1487 } | 1448 return adoptRef(new WebFrameImpl(ClientHandle::create(client))); |
| 1488 | 1449 } |
| 1489 WebFrameImpl::WebFrameImpl(PassRefPtr<ClientHandle> client_handle) | 1450 |
| 1490 : ALLOW_THIS_IN_INITIALIZER_LIST(frame_loader_client_(this)), | 1451 WebFrameImpl::WebFrameImpl(PassRefPtr<ClientHandle> clientHandle) |
| 1491 client_handle_(client_handle), | 1452 : m_frameLoaderClient(this) |
| 1492 active_match_frame_(NULL), | 1453 , m_clientHandle(clientHandle) |
| 1493 active_match_index_(-1), | 1454 , m_activeMatchFrame(0) |
| 1494 locating_active_rect_(false), | 1455 , m_activeMatchIndex(-1) |
| 1495 resume_scoping_from_range_(NULL), | 1456 , m_locatingActiveRect(false) |
| 1496 last_match_count_(-1), | 1457 , m_resumeScopingFromRange(0) |
| 1497 total_matchcount_(-1), | 1458 , m_lastMatchCount(-1) |
| 1498 frames_scoping_count_(-1), | 1459 , m_totalMatchCount(-1) |
| 1499 scoping_complete_(false), | 1460 , m_framesScopingCount(-1) |
| 1500 next_invalidate_after_(0) { | 1461 , m_scopingComplete(false) |
| 1501 ChromiumBridge::incrementStatsCounter(kWebFrameActiveCount); | 1462 , m_nextInvalidateAfter(0) |
| 1502 live_object_count_++; | 1463 { |
| 1503 } | 1464 ChromiumBridge::incrementStatsCounter(webFrameActiveCount); |
| 1504 | 1465 m_liveObjectCount++; |
| 1505 WebFrameImpl::~WebFrameImpl() { | 1466 } |
| 1506 ChromiumBridge::decrementStatsCounter(kWebFrameActiveCount); | 1467 |
| 1507 live_object_count_--; | 1468 WebFrameImpl::~WebFrameImpl() |
| 1508 | 1469 { |
| 1509 cancelPendingScopingEffort(); | 1470 ChromiumBridge::decrementStatsCounter(webFrameActiveCount); |
| 1510 ClearPasswordListeners(); | 1471 m_liveObjectCount--; |
| 1511 } | 1472 |
| 1512 | 1473 cancelPendingScopingEffort(); |
| 1513 void WebFrameImpl::InitMainFrame(WebViewImpl* webview_impl) { | 1474 clearPasswordListeners(); |
| 1514 RefPtr<Frame> frame = | 1475 } |
| 1515 Frame::create(webview_impl->page(), 0, &frame_loader_client_); | 1476 |
| 1516 frame_ = frame.get(); | 1477 void WebFrameImpl::initializeAsMainFrame(WebViewImpl* webViewImpl) |
| 1517 | 1478 { |
| 1518 // Add reference on behalf of FrameLoader. See comments in | 1479 RefPtr<Frame> frame = Frame::create(webViewImpl->page(), 0, &m_frameLoaderClient); |
| 1519 // WebFrameLoaderClient::frameLoaderDestroyed for more info. | 1480 m_frame = frame.get(); |
| 1520 ref(); | 1481 |
| 1521 | 1482 // Add reference on behalf of FrameLoader. See comments in |
| 1522 // We must call init() after frame_ is assigned because it is referenced | 1483 // WebFrameLoaderClient::frameLoaderDestroyed for more info. |
| 1523 // during init(). | 1484 ref(); |
| 1524 frame_->init(); | 1485 |
| 1525 } | 1486 // We must call init() after m_frame is assigned because it is referenced |
| 1526 | 1487 // during init(). |
| 1527 PassRefPtr<Frame> WebFrameImpl::CreateChildFrame( | 1488 m_frame->init(); |
| 1528 const FrameLoadRequest& request, HTMLFrameOwnerElement* owner_element) { | 1489 } |
| 1529 // TODO(darin): share code with initWithName() | 1490 |
| 1530 | 1491 PassRefPtr<Frame> WebFrameImpl::createChildFrame( |
| 1531 RefPtr<WebFrameImpl> webframe(adoptRef(new WebFrameImpl(client_handle_))); | 1492 const FrameLoadRequest& request, HTMLFrameOwnerElement* ownerElement) |
| 1532 | 1493 { |
| 1533 // Add an extra ref on behalf of the Frame/FrameLoader, which references the | 1494 RefPtr<WebFrameImpl> webframe(adoptRef(new WebFrameImpl(m_clientHandle))); |
| 1534 // WebFrame via the FrameLoaderClient interface. See the comment at the top | 1495 |
| 1535 // of this file for more info. | 1496 // Add an extra ref on behalf of the Frame/FrameLoader, which references the |
| 1536 webframe->ref(); | 1497 // WebFrame via the FrameLoaderClient interface. See the comment at the top |
| 1537 | 1498 // of this file for more info. |
| 1538 RefPtr<Frame> child_frame = Frame::create( | 1499 webframe->ref(); |
| 1539 frame_->page(), owner_element, &webframe->frame_loader_client_); | 1500 |
| 1540 webframe->frame_ = child_frame.get(); | 1501 RefPtr<Frame> childFrame = Frame::create( |
| 1541 | 1502 m_frame->page(), ownerElement, &webframe->m_frameLoaderClient); |
| 1542 child_frame->tree()->setName(request.frameName()); | 1503 webframe->m_frame = childFrame.get(); |
| 1543 | 1504 |
| 1544 frame_->tree()->appendChild(child_frame); | 1505 childFrame->tree()->setName(request.frameName()); |
| 1545 | 1506 |
| 1546 // Frame::init() can trigger onload event in the parent frame, | 1507 m_frame->tree()->appendChild(childFrame); |
| 1547 // which may detach this frame and trigger a null-pointer access | 1508 |
| 1548 // in FrameTree::removeChild. Move init() after appendChild call | 1509 // Frame::init() can trigger onload event in the parent frame, |
| 1549 // so that webframe->frame_ is in the tree before triggering | 1510 // which may detach this frame and trigger a null-pointer access |
| 1550 // onload event handler. | 1511 // in FrameTree::removeChild. Move init() after appendChild call |
| 1551 // Because the event handler may set webframe->frame_ to null, | 1512 // so that webframe->mFrame is in the tree before triggering |
| 1552 // it is necessary to check the value after calling init() and | 1513 // onload event handler. |
| 1553 // return without loading URL. | 1514 // Because the event handler may set webframe->mFrame to null, |
| 1554 // (b:791612) | 1515 // it is necessary to check the value after calling init() and |
| 1555 child_frame->init(); // create an empty document | 1516 // return without loading URL. |
| 1556 if (!child_frame->tree()->parent()) | 1517 // (b:791612) |
| 1557 return NULL; | 1518 childFrame->init(); // create an empty document |
| 1558 | 1519 if (!childFrame->tree()->parent()) |
| 1559 frame_->loader()->loadURLIntoChildFrame( | 1520 return 0; |
| 1560 request.resourceRequest().url(), | 1521 |
| 1561 request.resourceRequest().httpReferrer(), | 1522 m_frame->loader()->loadURLIntoChildFrame( |
| 1562 child_frame.get()); | 1523 request.resourceRequest().url(), |
| 1563 | 1524 request.resourceRequest().httpReferrer(), |
| 1564 // A synchronous navigation (about:blank) would have already processed | 1525 childFrame.get()); |
| 1565 // onload, so it is possible for the frame to have already been destroyed by | 1526 |
| 1566 // script in the page. | 1527 // A synchronous navigation (about:blank) would have already processed |
| 1567 if (!child_frame->tree()->parent()) | 1528 // onload, so it is possible for the frame to have already been destroyed by |
| 1568 return NULL; | 1529 // script in the page. |
| 1569 | 1530 if (!childFrame->tree()->parent()) |
| 1570 return child_frame.release(); | 1531 return 0; |
| 1571 } | 1532 |
| 1572 | 1533 return childFrame.release(); |
| 1573 void WebFrameImpl::Layout() { | 1534 } |
| 1574 // layout this frame | 1535 |
| 1575 FrameView* view = frame_->view(); | 1536 void WebFrameImpl::layout() |
| 1576 if (view) | 1537 { |
| 1577 view->layoutIfNeededRecursive(); | 1538 // layout this frame |
| 1578 } | 1539 FrameView* view = m_frame->view(); |
| 1579 | 1540 if (view) |
| 1580 void WebFrameImpl::Paint(WebCanvas* canvas, const WebRect& rect) { | 1541 view->layoutIfNeededRecursive(); |
| 1581 if (rect.isEmpty()) | 1542 } |
| 1582 return; | 1543 |
| 1583 IntRect dirty_rect(webkit_glue::WebRectToIntRect(rect)); | 1544 void WebFrameImpl::paint(WebCanvas* canvas, const WebRect& rect) |
| 1545 { |
| 1546 if (rect.isEmpty()) |
| 1547 return; |
| 1548 IntRect dirtyRect(rect); |
| 1584 #if WEBKIT_USING_CG | 1549 #if WEBKIT_USING_CG |
| 1585 GraphicsContext gc(canvas); | 1550 GraphicsContext gc(canvas); |
| 1586 WebCore::LocalCurrentGraphicsContext localContext(&gc); | 1551 LocalCurrentGraphicsContext localContext(&gc); |
| 1587 #elif WEBKIT_USING_SKIA | 1552 #elif WEBKIT_USING_SKIA |
| 1588 PlatformContextSkia context(canvas); | 1553 PlatformContextSkia context(canvas); |
| 1589 | 1554 |
| 1590 // PlatformGraphicsContext is actually a pointer to PlatformContextSkia | 1555 // PlatformGraphicsContext is actually a pointer to PlatformContextSkia |
| 1591 GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context)); | 1556 GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context)); |
| 1592 #else | 1557 #else |
| 1593 notImplemented(); | 1558 notImplemented(); |
| 1594 #endif | 1559 #endif |
| 1595 gc.save(); | 1560 gc.save(); |
| 1596 if (frame_->document() && frameview()) { | 1561 if (m_frame->document() && frameView()) { |
| 1597 gc.clip(dirty_rect); | 1562 gc.clip(dirtyRect); |
| 1598 frameview()->paint(&gc, dirty_rect); | 1563 frameView()->paint(&gc, dirtyRect); |
| 1599 frame_->page()->inspectorController()->drawNodeHighlight(gc); | 1564 m_frame->page()->inspectorController()->drawNodeHighlight(gc); |
| 1600 } else { | 1565 } else |
| 1601 gc.fillRect(dirty_rect, Color::white); | 1566 gc.fillRect(dirtyRect, Color::white); |
| 1602 } | 1567 gc.restore(); |
| 1603 gc.restore(); | 1568 } |
| 1604 } | 1569 |
| 1605 | 1570 void WebFrameImpl::createFrameView() |
| 1606 void WebFrameImpl::CreateFrameView() { | 1571 { |
| 1607 ASSERT(frame_); // If frame_ doesn't exist, we probably didn't init properly. | 1572 ASSERT(m_frame); // If m_frame doesn't exist, we probably didn't init properly. |
| 1608 | 1573 |
| 1609 WebCore::Page* page = frame_->page(); | 1574 Page* page = m_frame->page(); |
| 1610 ASSERT(page); | 1575 ASSERT(page); |
| 1611 | 1576 |
| 1612 ASSERT(page->mainFrame() != NULL); | 1577 ASSERT(page->mainFrame() != 0); |
| 1613 | 1578 |
| 1614 bool is_main_frame = frame_ == page->mainFrame(); | 1579 bool isMainFrame = m_frame == page->mainFrame(); |
| 1615 if (is_main_frame && frame_->view()) | 1580 if (isMainFrame && m_frame->view()) |
| 1616 frame_->view()->setParentVisible(false); | 1581 m_frame->view()->setParentVisible(false); |
| 1617 | 1582 |
| 1618 frame_->setView(0); | 1583 m_frame->setView(0); |
| 1619 | 1584 |
| 1620 WebViewImpl* web_view = GetWebViewImpl(); | 1585 WebViewImpl* webView = viewImpl(); |
| 1621 | 1586 |
| 1622 RefPtr<WebCore::FrameView> view; | 1587 RefPtr<FrameView> view; |
| 1623 if (is_main_frame) { | 1588 if (isMainFrame) |
| 1624 IntSize size = webkit_glue::WebSizeToIntSize(web_view->size()); | 1589 view = FrameView::create(m_frame, webView->size()); |
| 1625 view = FrameView::create(frame_, size); | 1590 else |
| 1626 } else { | 1591 view = FrameView::create(m_frame); |
| 1627 view = FrameView::create(frame_); | 1592 |
| 1628 } | 1593 m_frame->setView(view); |
| 1629 | 1594 |
| 1630 frame_->setView(view); | 1595 if (webView->isTransparent()) |
| 1631 | 1596 view->setTransparent(true); |
| 1632 if (web_view->isTransparent()) | 1597 |
| 1633 view->setTransparent(true); | 1598 // FIXME: The Mac code has a comment about this possibly being unnecessary. |
| 1634 | 1599 // See installInFrame in WebCoreFrameBridge.mm |
| 1635 // TODO(darin): The Mac code has a comment about this possibly being | 1600 if (m_frame->ownerRenderer()) |
| 1636 // unnecessary. See installInFrame in WebCoreFrameBridge.mm | 1601 m_frame->ownerRenderer()->setWidget(view.get()); |
| 1637 if (frame_->ownerRenderer()) | 1602 |
| 1638 frame_->ownerRenderer()->setWidget(view.get()); | 1603 if (HTMLFrameOwnerElement* owner = m_frame->ownerElement()) |
| 1639 | 1604 view->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); |
| 1640 if (HTMLFrameOwnerElement* owner = frame_->ownerElement()) { | 1605 |
| 1641 view->setCanHaveScrollbars( | 1606 if (isMainFrame) |
| 1642 owner->scrollingMode() != WebCore::ScrollbarAlwaysOff); | 1607 view->setParentVisible(true); |
| 1643 } | 1608 } |
| 1644 | 1609 |
| 1645 if (is_main_frame) | 1610 WebFrameImpl* WebFrameImpl::fromFrame(Frame* frame) |
| 1646 view->setParentVisible(true); | 1611 { |
| 1647 } | 1612 if (!frame) |
| 1648 | 1613 return 0; |
| 1649 // static | 1614 |
| 1650 WebFrameImpl* WebFrameImpl::FromFrame(WebCore::Frame* frame) { | 1615 return static_cast<FrameLoaderClientImpl*>(frame->loader()->client())->webFrame(); |
| 1651 if (!frame) | 1616 } |
| 1652 return NULL; | 1617 |
| 1653 return static_cast<WebFrameLoaderClient*>( | 1618 WebViewImpl* WebFrameImpl::viewImpl() const |
| 1654 frame->loader()->client())->webframe(); | 1619 { |
| 1655 } | 1620 if (!m_frame) |
| 1656 | 1621 return 0; |
| 1657 WebViewImpl* WebFrameImpl::GetWebViewImpl() const { | 1622 |
| 1658 if (!frame_) | 1623 return WebViewImpl::fromPage(m_frame->page()); |
| 1659 return NULL; | 1624 } |
| 1660 | 1625 |
| 1661 return WebViewImpl::FromPage(frame_->page()); | 1626 WebDataSourceImpl* WebFrameImpl::dataSourceImpl() const |
| 1662 } | 1627 { |
| 1663 | 1628 return static_cast<WebDataSourceImpl*>(dataSource()); |
| 1664 WebDataSourceImpl* WebFrameImpl::GetDataSourceImpl() const { | 1629 } |
| 1665 return static_cast<WebDataSourceImpl*>(dataSource()); | 1630 |
| 1666 } | 1631 WebDataSourceImpl* WebFrameImpl::provisionalDataSourceImpl() const |
| 1667 | 1632 { |
| 1668 WebDataSourceImpl* WebFrameImpl::GetProvisionalDataSourceImpl() const { | 1633 return static_cast<WebDataSourceImpl*>(provisionalDataSource()); |
| 1669 return static_cast<WebDataSourceImpl*>(provisionalDataSource()); | 1634 } |
| 1670 } | 1635 |
| 1671 | 1636 void WebFrameImpl::setFindEndstateFocusAndSelection() |
| 1672 void WebFrameImpl::SetFindEndstateFocusAndSelection() { | 1637 { |
| 1673 WebFrameImpl* main_frame_impl = GetWebViewImpl()->main_frame(); | 1638 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl(); |
| 1674 | 1639 |
| 1675 if (this == main_frame_impl->active_match_frame() && | 1640 if (this == mainFrameImpl->activeMatchFrame() && m_activeMatch.get()) { |
| 1676 active_match_.get()) { | 1641 // If the user has set the selection since the match was found, we |
| 1677 // If the user has set the selection since the match was found, we | 1642 // don't focus anything. |
| 1678 // don't focus anything. | 1643 VisibleSelection selection(frame()->selection()->selection()); |
| 1679 VisibleSelection selection(frame()->selection()->selection()); | 1644 if (!selection.isNone()) |
| 1680 if (!selection.isNone()) | 1645 return; |
| 1681 return; | 1646 |
| 1682 | 1647 // Try to find the first focusable node up the chain, which will, for |
| 1683 // Try to find the first focusable node up the chain, which will, for | 1648 // example, focus links if we have found text within the link. |
| 1684 // example, focus links if we have found text within the link. | 1649 Node* node = m_activeMatch->firstNode(); |
| 1685 Node* node = active_match_->firstNode(); | 1650 while (node && !node->isFocusable() && node != frame()->document()) |
| 1686 while (node && !node->isFocusable() && node != frame()->document()) | 1651 node = node->parent(); |
| 1687 node = node->parent(); | 1652 |
| 1688 | 1653 if (node && node != frame()->document()) { |
| 1689 if (node && node != frame()->document()) { | 1654 // Found a focusable parent node. Set focus to it. |
| 1690 // Found a focusable parent node. Set focus to it. | 1655 frame()->document()->setFocusedNode(node); |
| 1691 frame()->document()->setFocusedNode(node); | 1656 } else { |
| 1692 } else { | 1657 // Iterate over all the nodes in the range until we find a focusable node. |
| 1693 // Iterate over all the nodes in the range until we find a focusable node. | 1658 // This, for example, sets focus to the first link if you search for |
| 1694 // This, for example, sets focus to the first link if you search for | 1659 // text and text that is within one or more links. |
| 1695 // text and text that is within one or more links. | 1660 node = m_activeMatch->firstNode(); |
| 1696 node = active_match_->firstNode(); | 1661 while (node && node != m_activeMatch->pastLastNode()) { |
| 1697 while (node && node != active_match_->pastLastNode()) { | 1662 if (node->isFocusable()) { |
| 1698 if (node->isFocusable()) { | 1663 frame()->document()->setFocusedNode(node); |
| 1699 frame()->document()->setFocusedNode(node); | 1664 break; |
| 1700 break; | 1665 } |
| 1666 node = node->traverseNextNode(); |
| 1667 } |
| 1701 } | 1668 } |
| 1702 node = node->traverseNextNode(); | 1669 } |
| 1703 } | 1670 } |
| 1704 } | 1671 |
| 1705 } | 1672 void WebFrameImpl::didFail(const ResourceError& error, bool wasProvisional) |
| 1706 } | 1673 { |
| 1707 | 1674 if (!client()) |
| 1708 void WebFrameImpl::DidFail(const ResourceError& error, bool was_provisional) { | 1675 return; |
| 1709 if (!client()) | 1676 WebURLError webError = error; |
| 1710 return; | 1677 if (wasProvisional) |
| 1711 const WebURLError& web_error = | 1678 client()->didFailProvisionalLoad(this, webError); |
| 1712 webkit_glue::ResourceErrorToWebURLError(error); | 1679 else |
| 1713 if (was_provisional) { | 1680 client()->didFailLoad(this, webError); |
| 1714 client()->didFailProvisionalLoad(this, web_error); | 1681 } |
| 1715 } else { | 1682 |
| 1716 client()->didFailLoad(this, web_error); | 1683 void WebFrameImpl::setAllowsScrolling(bool flag) |
| 1717 } | 1684 { |
| 1718 } | 1685 m_frame->view()->setCanHaveScrollbars(flag); |
| 1719 | 1686 } |
| 1720 void WebFrameImpl::SetAllowsScrolling(bool flag) { | 1687 |
| 1721 frame_->view()->setCanHaveScrollbars(flag); | 1688 void WebFrameImpl::registerPasswordListener( |
| 1722 } | 1689 PassRefPtr<HTMLInputElement> inputElement, |
| 1723 | 1690 PasswordAutocompleteListener* listener) |
| 1724 void WebFrameImpl::RegisterPasswordListener( | 1691 { |
| 1725 PassRefPtr<HTMLInputElement> input_element, | 1692 RefPtr<HTMLInputElement> element = inputElement; |
| 1726 PasswordAutocompleteListener* listener) { | 1693 ASSERT(m_passwordListeners.find(element) == m_passwordListeners.end()); |
| 1727 RefPtr<HTMLInputElement> element = input_element; | 1694 m_passwordListeners.set(element, listener); |
| 1728 ASSERT(password_listeners_.find(element) == password_listeners_.end()); | 1695 } |
| 1729 password_listeners_.set(element, listener); | 1696 |
| 1730 } | 1697 PasswordAutocompleteListener* WebFrameImpl::getPasswordListener( |
| 1731 | 1698 HTMLInputElement* inputElement) |
| 1732 PasswordAutocompleteListener* WebFrameImpl::GetPasswordListener( | 1699 { |
| 1733 HTMLInputElement* input_element) { | 1700 return m_passwordListeners.get(RefPtr<HTMLInputElement>(inputElement)); |
| 1734 return password_listeners_.get(RefPtr<HTMLInputElement>(input_element)); | |
| 1735 } | |
| 1736 | |
| 1737 // WebFrameImpl protected ------------------------------------------------------ | |
| 1738 | |
| 1739 void WebFrameImpl::Closing() { | |
| 1740 frame_ = NULL; | |
| 1741 } | 1701 } |
| 1742 | 1702 |
| 1743 // WebFrameImpl private -------------------------------------------------------- | 1703 // WebFrameImpl private -------------------------------------------------------- |
| 1744 | 1704 |
| 1745 void WebFrameImpl::InvalidateArea(AreaToInvalidate area) { | 1705 void WebFrameImpl::closing() |
| 1746 ASSERT(frame() && frame()->view()); | 1706 { |
| 1747 FrameView* view = frame()->view(); | 1707 m_frame = 0; |
| 1748 | 1708 } |
| 1749 if ((area & INVALIDATE_ALL) == INVALIDATE_ALL) { | 1709 |
| 1750 view->invalidateRect(view->frameRect()); | 1710 void WebFrameImpl::invalidateArea(AreaToInvalidate area) |
| 1751 } else { | 1711 { |
| 1752 if ((area & INVALIDATE_CONTENT_AREA) == INVALIDATE_CONTENT_AREA) { | 1712 ASSERT(frame() && frame()->view()); |
| 1753 IntRect content_area( | 1713 FrameView* view = frame()->view(); |
| 1754 view->x(), view->y(), view->visibleWidth(), view->visibleHeight()); | 1714 |
| 1755 view->invalidateRect(content_area); | 1715 if ((area & InvalidateAll) == InvalidateAll) |
| 1756 } | 1716 view->invalidateRect(view->frameRect()); |
| 1757 | 1717 else { |
| 1758 if ((area & INVALIDATE_SCROLLBAR) == INVALIDATE_SCROLLBAR) { | 1718 if ((area & InvalidateContentArea) == InvalidateContentArea) { |
| 1759 // Invalidate the vertical scroll bar region for the view. | 1719 IntRect contentArea( |
| 1760 IntRect scroll_bar_vert( | 1720 view->x(), view->y(), view->visibleWidth(), view->visibleHeight()); |
| 1761 view->x() + view->visibleWidth(), view->y(), | 1721 view->invalidateRect(contentArea); |
| 1762 WebCore::ScrollbarTheme::nativeTheme()->scrollbarThickness(), | 1722 } |
| 1763 view->visibleHeight()); | 1723 |
| 1764 view->invalidateRect(scroll_bar_vert); | 1724 if ((area & InvalidateScrollbar) == InvalidateScrollbar) { |
| 1765 } | 1725 // Invalidate the vertical scroll bar region for the view. |
| 1766 } | 1726 IntRect scrollBarVert( |
| 1767 } | 1727 view->x() + view->visibleWidth(), view->y(), |
| 1768 | 1728 ScrollbarTheme::nativeTheme()->scrollbarThickness(), |
| 1769 void WebFrameImpl::AddMarker(WebCore::Range* range, bool active_match) { | 1729 view->visibleHeight()); |
| 1770 // Use a TextIterator to visit the potentially multiple nodes the range | 1730 view->invalidateRect(scrollBarVert); |
| 1771 // covers. | 1731 } |
| 1772 TextIterator markedText(range); | 1732 } |
| 1773 for (; !markedText.atEnd(); markedText.advance()) { | 1733 } |
| 1774 RefPtr<Range> textPiece = markedText.range(); | 1734 |
| 1775 int exception = 0; | 1735 void WebFrameImpl::addMarker(Range* range, bool activeMatch) |
| 1776 | 1736 { |
| 1777 WebCore::DocumentMarker marker = { | 1737 // Use a TextIterator to visit the potentially multiple nodes the range |
| 1778 WebCore::DocumentMarker::TextMatch, | 1738 // covers. |
| 1779 textPiece->startOffset(exception), | 1739 TextIterator markedText(range); |
| 1780 textPiece->endOffset(exception), | 1740 for (; !markedText.atEnd(); markedText.advance()) { |
| 1781 "", | 1741 RefPtr<Range> textPiece = markedText.range(); |
| 1782 active_match }; | 1742 int exception = 0; |
| 1783 | 1743 |
| 1784 if (marker.endOffset > marker.startOffset) { | 1744 DocumentMarker marker = { |
| 1785 // Find the node to add a marker to and add it. | 1745 DocumentMarker::TextMatch, |
| 1786 Node* node = textPiece->startContainer(exception); | 1746 textPiece->startOffset(exception), |
| 1787 frame()->document()->addMarker(node, marker); | 1747 textPiece->endOffset(exception), |
| 1788 | 1748 "", |
| 1789 // Rendered rects for markers in WebKit are not populated until each time | 1749 activeMatch |
| 1790 // the markers are painted. However, we need it to happen sooner, because | 1750 }; |
| 1791 // the whole purpose of tickmarks on the scrollbar is to show where | 1751 |
| 1792 // matches off-screen are (that haven't been painted yet). | 1752 if (marker.endOffset > marker.startOffset) { |
| 1793 Vector<WebCore::DocumentMarker> markers = | 1753 // Find the node to add a marker to and add it. |
| 1794 frame()->document()->markersForNode(node); | 1754 Node* node = textPiece->startContainer(exception); |
| 1795 frame()->document()->setRenderedRectForMarker( | 1755 frame()->document()->addMarker(node, marker); |
| 1796 textPiece->startContainer(exception), | 1756 |
| 1797 markers[markers.size() - 1], | 1757 // Rendered rects for markers in WebKit are not populated until each time |
| 1798 range->boundingBox()); | 1758 // the markers are painted. However, we need it to happen sooner, because |
| 1799 } | 1759 // the whole purpose of tickmarks on the scrollbar is to show where |
| 1800 } | 1760 // matches off-screen are (that haven't been painted yet). |
| 1801 } | 1761 Vector<DocumentMarker> markers = frame()->document()->markersForNode(node); |
| 1802 | 1762 frame()->document()->setRenderedRectForMarker( |
| 1803 void WebFrameImpl::SetMarkerActive(WebCore::Range* range, bool active) { | 1763 textPiece->startContainer(exception), |
| 1804 if (!range) | 1764 markers[markers.size() - 1], |
| 1805 return; | 1765 range->boundingBox()); |
| 1806 | 1766 } |
| 1807 frame()->document()->setMarkersActive(range, active); | 1767 } |
| 1808 } | 1768 } |
| 1809 | 1769 |
| 1810 int WebFrameImpl::OrdinalOfFirstMatchForFrame(WebFrameImpl* frame) const { | 1770 void WebFrameImpl::setMarkerActive(Range* range, bool active) |
| 1811 int ordinal = 0; | 1771 { |
| 1812 WebFrameImpl* main_frame_impl = GetWebViewImpl()->main_frame(); | 1772 if (!range) |
| 1813 // Iterate from the main frame up to (but not including) |frame| and | 1773 return; |
| 1814 // add up the number of matches found so far. | 1774 |
| 1815 for (WebFrameImpl* it = main_frame_impl; | 1775 frame()->document()->setMarkersActive(range, active); |
| 1816 it != frame; | 1776 } |
| 1817 it = static_cast<WebFrameImpl*>(it->traverseNext(true))) { | 1777 |
| 1818 if (it->last_match_count_ > 0) | 1778 int WebFrameImpl::ordinalOfFirstMatchForFrame(WebFrameImpl* frame) const |
| 1819 ordinal += it->last_match_count_; | 1779 { |
| 1820 } | 1780 int ordinal = 0; |
| 1821 | 1781 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl(); |
| 1822 return ordinal; | 1782 // Iterate from the main frame up to (but not including) |frame| and |
| 1823 } | 1783 // add up the number of matches found so far. |
| 1824 | 1784 for (WebFrameImpl* it = mainFrameImpl; |
| 1825 bool WebFrameImpl::ShouldScopeMatches(const string16& search_text) { | 1785 it != frame; |
| 1826 // Don't scope if we can't find a frame or if the frame is not visible. | 1786 it = static_cast<WebFrameImpl*>(it->traverseNext(true))) { |
| 1827 // The user may have closed the tab/application, so abort. | 1787 if (it->m_lastMatchCount > 0) |
| 1828 if (!frame() || !hasVisibleContent()) | 1788 ordinal += it->m_lastMatchCount; |
| 1829 return false; | 1789 } |
| 1830 | 1790 return ordinal; |
| 1831 ASSERT(frame()->document() && frame()->view()); | 1791 } |
| 1832 | 1792 |
| 1833 // If the frame completed the scoping operation and found 0 matches the last | 1793 bool WebFrameImpl::shouldScopeMatches(const String& searchText) |
| 1834 // time it was searched, then we don't have to search it again if the user is | 1794 { |
| 1835 // just adding to the search string or sending the same search string again. | 1795 // Don't scope if we can't find a frame or if the frame is not visible. |
| 1836 if (scoping_complete_ && | 1796 // The user may have closed the tab/application, so abort. |
| 1837 !last_search_string_.empty() && last_match_count_ == 0) { | 1797 if (!frame() || !hasVisibleContent()) |
| 1838 // Check to see if the search string prefixes match. | 1798 return false; |
| 1839 string16 previous_search_prefix = | 1799 |
| 1840 search_text.substr(0, last_search_string_.length()); | 1800 ASSERT(frame()->document() && frame()->view()); |
| 1841 | 1801 |
| 1842 if (previous_search_prefix == last_search_string_) { | 1802 // If the frame completed the scoping operation and found 0 matches the last |
| 1843 return false; // Don't search this frame, it will be fruitless. | 1803 // time it was searched, then we don't have to search it again if the user is |
| 1844 } | 1804 // just adding to the search string or sending the same search string again. |
| 1845 } | 1805 if (m_scopingComplete && !m_lastSearchString.isEmpty() && m_lastMatchCount == 0) { |
| 1846 | 1806 // Check to see if the search string prefixes match. |
| 1847 return true; | 1807 String previousSearchPrefix = |
| 1848 } | 1808 searchText.substring(0, m_lastSearchString.length()); |
| 1849 | 1809 |
| 1850 void WebFrameImpl::ScopeStringMatchesSoon( | 1810 if (previousSearchPrefix == m_lastSearchString) |
| 1851 int identifier, const WebString& search_text, | 1811 return false; // Don't search this frame, it will be fruitless. |
| 1852 const WebFindOptions& options, bool reset) { | 1812 } |
| 1853 deferred_scoping_work_.append(new DeferredScopeStringMatches( | 1813 |
| 1854 this, identifier, search_text, options, reset)); | 1814 return true; |
| 1855 } | 1815 } |
| 1856 | 1816 |
| 1857 void WebFrameImpl::CallScopeStringMatches( | 1817 void WebFrameImpl::scopeStringMatchesSoon(int identifier, const WebString& searchText, |
| 1858 DeferredScopeStringMatches* caller, int identifier, | 1818 const WebFindOptions& options, bool reset) |
| 1859 const WebString& search_text, const WebFindOptions& options, bool reset) { | 1819 { |
| 1860 deferred_scoping_work_.remove(deferred_scoping_work_.find(caller)); | 1820 m_deferredScopingWork.append(new DeferredScopeStringMatches( |
| 1861 | 1821 this, identifier, searchText, options, reset)); |
| 1862 scopeStringMatches(identifier, search_text, options, reset); | 1822 } |
| 1863 | 1823 |
| 1864 // This needs to happen last since search_text is passed by reference. | 1824 void WebFrameImpl::callScopeStringMatches(DeferredScopeStringMatches* caller, |
| 1865 delete caller; | 1825 int identifier, const WebString& searchText, |
| 1866 } | 1826 const WebFindOptions& options, bool reset) |
| 1867 | 1827 { |
| 1868 void WebFrameImpl::InvalidateIfNecessary() { | 1828 m_deferredScopingWork.remove(m_deferredScopingWork.find(caller)); |
| 1869 if (last_match_count_ > next_invalidate_after_) { | 1829 |
| 1870 // TODO(finnur): (http://b/1088165) Optimize the drawing of the | 1830 scopeStringMatches(identifier, searchText, options, reset); |
| 1871 // tickmarks and remove this. This calculation sets a milestone for when | 1831 |
| 1872 // next to invalidate the scrollbar and the content area. We do this so that | 1832 // This needs to happen last since searchText is passed by reference. |
| 1873 // we don't spend too much time drawing the scrollbar over and over again. | 1833 delete caller; |
| 1874 // Basically, up until the first 500 matches there is no throttle. After the | 1834 } |
| 1875 // first 500 matches, we set set the milestone further and further out (750, | 1835 |
| 1876 // 1125, 1688, 2K, 3K). | 1836 void WebFrameImpl::invalidateIfNecessary() |
| 1877 static const int start_slowing_down_after = 500; | 1837 { |
| 1878 static const int slowdown = 750; | 1838 if (m_lastMatchCount > m_nextInvalidateAfter) { |
| 1879 int i = (last_match_count_ / start_slowing_down_after); | 1839 // FIXME: (http://b/1088165) Optimize the drawing of the tickmarks and |
| 1880 next_invalidate_after_ += i * slowdown; | 1840 // remove this. This calculation sets a milestone for when next to |
| 1881 | 1841 // invalidate the scrollbar and the content area. We do this so that we |
| 1882 InvalidateArea(INVALIDATE_SCROLLBAR); | 1842 // don't spend too much time drawing the scrollbar over and over again. |
| 1883 } | 1843 // Basically, up until the first 500 matches there is no throttle. |
| 1884 } | 1844 // After the first 500 matches, we set set the milestone further and |
| 1885 | 1845 // further out (750, 1125, 1688, 2K, 3K). |
| 1886 void WebFrameImpl::ClearPasswordListeners() { | 1846 static const int startSlowingDownAfter = 500; |
| 1887 for (PasswordListenerMap::iterator iter = password_listeners_.begin(); | 1847 static const int slowdown = 750; |
| 1888 iter != password_listeners_.end(); ++iter) { | 1848 int i = (m_lastMatchCount / startSlowingDownAfter); |
| 1889 delete iter->second; | 1849 m_nextInvalidateAfter += i * slowdown; |
| 1890 } | 1850 |
| 1891 password_listeners_.clear(); | 1851 invalidateArea(InvalidateScrollbar); |
| 1892 } | 1852 } |
| 1893 | 1853 } |
| 1894 void WebFrameImpl::LoadJavaScriptURL(const KURL& url) { | 1854 |
| 1895 // This is copied from FrameLoader::executeIfJavaScriptURL. Unfortunately, | 1855 void WebFrameImpl::clearPasswordListeners() |
| 1896 // we cannot just use that method since it is private, and it also doesn't | 1856 { |
| 1897 // quite behave as we require it to for bookmarklets. The key difference is | 1857 deleteAllValues(m_passwordListeners); |
| 1898 // that we need to suppress loading the string result from evaluating the JS | 1858 m_passwordListeners.clear(); |
| 1899 // URL if executing the JS URL resulted in a location change. We also allow | 1859 } |
| 1900 // a JS URL to be loaded even if scripts on the page are otherwise disabled. | 1860 |
| 1901 | 1861 void WebFrameImpl::loadJavaScriptURL(const KURL& url) |
| 1902 if (!frame_->document() || !frame_->page()) | 1862 { |
| 1903 return; | 1863 // This is copied from FrameLoader::executeIfJavaScriptURL. Unfortunately, |
| 1904 | 1864 // we cannot just use that method since it is private, and it also doesn't |
| 1905 String script = | 1865 // quite behave as we require it to for bookmarklets. The key difference is |
| 1906 decodeURLEscapeSequences(url.string().substring(strlen("javascript:"))); | 1866 // that we need to suppress loading the string result from evaluating the JS |
| 1907 ScriptValue result = frame_->script()->executeScript(script, true); | 1867 // URL if executing the JS URL resulted in a location change. We also allow |
| 1908 | 1868 // a JS URL to be loaded even if scripts on the page are otherwise disabled. |
| 1909 String script_result; | 1869 |
| 1910 if (!result.getString(script_result)) | 1870 if (!m_frame->document() || !m_frame->page()) |
| 1911 return; | 1871 return; |
| 1912 | 1872 |
| 1913 SecurityOrigin* security_origin = frame_->document()->securityOrigin(); | 1873 String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:"))); |
| 1914 | 1874 ScriptValue result = m_frame->script()->executeScript(script, true); |
| 1915 if (!frame_->redirectScheduler()->locationChangePending()) { | 1875 |
| 1916 frame_->loader()->stopAllLoaders(); | 1876 String scriptResult; |
| 1917 frame_->loader()->begin(frame_->loader()->url(), true, security_origin); | 1877 if (!result.getString(scriptResult)) |
| 1918 frame_->loader()->write(script_result); | 1878 return; |
| 1919 frame_->loader()->end(); | 1879 |
| 1920 } | 1880 SecurityOrigin* securityOrigin = m_frame->document()->securityOrigin(); |
| 1921 } | 1881 |
| 1882 if (!m_frame->redirectScheduler()->locationChangePending()) { |
| 1883 m_frame->loader()->stopAllLoaders(); |
| 1884 m_frame->loader()->begin(m_frame->loader()->url(), true, securityOrigin); |
| 1885 m_frame->loader()->write(scriptResult); |
| 1886 m_frame->loader()->end(); |
| 1887 } |
| 1888 } |
| 1889 |
| 1890 } // namespace WebKit |
| OLD | NEW |