ChromeClientImpl.h revision 2fc2651226baac27029e38c9d6ef883fa32084db
1643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* 2643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Copyright (C) 2009 Google Inc. All rights reserved. 3db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * 5643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Redistribution and use in source and binary forms, with or without 6643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * modification, are permitted provided that the following conditions are 7643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * met: 8643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * 9643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * * Redistributions of source code must retain the above copyright 10643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * notice, this list of conditions and the following disclaimer. 11643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * * Redistributions in binary form must reproduce the above 12643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * copyright notice, this list of conditions and the following disclaimer 13643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * in the documentation and/or other materials provided with the 14643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * distribution. 15643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * * Neither the name of Google Inc. nor the names of its 16643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * contributors may be used to endorse or promote products derived from 17643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * this software without specific prior written permission. 18643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * 19643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30643ca7872b450ea4efacab6188849e5aac2ba161Steve Block */ 31643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 32643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#ifndef ChromeClientImpl_h 33643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define ChromeClientImpl_h 34643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 35643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "ChromeClientChromium.h" 36db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block#include "PopupMenu.h" 37db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block#include "SearchPopupMenu.h" 38643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 39643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocknamespace WebCore { 408a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockclass AccessibilityObject; 41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockclass FileChooser; 42643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockclass PopupContainer; 43db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockclass PopupMenuClient; 44643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockclass SecurityOrigin; 45643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstruct WindowFeatures; 46643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 47643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 48643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocknamespace WebKit { 49643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockclass WebViewImpl; 50643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstruct WebCursorInfo; 51643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstruct WebPopupMenuInfo; 52643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 53643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Handles window-level notifications from WebCore on behalf of a WebView. 54643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockclass ChromeClientImpl : public WebCore::ChromeClientChromium { 55643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockpublic: 56643ca7872b450ea4efacab6188849e5aac2ba161Steve Block explicit ChromeClientImpl(WebViewImpl* webView); 57643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual ~ChromeClientImpl(); 58643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 59643ca7872b450ea4efacab6188849e5aac2ba161Steve Block WebViewImpl* webView() const { return m_webView; } 60643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 61643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // ChromeClient methods: 62643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void chromeDestroyed(); 63643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void setWindowRect(const WebCore::FloatRect&); 64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual WebCore::FloatRect windowRect(); 65643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual WebCore::FloatRect pageRect(); 66643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual float scaleFactor(); 67643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void focus(); 68643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void unfocus(); 69643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool canTakeFocus(WebCore::FocusDirection); 70643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void takeFocus(WebCore::FocusDirection); 71643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void focusedNodeChanged(WebCore::Node*); 7228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu virtual void focusedFrameChanged(WebCore::Frame*); 73643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual WebCore::Page* createWindow( 74e14391e94c850b8bd03680c23b38978db68687a8John Reck WebCore::Frame*, const WebCore::FrameLoadRequest&, const WebCore::WindowFeatures&, const WebCore::NavigationAction&); 75643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void show(); 76643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool canRunModal(); 77643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void runModal(); 78643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void setToolbarsVisible(bool); 79643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool toolbarsVisible(); 80643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void setStatusbarVisible(bool); 81643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool statusbarVisible(); 82643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void setScrollbarsVisible(bool); 83643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool scrollbarsVisible(); 84643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void setMenubarVisible(bool); 85643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool menubarVisible(); 86643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void setResizable(bool); 87643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void addMessageToConsole( 88643ca7872b450ea4efacab6188849e5aac2ba161Steve Block WebCore::MessageSource, WebCore::MessageType, WebCore::MessageLevel, 89dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch const WTF::String& message, unsigned lineNumber, 90dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch const WTF::String& sourceID); 91643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool canRunBeforeUnloadConfirmPanel(); 92643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool runBeforeUnloadConfirmPanel( 93dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch const WTF::String& message, WebCore::Frame*); 94643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void closeWindowSoon(); 95dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch virtual void runJavaScriptAlert(WebCore::Frame*, const WTF::String&); 96dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch virtual bool runJavaScriptConfirm(WebCore::Frame*, const WTF::String&); 97643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool runJavaScriptPrompt( 98dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch WebCore::Frame*, const WTF::String& message, 99dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch const WTF::String& defaultValue, WTF::String& result); 100dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch virtual void setStatusbarText(const WTF::String& message); 101643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool shouldInterruptJavaScript(); 102643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual bool tabsToLinks() const; 103643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual WebCore::IntRect windowResizerRect() const; 1042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#if ENABLE(REGISTER_PROTOCOL_HANDLER) 1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block virtual void registerProtocolHandler(const String& scheme, const String& baseURL, const String& url, const String& title); 1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif 107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block virtual void invalidateWindow(const WebCore::IntRect&, bool); 108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block virtual void invalidateContentsAndWindow(const WebCore::IntRect&, bool); 109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block virtual void invalidateContentsForSlowScroll(const WebCore::IntRect&, bool); 110ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#if ENABLE(REQUEST_ANIMATION_FRAME) 111ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch virtual void scheduleAnimation(); 112ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#endif 113643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void scroll( 114643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const WebCore::IntSize& scrollDelta, const WebCore::IntRect& rectToScroll, 115643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const WebCore::IntRect& clipRect); 116643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual WebCore::IntPoint screenToWindow(const WebCore::IntPoint&) const; 117643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual WebCore::IntRect windowToScreen(const WebCore::IntRect&) const; 118643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual PlatformPageClient platformPageClient() const { return 0; } 119643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void contentsSizeChanged(WebCore::Frame*, const WebCore::IntSize&) const; 120643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void scrollRectIntoView( 121643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const WebCore::IntRect&, const WebCore::ScrollView*) const { } 122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void scrollbarsModeDidChange() const; 123643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void mouseDidMoveOverElement( 124643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const WebCore::HitTestResult& result, unsigned modifierFlags); 125dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch virtual void setToolTip(const WTF::String& tooltipText, WebCore::TextDirection); 126643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void print(WebCore::Frame*); 127643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void exceededDatabaseQuota( 128dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch WebCore::Frame*, const WTF::String& databaseName); 129643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#if ENABLE(OFFLINE_WEB_APPLICATIONS) 130643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); 131db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block virtual void reachedApplicationCacheOriginQuota(WebCore::SecurityOrigin*); 132643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif 133643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#if ENABLE(NOTIFICATIONS) 134643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual WebCore::NotificationPresenter* notificationPresenter() const; 135643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif 136692e5dbf12901edacf14812a6fae25462920af42Steve Block virtual void requestGeolocationPermissionForFrame(WebCore::Frame*, WebCore::Geolocation*); 137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block virtual void cancelGeolocationPermissionRequestForFrame(WebCore::Frame*, WebCore::Geolocation*); 138643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void runOpenPanel(WebCore::Frame*, PassRefPtr<WebCore::FileChooser>); 139dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch virtual void chooseIconForFiles(const Vector<WTF::String>&, WebCore::FileChooser*); 140ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch virtual void setCursor(const WebCore::Cursor&); 141643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void formStateDidChange(const WebCore::Node*); 142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if ENABLE(TOUCH_EVENTS) 143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: All touch events are forwarded regardless of whether or not they are needed. 144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block virtual void needTouchEvents(bool needTouchEvents) { } 145dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif 146dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 147dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if USE(ACCELERATED_COMPOSITING) 148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Pass 0 as the GraphicsLayer to detatch the root layer. 149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block virtual void attachRootGraphicsLayer(WebCore::Frame*, WebCore::GraphicsLayer*); 150643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Sets a flag to specify that the next time content is drawn to the window, 152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // the changes appear on the screen in synchrony with updates to GraphicsLayers. 153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block virtual void setNeedsOneShotDrawingSynchronization() { } 154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Sets a flag to specify that the view needs to be updated, so we need 156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // to do an eager layout before the drawing. 157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block virtual void scheduleCompositingLayerSync(); 1585abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick 1594a156157940f51b91eadd76f6c86f862ec0a1da0Ben Murdoch virtual CompositingTriggerFlags allowedCompositingTriggers() const; 160db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block#endif 161967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 162545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch virtual bool supportsFullscreenForNode(const WebCore::Node*); 163545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch virtual void enterFullscreenForNode(WebCore::Node*); 164545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch virtual void exitFullscreenForNode(WebCore::Node*); 165545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch 166643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // ChromeClientChromium methods: 167643ca7872b450ea4efacab6188849e5aac2ba161Steve Block virtual void popupOpened(WebCore::PopupContainer* popupContainer, 168643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const WebCore::IntRect& bounds, 169643ca7872b450ea4efacab6188849e5aac2ba161Steve Block bool handleExternally); 170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block virtual void popupClosed(WebCore::PopupContainer* popupContainer); 17168513a70bcd92384395513322f1b801e7bf9c729Steve Block virtual void postAccessibilityNotification(WebCore::AccessibilityObject*, WebCore::AXObjectCache::AXNotification); 172643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 173643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // ChromeClientImpl: 174ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch void setCursorForPlugin(const WebCursorInfo&); 175643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 176db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block virtual bool selectItemWritingDirectionIsNatural(); 1772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block virtual bool selectItemAlignmentFollowsMenuWritingDirection(); 178db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block virtual PassRefPtr<WebCore::PopupMenu> createPopupMenu(WebCore::PopupMenuClient*) const; 179db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block virtual PassRefPtr<WebCore::SearchPopupMenu> createSearchPopupMenu(WebCore::PopupMenuClient*) const; 180db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block 18128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#if ENABLE(CONTEXT_MENUS) 18228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu virtual void showContextMenu() { } 18328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#endif 18428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 185643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockprivate: 186643ca7872b450ea4efacab6188849e5aac2ba161Steve Block void getPopupMenuInfo(WebCore::PopupContainer*, WebPopupMenuInfo*); 187ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch void setCursor(const WebCursorInfo&); 188643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 189643ca7872b450ea4efacab6188849e5aac2ba161Steve Block WebViewImpl* m_webView; // weak pointer 190643ca7872b450ea4efacab6188849e5aac2ba161Steve Block bool m_toolbarsVisible; 191643ca7872b450ea4efacab6188849e5aac2ba161Steve Block bool m_statusbarVisible; 192643ca7872b450ea4efacab6188849e5aac2ba161Steve Block bool m_scrollbarsVisible; 193643ca7872b450ea4efacab6188849e5aac2ba161Steve Block bool m_menubarVisible; 194643ca7872b450ea4efacab6188849e5aac2ba161Steve Block bool m_resizable; 195643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}; 196643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 197643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} // namespace WebKit 198643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 199643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif 200