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

Unified Diff: sky/engine/web/WebLocalFrameImpl.cpp

Issue 1210153009: Remove (almost all of) //sky/engine/web (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sky/engine/web/WebLocalFrameImpl.h ('k') | sky/engine/web/WebNode.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/engine/web/WebLocalFrameImpl.cpp
diff --git a/sky/engine/web/WebLocalFrameImpl.cpp b/sky/engine/web/WebLocalFrameImpl.cpp
deleted file mode 100644
index ff29d93291589ee3c21c4626a3d15ae4fc5c96f1..0000000000000000000000000000000000000000
--- a/sky/engine/web/WebLocalFrameImpl.cpp
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// How ownership works
-// -------------------
-//
-// Big oh represents a refcounted relationship: owner O--- ownee
-//
-// WebView (for the toplevel frame only)
-// O
-// | WebFrame
-// | O
-// | |
-// Page O------- LocalFrame (m_mainFrame) O-------O FrameView
-// ||
-// ||
-// FrameLoader
-//
-// FrameLoader and LocalFrame are formerly one object that was split apart because
-// it got too big. They basically have the same lifetime, hence the double line.
-//
-// From the perspective of the embedder, WebFrame is simply an object that it
-// allocates by calling WebFrame::create() and must be freed by calling close().
-// Internally, WebFrame is actually refcounted and it holds a reference to its
-// corresponding LocalFrame in WebCore.
-//
-// How frames are destroyed
-// ------------------------
-//
-// The main frame is never destroyed and is re-used. The FrameLoader is re-used
-// and a reference to the main frame is kept by the Page.
-//
-// When frame content is replaced, all subframes are destroyed. This happens
-// in FrameLoader::detachFromParent for each subframe in a pre-order depth-first
-// traversal. Note that child node order may not match DOM node order!
-// detachFromParent() calls FrameLoaderClient::detachedFromParent(), which calls
-// WebFrame::frameDetached(). This triggers WebFrame to clear its reference to
-// LocalFrame, and also notifies the embedder via WebFrameClient that the frame is
-// detached. Most embedders will invoke close() on the WebFrame at this point,
-// triggering its deletion unless something else is still retaining a reference.
-//
-// Thie client is expected to be set whenever the WebLocalFrameImpl is attached to
-// the DOM.
-
-#include "sky/engine/web/WebLocalFrameImpl.h"
-
-#include <algorithm>
-#include "base/strings/stringprintf.h"
-#include "mojo/common/data_pipe_utils.h"
-#include "mojo/public/cpp/system/data_pipe.h"
-#include "sky/engine/bindings/exception_state.h"
-#include "sky/engine/bindings/exception_state_placeholder.h"
-#include "sky/engine/core/dom/Document.h"
-#include "sky/engine/core/dom/Node.h"
-#include "sky/engine/core/dom/NodeTraversal.h"
-#include "sky/engine/core/dom/shadow/ShadowRoot.h"
-#include "sky/engine/core/editing/Editor.h"
-#include "sky/engine/core/editing/FrameSelection.h"
-#include "sky/engine/core/editing/htmlediting.h"
-#include "sky/engine/core/editing/InputMethodController.h"
-#include "sky/engine/core/editing/PlainTextRange.h"
-#include "sky/engine/core/editing/SpellChecker.h"
-#include "sky/engine/core/editing/TextAffinity.h"
-#include "sky/engine/core/editing/TextIterator.h"
-#include "sky/engine/core/frame/FrameHost.h"
-#include "sky/engine/core/frame/FrameView.h"
-#include "sky/engine/core/frame/LocalDOMWindow.h"
-#include "sky/engine/core/frame/Settings.h"
-#include "sky/engine/core/html/HTMLAnchorElement.h"
-#include "sky/engine/core/inspector/ConsoleMessage.h"
-#include "sky/engine/core/loader/MojoLoader.h"
-#include "sky/engine/core/page/EventHandler.h"
-#include "sky/engine/core/page/FocusController.h"
-#include "sky/engine/core/page/Page.h"
-#include "sky/engine/core/rendering/HitTestResult.h"
-#include "sky/engine/core/rendering/RenderBox.h"
-#include "sky/engine/core/rendering/RenderLayer.h"
-#include "sky/engine/core/rendering/RenderObject.h"
-#include "sky/engine/core/rendering/RenderTreeAsText.h"
-#include "sky/engine/core/rendering/RenderView.h"
-#include "sky/engine/core/rendering/style/StyleInheritedData.h"
-#include "sky/engine/platform/clipboard/ClipboardUtilities.h"
-#include "sky/engine/platform/fonts/FontCache.h"
-#include "sky/engine/platform/graphics/GraphicsContext.h"
-#include "sky/engine/platform/graphics/skia/SkiaUtils.h"
-#include "sky/engine/platform/heap/Handle.h"
-#include "sky/engine/platform/network/ResourceRequest.h"
-#include "sky/engine/platform/TraceEvent.h"
-#include "sky/engine/platform/weborigin/KURL.h"
-#include "sky/engine/platform/weborigin/SecurityPolicy.h"
-#include "sky/engine/public/platform/Platform.h"
-#include "sky/engine/public/platform/WebFloatPoint.h"
-#include "sky/engine/public/platform/WebFloatRect.h"
-#include "sky/engine/public/platform/WebLayer.h"
-#include "sky/engine/public/platform/WebPoint.h"
-#include "sky/engine/public/platform/WebRect.h"
-#include "sky/engine/public/platform/WebSize.h"
-#include "sky/engine/public/platform/WebURLError.h"
-#include "sky/engine/public/platform/WebVector.h"
-#include "sky/engine/public/web/WebConsoleMessage.h"
-#include "sky/engine/public/web/WebDocument.h"
-#include "sky/engine/public/web/WebElement.h"
-#include "sky/engine/public/web/WebFrameClient.h"
-#include "sky/engine/public/web/WebNode.h"
-#include "sky/engine/public/web/WebRange.h"
-#include "sky/engine/public/web/WebScriptSource.h"
-#include "sky/engine/web/CompositionUnderlineVectorBuilder.h"
-#include "sky/engine/web/WebViewImpl.h"
-#include "sky/engine/wtf/CurrentTime.h"
-#include "sky/engine/wtf/HashMap.h"
-
-namespace blink {
-
-static int frameCount = 0;
-
-// Key for a StatsCounter tracking how many WebFrames are active.
-static const char webFrameActiveCount[] = "WebFrameActiveCount";
-
-static void frameContentAsPlainText(size_t maxChars, LocalFrame* frame, StringBuilder& output)
-{
- Document* document = frame->document();
- if (!document)
- return;
-
- if (!frame->view())
- return;
-
- // Select the document body.
- RefPtr<Range> range(document->createRange());
- TrackExceptionState exceptionState;
- range->selectNodeContents(document, exceptionState);
-
- if (!exceptionState.had_exception()) {
- // The text iterator will walk nodes giving us text. This is similar to
- // the plainText() function in core/editing/TextIterator.h, but we implement the maximum
- // size and also copy the results directly into a wstring, avoiding the
- // string conversion.
- for (TextIterator it(range.get()); !it.atEnd(); it.advance()) {
- it.appendTextToStringBuilder(output, 0, maxChars - output.length());
- if (output.length() >= maxChars)
- return; // Filled up the buffer.
- }
- }
-}
-
-// WebFrame -------------------------------------------------------------------
-
-int WebFrame::instanceCount()
-{
- return frameCount;
-}
-
-bool WebLocalFrameImpl::isWebLocalFrame() const
-{
- return true;
-}
-
-WebLocalFrame* WebLocalFrameImpl::toWebLocalFrame()
-{
- return this;
-}
-
-void WebLocalFrameImpl::close()
-{
- m_client = 0;
-
- deref(); // Balances ref() acquired in WebFrame::create
-}
-
-WebSize WebLocalFrameImpl::contentsSize() const
-{
- return frame()->view()->size();
-}
-
-bool WebLocalFrameImpl::hasVisibleContent() const
-{
- return frame()->view()->width() > 0 && frame()->view()->height() > 0;
-}
-
-WebRect WebLocalFrameImpl::visibleContentRect() const
-{
- return frame()->view()->frameRect();
-}
-
-WebView* WebLocalFrameImpl::view() const
-{
- return viewImpl();
-}
-
-WebDocument WebLocalFrameImpl::document() const
-{
- if (!frame() || !frame()->document())
- return WebDocument();
- return WebDocument(frame()->document());
-}
-
-void WebLocalFrameImpl::executeScript(const WebScriptSource& source)
-{
- ASSERT(frame());
- // TODO(dart)
-}
-
-void WebLocalFrameImpl::addMessageToConsole(const WebConsoleMessage& message)
-{
- ASSERT(frame());
-
- MessageLevel webCoreMessageLevel;
- switch (message.level) {
- case WebConsoleMessage::LevelDebug:
- webCoreMessageLevel = DebugMessageLevel;
- break;
- case WebConsoleMessage::LevelLog:
- webCoreMessageLevel = LogMessageLevel;
- break;
- case WebConsoleMessage::LevelWarning:
- webCoreMessageLevel = WarningMessageLevel;
- break;
- case WebConsoleMessage::LevelError:
- webCoreMessageLevel = ErrorMessageLevel;
- break;
- default:
- ASSERT_NOT_REACHED();
- return;
- }
-
- frame()->document()->addConsoleMessage(ConsoleMessage::create(OtherMessageSource, webCoreMessageLevel, message.text));
-}
-
-void WebLocalFrameImpl::collectGarbage()
-{
- // TODO(dart): Implement.
-}
-
-void WebLocalFrameImpl::loadFromDataPipeWithURL(mojo::ScopedDataPipeConsumerHandle responseStream, const WebURL& url)
-{
- frame()->mojoLoader().init(url);
- frame()->mojoLoader().parse(responseStream.Pass());
-}
-
-void WebLocalFrameImpl::load(const WebURL& url)
-{
- frame()->mojoLoader().init(url);
- m_fetcher = adoptPtr(new MojoFetcher(this, url));
-}
-
-void WebLocalFrameImpl::OnReceivedResponse(mojo::URLResponsePtr response)
-{
- m_fetcher.clear();
- if (response->body.is_valid()) {
- frame()->mojoLoader().parse(response->body.Pass());
- return;
- }
- LOG(ERROR) << "Response for " << response->url
- << " (status " << response->status_code << ") has no body.";
-
- // TODO(eseidel): This is a hack, but makes debugging way easier.
- mojo::DataPipe pipe;
- frame()->mojoLoader().parse(pipe.consumer_handle.Pass());
- std::string error_response = base::StringPrintf(
- "<error><h style='display: paragraph'>Empty Body</h>"
- "<l style='display: paragraph'>%d %s</l>"
- "<m style='display: paragraph'>%s</m></t></error>",
- response->status_code, response->status_line.get().c_str(),
- response->error->description.get().c_str());
-
- uint32_t length = error_response.length();
- MojoWriteData(pipe.producer_handle.get().value(),
- error_response.data(),
- &length,
- MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
-}
-
-void WebLocalFrameImpl::replaceSelection(const WebString& text)
-{
- bool selectReplacement = false;
- bool smartReplace = true;
- frame()->editor().replaceSelectionWithText(text, selectReplacement, smartReplace);
-}
-
-void WebLocalFrameImpl::insertText(const WebString& text)
-{
- if (frame()->inputMethodController().hasComposition())
- frame()->inputMethodController().confirmComposition(text);
- else
- frame()->editor().insertText(text, 0);
-}
-
-void WebLocalFrameImpl::setMarkedText(const WebString& text, unsigned location, unsigned length)
-{
- Vector<CompositionUnderline> decorations;
- frame()->inputMethodController().setComposition(text, decorations, location, length);
-}
-
-void WebLocalFrameImpl::unmarkText()
-{
- frame()->inputMethodController().cancelComposition();
-}
-
-bool WebLocalFrameImpl::hasMarkedText() const
-{
- return frame()->inputMethodController().hasComposition();
-}
-
-bool WebLocalFrameImpl::executeCommand(const WebString& name, const WebNode& node)
-{
- 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.
- String command = name;
-
- // Make sure the first letter is upper case.
- command.replace(0, 1, command.substring(0, 1).upper());
-
- // Remove the trailing ':' if existing.
- if (command[command.length() - 1] == UChar(':'))
- command = command.substring(0, command.length() - 1);
-
- return frame()->editor().executeCommand(command);
-}
-
-bool WebLocalFrameImpl::executeCommand(const WebString& name, const WebString& value, const WebNode& node)
-{
- ASSERT(frame());
-
- return frame()->editor().executeCommand(name, value);
-}
-
-bool WebLocalFrameImpl::isCommandEnabled(const WebString& name) const
-{
- ASSERT(frame());
- return frame()->editor().command(name).isEnabled();
-}
-
-void WebLocalFrameImpl::enableContinuousSpellChecking(bool enable)
-{
- if (enable == isContinuousSpellCheckingEnabled())
- return;
- frame()->spellChecker().toggleContinuousSpellChecking();
-}
-
-bool WebLocalFrameImpl::isContinuousSpellCheckingEnabled() const
-{
- return frame()->spellChecker().isContinuousSpellCheckingEnabled();
-}
-
-void WebLocalFrameImpl::requestTextChecking(const WebElement& webElement)
-{
- if (webElement.isNull())
- return;
- frame()->spellChecker().requestTextChecking(*webElement.constUnwrap<Element>());
-}
-
-void WebLocalFrameImpl::replaceMisspelledRange(const WebString& text)
-{
- frame()->spellChecker().replaceMisspelledRange(text);
-}
-
-void WebLocalFrameImpl::removeSpellingMarkers()
-{
- frame()->spellChecker().removeSpellingMarkers();
-}
-
-bool WebLocalFrameImpl::hasSelection() const
-{
- // frame()->selection()->isNone() never returns true.
- return frame()->selection().start() != frame()->selection().end();
-}
-
-WebRange WebLocalFrameImpl::selectionRange() const
-{
- return frame()->selection().toNormalizedRange();
-}
-
-WebString WebLocalFrameImpl::selectionAsText() const
-{
- RefPtr<Range> range = frame()->selection().toNormalizedRange();
- if (!range)
- return WebString();
-
- String text = range->text();
- replaceNBSPWithSpace(text);
- return text;
-}
-
-void WebLocalFrameImpl::selectWordAroundPosition(LocalFrame* frame, VisiblePosition position)
-{
- VisibleSelection selection(position);
- selection.expandUsingGranularity(WordGranularity);
-
- TextGranularity granularity = selection.isRange() ? WordGranularity : CharacterGranularity;
- frame->selection().setSelection(selection, granularity);
-}
-
-bool WebLocalFrameImpl::selectWordAroundCaret()
-{
- FrameSelection& selection = frame()->selection();
- if (selection.isNone() || selection.isRange())
- return false;
- selectWordAroundPosition(frame(), selection.selection().visibleStart());
- return true;
-}
-
-void WebLocalFrameImpl::selectRange(const WebPoint& base, const WebPoint& extent)
-{
- moveRangeSelection(base, extent);
-}
-
-void WebLocalFrameImpl::selectRange(const WebRange& webRange)
-{
- if (RefPtr<Range> range = static_cast<PassRefPtr<Range> >(webRange))
- frame()->selection().setSelectedRange(range.get(), VP_DEFAULT_AFFINITY, FrameSelection::NonDirectional, NotUserTriggered);
-}
-
-void WebLocalFrameImpl::moveRangeSelection(const WebPoint& base, const WebPoint& extent)
-{
- VisiblePosition basePosition = visiblePositionForWindowPoint(base);
- VisiblePosition extentPosition = visiblePositionForWindowPoint(extent);
- VisibleSelection newSelection = VisibleSelection(basePosition, extentPosition);
- frame()->selection().setSelection(newSelection, CharacterGranularity);
-}
-
-void WebLocalFrameImpl::moveCaretSelection(const WebPoint& point)
-{
- Element* editable = frame()->selection().rootEditableElement();
- if (!editable)
- return;
-
- VisiblePosition position = visiblePositionForWindowPoint(point);
- frame()->selection().moveTo(position, UserTriggered);
-}
-
-bool WebLocalFrameImpl::setEditableSelectionOffsets(int start, int end)
-{
- return frame()->inputMethodController().setEditableSelectionOffsets(PlainTextRange(start, end));
-}
-
-bool WebLocalFrameImpl::setCompositionFromExistingText(int compositionStart, int compositionEnd, const WebVector<WebCompositionUnderline>& underlines)
-{
- if (!frame()->editor().canEdit())
- return false;
-
- InputMethodController& inputMethodController = frame()->inputMethodController();
- inputMethodController.cancelComposition();
-
- if (compositionStart == compositionEnd)
- return true;
-
- inputMethodController.setCompositionFromExistingText(CompositionUnderlineVectorBuilder(underlines), compositionStart, compositionEnd);
-
- return true;
-}
-
-void WebLocalFrameImpl::extendSelectionAndDelete(int before, int after)
-{
- frame()->inputMethodController().extendSelectionAndDelete(before, after);
-}
-
-void WebLocalFrameImpl::setCaretVisible(bool visible)
-{
- frame()->selection().setCaretVisible(visible);
-}
-
-VisiblePosition WebLocalFrameImpl::visiblePositionForWindowPoint(const WebPoint& point)
-{
- HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping;
- HitTestResult result(frame()->view()->windowToContents(roundedIntPoint(FloatPoint(point))));
- frame()->document()->renderView()->hitTest(request, result.hitTestLocation(), result);
-
- if (Node* node = result.targetNode())
- return frame()->selection().selection().visiblePositionRespectingEditingBoundary(result.localPoint(), node);
- return VisiblePosition();
-}
-
-WebString WebLocalFrameImpl::contentAsText(size_t maxChars) const
-{
- if (!frame())
- return WebString();
- StringBuilder text;
- frameContentAsPlainText(maxChars, frame(), text);
- return text.toString();
-}
-
-WebString WebLocalFrameImpl::renderTreeAsText(RenderAsTextControls toShow) const
-{
- RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal;
-
- if (toShow & RenderAsTextDebug)
- behavior |= RenderAsTextShowCompositedLayers | RenderAsTextShowAddresses | RenderAsTextShowIDAndClass | RenderAsTextShowLayerNesting;
-
- return externalRepresentation(frame(), behavior);
-}
-
-bool WebLocalFrameImpl::selectionStartHasSpellingMarkerFor(int from, int length) const
-{
- if (!frame())
- return false;
- return frame()->spellChecker().selectionStartHasSpellingMarkerFor(from, length);
-}
-
-// WebLocalFrameImpl public ---------------------------------------------------------
-
-WebLocalFrame* WebLocalFrame::create(WebFrameClient* client)
-{
- return WebLocalFrameImpl::create(client);
-}
-
-WebLocalFrameImpl* WebLocalFrameImpl::create(WebFrameClient* client)
-{
- return adoptRef(new WebLocalFrameImpl(client)).leakRef();
-}
-
-WebLocalFrameImpl::WebLocalFrameImpl(WebFrameClient* client)
- : m_frameLoaderClientImpl(this)
- , m_client(client)
- , m_inputEventsScaleFactorForEmulation(1)
-{
- Platform::current()->incrementStatsCounter(webFrameActiveCount);
- frameCount++;
-}
-
-WebLocalFrameImpl::~WebLocalFrameImpl()
-{
- Platform::current()->decrementStatsCounter(webFrameActiveCount);
- frameCount--;
-}
-
-void WebLocalFrameImpl::setCoreFrame(PassRefPtr<LocalFrame> frame)
-{
- m_frame = frame;
-}
-
-PassRefPtr<LocalFrame> WebLocalFrameImpl::initializeCoreFrame(FrameHost* host)
-{
- RefPtr<LocalFrame> frame = LocalFrame::create(&m_frameLoaderClientImpl, host);
- setCoreFrame(frame);
- return frame;
-}
-
-void WebLocalFrameImpl::createFrameView()
-{
- TRACE_EVENT0("blink", "WebLocalFrameImpl::createFrameView");
-
- ASSERT(frame()); // If frame() doesn't exist, we probably didn't init properly.
-
- WebViewImpl* webView = viewImpl();
- frame()->createView(webView->size(), webView->baseBackgroundColor(), webView->isTransparent());
- frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation);
-}
-
-WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame* frame)
-{
- if (!frame)
- return 0;
- return fromFrame(*frame);
-}
-
-WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame& frame)
-{
- FrameLoaderClient* client = frame.loaderClient();
- if (!client || !client->isFrameLoaderClientImpl())
- return 0;
- return toFrameLoaderClientImpl(client)->webFrame();
-}
-
-WebViewImpl* WebLocalFrameImpl::viewImpl() const
-{
- if (!frame())
- return 0;
- return WebViewImpl::fromPage(frame()->page());
-}
-
-void WebLocalFrameImpl::didFail(const ResourceError& error)
-{
- if (!client())
- return;
- client()->didFailLoad(this, error);
-}
-
-void WebLocalFrameImpl::setInputEventsTransformForEmulation(const IntSize& offset, float contentScaleFactor)
-{
- m_inputEventsOffsetForEmulation = offset;
- m_inputEventsScaleFactorForEmulation = contentScaleFactor;
- if (frame()->view())
- frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation);
-}
-
-} // namespace blink
« no previous file with comments | « sky/engine/web/WebLocalFrameImpl.h ('k') | sky/engine/web/WebNode.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698