summaryrefslogtreecommitdiffstats
path: root/webkit/glue/webframe_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/glue/webframe_impl.cc')
-rw-r--r--webkit/glue/webframe_impl.cc1598
1 files changed, 799 insertions, 799 deletions
diff --git a/webkit/glue/webframe_impl.cc b/webkit/glue/webframe_impl.cc
index 4f784f2..2c4eb12 100644
--- a/webkit/glue/webframe_impl.cc
+++ b/webkit/glue/webframe_impl.cc
@@ -359,9 +359,11 @@ class ChromePrintContext : public WebCore::PrintContext {
DISALLOW_COPY_AND_ASSIGN(ChromePrintContext);
};
-// WebFrameImpl ----------------------------------------------------------------
+static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader) {
+ return loader ? WebDataSourceImpl::FromLoader(loader) : NULL;
+}
-int WebFrameImpl::live_object_count_ = 0;
+// WebFrame -------------------------------------------------------------------
// static
WebFrame* WebFrame::frameForEnteredContext() {
@@ -383,123 +385,8 @@ WebFrame* WebFrame::frameForCurrentContext() {
return NULL;
}
-WebFrameImpl::WebFrameImpl()
- : ALLOW_THIS_IN_INITIALIZER_LIST(frame_loader_client_(this)),
- ALLOW_THIS_IN_INITIALIZER_LIST(scope_matches_factory_(this)),
- plugin_delegate_(NULL),
- active_match_frame_(NULL),
- active_match_index_(-1),
- locating_active_rect_(false),
- resume_scoping_from_range_(NULL),
- last_match_count_(-1),
- total_matchcount_(-1),
- frames_scoping_count_(-1),
- scoping_complete_(false),
- next_invalidate_after_(0) {
- StatsCounter(kWebFrameActiveCount).Increment();
- live_object_count_++;
-}
-
-WebFrameImpl::~WebFrameImpl() {
- StatsCounter(kWebFrameActiveCount).Decrement();
- live_object_count_--;
-
- cancelPendingScopingEffort();
- ClearPasswordListeners();
-}
-
-// WebFrame -------------------------------------------------------------------
-
-void WebFrameImpl::InitMainFrame(WebViewImpl* webview_impl) {
- RefPtr<Frame> frame =
- Frame::create(webview_impl->page(), 0, &frame_loader_client_);
- frame_ = frame.get();
-
- // Add reference on behalf of FrameLoader. See comments in
- // WebFrameLoaderClient::frameLoaderDestroyed for more info.
- AddRef();
-
- // We must call init() after frame_ is assigned because it is referenced
- // during init().
- frame_->init();
-}
-
-void WebFrameImpl::reload() {
- frame_->loader()->saveDocumentAndScrollState();
-
- stopLoading(); // Make sure existing activity stops.
- frame_->loader()->reload();
-}
-
-void WebFrameImpl::loadRequest(const WebURLRequest& request) {
- const ResourceRequest* resource_request =
- webkit_glue::WebURLRequestToResourceRequest(&request);
- DCHECK(resource_request);
-
- if (resource_request->url().protocolIs("javascript")) {
- LoadJavaScriptURL(resource_request->url());
- return;
- }
-
- stopLoading(); // Make sure existing activity stops.
- frame_->loader()->load(*resource_request, false);
-}
-
-void WebFrameImpl::loadHistoryItem(const WebHistoryItem& item) {
- RefPtr<HistoryItem> history_item =
- webkit_glue::WebHistoryItemToHistoryItem(item);
- DCHECK(history_item.get());
-
- stopLoading(); // Make sure existing activity stops.
-
- // If there is no current_item, which happens when we are navigating in
- // session history after a crash, we need to manufacture one otherwise WebKit
- // hoarks. This is probably the wrong thing to do, but it seems to work.
- RefPtr<HistoryItem> current_item = frame_->loader()->currentHistoryItem();
- if (!current_item) {
- current_item = HistoryItem::create();
- current_item->setLastVisitWasFailure(true);
- frame_->loader()->setCurrentHistoryItem(current_item);
- GetWebViewImpl()->SetCurrentHistoryItem(current_item.get());
- }
-
- frame_->loader()->goToItem(history_item.get(),
- WebCore::FrameLoadTypeIndexedBackForward);
-}
-
-void WebFrameImpl::loadData(const WebData& data,
- const WebString& mime_type,
- const WebString& text_encoding,
- const WebURL& base_url,
- const WebURL& unreachable_url,
- bool replace) {
- SubstituteData subst_data(
- webkit_glue::WebDataToSharedBuffer(data),
- webkit_glue::WebStringToString(mime_type),
- webkit_glue::WebStringToString(text_encoding),
- webkit_glue::WebURLToKURL(unreachable_url));
- DCHECK(subst_data.isValid());
-
- stopLoading(); // Make sure existing activity stops.
- frame_->loader()->load(ResourceRequest(webkit_glue::WebURLToKURL(base_url)),
- subst_data, false);
- if (replace) {
- // Do this to force WebKit to treat the load as replacing the currently
- // loaded page.
- frame_->loader()->setReplacing();
- }
-}
-
-void WebFrameImpl::loadHTMLString(const WebData& data,
- const WebURL& base_url,
- const WebURL& unreachable_url,
- bool replace) {
- loadData(data,
- WebString::fromUTF8("text/html"),
- WebString::fromUTF8("UTF-8"),
- base_url,
- unreachable_url,
- replace);
+WebString WebFrameImpl::name() const {
+ return webkit_glue::StringToWebString(frame_->tree()->name());
}
WebURL WebFrameImpl::url() const {
@@ -544,6 +431,18 @@ WebURL WebFrameImpl::openSearchDescriptionURL() const {
return WebURL();
}
+WebSize WebFrameImpl::scrollOffset() const {
+ WebCore::FrameView* view = frameview();
+ if (view)
+ return webkit_glue::IntSizeToWebSize(view->scrollOffset());
+
+ return WebSize();
+}
+
+WebSize WebFrameImpl::contentsSize() const {
+ return webkit_glue::IntSizeToWebSize(frame()->view()->contentsSize());
+}
+
int WebFrameImpl::contentsPreferredWidth() const {
if ((frame_->document() != NULL) &&
(frame_->document()->renderView() != NULL)) {
@@ -553,63 +452,13 @@ int WebFrameImpl::contentsPreferredWidth() const {
}
}
-WebHistoryItem WebFrameImpl::previousHistoryItem() const {
- // We use the previous item here because documentState (filled-out forms)
- // only get saved to history when it becomes the previous item. The caller
- // is expected to query the history item after a navigation occurs, after
- // the desired history item has become the previous entry.
- return webkit_glue::HistoryItemToWebHistoryItem(
- GetWebViewImpl()->GetPreviousHistoryItem());
-}
-
-WebHistoryItem WebFrameImpl::currentHistoryItem() const {
- frame_->loader()->saveDocumentAndScrollState();
-
- return webkit_glue::HistoryItemToWebHistoryItem(
- frame_->page()->backForwardList()->currentItem());
-}
-
-static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader) {
- return loader ? WebDataSourceImpl::FromLoader(loader) : NULL;
-}
-
-WebDataSource* WebFrameImpl::dataSource() const {
- return DataSourceForDocLoader(frame_->loader()->documentLoader());
-}
-
-WebDataSourceImpl* WebFrameImpl::GetDataSourceImpl() const {
- return static_cast<WebDataSourceImpl*>(dataSource());
-}
-
-WebDataSource* WebFrameImpl::provisionalDataSource() const {
- FrameLoader* frame_loader = frame_->loader();
-
- // We regard the policy document loader as still provisional.
- DocumentLoader* doc_loader = frame_loader->provisionalDocumentLoader();
- if (!doc_loader)
- doc_loader = frame_loader->policyDocumentLoader();
-
- return DataSourceForDocLoader(doc_loader);
-}
-
-WebDataSourceImpl* WebFrameImpl::GetProvisionalDataSourceImpl() const {
- return static_cast<WebDataSourceImpl*>(provisionalDataSource());
-}
-
-void WebFrameImpl::stopLoading() {
- if (!frame_)
- return;
-
- // TODO(darin): Figure out what we should really do here. It seems like a
- // bug that FrameLoader::stopLoading doesn't call stopAllLoaders.
- frame_->loader()->stopAllLoaders();
- frame_->loader()->stopLoading(false);
+bool WebFrameImpl::hasVisibleContent() const {
+ return frame()->view()->visibleWidth() > 0 &&
+ frame()->view()->visibleHeight() > 0;
}
-bool WebFrameImpl::isLoading() const {
- if (!frame_)
- return false;
- return frame_->loader()->isLoading();
+WebView* WebFrameImpl::view() const {
+ return GetWebViewImpl();
}
WebFrame* WebFrameImpl::opener() const {
@@ -637,20 +486,60 @@ WebFrame* WebFrameImpl::top() const {
return NULL;
}
-void WebFrameImpl::enableViewSourceMode(bool enable) {
- if (frame_)
- frame_->setInViewSourceMode(enable);
+WebFrame* WebFrameImpl::firstChild() const {
+ return FromFrame(frame()->tree()->firstChild());
}
-bool WebFrameImpl::isViewSourceModeEnabled() const {
- if (frame_)
- return frame_->inViewSourceMode();
+WebFrame* WebFrameImpl::lastChild() const {
+ return FromFrame(frame()->tree()->lastChild());
+}
- return false;
+WebFrame* WebFrameImpl::nextSibling() const {
+ return FromFrame(frame()->tree()->nextSibling());
}
-WebView* WebFrameImpl::view() const {
- return GetWebViewImpl();
+WebFrame* WebFrameImpl::previousSibling() const {
+ return FromFrame(frame()->tree()->previousSibling());
+}
+
+WebFrame* WebFrameImpl::traverseNext(bool wrap) const {
+ return FromFrame(frame()->tree()->traverseNextWithWrap(wrap));
+}
+
+WebFrame* WebFrameImpl::traversePrevious(bool wrap) const {
+ return FromFrame(frame()->tree()->traversePreviousWithWrap(wrap));
+}
+
+WebFrame* WebFrameImpl::findChildByName(const WebKit::WebString& name) const {
+ return FromFrame(frame()->tree()->child(
+ webkit_glue::WebStringToString(name)));
+}
+
+WebFrame* WebFrameImpl::findChildByExpression(
+ const WebKit::WebString& xpath) const {
+ if (xpath.isEmpty())
+ return NULL;
+
+ Document* document = frame_->document();
+
+ ExceptionCode ec = 0;
+ PassRefPtr<XPathResult> xpath_result =
+ document->evaluate(webkit_glue::WebStringToString(xpath),
+ document,
+ NULL, /* namespace */
+ XPathResult::ORDERED_NODE_ITERATOR_TYPE,
+ NULL, /* XPathResult object */
+ ec);
+ if (!xpath_result.get())
+ return NULL;
+
+ Node* node = xpath_result->iterateNext(ec);
+
+ if (!node || !node->isFrameOwnerElement())
+ return NULL;
+ HTMLFrameOwnerElement* frame_element =
+ static_cast<HTMLFrameOwnerElement*>(node);
+ return FromFrame(frame_element->contentFrame());
}
void WebFrameImpl::forms(WebVector<WebForm>& results) const {
@@ -681,6 +570,20 @@ WebString WebFrameImpl::securityOrigin() const {
return WebString::fromUTF8("null");
}
+void WebFrameImpl::grantUniversalAccess() {
+ DCHECK(frame_ && frame_->document());
+ if (frame_ && frame_->document()) {
+ frame_->document()->securityOrigin()->grantUniversalAccess();
+ }
+}
+
+NPObject* WebFrameImpl::windowObject() const {
+ if (!frame_)
+ return NULL;
+
+ return frame_->script()->windowScriptNPObject();
+}
+
void WebFrameImpl::bindToWindowObject(const WebString& name,
NPObject* object) {
DCHECK(frame_);
@@ -707,8 +610,72 @@ void WebFrameImpl::bindToWindowObject(const WebString& name,
#endif
}
+void WebFrameImpl::executeScript(const WebScriptSource& source) {
+ frame_->loader()->executeScript(
+ WebCore::ScriptSourceCode(
+ webkit_glue::WebStringToString(source.code),
+ webkit_glue::WebURLToKURL(source.url),
+ source.startLine));
+}
+
+void WebFrameImpl::executeScriptInNewContext(
+ const WebScriptSource* sources_in, unsigned num_sources,
+ int extension_group) {
+ Vector<WebCore::ScriptSourceCode> sources;
+
+ for (unsigned i = 0; i < num_sources; ++i) {
+ sources.append(WebCore::ScriptSourceCode(
+ webkit_glue::WebStringToString(sources_in[i].code),
+ webkit_glue::WebURLToKURL(sources_in[i].url),
+ sources_in[i].startLine));
+ }
+
+ frame_->script()->evaluateInNewContext(sources, extension_group);
+}
+
+void WebFrameImpl::executeScriptInNewWorld(
+ const WebScriptSource* sources_in, unsigned num_sources,
+ int extension_group) {
+ Vector<WebCore::ScriptSourceCode> sources;
+
+ for (unsigned i = 0; i < num_sources; ++i) {
+ sources.append(WebCore::ScriptSourceCode(
+ webkit_glue::WebStringToString(sources_in[i].code),
+ webkit_glue::WebURLToKURL(sources_in[i].url),
+ sources_in[i].startLine));
+ }
+
+ frame_->script()->evaluateInNewWorld(sources, extension_group);
+}
+
+void WebFrameImpl::addMessageToConsole(const WebConsoleMessage& message) {
+ ASSERT(frame());
+
+ WebCore::MessageLevel webcore_message_level;
+ switch (message.level) {
+ case WebConsoleMessage::LevelTip:
+ webcore_message_level = WebCore::TipMessageLevel;
+ break;
+ case WebConsoleMessage::LevelLog:
+ webcore_message_level = WebCore::LogMessageLevel;
+ break;
+ case WebConsoleMessage::LevelWarning:
+ webcore_message_level = WebCore::WarningMessageLevel;
+ break;
+ case WebConsoleMessage::LevelError:
+ webcore_message_level = WebCore::ErrorMessageLevel;
+ break;
+ default:
+ NOTREACHED();
+ return;
+ }
+
+ frame()->domWindow()->console()->addMessage(
+ WebCore::OtherMessageSource, WebCore::LogMessageType,
+ webcore_message_level, webkit_glue::WebStringToString(message.text),
+ 1, String());
+}
-// Call JavaScript garbage collection.
void WebFrameImpl::collectGarbage() {
if (!frame_)
return;
@@ -720,96 +687,388 @@ void WebFrameImpl::collectGarbage() {
#endif
}
-void WebFrameImpl::grantUniversalAccess() {
- DCHECK(frame_ && frame_->document());
- if (frame_ && frame_->document()) {
- frame_->document()->securityOrigin()->grantUniversalAccess();
+#if USE(V8)
+ // Returns the V8 context for this frame, or an empty handle if there is
+ // none.
+v8::Local<v8::Context> WebFrameImpl::mainWorldScriptContext() const {
+ if (!frame_)
+ return v8::Local<v8::Context>();
+
+ return WebCore::V8Proxy::mainWorldContext(frame_);
+}
+#endif
+
+bool WebFrameImpl::insertStyleText(const WebString& css) {
+ Document* document = frame()->document();
+ if (!document)
+ return false;
+ WebCore::Element* document_element = document->documentElement();
+ if (!document_element)
+ return false;
+
+ RefPtr<WebCore::Element> stylesheet = document->createElement(
+ WebCore::HTMLNames::styleTag, false);
+ ExceptionCode err = 0;
+ stylesheet->setTextContent(webkit_glue::WebStringToString(css), err);
+ DCHECK(!err) << "Failed to set style element content";
+ WebCore::Node* first = document_element->firstChild();
+ bool success = document_element->insertBefore(stylesheet, first, err);
+ DCHECK(success) << "Failed to insert stylesheet";
+ return success;
+}
+
+void WebFrameImpl::reload() {
+ frame_->loader()->saveDocumentAndScrollState();
+
+ stopLoading(); // Make sure existing activity stops.
+ frame_->loader()->reload();
+}
+
+void WebFrameImpl::loadRequest(const WebURLRequest& request) {
+ const ResourceRequest* resource_request =
+ webkit_glue::WebURLRequestToResourceRequest(&request);
+ DCHECK(resource_request);
+
+ if (resource_request->url().protocolIs("javascript")) {
+ LoadJavaScriptURL(resource_request->url());
+ return;
}
+
+ stopLoading(); // Make sure existing activity stops.
+ frame_->loader()->load(*resource_request, false);
}
-WebString WebFrameImpl::contentAsText(size_t max_chars) const {
- if (!frame_)
- return WebString();
+void WebFrameImpl::loadHistoryItem(const WebHistoryItem& item) {
+ RefPtr<HistoryItem> history_item =
+ webkit_glue::WebHistoryItemToHistoryItem(item);
+ DCHECK(history_item.get());
- std::wstring text;
- FrameContentAsPlainText(max_chars, frame_, &text);
- // TODO(darin): Too many string copies!!!
- return WideToUTF16Hack(text);
+ stopLoading(); // Make sure existing activity stops.
+
+ // If there is no current_item, which happens when we are navigating in
+ // session history after a crash, we need to manufacture one otherwise WebKit
+ // hoarks. This is probably the wrong thing to do, but it seems to work.
+ RefPtr<HistoryItem> current_item = frame_->loader()->currentHistoryItem();
+ if (!current_item) {
+ current_item = HistoryItem::create();
+ current_item->setLastVisitWasFailure(true);
+ frame_->loader()->setCurrentHistoryItem(current_item);
+ GetWebViewImpl()->SetCurrentHistoryItem(current_item.get());
+ }
+
+ frame_->loader()->goToItem(history_item.get(),
+ WebCore::FrameLoadTypeIndexedBackForward);
}
-NPObject* WebFrameImpl::windowObject() const {
- if (!frame_)
- return NULL;
+void WebFrameImpl::loadData(const WebData& data,
+ const WebString& mime_type,
+ const WebString& text_encoding,
+ const WebURL& base_url,
+ const WebURL& unreachable_url,
+ bool replace) {
+ SubstituteData subst_data(
+ webkit_glue::WebDataToSharedBuffer(data),
+ webkit_glue::WebStringToString(mime_type),
+ webkit_glue::WebStringToString(text_encoding),
+ webkit_glue::WebURLToKURL(unreachable_url));
+ DCHECK(subst_data.isValid());
- return frame_->script()->windowScriptNPObject();
+ stopLoading(); // Make sure existing activity stops.
+ frame_->loader()->load(ResourceRequest(webkit_glue::WebURLToKURL(base_url)),
+ subst_data, false);
+ if (replace) {
+ // Do this to force WebKit to treat the load as replacing the currently
+ // loaded page.
+ frame_->loader()->setReplacing();
+ }
}
-#if USE(V8)
- // Returns the V8 context for this frame, or an empty handle if there is
- // none.
-v8::Local<v8::Context> WebFrameImpl::mainWorldScriptContext() const {
+void WebFrameImpl::loadHTMLString(const WebData& data,
+ const WebURL& base_url,
+ const WebURL& unreachable_url,
+ bool replace) {
+ loadData(data,
+ WebString::fromUTF8("text/html"),
+ WebString::fromUTF8("UTF-8"),
+ base_url,
+ unreachable_url,
+ replace);
+}
+
+bool WebFrameImpl::isLoading() const {
if (!frame_)
- return v8::Local<v8::Context>();
+ return false;
+ return frame_->loader()->isLoading();
+}
- return WebCore::V8Proxy::mainWorldContext(frame_);
+void WebFrameImpl::stopLoading() {
+ if (!frame_)
+ return;
+
+ // TODO(darin): Figure out what we should really do here. It seems like a
+ // bug that FrameLoader::stopLoading doesn't call stopAllLoaders.
+ frame_->loader()->stopAllLoaders();
+ frame_->loader()->stopLoading(false);
}
-#endif
-void WebFrameImpl::InvalidateArea(AreaToInvalidate area) {
- ASSERT(frame() && frame()->view());
- FrameView* view = frame()->view();
+WebDataSource* WebFrameImpl::provisionalDataSource() const {
+ FrameLoader* frame_loader = frame_->loader();
- if ((area & INVALIDATE_ALL) == INVALIDATE_ALL) {
- view->invalidateRect(view->frameRect());
- } else {
- if ((area & INVALIDATE_CONTENT_AREA) == INVALIDATE_CONTENT_AREA) {
- IntRect content_area(
- view->x(), view->y(), view->visibleWidth(), view->visibleHeight());
- view->invalidateRect(content_area);
- }
+ // We regard the policy document loader as still provisional.
+ DocumentLoader* doc_loader = frame_loader->provisionalDocumentLoader();
+ if (!doc_loader)
+ doc_loader = frame_loader->policyDocumentLoader();
- if ((area & INVALIDATE_SCROLLBAR) == INVALIDATE_SCROLLBAR) {
- // Invalidate the vertical scroll bar region for the view.
- IntRect scroll_bar_vert(
- view->x() + view->visibleWidth(), view->y(),
- WebCore::ScrollbarTheme::nativeTheme()->scrollbarThickness(),
- view->visibleHeight());
- view->invalidateRect(scroll_bar_vert);
+ return DataSourceForDocLoader(doc_loader);
+}
+
+WebDataSource* WebFrameImpl::dataSource() const {
+ return DataSourceForDocLoader(frame_->loader()->documentLoader());
+}
+
+WebHistoryItem WebFrameImpl::previousHistoryItem() const {
+ // We use the previous item here because documentState (filled-out forms)
+ // only get saved to history when it becomes the previous item. The caller
+ // is expected to query the history item after a navigation occurs, after
+ // the desired history item has become the previous entry.
+ return webkit_glue::HistoryItemToWebHistoryItem(
+ GetWebViewImpl()->GetPreviousHistoryItem());
+}
+
+WebHistoryItem WebFrameImpl::currentHistoryItem() const {
+ frame_->loader()->saveDocumentAndScrollState();
+
+ return webkit_glue::HistoryItemToWebHistoryItem(
+ frame_->page()->backForwardList()->currentItem());
+}
+
+void WebFrameImpl::enableViewSourceMode(bool enable) {
+ if (frame_)
+ frame_->setInViewSourceMode(enable);
+}
+
+bool WebFrameImpl::isViewSourceModeEnabled() const {
+ if (frame_)
+ return frame_->inViewSourceMode();
+
+ return false;
+}
+
+void WebFrameImpl::dispatchWillSendRequest(WebURLRequest& request) {
+ ResourceResponse response;
+ frame_->loader()->client()->dispatchWillSendRequest(NULL, 0,
+ *webkit_glue::WebURLRequestToMutableResourceRequest(&request),
+ response);
+}
+
+void WebFrameImpl::commitDocumentData(const char* data, size_t data_len) {
+ DocumentLoader* document_loader = frame_->loader()->documentLoader();
+
+ // Set the text encoding. This calls begin() for us. It is safe to call
+ // this multiple times (Mac does: page/mac/WebCoreFrameBridge.mm).
+ bool user_chosen = true;
+ String encoding = document_loader->overrideEncoding();
+ if (encoding.isNull()) {
+ user_chosen = false;
+ encoding = document_loader->response().textEncodingName();
+ }
+ frame_->loader()->setEncoding(encoding, user_chosen);
+
+ // NOTE: mac only does this if there is a document
+ frame_->loader()->addData(data, data_len);
+}
+
+unsigned WebFrameImpl::unloadListenerCount() const {
+ return frame()->domWindow()->pendingUnloadEventListeners();
+}
+
+void WebFrameImpl::replaceSelection(const WebString& wtext) {
+ String text = webkit_glue::WebStringToString(wtext);
+ RefPtr<DocumentFragment> fragment = createFragmentFromText(
+ frame()->selection()->toNormalizedRange().get(), text);
+ WebCore::applyCommand(WebCore::ReplaceSelectionCommand::create(
+ frame()->document(), fragment.get(), false, true, true));
+}
+
+void WebFrameImpl::insertText(const WebString& text) {
+ frame()->editor()->insertText(webkit_glue::WebStringToString(text), NULL);
+}
+
+void WebFrameImpl::setMarkedText(
+ const WebString& text, unsigned location, unsigned length) {
+ WebCore::Editor* editor = frame()->editor();
+ WebCore::String str = webkit_glue::WebStringToString(text);
+
+ editor->confirmComposition(str);
+
+ WTF::Vector<WebCore::CompositionUnderline> decorations;
+ editor->setComposition(str, decorations, location, length);
+}
+
+void WebFrameImpl::unmarkText() {
+ frame()->editor()->confirmCompositionWithoutDisturbingSelection();
+}
+
+bool WebFrameImpl::hasMarkedText() const {
+ return frame()->editor()->hasComposition();
+}
+
+WebRange WebFrameImpl::markedRange() const {
+ return webkit_glue::RangeToWebRange(frame()->editor()->compositionRange());
+}
+
+bool WebFrameImpl::executeCommand(const WebString& name) {
+ ASSERT(frame());
+
+ if (name.length() <= 2)
+ return false;
+
+ // Since we don't have NSControl, we will convert the format of command
+ // string and call the function on Editor directly.
+ string16 command = name;
+
+ // Make sure the first letter is upper case.
+ command.replace(0, 1, 1, toupper(command.at(0)));
+
+ // Remove the trailing ':' if existing.
+ if (command.at(command.length() - 1) == ':')
+ command.erase(command.length() - 1, 1);
+
+ bool rv = true;
+
+ // Specially handling commands that Editor::execCommand does not directly
+ // support.
+ if (EqualsASCII(command, "DeleteToEndOfParagraph")) {
+ WebCore::Editor* editor = frame()->editor();
+ if (!editor->deleteWithDirection(WebCore::SelectionController::FORWARD,
+ WebCore::ParagraphBoundary,
+ true,
+ false)) {
+ editor->deleteWithDirection(WebCore::SelectionController::FORWARD,
+ WebCore::CharacterGranularity,
+ true,
+ false);
}
+ } else if (EqualsASCII(command, "Indent")) {
+ frame()->editor()->indent();
+ } else if (EqualsASCII(command, "Outdent")) {
+ frame()->editor()->outdent();
+ } else if (EqualsASCII(command, "DeleteBackward")) {
+ rv = frame()->editor()->command(AtomicString("BackwardDelete")).execute();
+ } else if (EqualsASCII(command, "DeleteForward")) {
+ rv = frame()->editor()->command(AtomicString("ForwardDelete")).execute();
+ } else {
+ rv = frame()->editor()->command(AtomicString(command.c_str())).execute();
}
+ return rv;
}
-void WebFrameImpl::increaseMatchCount(int count, int request_id) {
- // This function should only be called on the mainframe.
- DCHECK(!parent());
+bool WebFrameImpl::executeCommand(const WebString& name,
+ const WebString& value) {
+ ASSERT(frame());
+ return frame()->editor()->command(webkit_glue::WebStringToString(name)).
+ execute(webkit_glue::WebStringToString(value));
+}
- total_matchcount_ += count;
+bool WebFrameImpl::isCommandEnabled(const WebString& name) const {
+ ASSERT(frame());
+ return frame()->editor()->command(webkit_glue::WebStringToString(name)).
+ isEnabled();
+}
- // Update the UI with the latest findings.
- WebViewDelegate* webview_delegate = GetWebViewImpl()->GetDelegate();
- DCHECK(webview_delegate);
- if (webview_delegate)
- webview_delegate->ReportFindInPageMatchCount(total_matchcount_, request_id,
- frames_scoping_count_ == 0);
+void WebFrameImpl::enableContinuousSpellChecking(bool enable) {
+ if (enable == isContinuousSpellCheckingEnabled())
+ return;
+ frame()->editor()->toggleContinuousSpellChecking();
}
-void WebFrameImpl::reportFindInPageSelection(const WebRect& selection_rect,
- int active_match_ordinal,
- int request_id) {
- // Update the UI with the latest selection rect.
- WebViewDelegate* webview_delegate = GetWebViewImpl()->GetDelegate();
- DCHECK(webview_delegate);
- if (webview_delegate) {
- webview_delegate->ReportFindInPageSelection(
- request_id,
- OrdinalOfFirstMatchForFrame(this) + active_match_ordinal,
- selection_rect);
+bool WebFrameImpl::isContinuousSpellCheckingEnabled() const {
+ return frame()->editor()->isContinuousSpellCheckingEnabled();
+}
+
+void WebFrameImpl::selectAll() {
+ frame()->selection()->selectAll();
+
+ WebViewDelegate* d = GetWebViewImpl()->GetDelegate();
+ if (d)
+ d->UserMetricsRecordAction(L"SelectAll");
+}
+
+void WebFrameImpl::clearSelection() {
+ frame()->selection()->clear();
+}
+
+bool WebFrameImpl::hasSelection() const {
+ // frame()->selection()->isNone() never returns true.
+ return (frame()->selection()->start() != frame()->selection()->end());
+}
+
+WebRange WebFrameImpl::selectionRange() const {
+ return webkit_glue::RangeToWebRange(
+ frame()->selection()->toNormalizedRange());
+}
+
+WebString WebFrameImpl::selectionAsText() const {
+ RefPtr<Range> range = frame()->selection()->toNormalizedRange();
+ if (!range.get())
+ return WebString();
+
+ String text = range->text();
+#if defined(OS_WIN)
+ WebCore::replaceNewlinesWithWindowsStyleNewlines(text);
+#endif
+ WebCore::replaceNBSPWithSpace(text);
+ return webkit_glue::StringToWebString(text);
+}
+
+WebString WebFrameImpl::selectionAsMarkup() const {
+ RefPtr<Range> range = frame()->selection()->toNormalizedRange();
+ if (!range.get())
+ return WebString();
+
+ String markup = WebCore::createMarkup(range.get(), 0);
+ return webkit_glue::StringToWebString(markup);
+}
+
+int WebFrameImpl::printBegin(const WebSize& page_size) {
+ DCHECK_EQ(frame()->document()->isFrameSet(), false);
+
+ print_context_.reset(new ChromePrintContext(frame()));
+ WebCore::FloatRect rect(0, 0,
+ static_cast<float>(page_size.width),
+ static_cast<float>(page_size.height));
+ print_context_->begin(rect.width());
+ float page_height;
+ // We ignore the overlays calculation for now since they are generated in the
+ // browser. page_height is actually an output parameter.
+ print_context_->computePageRects(rect, 0, 0, 1.0, page_height);
+ return print_context_->pageCount();
+}
+
+float WebFrameImpl::printPage(int page, WebCanvas* canvas) {
+ // Ensure correct state.
+ if (!print_context_.get() || page < 0 || !frame() || !frame()->document()) {
+ NOTREACHED();
+ return 0;
}
+
+#if defined(OS_WIN) || defined(OS_LINUX)
+ PlatformContextSkia context(canvas);
+ GraphicsContext spool(&context);
+#elif defined(OS_MACOSX)
+ CGContextRef context = canvas->beginPlatformPaint();
+ GraphicsContext spool(context);
+ WebCore::LocalCurrentGraphicsContext localContext(&spool);
+#endif
+
+ return print_context_->spoolPage(spool, page);
}
-void WebFrameImpl::resetMatchCount() {
- total_matchcount_ = 0;
- frames_scoping_count_ = 0;
+void WebFrameImpl::printEnd() {
+ DCHECK(print_context_.get());
+ if (print_context_.get())
+ print_context_->end();
+ print_context_.reset(NULL);
}
bool WebFrameImpl::find(int request_id,
@@ -913,105 +1172,18 @@ bool WebFrameImpl::find(int request_id,
return found;
}
-int WebFrameImpl::OrdinalOfFirstMatchForFrame(WebFrameImpl* frame) const {
- int ordinal = 0;
- WebViewImpl* web_view = GetWebViewImpl();
- WebFrameImpl* const main_frame_impl = GetWebViewImpl()->main_frame();
- // Iterate from the main frame up to (but not including) |frame| and
- // add up the number of matches found so far.
- for (WebFrameImpl* it = main_frame_impl;
- it != frame;
- it = static_cast<WebFrameImpl*>(
- web_view->GetNextFrameAfter(it, true))) {
- if (it->last_match_count_ > 0)
- ordinal += it->last_match_count_;
- }
-
- return ordinal;
-}
-
-bool WebFrameImpl::ShouldScopeMatches(const string16& search_text) {
- // Don't scope if we can't find a frame or if the frame is not visible.
- // The user may have closed the tab/application, so abort.
- if (!frame() || !hasVisibleContent())
- return false;
-
- DCHECK(frame()->document() && frame()->view());
-
- // If the frame completed the scoping operation and found 0 matches the last
- // time it was searched, then we don't have to search it again if the user is
- // just adding to the search string or sending the same search string again.
- if (scoping_complete_ &&
- !last_search_string_.empty() && last_match_count_ == 0) {
- // Check to see if the search string prefixes match.
- string16 previous_search_prefix =
- search_text.substr(0, last_search_string_.length());
-
- if (previous_search_prefix == last_search_string_) {
- return false; // Don't search this frame, it will be fruitless.
- }
- }
-
- return true;
-}
-
-void WebFrameImpl::InvalidateIfNecessary() {
- if (last_match_count_ > next_invalidate_after_) {
- // TODO(finnur): (http://b/1088165) Optimize the drawing of the
- // tickmarks and remove this. This calculation sets a milestone for when
- // next to invalidate the scrollbar and the content area. We do this so that
- // we don't spend too much time drawing the scrollbar over and over again.
- // Basically, up until the first 500 matches there is no throttle. After the
- // first 500 matches, we set set the milestone further and further out (750,
- // 1125, 1688, 2K, 3K).
- static const int start_slowing_down_after = 500;
- static const int slowdown = 750;
- int i = (last_match_count_ / start_slowing_down_after);
- next_invalidate_after_ += i * slowdown;
-
- InvalidateArea(INVALIDATE_SCROLLBAR);
- }
-}
-
-void WebFrameImpl::AddMarker(WebCore::Range* range, bool active_match) {
- // Use a TextIterator to visit the potentially multiple nodes the range
- // covers.
- TextIterator markedText(range);
- for (; !markedText.atEnd(); markedText.advance()) {
- RefPtr<Range> textPiece = markedText.range();
- int exception = 0;
-
- WebCore::DocumentMarker marker = {
- WebCore::DocumentMarker::TextMatch,
- textPiece->startOffset(exception),
- textPiece->endOffset(exception),
- "",
- active_match };
-
- if (marker.endOffset > marker.startOffset) {
- // Find the node to add a marker to and add it.
- Node* node = textPiece->startContainer(exception);
- frame()->document()->addMarker(node, marker);
-
- // Rendered rects for markers in WebKit are not populated until each time
- // the markers are painted. However, we need it to happen sooner, because
- // the whole purpose of tickmarks on the scrollbar is to show where
- // matches off-screen are (that haven't been painted yet).
- Vector<WebCore::DocumentMarker> markers =
- frame()->document()->markersForNode(node);
- frame()->document()->setRenderedRectForMarker(
- textPiece->startContainer(exception),
- markers[markers.size() - 1],
- range->boundingBox());
- }
- }
-}
+void WebFrameImpl::stopFinding(bool clear_selection) {
+ if (!clear_selection)
+ SetFindEndstateFocusAndSelection();
+ cancelPendingScopingEffort();
-void WebFrameImpl::SetMarkerActive(WebCore::Range* range, bool active) {
- if (!range)
- return;
+ // Remove all markers for matches found and turn off the highlighting.
+ if (!parent())
+ frame()->document()->removeMarkers(WebCore::DocumentMarker::TextMatch);
+ frame()->setMarkedTextMatchesAreHighlighted(false);
- frame()->document()->setMarkersActive(range, active);
+ // Let the frame know that we don't want tickmarks or highlighting anymore.
+ InvalidateArea(INVALIDATE_ALL);
}
void WebFrameImpl::scopeStringMatches(int request_id,
@@ -1207,147 +1379,177 @@ void WebFrameImpl::cancelPendingScopingEffort() {
active_match_index_ = -1;
}
-void WebFrameImpl::SetFindEndstateFocusAndSelection() {
- WebFrameImpl* main_frame_impl = GetWebViewImpl()->main_frame();
+void WebFrameImpl::increaseMatchCount(int count, int request_id) {
+ // This function should only be called on the mainframe.
+ DCHECK(!parent());
- if (this == main_frame_impl->active_match_frame() &&
- active_match_.get()) {
- // If the user has set the selection since the match was found, we
- // don't focus anything.
- VisibleSelection selection(frame()->selection()->selection());
- if (!selection.isNone())
- return;
+ total_matchcount_ += count;
- // Try to find the first focusable node up the chain, which will, for
- // example, focus links if we have found text within the link.
- Node* node = active_match_->firstNode();
- while (node && !node->isFocusable() && node != frame()->document())
- node = node->parent();
+ // Update the UI with the latest findings.
+ WebViewDelegate* webview_delegate = GetWebViewImpl()->GetDelegate();
+ DCHECK(webview_delegate);
+ if (webview_delegate)
+ webview_delegate->ReportFindInPageMatchCount(total_matchcount_, request_id,
+ frames_scoping_count_ == 0);
+}
- if (node && node != frame()->document()) {
- // Found a focusable parent node. Set focus to it.
- frame()->document()->setFocusedNode(node);
- } else {
- // Iterate over all the nodes in the range until we find a focusable node.
- // This, for example, sets focus to the first link if you search for
- // text and text that is within one or more links.
- node = active_match_->firstNode();
- while (node && node != active_match_->pastLastNode()) {
- if (node->isFocusable()) {
- frame()->document()->setFocusedNode(node);
- break;
- }
- node = node->traverseNextNode();
- }
- }
+void WebFrameImpl::reportFindInPageSelection(const WebRect& selection_rect,
+ int active_match_ordinal,
+ int request_id) {
+ // Update the UI with the latest selection rect.
+ WebViewDelegate* webview_delegate = GetWebViewImpl()->GetDelegate();
+ DCHECK(webview_delegate);
+ if (webview_delegate) {
+ webview_delegate->ReportFindInPageSelection(
+ request_id,
+ OrdinalOfFirstMatchForFrame(this) + active_match_ordinal,
+ selection_rect);
}
}
-void WebFrameImpl::stopFinding(bool clear_selection) {
- if (!clear_selection)
- SetFindEndstateFocusAndSelection();
- cancelPendingScopingEffort();
-
- // Remove all markers for matches found and turn off the highlighting.
- if (!parent())
- frame()->document()->removeMarkers(WebCore::DocumentMarker::TextMatch);
- frame()->setMarkedTextMatchesAreHighlighted(false);
-
- // Let the frame know that we don't want tickmarks or highlighting anymore.
- InvalidateArea(INVALIDATE_ALL);
+void WebFrameImpl::resetMatchCount() {
+ total_matchcount_ = 0;
+ frames_scoping_count_ = 0;
}
-void WebFrameImpl::selectAll() {
- frame()->selection()->selectAll();
+WebString WebFrameImpl::contentAsText(size_t max_chars) const {
+ if (!frame_)
+ return WebString();
- WebViewDelegate* d = GetWebViewImpl()->GetDelegate();
- if (d)
- d->UserMetricsRecordAction(L"SelectAll");
+ std::wstring text;
+ FrameContentAsPlainText(max_chars, frame_, &text);
+ // TODO(darin): Too many string copies!!!
+ return WideToUTF16Hack(text);
}
-WebRange WebFrameImpl::selectionRange() const {
- return webkit_glue::RangeToWebRange(
- frame()->selection()->toNormalizedRange());
+WebString WebFrameImpl::contentAsMarkup() const {
+ return webkit_glue::StringToWebString(createFullMarkup(frame_->document()));
}
-WebString WebFrameImpl::selectionAsText() const {
- RefPtr<Range> range = frame()->selection()->toNormalizedRange();
- if (!range.get())
- return WebString();
+// WebFrameImpl public ---------------------------------------------------------
- String text = range->text();
-#if defined(OS_WIN)
- WebCore::replaceNewlinesWithWindowsStyleNewlines(text);
-#endif
- WebCore::replaceNBSPWithSpace(text);
- return webkit_glue::StringToWebString(text);
+int WebFrameImpl::live_object_count_ = 0;
+
+WebFrameImpl::WebFrameImpl()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(frame_loader_client_(this)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(scope_matches_factory_(this)),
+ plugin_delegate_(NULL),
+ active_match_frame_(NULL),
+ active_match_index_(-1),
+ locating_active_rect_(false),
+ resume_scoping_from_range_(NULL),
+ last_match_count_(-1),
+ total_matchcount_(-1),
+ frames_scoping_count_(-1),
+ scoping_complete_(false),
+ next_invalidate_after_(0) {
+ StatsCounter(kWebFrameActiveCount).Increment();
+ live_object_count_++;
}
-WebString WebFrameImpl::selectionAsMarkup() const {
- RefPtr<Range> range = frame()->selection()->toNormalizedRange();
- if (!range.get())
- return WebString();
+WebFrameImpl::~WebFrameImpl() {
+ StatsCounter(kWebFrameActiveCount).Decrement();
+ live_object_count_--;
- String markup = WebCore::createMarkup(range.get(), 0);
- return webkit_glue::StringToWebString(markup);
+ cancelPendingScopingEffort();
+ ClearPasswordListeners();
}
-void WebFrameImpl::replaceSelection(const WebString& wtext) {
- String text = webkit_glue::WebStringToString(wtext);
- RefPtr<DocumentFragment> fragment = createFragmentFromText(
- frame()->selection()->toNormalizedRange().get(), text);
- WebCore::applyCommand(WebCore::ReplaceSelectionCommand::create(
- frame()->document(), fragment.get(), false, true, true));
-}
+void WebFrameImpl::InitMainFrame(WebViewImpl* webview_impl) {
+ RefPtr<Frame> frame =
+ Frame::create(webview_impl->page(), 0, &frame_loader_client_);
+ frame_ = frame.get();
-void WebFrameImpl::insertText(const WebString& text) {
- frame()->editor()->insertText(webkit_glue::WebStringToString(text), NULL);
+ // Add reference on behalf of FrameLoader. See comments in
+ // WebFrameLoaderClient::frameLoaderDestroyed for more info.
+ AddRef();
+
+ // We must call init() after frame_ is assigned because it is referenced
+ // during init().
+ frame_->init();
}
-void WebFrameImpl::setMarkedText(
- const WebString& text, unsigned location, unsigned length) {
- WebCore::Editor* editor = frame()->editor();
- WebCore::String str = webkit_glue::WebStringToString(text);
+PassRefPtr<Frame> WebFrameImpl::CreateChildFrame(
+ const FrameLoadRequest& request, HTMLFrameOwnerElement* owner_element) {
+ // TODO(darin): share code with initWithName()
- editor->confirmComposition(str);
+ scoped_refptr<WebFrameImpl> webframe = new WebFrameImpl();
- WTF::Vector<WebCore::CompositionUnderline> decorations;
- editor->setComposition(str, decorations, location, length);
-}
+ // Add an extra ref on behalf of the Frame/FrameLoader, which references the
+ // WebFrame via the FrameLoaderClient interface. See the comment at the top
+ // of this file for more info.
+ webframe->AddRef();
-void WebFrameImpl::unmarkText() {
- frame()->editor()->confirmCompositionWithoutDisturbingSelection();
-}
+ RefPtr<Frame> child_frame = Frame::create(
+ frame_->page(), owner_element, &webframe->frame_loader_client_);
+ webframe->frame_ = child_frame.get();
-bool WebFrameImpl::hasMarkedText() const {
- return frame()->editor()->hasComposition();
-}
+ child_frame->tree()->setName(request.frameName());
-WebRange WebFrameImpl::markedRange() const {
- return webkit_glue::RangeToWebRange(frame()->editor()->compositionRange());
-}
+ frame_->tree()->appendChild(child_frame);
-void WebFrameImpl::enableContinuousSpellChecking(bool enable) {
- if (enable == isContinuousSpellCheckingEnabled())
- return;
- frame()->editor()->toggleContinuousSpellChecking();
-}
+ // Frame::init() can trigger onload event in the parent frame,
+ // which may detach this frame and trigger a null-pointer access
+ // in FrameTree::removeChild. Move init() after appendChild call
+ // so that webframe->frame_ is in the tree before triggering
+ // onload event handler.
+ // Because the event handler may set webframe->frame_ to null,
+ // it is necessary to check the value after calling init() and
+ // return without loading URL.
+ // (b:791612)
+ child_frame->init(); // create an empty document
+ if (!child_frame->tree()->parent())
+ return NULL;
-bool WebFrameImpl::isContinuousSpellCheckingEnabled() const {
- return frame()->editor()->isContinuousSpellCheckingEnabled();
-}
+ frame_->loader()->loadURLIntoChildFrame(
+ request.resourceRequest().url(),
+ request.resourceRequest().httpReferrer(),
+ child_frame.get());
-void WebFrameImpl::clearSelection() {
- frame()->selection()->clear();
+ // A synchronous navigation (about:blank) would have already processed
+ // onload, so it is possible for the frame to have already been destroyed by
+ // script in the page.
+ if (!child_frame->tree()->parent())
+ return NULL;
+
+ return child_frame.release();
}
-bool WebFrameImpl::hasSelection() const {
- // frame()->selection()->isNone() never returns true.
- return (frame()->selection()->start() != frame()->selection()->end());
+void WebFrameImpl::Layout() {
+ // layout this frame
+ FrameView* view = frame_->view();
+ if (view)
+ view->layout();
+
+ // recursively layout child frames
+ Frame* child = frame_->tree()->firstChild();
+ for (; child; child = child->tree()->nextSibling())
+ FromFrame(child)->Layout();
}
-WebString WebFrameImpl::contentAsMarkup() const {
- return webkit_glue::StringToWebString(createFullMarkup(frame_->document()));
+void WebFrameImpl::Paint(skia::PlatformCanvas* canvas, const WebRect& rect) {
+ static StatsRate rendering("WebFramePaintTime");
+ StatsScope<StatsRate> rendering_scope(rendering);
+
+ if (!rect.isEmpty()) {
+ IntRect dirty_rect(webkit_glue::WebRectToIntRect(rect));
+#if defined(OS_MACOSX)
+ CGContextRef context = canvas->getTopPlatformDevice().GetBitmapContext();
+ GraphicsContext gc(context);
+ WebCore::LocalCurrentGraphicsContext localContext(&gc);
+#else
+ PlatformContextSkia context(canvas);
+
+ // PlatformGraphicsContext is actually a pointer to PlatformContextSkia
+ GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context));
+#endif
+ if (frame_->document() && frameview()) {
+ frameview()->paint(&gc, dirty_rect);
+ frame_->page()->inspectorController()->drawNodeHighlight(gc);
+ } else {
+ gc.fillRect(dirty_rect, Color::white);
+ }
+ }
}
void WebFrameImpl::CreateFrameView() {
@@ -1412,49 +1614,50 @@ WebViewImpl* WebFrameImpl::GetWebViewImpl() const {
frame_->page()->chrome()->client())->webview();
}
-// WebFrame --------------------------------------------------------------------
-
-void WebFrameImpl::Layout() {
- // layout this frame
- FrameView* view = frame_->view();
- if (view)
- view->layout();
+WebDataSourceImpl* WebFrameImpl::GetDataSourceImpl() const {
+ return static_cast<WebDataSourceImpl*>(dataSource());
+}
- // recursively layout child frames
- Frame* child = frame_->tree()->firstChild();
- for (; child; child = child->tree()->nextSibling())
- FromFrame(child)->Layout();
+WebDataSourceImpl* WebFrameImpl::GetProvisionalDataSourceImpl() const {
+ return static_cast<WebDataSourceImpl*>(provisionalDataSource());
}
-void WebFrameImpl::Paint(skia::PlatformCanvas* canvas, const WebRect& rect) {
- static StatsRate rendering("WebFramePaintTime");
- StatsScope<StatsRate> rendering_scope(rendering);
+void WebFrameImpl::SetFindEndstateFocusAndSelection() {
+ WebFrameImpl* main_frame_impl = GetWebViewImpl()->main_frame();
- if (!rect.isEmpty()) {
- IntRect dirty_rect(webkit_glue::WebRectToIntRect(rect));
-#if defined(OS_MACOSX)
- CGContextRef context = canvas->getTopPlatformDevice().GetBitmapContext();
- GraphicsContext gc(context);
- WebCore::LocalCurrentGraphicsContext localContext(&gc);
-#else
- PlatformContextSkia context(canvas);
+ if (this == main_frame_impl->active_match_frame() &&
+ active_match_.get()) {
+ // If the user has set the selection since the match was found, we
+ // don't focus anything.
+ VisibleSelection selection(frame()->selection()->selection());
+ if (!selection.isNone())
+ return;
- // PlatformGraphicsContext is actually a pointer to PlatformContextSkia
- GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context));
-#endif
- if (frame_->document() && frameview()) {
- frameview()->paint(&gc, dirty_rect);
- frame_->page()->inspectorController()->drawNodeHighlight(gc);
+ // Try to find the first focusable node up the chain, which will, for
+ // example, focus links if we have found text within the link.
+ Node* node = active_match_->firstNode();
+ while (node && !node->isFocusable() && node != frame()->document())
+ node = node->parent();
+
+ if (node && node != frame()->document()) {
+ // Found a focusable parent node. Set focus to it.
+ frame()->document()->setFocusedNode(node);
} else {
- gc.fillRect(dirty_rect, Color::white);
+ // Iterate over all the nodes in the range until we find a focusable node.
+ // This, for example, sets focus to the first link if you search for
+ // text and text that is within one or more links.
+ node = active_match_->firstNode();
+ while (node && node != active_match_->pastLastNode()) {
+ if (node->isFocusable()) {
+ frame()->document()->setFocusedNode(node);
+ break;
+ }
+ node = node->traverseNextNode();
+ }
}
}
}
-void WebFrameImpl::Closing() {
- frame_ = NULL;
-}
-
void WebFrameImpl::DidFail(const ResourceError& error, bool was_provisional) {
WebViewImpl* web_view = GetWebViewImpl();
WebViewDelegate* delegate = web_view->delegate();
@@ -1469,357 +1672,154 @@ void WebFrameImpl::DidFail(const ResourceError& error, bool was_provisional) {
}
}
-void WebFrameImpl::dispatchWillSendRequest(WebURLRequest& request) {
- ResourceResponse response;
- frame_->loader()->client()->dispatchWillSendRequest(NULL, 0,
- *webkit_glue::WebURLRequestToMutableResourceRequest(&request),
- response);
+void WebFrameImpl::SetAllowsScrolling(bool flag) {
+ frame_->view()->setCanHaveScrollbars(flag);
}
-void WebFrameImpl::commitDocumentData(const char* data, size_t data_len) {
- DocumentLoader* document_loader = frame_->loader()->documentLoader();
-
- // Set the text encoding. This calls begin() for us. It is safe to call
- // this multiple times (Mac does: page/mac/WebCoreFrameBridge.mm).
- bool user_chosen = true;
- String encoding = document_loader->overrideEncoding();
- if (encoding.isNull()) {
- user_chosen = false;
- encoding = document_loader->response().textEncodingName();
- }
- frame_->loader()->setEncoding(encoding, user_chosen);
-
- // NOTE: mac only does this if there is a document
- frame_->loader()->addData(data, data_len);
+void WebFrameImpl::RegisterPasswordListener(
+ PassRefPtr<WebCore::HTMLInputElement> input_element,
+ webkit_glue::PasswordAutocompleteListener* listener) {
+ RefPtr<WebCore::HTMLInputElement> element = input_element;
+ DCHECK(password_listeners_.find(element) == password_listeners_.end());
+ password_listeners_.set(element, listener);
}
-void WebFrameImpl::executeScript(const WebScriptSource& source) {
- frame_->loader()->executeScript(
- WebCore::ScriptSourceCode(
- webkit_glue::WebStringToString(source.code),
- webkit_glue::WebURLToKURL(source.url),
- source.startLine));
+webkit_glue::PasswordAutocompleteListener* WebFrameImpl::GetPasswordListener(
+ WebCore::HTMLInputElement* input_element) {
+ return password_listeners_.get(input_element);
}
-bool WebFrameImpl::insertStyleText(const WebString& css) {
- Document* document = frame()->document();
- if (!document)
- return false;
- WebCore::Element* document_element = document->documentElement();
- if (!document_element)
- return false;
+// WebFrameImpl protected ------------------------------------------------------
- RefPtr<WebCore::Element> stylesheet = document->createElement(
- WebCore::HTMLNames::styleTag, false);
- ExceptionCode err = 0;
- stylesheet->setTextContent(webkit_glue::WebStringToString(css), err);
- DCHECK(!err) << "Failed to set style element content";
- WebCore::Node* first = document_element->firstChild();
- bool success = document_element->insertBefore(stylesheet, first, err);
- DCHECK(success) << "Failed to insert stylesheet";
- return success;
+void WebFrameImpl::Closing() {
+ frame_ = NULL;
}
-void WebFrameImpl::executeScriptInNewContext(
- const WebScriptSource* sources_in, unsigned num_sources,
- int extension_group) {
- Vector<WebCore::ScriptSourceCode> sources;
+// WebFrameImpl private --------------------------------------------------------
- for (unsigned i = 0; i < num_sources; ++i) {
- sources.append(WebCore::ScriptSourceCode(
- webkit_glue::WebStringToString(sources_in[i].code),
- webkit_glue::WebURLToKURL(sources_in[i].url),
- sources_in[i].startLine));
- }
-
- frame_->script()->evaluateInNewContext(sources, extension_group);
-}
+void WebFrameImpl::InvalidateArea(AreaToInvalidate area) {
+ ASSERT(frame() && frame()->view());
+ FrameView* view = frame()->view();
-void WebFrameImpl::executeScriptInNewWorld(
- const WebScriptSource* sources_in, unsigned num_sources,
- int extension_group) {
- Vector<WebCore::ScriptSourceCode> sources;
+ if ((area & INVALIDATE_ALL) == INVALIDATE_ALL) {
+ view->invalidateRect(view->frameRect());
+ } else {
+ if ((area & INVALIDATE_CONTENT_AREA) == INVALIDATE_CONTENT_AREA) {
+ IntRect content_area(
+ view->x(), view->y(), view->visibleWidth(), view->visibleHeight());
+ view->invalidateRect(content_area);
+ }
- for (unsigned i = 0; i < num_sources; ++i) {
- sources.append(WebCore::ScriptSourceCode(
- webkit_glue::WebStringToString(sources_in[i].code),
- webkit_glue::WebURLToKURL(sources_in[i].url),
- sources_in[i].startLine));
+ if ((area & INVALIDATE_SCROLLBAR) == INVALIDATE_SCROLLBAR) {
+ // Invalidate the vertical scroll bar region for the view.
+ IntRect scroll_bar_vert(
+ view->x() + view->visibleWidth(), view->y(),
+ WebCore::ScrollbarTheme::nativeTheme()->scrollbarThickness(),
+ view->visibleHeight());
+ view->invalidateRect(scroll_bar_vert);
+ }
}
-
- frame_->script()->evaluateInNewWorld(sources, extension_group);
-}
-
-WebString WebFrameImpl::name() const {
- return webkit_glue::StringToWebString(frame_->tree()->name());
-}
-
-bool WebFrameImpl::hasVisibleContent() const {
- return frame()->view()->visibleWidth() > 0 &&
- frame()->view()->visibleHeight() > 0;
}
-PassRefPtr<Frame> WebFrameImpl::CreateChildFrame(
- const FrameLoadRequest& request, HTMLFrameOwnerElement* owner_element) {
- // TODO(darin): share code with initWithName()
-
- scoped_refptr<WebFrameImpl> webframe = new WebFrameImpl();
-
- // Add an extra ref on behalf of the Frame/FrameLoader, which references the
- // WebFrame via the FrameLoaderClient interface. See the comment at the top
- // of this file for more info.
- webframe->AddRef();
-
- RefPtr<Frame> child_frame = Frame::create(
- frame_->page(), owner_element, &webframe->frame_loader_client_);
- webframe->frame_ = child_frame.get();
-
- child_frame->tree()->setName(request.frameName());
-
- frame_->tree()->appendChild(child_frame);
-
- // Frame::init() can trigger onload event in the parent frame,
- // which may detach this frame and trigger a null-pointer access
- // in FrameTree::removeChild. Move init() after appendChild call
- // so that webframe->frame_ is in the tree before triggering
- // onload event handler.
- // Because the event handler may set webframe->frame_ to null,
- // it is necessary to check the value after calling init() and
- // return without loading URL.
- // (b:791612)
- child_frame->init(); // create an empty document
- if (!child_frame->tree()->parent())
- return NULL;
-
- frame_->loader()->loadURLIntoChildFrame(
- request.resourceRequest().url(),
- request.resourceRequest().httpReferrer(),
- child_frame.get());
-
- // A synchronous navigation (about:blank) would have already processed
- // onload, so it is possible for the frame to have already been destroyed by
- // script in the page.
- if (!child_frame->tree()->parent())
- return NULL;
-
- return child_frame.release();
-}
-
-bool WebFrameImpl::executeCommand(const WebString& name) {
- ASSERT(frame());
-
- if (name.length() <= 2)
- return false;
-
- // Since we don't have NSControl, we will convert the format of command
- // string and call the function on Editor directly.
- string16 command = name;
-
- // Make sure the first letter is upper case.
- command.replace(0, 1, 1, toupper(command.at(0)));
+void WebFrameImpl::AddMarker(WebCore::Range* range, bool active_match) {
+ // Use a TextIterator to visit the potentially multiple nodes the range
+ // covers.
+ TextIterator markedText(range);
+ for (; !markedText.atEnd(); markedText.advance()) {
+ RefPtr<Range> textPiece = markedText.range();
+ int exception = 0;
- // Remove the trailing ':' if existing.
- if (command.at(command.length() - 1) == ':')
- command.erase(command.length() - 1, 1);
+ WebCore::DocumentMarker marker = {
+ WebCore::DocumentMarker::TextMatch,
+ textPiece->startOffset(exception),
+ textPiece->endOffset(exception),
+ "",
+ active_match };
- bool rv = true;
+ if (marker.endOffset > marker.startOffset) {
+ // Find the node to add a marker to and add it.
+ Node* node = textPiece->startContainer(exception);
+ frame()->document()->addMarker(node, marker);
- // Specially handling commands that Editor::execCommand does not directly
- // support.
- if (EqualsASCII(command, "DeleteToEndOfParagraph")) {
- WebCore::Editor* editor = frame()->editor();
- if (!editor->deleteWithDirection(WebCore::SelectionController::FORWARD,
- WebCore::ParagraphBoundary,
- true,
- false)) {
- editor->deleteWithDirection(WebCore::SelectionController::FORWARD,
- WebCore::CharacterGranularity,
- true,
- false);
+ // Rendered rects for markers in WebKit are not populated until each time
+ // the markers are painted. However, we need it to happen sooner, because
+ // the whole purpose of tickmarks on the scrollbar is to show where
+ // matches off-screen are (that haven't been painted yet).
+ Vector<WebCore::DocumentMarker> markers =
+ frame()->document()->markersForNode(node);
+ frame()->document()->setRenderedRectForMarker(
+ textPiece->startContainer(exception),
+ markers[markers.size() - 1],
+ range->boundingBox());
}
- } else if (EqualsASCII(command, "Indent")) {
- frame()->editor()->indent();
- } else if (EqualsASCII(command, "Outdent")) {
- frame()->editor()->outdent();
- } else if (EqualsASCII(command, "DeleteBackward")) {
- rv = frame()->editor()->command(AtomicString("BackwardDelete")).execute();
- } else if (EqualsASCII(command, "DeleteForward")) {
- rv = frame()->editor()->command(AtomicString("ForwardDelete")).execute();
- } else {
- rv = frame()->editor()->command(AtomicString(command.c_str())).execute();
}
- return rv;
}
-bool WebFrameImpl::executeCommand(const WebString& name,
- const WebString& value) {
- ASSERT(frame());
- return frame()->editor()->command(webkit_glue::WebStringToString(name)).
- execute(webkit_glue::WebStringToString(value));
-}
+void WebFrameImpl::SetMarkerActive(WebCore::Range* range, bool active) {
+ if (!range)
+ return;
-bool WebFrameImpl::isCommandEnabled(const WebString& name) const {
- ASSERT(frame());
- return frame()->editor()->command(webkit_glue::WebStringToString(name)).
- isEnabled();
+ frame()->document()->setMarkersActive(range, active);
}
-void WebFrameImpl::addMessageToConsole(const WebConsoleMessage& message) {
- ASSERT(frame());
-
- WebCore::MessageLevel webcore_message_level;
- switch (message.level) {
- case WebConsoleMessage::LevelTip:
- webcore_message_level = WebCore::TipMessageLevel;
- break;
- case WebConsoleMessage::LevelLog:
- webcore_message_level = WebCore::LogMessageLevel;
- break;
- case WebConsoleMessage::LevelWarning:
- webcore_message_level = WebCore::WarningMessageLevel;
- break;
- case WebConsoleMessage::LevelError:
- webcore_message_level = WebCore::ErrorMessageLevel;
- break;
- default:
- NOTREACHED();
- return;
+int WebFrameImpl::OrdinalOfFirstMatchForFrame(WebFrameImpl* frame) const {
+ int ordinal = 0;
+ WebViewImpl* web_view = GetWebViewImpl();
+ WebFrameImpl* const main_frame_impl = GetWebViewImpl()->main_frame();
+ // Iterate from the main frame up to (but not including) |frame| and
+ // add up the number of matches found so far.
+ for (WebFrameImpl* it = main_frame_impl;
+ it != frame;
+ it = static_cast<WebFrameImpl*>(
+ web_view->GetNextFrameAfter(it, true))) {
+ if (it->last_match_count_ > 0)
+ ordinal += it->last_match_count_;
}
- frame()->domWindow()->console()->addMessage(
- WebCore::OtherMessageSource, WebCore::LogMessageType,
- webcore_message_level, webkit_glue::WebStringToString(message.text),
- 1, String());
-}
-
-WebSize WebFrameImpl::scrollOffset() const {
- WebCore::FrameView* view = frameview();
- if (view)
- return webkit_glue::IntSizeToWebSize(view->scrollOffset());
-
- return WebSize();
-}
-
-WebSize WebFrameImpl::contentsSize() const {
- return webkit_glue::IntSizeToWebSize(frame()->view()->contentsSize());
-}
-
-WebFrame* WebFrameImpl::firstChild() const {
- return FromFrame(frame()->tree()->firstChild());
-}
-
-WebFrame* WebFrameImpl::lastChild() const {
- return FromFrame(frame()->tree()->lastChild());
-}
-
-WebFrame* WebFrameImpl::nextSibling() const {
- return FromFrame(frame()->tree()->nextSibling());
-}
-
-WebFrame* WebFrameImpl::previousSibling() const {
- return FromFrame(frame()->tree()->previousSibling());
-}
-
-WebFrame* WebFrameImpl::traverseNext(bool wrap) const {
- return FromFrame(frame()->tree()->traverseNextWithWrap(wrap));
-}
-
-WebFrame* WebFrameImpl::traversePrevious(bool wrap) const {
- return FromFrame(frame()->tree()->traversePreviousWithWrap(wrap));
-}
-
-WebFrame* WebFrameImpl::findChildByName(const WebKit::WebString& name) const {
- return FromFrame(frame()->tree()->child(
- webkit_glue::WebStringToString(name)));
-}
-
-WebFrame* WebFrameImpl::findChildByExpression(
- const WebKit::WebString& xpath) const {
- if (xpath.isEmpty())
- return NULL;
-
- Document* document = frame_->document();
-
- ExceptionCode ec = 0;
- PassRefPtr<XPathResult> xpath_result =
- document->evaluate(webkit_glue::WebStringToString(xpath),
- document,
- NULL, /* namespace */
- XPathResult::ORDERED_NODE_ITERATOR_TYPE,
- NULL, /* XPathResult object */
- ec);
- if (!xpath_result.get())
- return NULL;
-
- Node* node = xpath_result->iterateNext(ec);
-
- if (!node || !node->isFrameOwnerElement())
- return NULL;
- HTMLFrameOwnerElement* frame_element =
- static_cast<HTMLFrameOwnerElement*>(node);
- return FromFrame(frame_element->contentFrame());
+ return ordinal;
}
-void WebFrameImpl::SetAllowsScrolling(bool flag) {
- frame_->view()->setCanHaveScrollbars(flag);
-}
+bool WebFrameImpl::ShouldScopeMatches(const string16& search_text) {
+ // Don't scope if we can't find a frame or if the frame is not visible.
+ // The user may have closed the tab/application, so abort.
+ if (!frame() || !hasVisibleContent())
+ return false;
-int WebFrameImpl::printBegin(const WebSize& page_size) {
- DCHECK_EQ(frame()->document()->isFrameSet(), false);
+ DCHECK(frame()->document() && frame()->view());
- print_context_.reset(new ChromePrintContext(frame()));
- WebCore::FloatRect rect(0, 0,
- static_cast<float>(page_size.width),
- static_cast<float>(page_size.height));
- print_context_->begin(rect.width());
- float page_height;
- // We ignore the overlays calculation for now since they are generated in the
- // browser. page_height is actually an output parameter.
- print_context_->computePageRects(rect, 0, 0, 1.0, page_height);
- return print_context_->pageCount();
-}
+ // If the frame completed the scoping operation and found 0 matches the last
+ // time it was searched, then we don't have to search it again if the user is
+ // just adding to the search string or sending the same search string again.
+ if (scoping_complete_ &&
+ !last_search_string_.empty() && last_match_count_ == 0) {
+ // Check to see if the search string prefixes match.
+ string16 previous_search_prefix =
+ search_text.substr(0, last_search_string_.length());
-float WebFrameImpl::printPage(int page, WebCanvas* canvas) {
- // Ensure correct state.
- if (!print_context_.get() || page < 0 || !frame() || !frame()->document()) {
- NOTREACHED();
- return 0;
+ if (previous_search_prefix == last_search_string_) {
+ return false; // Don't search this frame, it will be fruitless.
+ }
}
-#if defined(OS_WIN) || defined(OS_LINUX)
- PlatformContextSkia context(canvas);
- GraphicsContext spool(&context);
-#elif defined(OS_MACOSX)
- CGContextRef context = canvas->beginPlatformPaint();
- GraphicsContext spool(context);
- WebCore::LocalCurrentGraphicsContext localContext(&spool);
-#endif
-
- return print_context_->spoolPage(spool, page);
-}
-
-void WebFrameImpl::printEnd() {
- DCHECK(print_context_.get());
- if (print_context_.get())
- print_context_->end();
- print_context_.reset(NULL);
-}
-
-unsigned WebFrameImpl::unloadListenerCount() const {
- return frame()->domWindow()->pendingUnloadEventListeners();
+ return true;
}
-void WebFrameImpl::RegisterPasswordListener(
- PassRefPtr<WebCore::HTMLInputElement> input_element,
- webkit_glue::PasswordAutocompleteListener* listener) {
- RefPtr<WebCore::HTMLInputElement> element = input_element;
- DCHECK(password_listeners_.find(element) == password_listeners_.end());
- password_listeners_.set(element, listener);
-}
+void WebFrameImpl::InvalidateIfNecessary() {
+ if (last_match_count_ > next_invalidate_after_) {
+ // TODO(finnur): (http://b/1088165) Optimize the drawing of the
+ // tickmarks and remove this. This calculation sets a milestone for when
+ // next to invalidate the scrollbar and the content area. We do this so that
+ // we don't spend too much time drawing the scrollbar over and over again.
+ // Basically, up until the first 500 matches there is no throttle. After the
+ // first 500 matches, we set set the milestone further and further out (750,
+ // 1125, 1688, 2K, 3K).
+ static const int start_slowing_down_after = 500;
+ static const int slowdown = 750;
+ int i = (last_match_count_ / start_slowing_down_after);
+ next_invalidate_after_ += i * slowdown;
-webkit_glue::PasswordAutocompleteListener* WebFrameImpl::GetPasswordListener(
- WebCore::HTMLInputElement* input_element) {
- return password_listeners_.get(input_element);
+ InvalidateArea(INVALIDATE_SCROLLBAR);
+ }
}
void WebFrameImpl::ClearPasswordListeners() {