src/hbcore/devicedialogbase/devicedialogserver/hbdevicedialogmanager_p.cpp
changeset 30 80e4d18b72f5
parent 28 b7da29130b0e
--- a/src/hbcore/devicedialogbase/devicedialogserver/hbdevicedialogmanager_p.cpp	Fri Sep 17 08:32:10 2010 +0300
+++ b/src/hbcore/devicedialogbase/devicedialogserver/hbdevicedialogmanager_p.cpp	Mon Oct 04 00:38:12 2010 +0300
@@ -115,8 +115,8 @@
     if (event->type() ==  QEvent::QEvent::GraphicsSceneResize) {
         HbPopup *popup = qobject_cast<HbPopup*>(obj);
         if (popup) {
-            QRectF rect = popup->rect();
-            rect.moveTo(popup->pos());
+            QRectF rect = popup->mapToScene(popup->rect()).boundingRect();
+            rect = mDeviceDialogManger->mMainWindow->mapFromScene(rect).boundingRect();
             HbDeviceDialogsContainer::Dialog & dialog = mDeviceDialogManger->mDialogs.find(popup);
             mDeviceDialogManger->addRegionRect(dialog.id(), rect);
         }
@@ -240,6 +240,7 @@
 {
     TRACE_ENTRY
 
+    parameters.mError = HbDeviceDialogNoError;
     int id = 0;
 
     HbDeviceDialogPlugin::DeviceDialogInfo info;
@@ -290,8 +291,16 @@
     HbDeviceDialogsContainer::Dialog &dialog = mDialogs.find(id);
     if (dialog.isValid()) {
         HbDeviceDialogInterface *interface = dialog.widget();
-        bool success = interface->setDeviceDialogParameters(parameters);
-        if (!success) {
+        bool success = false;
+        bool catched  = false;
+        try {
+            success = interface->setDeviceDialogParameters(parameters);
+        } catch (const std::bad_alloc &) {
+            catched = true;
+        }
+        if (catched) {
+            ret = HbDeviceDialogGeneralError;
+        } else if (!success) {
             ret = checkpluginerror(interface->deviceDialogError());
         } else {
             ret = HbDeviceDialogNoError;
@@ -314,9 +323,13 @@
         if (!byClient) {
             dialog.setFlags(HbDeviceDialogsContainer::Dialog::ClosedByServer);
         }
-        dialog.widget()->closeDeviceDialog(byClient);
+        ret = HbDeviceDialogNoError;
+        try {
+            dialog.widget()->closeDeviceDialog(byClient);
+        }  catch(const std::bad_alloc &) {
+            ret = HbDeviceDialogGeneralError;
+        }
         startHousekeeperTimer();
-        ret = HbDeviceDialogNoError;
     }
     TRACE_EXIT
     return ret;
@@ -350,6 +363,11 @@
 int HbDeviceDialogManagerPrivate::activateIndicator(
     HbDeviceDialogServer::IndicatorParameters &parameters)
 {
+    // In order to prevent dialogs/indicators trowing bad_alloc during execution, amount
+    // of heap available is checked before activation is allowed.
+    if (!heapAvailable(NormalLevelMinHeap)) {
+        return HbDeviceDialogGeneralError;        
+    }
     QVariantMap credentials;
     addSecurityCredentials(parameters, credentials);
     int result = HbDeviceDialogNoError;
@@ -461,7 +479,7 @@
     RWindowBase *win =
         static_cast<RWindowBase*>(mMainWindow->effectiveWinId()->DrawableWindow());
     if (win) {
-        RRegionBuf<1> windowRegion(QRectToTRect(mMainWindow->sceneRect()));
+        RRegionBuf<1> windowRegion(QRectToTRect(mMainWindow->rect()));
         win->SetShape(windowRegion);
     }
 }
@@ -636,7 +654,12 @@
     HbDeviceDialogServer::DialogParameters &parameters,
     HbDeviceDialogPlugin::DeviceDialogInfo &deviceDialogInfo, HbPopup *&popup)
 {
-    parameters.mError = HbDeviceDialogNoError;
+    // In order to prevent a dialog trowing bad_alloc when it is executing, amount
+    // of heap available is checked before new dialog is allowed.
+    if (!heapAvailable(SecurityLevelMinHeap)) {
+        parameters.mError = HbDeviceDialogGeneralError;
+        return 0;
+    }
 
     QString pluginFilePath;
     if (!mPluginManager.loadPlugin(parameters.mType, QString(), &pluginFilePath)) {
@@ -658,6 +681,15 @@
         return 0;
     }
 
+    // Normal level device dialogs require bigger heap reserve in order to not to
+    // block higher level dialogs.
+    if (deviceDialogInfo.showLevel == HbDeviceDialogPlugin::NormalLevel &&
+        !heapAvailable(NormalLevelMinHeap)) {
+        parameters.mError = HbDeviceDialogGeneralError;
+        mPluginManager.unloadPlugin(pluginFilePath);
+        return 0;
+    }
+
     // Plugin may request security check of the client
     if (deviceDialogInfo.flags & HbDeviceDialogPlugin::SecurityCheck) {
         QVariantMap credentials;
@@ -819,6 +851,34 @@
     return true;
 }
 
+// Check there is minimum amount of heap available
+bool HbDeviceDialogManagerPrivate::heapAvailable(int aBytes)
+{
+    const int MaxFragments = 16;
+    const int MinFragmentSize = 0x1000; // 4 kB
+    int fragmentSize = aBytes / MaxFragments;
+    if (fragmentSize < MinFragmentSize) {
+        fragmentSize = MinFragmentSize;
+    }
+    char *fragments[MaxFragments];
+    memset(&fragments, 0, sizeof(fragments));
+    bool success = true;
+    int i = 0;
+    while(success && i < MaxFragments && aBytes >= 0) {
+        try {
+            fragments[i] = new char[fragmentSize];
+        } catch(const std::bad_alloc &) {
+            success = false;
+        }
+        i++;
+        aBytes -= fragmentSize;
+    }
+    for(--i; i >= 0; i--) {
+        delete [] fragments[i];
+    }
+    return success;
+}
+
 // Called by device dialog widget to send some data to client.
 void HbDeviceDialogManagerPrivate::deviceDialogUpdate(const QVariantMap &data) const
 {