Home | History | Annotate | Download | only in inspector
      1 /*
      2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Matt Lilek <webkit (at) mattlilek.com>
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * 1.  Redistributions of source code must retain the above copyright
     10  *     notice, this list of conditions and the following disclaimer.
     11  * 2.  Redistributions in binary form must reproduce the above copyright
     12  *     notice, this list of conditions and the following disclaimer in the
     13  *     documentation and/or other materials provided with the distribution.
     14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     15  *     its contributors may be used to endorse or promote products derived
     16  *     from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include "config.h"
     31 #include "core/inspector/InspectorFrontendHost.h"
     32 
     33 #include "bindings/v8/ScriptFunctionCall.h"
     34 #include "core/dom/UserGestureIndicator.h"
     35 #include "core/inspector/InspectorController.h"
     36 #include "core/inspector/InspectorFrontendClient.h"
     37 #include "core/loader/FrameLoader.h"
     38 #include "core/loader/TextResourceDecoder.h"
     39 #include "core/page/ContextMenuController.h"
     40 #include "core/page/ContextMenuProvider.h"
     41 #include "core/page/Frame.h"
     42 #include "core/page/Page.h"
     43 #include "core/platform/ContextMenu.h"
     44 #include "core/platform/ContextMenuItem.h"
     45 #include "core/platform/Pasteboard.h"
     46 #include "core/platform/network/ResourceError.h"
     47 #include "core/platform/network/ResourceRequest.h"
     48 #include "core/platform/network/ResourceResponse.h"
     49 #include "core/rendering/RenderTheme.h"
     50 #include "modules/filesystem/DOMFileSystem.h"
     51 
     52 namespace WebCore {
     53 
     54 class FrontendMenuProvider : public ContextMenuProvider {
     55 public:
     56     static PassRefPtr<FrontendMenuProvider> create(InspectorFrontendHost* frontendHost, ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items)
     57     {
     58         return adoptRef(new FrontendMenuProvider(frontendHost, frontendApiObject, items));
     59     }
     60 
     61     void disconnect()
     62     {
     63         m_frontendApiObject = ScriptObject();
     64         m_frontendHost = 0;
     65     }
     66 
     67 private:
     68     FrontendMenuProvider(InspectorFrontendHost* frontendHost, ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items)
     69         : m_frontendHost(frontendHost)
     70         , m_frontendApiObject(frontendApiObject)
     71         , m_items(items)
     72     {
     73     }
     74 
     75     virtual ~FrontendMenuProvider()
     76     {
     77         contextMenuCleared();
     78     }
     79 
     80     virtual void populateContextMenu(ContextMenu* menu)
     81     {
     82         for (size_t i = 0; i < m_items.size(); ++i)
     83             menu->appendItem(m_items[i]);
     84     }
     85 
     86     virtual void contextMenuItemSelected(const ContextMenuItem* item)
     87     {
     88         if (m_frontendHost) {
     89             UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
     90             int itemNumber = item->action() - ContextMenuItemBaseCustomTag;
     91 
     92             ScriptFunctionCall function(m_frontendApiObject, "contextMenuItemSelected");
     93             function.appendArgument(itemNumber);
     94             function.call();
     95         }
     96     }
     97 
     98     virtual void contextMenuCleared()
     99     {
    100         if (m_frontendHost) {
    101             ScriptFunctionCall function(m_frontendApiObject, "contextMenuCleared");
    102             function.call();
    103 
    104             m_frontendHost->m_menuProvider = 0;
    105         }
    106         m_items.clear();
    107     }
    108 
    109     InspectorFrontendHost* m_frontendHost;
    110     ScriptObject m_frontendApiObject;
    111     Vector<ContextMenuItem> m_items;
    112 };
    113 
    114 InspectorFrontendHost::InspectorFrontendHost(InspectorFrontendClient* client, Page* frontendPage)
    115     : m_client(client)
    116     , m_frontendPage(frontendPage)
    117     , m_menuProvider(0)
    118 {
    119     ScriptWrappable::init(this);
    120 }
    121 
    122 InspectorFrontendHost::~InspectorFrontendHost()
    123 {
    124     ASSERT(!m_client);
    125 }
    126 
    127 void InspectorFrontendHost::disconnectClient()
    128 {
    129     m_client = 0;
    130     if (m_menuProvider)
    131         m_menuProvider->disconnect();
    132     m_frontendPage = 0;
    133 }
    134 
    135 void InspectorFrontendHost::loaded()
    136 {
    137 }
    138 
    139 void InspectorFrontendHost::requestSetDockSide(const String& side)
    140 {
    141     if (!m_client)
    142         return;
    143     if (side == "undocked")
    144         m_client->requestSetDockSide(InspectorFrontendClient::Undocked);
    145     else if (side == "right")
    146         m_client->requestSetDockSide(InspectorFrontendClient::DockedToRight);
    147     else if (side == "bottom")
    148         m_client->requestSetDockSide(InspectorFrontendClient::DockedToBottom);
    149 }
    150 
    151 void InspectorFrontendHost::closeWindow()
    152 {
    153     if (m_client) {
    154         m_client->closeWindow();
    155         disconnectClient(); // Disconnect from client.
    156     }
    157 }
    158 
    159 void InspectorFrontendHost::bringToFront()
    160 {
    161     if (m_client)
    162         m_client->bringToFront();
    163 }
    164 
    165 void InspectorFrontendHost::setZoomFactor(float zoom)
    166 {
    167     m_frontendPage->mainFrame()->setPageAndTextZoomFactors(zoom, 1);
    168 }
    169 
    170 void InspectorFrontendHost::inspectedURLChanged(const String& newURL)
    171 {
    172     if (m_client)
    173         m_client->inspectedURLChanged(newURL);
    174 }
    175 
    176 void InspectorFrontendHost::setAttachedWindowHeight(unsigned height)
    177 {
    178     if (m_client)
    179         m_client->changeAttachedWindowHeight(height);
    180 }
    181 
    182 void InspectorFrontendHost::moveWindowBy(float x, float y) const
    183 {
    184     if (m_client)
    185         m_client->moveWindowBy(x, y);
    186 }
    187 
    188 void InspectorFrontendHost::setInjectedScriptForOrigin(const String& origin, const String& script)
    189 {
    190     ASSERT(m_frontendPage->inspectorController());
    191     m_frontendPage->inspectorController()->setInjectedScriptForOrigin(origin, script);
    192 }
    193 
    194 String InspectorFrontendHost::localizedStringsURL()
    195 {
    196     return "";
    197 }
    198 
    199 void InspectorFrontendHost::copyText(const String& text)
    200 {
    201     Pasteboard::generalPasteboard()->writePlainText(text, Pasteboard::CannotSmartReplace);
    202 }
    203 
    204 void InspectorFrontendHost::openInNewTab(const String& url)
    205 {
    206     if (m_client)
    207         m_client->openInNewTab(url);
    208 }
    209 
    210 bool InspectorFrontendHost::canSave()
    211 {
    212     return true;
    213 }
    214 
    215 void InspectorFrontendHost::save(const String& url, const String& content, bool forceSaveAs)
    216 {
    217     if (m_client)
    218         m_client->save(url, content, forceSaveAs);
    219 }
    220 
    221 void InspectorFrontendHost::append(const String& url, const String& content)
    222 {
    223     if (m_client)
    224         m_client->append(url, content);
    225 }
    226 
    227 void InspectorFrontendHost::close(const String&)
    228 {
    229 }
    230 
    231 void InspectorFrontendHost::sendMessageToBackend(const String& message)
    232 {
    233     if (m_client)
    234         m_client->sendMessageToBackend(message);
    235 }
    236 
    237 void InspectorFrontendHost::showContextMenu(Event* event, const Vector<ContextMenuItem>& items)
    238 {
    239     if (!event)
    240         return;
    241 
    242     ASSERT(m_frontendPage);
    243     ScriptState* frontendScriptState = mainWorldScriptState(m_frontendPage->mainFrame());
    244     ScriptObject frontendApiObject;
    245     if (!ScriptGlobalObject::get(frontendScriptState, "InspectorFrontendAPI", frontendApiObject)) {
    246         ASSERT_NOT_REACHED();
    247         return;
    248     }
    249     RefPtr<FrontendMenuProvider> menuProvider = FrontendMenuProvider::create(this, frontendApiObject, items);
    250     ContextMenuController* menuController = m_frontendPage->contextMenuController();
    251     menuController->showContextMenu(event, menuProvider);
    252     m_menuProvider = menuProvider.get();
    253 }
    254 
    255 String InspectorFrontendHost::loadResourceSynchronously(const String& url)
    256 {
    257     ResourceRequest request(url);
    258     request.setHTTPMethod("GET");
    259 
    260     Vector<char> data;
    261     ResourceError error;
    262     ResourceResponse response;
    263     m_frontendPage->mainFrame()->loader()->loadResourceSynchronously(request, DoNotAllowStoredCredentials, error, response, data);
    264     WTF::TextEncoding textEncoding(response.textEncodingName());
    265     bool useDetector = false;
    266     if (!textEncoding.isValid()) {
    267         textEncoding = UTF8Encoding();
    268         useDetector = true;
    269     }
    270     RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/plain", textEncoding, useDetector);
    271     return decoder->decode(data.data(), data.size()) + decoder->flush();
    272 }
    273 
    274 String InspectorFrontendHost::getSelectionBackgroundColor()
    275 {
    276     Color color = m_frontendPage->theme()->activeSelectionBackgroundColor();
    277     return color != Color::transparent ? color.serialized() : "";
    278 }
    279 
    280 String InspectorFrontendHost::getSelectionForegroundColor()
    281 {
    282     Color color = m_frontendPage->theme()->activeSelectionForegroundColor();
    283     return color != Color::transparent ? color.serialized() : "";
    284 }
    285 
    286 bool InspectorFrontendHost::supportsFileSystems()
    287 {
    288     return true;
    289 }
    290 
    291 void InspectorFrontendHost::requestFileSystems()
    292 {
    293     if (m_client)
    294         m_client->requestFileSystems();
    295 }
    296 
    297 void InspectorFrontendHost::addFileSystem()
    298 {
    299     if (m_client)
    300         m_client->addFileSystem();
    301 }
    302 
    303 void InspectorFrontendHost::removeFileSystem(const String& fileSystemPath)
    304 {
    305     if (m_client)
    306         m_client->removeFileSystem(fileSystemPath);
    307 }
    308 
    309 PassRefPtr<DOMFileSystem> InspectorFrontendHost::isolatedFileSystem(const String& fileSystemName, const String& rootURL)
    310 {
    311     ScriptExecutionContext* context = m_frontendPage->mainFrame()->document();
    312     return DOMFileSystem::create(context, fileSystemName, FileSystemTypeIsolated, KURL(ParsedURLString, rootURL), AsyncFileSystem::create());
    313 }
    314 
    315 void InspectorFrontendHost::indexPath(int requestId, const String& fileSystemPath)
    316 {
    317     if (m_client)
    318         m_client->indexPath(requestId, fileSystemPath);
    319 }
    320 
    321 void InspectorFrontendHost::stopIndexing(int requestId)
    322 {
    323     if (m_client)
    324         m_client->stopIndexing(requestId);
    325 }
    326 
    327 void InspectorFrontendHost::searchInPath(int requestId, const String& fileSystemPath, const String& query)
    328 {
    329     if (m_client)
    330         m_client->searchInPath(requestId, fileSystemPath, query);
    331 }
    332 
    333 bool InspectorFrontendHost::isUnderTest()
    334 {
    335     return m_client && m_client->isUnderTest();
    336 }
    337 
    338 bool InspectorFrontendHost::canSaveAs()
    339 {
    340     return false;
    341 }
    342 
    343 bool InspectorFrontendHost::canInspectWorkers()
    344 {
    345     return false;
    346 }
    347 
    348 String InspectorFrontendHost::hiddenPanels()
    349 {
    350     return "";
    351 }
    352 
    353 } // namespace WebCore
    354